2 * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
19 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
23 #include "pipespawn.h"
24 #include <string.h> /* memset() */
28 #ifdef HAVE_SYS_TAPE_H
29 # include <sys/tape.h>
31 #ifdef HAVE_SYS_MTIO_H
32 # include <sys/mtio.h>
38 /* This is equal to 2*1024*1024*1024 - 16*1024*1024 - 1, but written
39 explicitly to avoid overflow issues. */
40 #define RESETOFS_THRESHOLD (0x7effffff)
42 /* Largest possible block size on SCSI systems. */
43 #define LARGEST_BLOCK_ESTIMATE (16 * 1024 * 1024)
46 * Type checking and casting macros
49 #define TYPE_TAPE_DEVICE (tape_device_get_type())
50 #define TAPE_DEVICE(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), tape_device_get_type(), TapeDevice)
51 #define TAPE_DEVICE_CONST(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), tape_device_get_type(), TapeDevice const)
52 #define TAPE_DEVICE_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), tape_device_get_type(), TapeDeviceClass)
53 #define IS_TAPE_DEVICE(obj) G_TYPE_CHECK_INSTANCE_TYPE((obj), tape_device_get_type ())
54 #define TAPE_DEVICE_GET_CLASS(obj) G_TYPE_INSTANCE_GET_CLASS((obj), tape_device_get_type(), TapeDeviceClass)
55 GType tape_device_get_type (void);
58 * Main object structure
60 typedef struct TapeDevicePrivate_s TapeDevicePrivate;
61 typedef struct _TapeDevice {
64 /* It should go without saying that all this stuff is
65 * look-but-don't-touch. */
67 /* characteristics of the device */
68 gboolean fsf, bsf, fsr, bsr, eom, bsf_after_eom, broken_gmt_online;
70 gboolean nonblocking_open, fsf_after_filemark;
73 /* 0 if we opened with O_RDWR; error otherwise. */
74 gboolean write_open_errno;
77 TapeDevicePrivate * private;
80 struct TapeDevicePrivate_s {
81 /* This holds the total number of bytes written to the device,
82 modulus RESETOFS_THRESHOLD. */
84 char * device_filename;
85 gsize read_block_size;
92 typedef struct _TapeDeviceClass TapeDeviceClass;
93 struct _TapeDeviceClass {
94 DeviceClass __parent__;
97 void tape_device_register(void);
99 /* useful callback for tape ops */
100 void tape_device_set_capabilities(TapeDevice *self,
101 gboolean fsf, PropertySurety fsf_surety, PropertySource fsf_source,
102 gboolean fsf_after_filemark, PropertySurety faf_surety, PropertySource faf_source,
103 gboolean bsf, PropertySurety bsf_surety, PropertySource bsf_source,
104 gboolean fsr, PropertySurety fsr_surety, PropertySource fsr_source,
105 gboolean bsr, PropertySurety bsr_surety, PropertySource bsr_source,
106 gboolean eom, PropertySurety eom_surety, PropertySource eom_source,
107 gboolean leom, PropertySurety leom_surety, PropertySource leom_source,
108 gboolean bsf_after_eom, PropertySurety bae_surety, PropertySource bae_source,
109 guint final_filemarks, PropertySurety ff_surety, PropertySource ff_source);
111 /* Real Operations (always return FALSE if not implemented) */
112 gboolean tape_rewind(int fd);
113 gboolean tape_fsf(int fd, guint count);
114 gboolean tape_bsf(int fd, guint count);
115 gboolean tape_fsr(int fd, guint count);
116 gboolean tape_bsr(int fd, guint count);
117 gint tape_fileno(int fd);
119 /* tape_fileno returns tape position file number, or one of these: */
120 #define TAPE_OP_ERROR -1
121 #define TAPE_POSITION_UNKNOWN -2
123 /* Possible (abstracted) results from a system I/O operation. */
126 RESULT_ERROR, /* Undefined error (*errmsg set) */
127 RESULT_SMALL_BUFFER, /* Tried to read with a buffer that is too
129 RESULT_NO_DATA, /* End of File, while reading */
130 RESULT_NO_SPACE, /* Out of space. Sometimes we don't know if
131 it was this or I/O error, but this is the
132 preferred explanation. */
136 /* returns a fileno like tape_fileno */
137 gint tape_eod(int fd);
139 gboolean tape_weof(int fd, guint8 count);
140 gboolean tape_setcompression(int fd, gboolean on);
142 gboolean tape_offl(int fd);
144 DeviceStatusFlags tape_is_tape_device(int fd);
145 DeviceStatusFlags tape_is_ready(int fd, TapeDevice *t_self);
147 #define tape_device_read_size(self) \
148 (((TapeDevice *)(self))->private->read_block_size? \
149 ((TapeDevice *)(self))->private->read_block_size : ((Device *)(self))->block_size)
152 * Our device-specific properties.
155 #define PROPERTY_BROKEN_GMT_ONLINE (device_property_broken_gmt_online.ID)
156 #define PROPERTY_FSF (device_property_fsf.ID)
157 #define PROPERTY_FSF_AFTER_FILEMARK (device_property_fsf_after_filemark.ID)
158 #define PROPERTY_BSF (device_property_bsf.ID)
159 #define PROPERTY_FSR (device_property_fsr.ID)
160 #define PROPERTY_BSR (device_property_bsr.ID)
161 #define PROPERTY_EOM (device_property_eom.ID)
162 #define PROPERTY_BSF_AFTER_EOM (device_property_bsf_after_eom.ID)
163 #define PROPERTY_NONBLOCKING_OPEN (device_property_nonblocking_open.ID)
164 #define PROPERTY_FINAL_FILEMARKS (device_property_final_filemarks.ID)
166 static DevicePropertyBase device_property_broken_gmt_online;
167 static DevicePropertyBase device_property_fsf;
168 static DevicePropertyBase device_property_fsf_after_filemark;
169 static DevicePropertyBase device_property_bsf;
170 static DevicePropertyBase device_property_fsr;
171 static DevicePropertyBase device_property_bsr;
172 static DevicePropertyBase device_property_eom;
173 static DevicePropertyBase device_property_bsf_after_eom;
174 static DevicePropertyBase device_property_nonblocking_open;
175 static DevicePropertyBase device_property_final_filemarks;
176 static DevicePropertyBase device_property_read_buffer_size; /* old name for READ_BLOCK_SIZE */
178 /* here are local prototypes */
179 static void tape_device_init (TapeDevice * o);
180 static void tape_device_class_init (TapeDeviceClass * c);
181 static void tape_device_base_init (TapeDeviceClass * c);
182 static gboolean tape_device_set_feature_property_fn(Device *p_self, DevicePropertyBase *base,
183 GValue *val, PropertySurety surety, PropertySource source);
184 static gboolean tape_device_set_final_filemarks_fn(Device *p_self, DevicePropertyBase *base,
185 GValue *val, PropertySurety surety, PropertySource source);
186 static gboolean tape_device_set_compression_fn(Device *p_self, DevicePropertyBase *base,
187 GValue *val, PropertySurety surety, PropertySource source);
188 static gboolean tape_device_get_read_block_size_fn(Device *p_self, DevicePropertyBase *base,
189 GValue *val, PropertySurety *surety, PropertySource *source);
190 static gboolean tape_device_set_read_block_size_fn(Device *p_self, DevicePropertyBase *base,
191 GValue *val, PropertySurety surety, PropertySource source);
192 static void tape_device_open_device (Device * self, char * device_name, char * device_type, char * device_node);
193 static Device * tape_device_factory (char * device_name, char * device_type, char * device_node);
194 static DeviceStatusFlags tape_device_read_label(Device * self);
195 static gboolean tape_device_write_block(Device * self, guint size, gpointer data);
196 static int tape_device_read_block(Device * self, gpointer buf,
198 static gboolean tape_device_start (Device * self, DeviceAccessMode mode,
199 char * label, char * timestamp);
200 static gboolean tape_device_start_file (Device * self, dumpfile_t * ji);
201 static gboolean tape_device_finish_file (Device * self);
202 static dumpfile_t * tape_device_seek_file (Device * self, guint file);
203 static gboolean tape_device_seek_block (Device * self, guint64 block);
204 static gboolean tape_device_eject (Device * self);
205 static gboolean tape_device_finish (Device * self);
206 static IoResult tape_device_robust_read (TapeDevice * self, void * buf,
207 int * count, char **errmsg);
208 static IoResult tape_device_robust_write (TapeDevice * self, void * buf, int count, char **errmsg);
209 static gboolean tape_device_fsf (TapeDevice * self, guint count);
210 static gboolean tape_device_fsr (TapeDevice * self, guint count);
211 static gboolean tape_device_bsr (TapeDevice * self, guint count, guint file, guint block);
212 static gboolean tape_device_eod (TapeDevice * self);
214 /* pointer to the class of our parent */
215 static DeviceClass *parent_class = NULL;
217 GType tape_device_get_type (void)
219 static GType type = 0;
221 if G_UNLIKELY(type == 0) {
222 static const GTypeInfo info = {
223 sizeof (TapeDeviceClass),
224 (GBaseInitFunc) tape_device_base_init,
225 (GBaseFinalizeFunc) NULL,
226 (GClassInitFunc) tape_device_class_init,
227 (GClassFinalizeFunc) NULL,
228 NULL /* class_data */,
231 (GInstanceInitFunc) tape_device_init,
235 type = g_type_register_static (TYPE_DEVICE, "TapeDevice",
236 &info, (GTypeFlags)0);
243 tape_device_init (TapeDevice * self) {
247 d_self = DEVICE(self);
248 bzero(&response, sizeof(response));
250 self->private = g_new0(TapeDevicePrivate, 1);
252 /* Clear all fields. */
253 d_self->block_size = 32768;
254 d_self->min_block_size = 32768;
255 d_self->max_block_size = LARGEST_BLOCK_ESTIMATE;
256 self->broken_gmt_online = FALSE;
260 /* set all of the feature properties to an unsure default of FALSE */
261 self->broken_gmt_online = FALSE;
268 self->bsf_after_eom = FALSE;
270 g_value_init(&response, G_TYPE_BOOLEAN);
271 g_value_set_boolean(&response, FALSE);
272 device_set_simple_property(d_self, PROPERTY_BROKEN_GMT_ONLINE,
273 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
274 device_set_simple_property(d_self, PROPERTY_FSF,
275 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
276 device_set_simple_property(d_self, PROPERTY_FSF_AFTER_FILEMARK,
277 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
278 device_set_simple_property(d_self, PROPERTY_BSF,
279 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
280 device_set_simple_property(d_self, PROPERTY_FSR,
281 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
282 device_set_simple_property(d_self, PROPERTY_BSR,
283 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
284 device_set_simple_property(d_self, PROPERTY_EOM,
285 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
286 device_set_simple_property(d_self, PROPERTY_LEOM,
287 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
288 device_set_simple_property(d_self, PROPERTY_BSF_AFTER_EOM,
289 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
291 #ifdef DEFAULT_TAPE_NON_BLOCKING_OPEN
292 self->nonblocking_open = TRUE;
294 self->nonblocking_open = FALSE;
296 g_value_set_boolean(&response, self->nonblocking_open);
297 device_set_simple_property(d_self, PROPERTY_NONBLOCKING_OPEN,
298 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
299 g_value_unset(&response);
301 self->final_filemarks = 2;
302 g_value_init(&response, G_TYPE_UINT);
303 g_value_set_uint(&response, self->final_filemarks);
304 device_set_simple_property(d_self, PROPERTY_FINAL_FILEMARKS,
305 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
306 g_value_unset(&response);
308 self->private->read_block_size = 0;
309 g_value_init(&response, G_TYPE_UINT);
310 g_value_set_uint(&response, self->private->read_block_size);
311 device_set_simple_property(d_self, PROPERTY_READ_BLOCK_SIZE,
312 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DEFAULT);
313 g_value_unset(&response);
315 self->private->write_count = 0;
316 self->private->device_filename = NULL;
318 /* Static properites */
319 g_value_init(&response, CONCURRENCY_PARADIGM_TYPE);
320 g_value_set_enum(&response, CONCURRENCY_PARADIGM_EXCLUSIVE);
321 device_set_simple_property(d_self, PROPERTY_CONCURRENCY,
322 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
323 g_value_unset(&response);
325 g_value_init(&response, STREAMING_REQUIREMENT_TYPE);
326 g_value_set_enum(&response, STREAMING_REQUIREMENT_DESIRED);
327 device_set_simple_property(d_self, PROPERTY_STREAMING,
328 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
329 g_value_unset(&response);
331 g_value_init(&response, G_TYPE_BOOLEAN);
332 g_value_set_boolean(&response, TRUE);
333 device_set_simple_property(d_self, PROPERTY_APPENDABLE,
334 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
335 g_value_unset(&response);
337 g_value_init(&response, G_TYPE_BOOLEAN);
338 g_value_set_boolean(&response, FALSE);
339 device_set_simple_property(d_self, PROPERTY_PARTIAL_DELETION,
340 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
341 g_value_unset(&response);
343 g_value_init(&response, G_TYPE_BOOLEAN);
344 g_value_set_boolean(&response, FALSE);
345 device_set_simple_property(d_self, PROPERTY_FULL_DELETION,
346 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
347 g_value_unset(&response);
349 g_value_init(&response, MEDIA_ACCESS_MODE_TYPE);
350 g_value_set_enum(&response, MEDIA_ACCESS_MODE_READ_WRITE);
351 device_set_simple_property(d_self, PROPERTY_MEDIUM_ACCESS_TYPE,
352 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
353 g_value_unset(&response);
356 static void tape_device_finalize(GObject * obj_self) {
357 TapeDevice * self = TAPE_DEVICE(obj_self);
359 if(G_OBJECT_CLASS(parent_class)->finalize) \
360 (* G_OBJECT_CLASS(parent_class)->finalize)(obj_self);
362 robust_close(self->fd);
364 amfree(self->private->device_filename);
365 amfree(self->private);
369 tape_device_class_init (TapeDeviceClass * c)
371 DeviceClass *device_class = (DeviceClass *)c;
372 GObjectClass *g_object_class = (GObjectClass *)c;
374 parent_class = g_type_class_ref (TYPE_DEVICE);
376 device_class->open_device = tape_device_open_device;
377 device_class->read_label = tape_device_read_label;
378 device_class->write_block = tape_device_write_block;
379 device_class->read_block = tape_device_read_block;
380 device_class->start = tape_device_start;
381 device_class->start_file = tape_device_start_file;
382 device_class->finish_file = tape_device_finish_file;
383 device_class->seek_file = tape_device_seek_file;
384 device_class->seek_block = tape_device_seek_block;
385 device_class->eject = tape_device_eject;
386 device_class->finish = tape_device_finish;
388 g_object_class->finalize = tape_device_finalize;
392 tape_device_base_init (TapeDeviceClass * c)
394 DeviceClass *device_class = (DeviceClass *)c;
396 device_class_register_property(device_class, PROPERTY_BROKEN_GMT_ONLINE,
397 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
398 device_simple_property_get_fn,
399 tape_device_set_feature_property_fn);
401 device_class_register_property(device_class, PROPERTY_FSF,
402 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
403 device_simple_property_get_fn,
404 tape_device_set_feature_property_fn);
406 device_class_register_property(device_class, PROPERTY_FSF_AFTER_FILEMARK,
407 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
408 device_simple_property_get_fn,
409 tape_device_set_feature_property_fn);
411 device_class_register_property(device_class, PROPERTY_BSF,
412 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
413 device_simple_property_get_fn,
414 tape_device_set_feature_property_fn);
416 device_class_register_property(device_class, PROPERTY_FSR,
417 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
418 device_simple_property_get_fn,
419 tape_device_set_feature_property_fn);
421 device_class_register_property(device_class, PROPERTY_BSR,
422 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
423 device_simple_property_get_fn,
424 tape_device_set_feature_property_fn);
426 device_class_register_property(device_class, PROPERTY_EOM,
427 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
428 device_simple_property_get_fn,
429 tape_device_set_feature_property_fn);
431 device_class_register_property(device_class, PROPERTY_BSF_AFTER_EOM,
432 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
433 device_simple_property_get_fn,
434 tape_device_set_feature_property_fn);
436 device_class_register_property(device_class, PROPERTY_NONBLOCKING_OPEN,
437 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
438 device_simple_property_get_fn,
439 tape_device_set_feature_property_fn);
441 device_class_register_property(device_class, PROPERTY_FINAL_FILEMARKS,
442 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
443 device_simple_property_get_fn,
444 tape_device_set_final_filemarks_fn);
446 /* We don't (yet?) support reading the device's compression state, so not
448 device_class_register_property(device_class, PROPERTY_COMPRESSION,
449 PROPERTY_ACCESS_SET_MASK,
451 tape_device_set_compression_fn);
453 device_class_register_property(device_class, PROPERTY_READ_BLOCK_SIZE,
454 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
455 tape_device_get_read_block_size_fn,
456 tape_device_set_read_block_size_fn);
458 device_class_register_property(device_class, device_property_read_buffer_size.ID,
459 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
460 tape_device_get_read_block_size_fn,
461 tape_device_set_read_block_size_fn);
463 /* add the ability to set LEOM to FALSE, for testing purposes */
464 device_class_register_property(device_class, PROPERTY_LEOM,
465 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
466 device_simple_property_get_fn,
467 tape_device_set_feature_property_fn);
471 tape_device_set_feature_property_fn(Device *p_self, DevicePropertyBase *base,
472 GValue *val, PropertySurety surety, PropertySource source)
474 TapeDevice *self = TAPE_DEVICE(p_self);
476 gboolean old_bool, new_bool;
477 PropertySurety old_surety;
478 PropertySource old_source;
480 new_bool = g_value_get_boolean(val);
482 /* get the old source and surety and see if we're willing to make this change */
483 bzero(&old_val, sizeof(old_val));
484 if (device_get_simple_property(p_self, base->ID, &old_val, &old_surety, &old_source)) {
485 old_bool = g_value_get_boolean(&old_val);
487 if (old_surety == PROPERTY_SURETY_GOOD && old_source == PROPERTY_SOURCE_DETECTED) {
488 if (new_bool != old_bool) {
489 device_set_error(p_self, vstrallocf(_(
490 "Value for property '%s' was autodetected and cannot be changed"),
492 DEVICE_STATUS_DEVICE_ERROR);
495 /* pretend we set it, but don't change surety/source */
501 /* (note: PROPERTY_* are not constants, so we can't use switch) */
502 if (base->ID == PROPERTY_BROKEN_GMT_ONLINE)
503 self->broken_gmt_online = new_bool;
504 else if (base->ID == PROPERTY_FSF)
505 self->fsf = new_bool;
506 else if (base->ID == PROPERTY_FSF_AFTER_FILEMARK)
507 self->fsf_after_filemark = new_bool;
508 else if (base->ID == PROPERTY_BSF)
509 self->bsf = new_bool;
510 else if (base->ID == PROPERTY_FSR)
511 self->fsr = new_bool;
512 else if (base->ID == PROPERTY_BSR)
513 self->bsr = new_bool;
514 else if (base->ID == PROPERTY_EOM)
515 self->eom = new_bool;
516 else if (base->ID == PROPERTY_BSF_AFTER_EOM)
517 self->bsf_after_eom = new_bool;
518 else if (base->ID == PROPERTY_NONBLOCKING_OPEN)
519 self->nonblocking_open = new_bool;
520 else if (base->ID == PROPERTY_LEOM)
521 self->leom = new_bool;
523 return FALSE; /* shouldn't happen */
525 return device_simple_property_set_fn(p_self, base, val, surety, source);
529 tape_device_set_final_filemarks_fn(Device *p_self, DevicePropertyBase *base,
530 GValue *val, PropertySurety surety, PropertySource source)
532 TapeDevice *self = TAPE_DEVICE(p_self);
534 gboolean old_int, new_int;
535 PropertySurety old_surety;
536 PropertySource old_source;
538 new_int = g_value_get_uint(val);
540 /* get the old source and surety and see if we're willing to make this change */
541 bzero(&old_val, sizeof(old_val));
542 if (device_get_simple_property(p_self, base->ID, &old_val, &old_surety, &old_source)) {
543 old_int = g_value_get_uint(&old_val);
545 if (old_surety == PROPERTY_SURETY_GOOD && old_source == PROPERTY_SOURCE_DETECTED) {
546 if (new_int != old_int) {
547 device_set_error(p_self, vstrallocf(_(
548 "Value for property '%s' was autodetected and cannot be changed"),
550 DEVICE_STATUS_DEVICE_ERROR);
553 /* pretend we set it, but don't change surety/source */
559 self->final_filemarks = new_int;
561 return device_simple_property_set_fn(p_self, base, val, surety, source);
565 tape_device_set_compression_fn(Device *p_self, DevicePropertyBase *base,
566 GValue *val, PropertySurety surety, PropertySource source)
568 TapeDevice *self = TAPE_DEVICE(p_self);
569 gboolean request = g_value_get_boolean(val);
571 /* We allow this property to be set at any time. This is mostly
572 * because setting compression is a hit-and-miss proposition
573 * at any time; some drives accept the mode setting but don't
574 * actually support compression, while others do support
575 * compression but do it via density settings or some other
576 * way. Set this property whenever you want, but all we'll do
577 * is report whether or not the ioctl succeeded. */
578 if (tape_setcompression(self->fd, request)) {
579 /* looks good .. let's start the device over, though */
580 device_clear_volume_details(p_self);
582 device_set_error(p_self,
583 g_strdup("Error setting COMPRESION property"),
584 DEVICE_STATUS_DEVICE_ERROR);
588 return device_simple_property_set_fn(p_self, base, val, surety, source);
592 tape_device_get_read_block_size_fn(Device *p_self, DevicePropertyBase *base G_GNUC_UNUSED,
593 GValue *val, PropertySurety *surety, PropertySource *source)
595 /* use the READ_BLOCK_SIZE, even if we're invoked to get the old READ_BUFFER_SIZE */
596 return device_simple_property_get_fn(p_self, &device_property_read_block_size,
597 val, surety, source);
601 tape_device_set_read_block_size_fn(Device *p_self, DevicePropertyBase *base G_GNUC_UNUSED,
602 GValue *val, PropertySurety surety, PropertySource source)
604 TapeDevice *self = TAPE_DEVICE(p_self);
605 guint read_block_size = g_value_get_uint(val);
607 if (read_block_size != 0 &&
608 ((gsize)read_block_size < p_self->block_size ||
609 (gsize)read_block_size > p_self->max_block_size)) {
610 device_set_error(p_self,
611 g_strdup_printf("Error setting READ-BLOCk-SIZE property to '%u', it must be between %zu and %zu", read_block_size, p_self->block_size, p_self->max_block_size),
612 DEVICE_STATUS_DEVICE_ERROR);
616 self->private->read_block_size = read_block_size;
618 /* use the READ_BLOCK_SIZE, even if we're invoked to get the old READ_BUFFER_SIZE */
619 return device_simple_property_set_fn(p_self, &device_property_read_block_size,
620 val, surety, source);
623 void tape_device_register(void) {
624 static const char * device_prefix_list[] = { "tape", NULL };
626 /* First register tape-specific properties */
627 device_property_fill_and_register(&device_property_broken_gmt_online,
628 G_TYPE_BOOLEAN, "broken_gmt_online",
629 "Does this drive support the GMT_ONLINE macro?");
631 device_property_fill_and_register(&device_property_fsf,
632 G_TYPE_BOOLEAN, "fsf",
633 "Does this drive support the MTFSF command?");
635 device_property_fill_and_register(&device_property_fsf_after_filemark,
636 G_TYPE_BOOLEAN, "fsf_after_filemark",
637 "Does this drive needs a FSF if a filemark is already read?");
639 device_property_fill_and_register(&device_property_bsf,
640 G_TYPE_BOOLEAN, "bsf",
641 "Does this drive support the MTBSF command?" );
643 device_property_fill_and_register(&device_property_fsr,
644 G_TYPE_BOOLEAN, "fsr",
645 "Does this drive support the MTFSR command?");
647 device_property_fill_and_register(&device_property_bsr,
648 G_TYPE_BOOLEAN, "bsr",
649 "Does this drive support the MTBSR command?");
651 device_property_fill_and_register(&device_property_eom,
652 G_TYPE_BOOLEAN, "eom",
653 "Does this drive support the MTEOM command?");
655 device_property_fill_and_register(&device_property_bsf_after_eom,
658 "Does this drive require an MTBSF after MTEOM in order to append?" );
660 device_property_fill_and_register(&device_property_nonblocking_open,
663 "Does this drive require a open with O_NONBLOCK?" );
665 device_property_fill_and_register(&device_property_final_filemarks,
666 G_TYPE_UINT, "final_filemarks",
667 "How many filemarks to write after the last tape file?" );
669 device_property_fill_and_register(&device_property_read_buffer_size,
670 G_TYPE_UINT, "read_buffer_size",
671 "(deprecated name for READ_BLOCK_SIZE)");
673 /* Then the device itself */
674 register_device(tape_device_factory, device_prefix_list);
677 /* Open the tape device, trying various combinations of O_RDWR and
678 O_NONBLOCK. Returns -1 and calls device_set_error for errors
679 On Linux, with O_NONBLOCK, the kernel just checks the state once,
680 whereas it checks it every second for ST_BLOCK_SECONDS if O_NONBLOCK is
681 not given. Amanda already have the code to poll, we want open to check
682 the state only once. */
684 static int try_open_tape_device(TapeDevice * self, char * device_filename) {
687 DeviceStatusFlags new_status;
692 if (self->nonblocking_open) {
693 nonblocking = O_NONBLOCK;
698 fd = robust_open(device_filename, O_RDWR | nonblocking, 0);
700 if (fd < 0 && nonblocking && (save_errno == EWOULDBLOCK || save_errno == EINVAL)) {
701 /* Maybe we don't support O_NONBLOCK for tape devices. */
702 fd = robust_open(device_filename, O_RDWR, 0);
706 fd = robust_open(device_filename, O_RDWR, 0);
710 self->write_open_errno = 0;
712 if (errno == EACCES || errno == EPERM
717 /* Device is write-protected. */
718 self->write_open_errno = errno;
720 fd = robust_open(device_filename, O_RDONLY | nonblocking, 0);
722 if (fd < 0 && nonblocking && (save_errno == EWOULDBLOCK || save_errno == EINVAL)) {
723 fd = robust_open(device_filename, O_RDONLY, 0);
727 fd = robust_open(device_filename, O_RDONLY, 0);
733 /* Clear O_NONBLOCK for operations from now on. */
734 if (fd >= 0 && nonblocking)
735 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
737 /* function continues after #endif */
739 #endif /* O_NONBLOCK */
742 DeviceStatusFlags status_flag = 0;
744 status_flag = DEVICE_STATUS_DEVICE_BUSY;
746 status_flag = DEVICE_STATUS_DEVICE_ERROR;
747 device_set_error(DEVICE(self),
748 vstrallocf(_("Can't open tape device %s: %s"), self->private->device_filename, strerror(errno)),
753 /* Check that this is actually a tape device. */
754 new_status = tape_is_tape_device(fd);
755 if (new_status & DEVICE_STATUS_DEVICE_ERROR) {
756 device_set_error(DEVICE(self),
757 vstrallocf(_("File %s is not a tape device"), self->private->device_filename),
762 if (new_status & DEVICE_STATUS_VOLUME_MISSING) {
763 device_set_error(DEVICE(self),
764 vstrallocf(_("Tape device %s is not ready or is empty"), self->private->device_filename),
770 new_status = tape_is_ready(fd, self);
771 if (new_status & DEVICE_STATUS_VOLUME_MISSING) {
772 device_set_error(DEVICE(self),
773 vstrallocf(_("Tape device %s is empty"), self->private->device_filename),
778 if (new_status != DEVICE_STATUS_SUCCESS) {
779 device_set_error(DEVICE(self),
780 vstrallocf(_("Tape device %s is not ready or is empty"), self->private->device_filename),
790 tape_device_open_device (Device * dself, char * device_name,
791 char * device_type, char * device_node) {
795 self = TAPE_DEVICE(dself);
798 self->private->device_filename = stralloc(device_node);
800 /* Set tape drive/OS info */
801 bzero(&val, sizeof(val));
802 g_value_init(&val, G_TYPE_BOOLEAN);
805 g_value_set_boolean(&val, self->fsf);
806 device_set_simple_property(dself, PROPERTY_FSF, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
808 self->fsf_after_filemark = DEFAULT_FSF_AFTER_FILEMARK;
809 g_value_set_boolean(&val, self->fsf_after_filemark);
810 device_set_simple_property(dself, PROPERTY_FSF_AFTER_FILEMARK, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
813 g_value_set_boolean(&val, self->bsf);
814 device_set_simple_property(dself, PROPERTY_BSF, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
817 g_value_set_boolean(&val, self->fsr);
818 device_set_simple_property(dself, PROPERTY_FSR, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
821 g_value_set_boolean(&val, self->bsr);
822 device_set_simple_property(dself, PROPERTY_BSR, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
825 g_value_set_boolean(&val, self->eom);
826 device_set_simple_property(dself, PROPERTY_EOM, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
829 g_value_set_boolean(&val, self->leom);
830 device_set_simple_property(dself, PROPERTY_LEOM, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
832 self->bsf_after_eom = FALSE;
833 g_value_set_boolean(&val, self->bsf_after_eom);
834 device_set_simple_property(dself, PROPERTY_BSF_AFTER_EOM, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
837 g_value_init(&val, G_TYPE_UINT);
839 self->final_filemarks = 2;
840 g_value_set_uint(&val, self->final_filemarks);
841 device_set_simple_property(dself, PROPERTY_FINAL_FILEMARKS, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
846 if (parent_class->open_device) {
847 parent_class->open_device(dself, device_name, device_type, device_node);
852 static DeviceStatusFlags tape_device_read_label(Device * dself) {
854 char * header_buffer;
858 DeviceStatusFlags new_status;
861 self = TAPE_DEVICE(dself);
863 amfree(dself->volume_label);
864 amfree(dself->volume_time);
865 dumpfile_free(dself->volume_header);
866 dself->volume_header = NULL;
868 if (device_in_error(self)) return dself->status;
870 if (self->fd == -1) {
871 self->fd = try_open_tape_device(self, self->private->device_filename);
872 /* if the open failed, then try_open_tape_device already set the
873 * approppriate error status */
875 return dself->status;
879 if (!tape_rewind(self->fd)) {
880 device_set_error(dself,
881 vstrallocf(_("Error rewinding device %s to read label: %s"),
882 self->private->device_filename, strerror(errno)),
883 DEVICE_STATUS_DEVICE_ERROR
884 | DEVICE_STATUS_VOLUME_ERROR);
885 return dself->status;
888 buffer_len = tape_device_read_size(self);
889 header_buffer = malloc(buffer_len);
890 result = tape_device_robust_read(self, header_buffer, &buffer_len, &msg);
892 if (result != RESULT_SUCCESS) {
894 tape_rewind(self->fd);
898 msg = stralloc(_("no data"));
899 new_status = (DEVICE_STATUS_VOLUME_ERROR |
900 DEVICE_STATUS_VOLUME_UNLABELED);
901 header = dself->volume_header = g_new(dumpfile_t, 1);
905 case RESULT_SMALL_BUFFER:
906 msg = stralloc(_("block size too small"));
907 new_status = (DEVICE_STATUS_DEVICE_ERROR |
908 DEVICE_STATUS_VOLUME_ERROR);
909 header = dself->volume_header = g_new(dumpfile_t, 1);
911 header->type = F_WEIRD;
915 msg = stralloc(_("unknown error"));
917 new_status = (DEVICE_STATUS_DEVICE_ERROR |
918 DEVICE_STATUS_VOLUME_ERROR |
919 DEVICE_STATUS_VOLUME_UNLABELED);
922 device_set_error(dself,
923 g_strdup_printf(_("Error reading Amanda header: %s"),
924 msg? msg : _("unknown error")),
927 return dself->status;
930 dself->header_block_size = buffer_len;
931 header = dself->volume_header = g_new(dumpfile_t, 1);
934 parse_file_header(header_buffer, header, buffer_len);
935 amfree(header_buffer);
936 if (header->type != F_TAPESTART) {
937 device_set_error(dself,
938 stralloc(_("No tapestart header -- unlabeled device?")),
939 DEVICE_STATUS_VOLUME_UNLABELED);
940 return dself->status;
943 dself->volume_label = g_strdup(header->name);
944 dself->volume_time = g_strdup(header->datestamp);
945 /* dself->volume_header is already set */
947 device_set_error(dself, NULL, DEVICE_STATUS_SUCCESS);
949 return dself->status;
953 tape_device_write_block(Device * pself, guint size, gpointer data) {
955 char *replacement_buffer = NULL;
959 self = TAPE_DEVICE(pself);
961 g_assert(self->fd >= 0);
962 if (device_in_error(self)) return FALSE;
964 /* zero out to the end of a short block -- tape devices only write
966 if (size < pself->block_size) {
967 replacement_buffer = malloc(pself->block_size);
968 memcpy(replacement_buffer, data, size);
969 bzero(replacement_buffer+size, pself->block_size-size);
971 data = replacement_buffer;
972 size = pself->block_size;
975 result = tape_device_robust_write(self, data, size, &msg);
976 amfree(replacement_buffer);
982 case RESULT_NO_SPACE:
983 device_set_error(pself,
984 stralloc(_("No space left on device")),
985 DEVICE_STATUS_VOLUME_ERROR);
986 pself->is_eom = TRUE;
990 msg = stralloc(_("unknown error"));
992 device_set_error(pself,
993 g_strdup_printf(_("Error writing block: %s"), msg),
994 DEVICE_STATUS_DEVICE_ERROR);
1000 g_mutex_lock(pself->device_mutex);
1001 pself->bytes_written += size;
1002 g_mutex_unlock(pself->device_mutex);
1007 static int tape_device_read_block (Device * pself, gpointer buf,
1012 gssize read_block_size = tape_device_read_size(pself);
1015 self = TAPE_DEVICE(pself);
1017 g_assert(self->fd >= 0);
1018 if (device_in_error(self)) return -1;
1020 g_assert(read_block_size < INT_MAX); /* data type mismatch */
1021 if (buf == NULL || *size_req < (int)read_block_size) {
1022 /* Just a size query. */
1023 *size_req = (int)read_block_size;
1028 result = tape_device_robust_read(self, buf, &size, &msg);
1030 case RESULT_SUCCESS:
1033 g_mutex_lock(pself->device_mutex);
1034 pself->bytes_read += size;
1035 g_mutex_unlock(pself->device_mutex);
1037 case RESULT_SMALL_BUFFER: {
1041 /* If this happens, it means that we have:
1042 * (next block size) > (buffer size) >= (read_block_size)
1043 * The solution is to ask for an even bigger buffer. We also play
1044 * some games to refrain from reading above the SCSI limit or from
1045 * integer overflow. Note that not all devices will tell us about
1046 * this problem -- some will just discard the "extra" data. */
1047 new_size = MIN(INT_MAX/2 - 1, *size_req) * 2;
1048 if (new_size > LARGEST_BLOCK_ESTIMATE &&
1049 *size_req < LARGEST_BLOCK_ESTIMATE) {
1050 new_size = LARGEST_BLOCK_ESTIMATE;
1052 g_assert (new_size > (gsize)*size_req);
1054 g_info("Device %s indicated blocksize %zd was too small; using %zd.",
1055 pself->device_name, (gsize)*size_req, new_size);
1056 *size_req = (int)new_size;
1057 self->private->read_block_size = new_size;
1059 bzero(&newval, sizeof(newval));
1060 g_value_init(&newval, G_TYPE_UINT);
1061 g_value_set_uint(&newval, self->private->read_block_size);
1062 device_set_simple_property(pself, PROPERTY_READ_BLOCK_SIZE,
1063 &newval, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
1064 g_value_unset(&newval);
1068 case RESULT_NO_DATA:
1069 pself->is_eof = TRUE;
1070 g_mutex_lock(pself->device_mutex);
1071 pself->in_file = FALSE;
1072 g_mutex_unlock(pself->device_mutex);
1073 device_set_error(pself,
1075 DEVICE_STATUS_SUCCESS);
1079 msg = stralloc(_("unknown error"));
1081 device_set_error(pself,
1082 vstrallocf(_("Error reading from tape device: %s"), msg),
1083 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1088 g_assert_not_reached();
1091 /* Just a helper function for tape_device_start(). */
1092 static gboolean write_tapestart_header(TapeDevice * self, char * label,
1095 dumpfile_t * header;
1097 Device * d_self = (Device*)self;
1100 tape_rewind(self->fd);
1102 header = make_tapestart_header(d_self, label, timestamp);
1103 g_assert(header != NULL);
1104 header_buf = device_build_amanda_header(d_self, header, NULL);
1105 if (header_buf == NULL) {
1106 device_set_error(d_self,
1107 stralloc(_("Tapestart header won't fit in a single block!")),
1108 DEVICE_STATUS_DEVICE_ERROR);
1109 dumpfile_free(header);
1112 dumpfile_free(d_self->volume_header);
1113 d_self->volume_header = NULL;
1115 result = tape_device_robust_write(self, header_buf, d_self->block_size, &msg);
1116 if (result != RESULT_SUCCESS) {
1117 device_set_error(d_self,
1118 g_strdup_printf(_("Error writing tapestart header: %s"),
1119 (result == RESULT_ERROR)? msg : _("out of space")),
1120 DEVICE_STATUS_DEVICE_ERROR);
1122 if (result == RESULT_NO_SPACE)
1123 d_self->is_eom = TRUE;
1126 dumpfile_free(header);
1131 d_self->header_block_size = d_self->block_size;
1134 if (!tape_weof(self->fd, 1)) {
1135 device_set_error(d_self,
1136 vstrallocf(_("Error writing filemark: %s"),
1138 DEVICE_STATUS_DEVICE_ERROR|DEVICE_STATUS_VOLUME_ERROR);
1139 /* can't tell if this was EOM or not, so assume it is */
1140 d_self->is_eom = TRUE;
1141 dumpfile_free(header);
1145 d_self->volume_header = header;
1150 tape_device_start (Device * d_self, DeviceAccessMode mode, char * label,
1154 self = TAPE_DEVICE(d_self);
1156 if (device_in_error(self)) return FALSE;
1158 if (self->fd == -1) {
1159 self->fd = try_open_tape_device(self, self->private->device_filename);
1160 /* if the open failed, then try_open_tape_device already set the
1161 * approppriate error status */
1166 if (mode != ACCESS_WRITE && d_self->volume_label == NULL) {
1167 /* we need a labeled volume for APPEND and READ */
1168 if (tape_device_read_label(d_self) != DEVICE_STATUS_SUCCESS)
1172 d_self->access_mode = mode;
1173 g_mutex_lock(d_self->device_mutex);
1174 d_self->in_file = FALSE;
1175 g_mutex_unlock(d_self->device_mutex);
1177 if (IS_WRITABLE_ACCESS_MODE(mode)) {
1178 if (self->write_open_errno != 0) {
1179 /* We tried and failed to open the device in write mode. */
1180 device_set_error(d_self,
1181 vstrallocf(_("Can't open tape device %s for writing: %s"),
1182 self->private->device_filename, strerror(self->write_open_errno)),
1183 DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
1185 } else if (!tape_rewind(self->fd)) {
1186 device_set_error(d_self,
1187 vstrallocf(_("Error rewinding device to start: %s"), strerror(errno)),
1188 DEVICE_STATUS_DEVICE_ERROR);
1193 /* Position the tape */
1196 if (d_self->volume_label == NULL && device_read_label(d_self) != DEVICE_STATUS_SUCCESS) {
1197 /* device_read_label already set our error message */
1201 if (!tape_device_eod(self)) {
1202 device_set_error(d_self,
1203 vstrallocf(_("Couldn't seek to end of tape: %s"), strerror(errno)),
1204 DEVICE_STATUS_DEVICE_ERROR);
1210 if (d_self->volume_label == NULL && device_read_label(d_self) != DEVICE_STATUS_SUCCESS) {
1211 /* device_read_label already set our error message */
1215 if (!tape_rewind(self->fd)) {
1216 device_set_error(d_self,
1217 vstrallocf(_("Error rewinding device after reading label: %s"), strerror(errno)),
1218 DEVICE_STATUS_DEVICE_ERROR);
1225 if (!write_tapestart_header(self, label, timestamp)) {
1226 /* write_tapestart_header already set the error status */
1230 d_self->volume_label = newstralloc(d_self->volume_label, label);
1231 d_self->volume_time = newstralloc(d_self->volume_time, timestamp);
1233 /* unset the VOLUME_UNLABELED flag, if it was set */
1234 device_set_error(d_self, NULL, DEVICE_STATUS_SUCCESS);
1239 g_assert_not_reached();
1245 static gboolean tape_device_start_file(Device * d_self,
1246 dumpfile_t * info) {
1249 char * amanda_header;
1252 self = TAPE_DEVICE(d_self);
1254 g_assert(self->fd >= 0);
1255 if (device_in_error(self)) return FALSE;
1257 /* set the blocksize in the header properly */
1258 info->blocksize = d_self->block_size;
1260 /* Make the Amanda header suitable for writing to the device. */
1261 /* Then write the damn thing. */
1262 amanda_header = device_build_amanda_header(d_self, info, NULL);
1263 if (amanda_header == NULL) {
1264 device_set_error(d_self,
1265 stralloc(_("Amanda file header won't fit in a single block!")),
1266 DEVICE_STATUS_DEVICE_ERROR);
1270 result = tape_device_robust_write(self, amanda_header, d_self->block_size, &msg);
1271 if (result != RESULT_SUCCESS) {
1272 device_set_error(d_self,
1273 vstrallocf(_("Error writing file header: %s"),
1274 (result == RESULT_ERROR)? msg : _("out of space")),
1275 DEVICE_STATUS_DEVICE_ERROR);
1277 if (result == RESULT_NO_SPACE)
1278 d_self->is_eom = TRUE;
1280 amfree(amanda_header);
1284 amfree(amanda_header);
1286 /* arrange the file numbers correctly */
1288 if (d_self->file >= 0)
1290 g_mutex_lock(d_self->device_mutex);
1291 d_self->in_file = TRUE;
1292 d_self->bytes_written = 0;
1293 g_mutex_unlock(d_self->device_mutex);
1298 tape_device_finish_file (Device * d_self) {
1301 self = TAPE_DEVICE(d_self);
1302 if (device_in_error(d_self)) return FALSE;
1304 if (!tape_weof(self->fd, 1)) {
1305 device_set_error(d_self,
1306 vstrallocf(_("Error writing filemark: %s"), strerror(errno)),
1307 DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
1308 /* can't tell if this was EOM or not, so assume it is */
1309 d_self->is_eom = TRUE;
1313 g_mutex_lock(d_self->device_mutex);
1314 d_self->in_file = FALSE;
1315 g_mutex_unlock(d_self->device_mutex);
1320 tape_device_seek_file (Device * d_self, guint file) {
1324 char * header_buffer;
1330 self = TAPE_DEVICE(d_self);
1332 if (device_in_error(self)) return NULL;
1334 difference = file - d_self->file;
1336 /* Check if we already read a filemark. */
1337 /* If we already read a filemark and the drive automaticaly goes to the
1338 next file, then we must reduce the difference by one. */
1339 if (d_self->is_eof && !self->fsf_after_filemark) {
1343 d_self->is_eof = FALSE;
1345 g_mutex_lock(d_self->device_mutex);
1346 d_self->in_file = FALSE;
1347 d_self->bytes_read = 0;
1348 g_mutex_unlock(d_self->device_mutex);
1351 if (difference > 0) {
1352 /* Seeking forwards */
1353 if (!tape_device_fsf(self, difference)) {
1354 tape_rewind(self->fd);
1355 device_set_error(d_self,
1356 vstrallocf(_("Could not seek forward to file %d"), file),
1357 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1360 } else { /* (difference <= 0) */
1361 /* Seeking backwards, or to this file itself */
1363 /* if the drive supports bsf, we can do this the fancy way */
1365 /* bsf one more than the difference */
1366 if (!tape_bsf(self->fd, -difference + 1)) {
1367 tape_rewind(self->fd);
1368 device_set_error(d_self,
1369 vstrallocf(_("Could not seek backward to file %d"), file),
1370 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1374 /* now we are on the BOT side of the desired filemark, so FSF to get to the
1376 if (!tape_device_fsf(self, 1)) {
1377 tape_rewind(self->fd);
1378 device_set_error(d_self,
1379 vstrallocf(_("Could not seek forward to file %d"), file),
1380 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1384 /* no BSF, so just rewind and seek forward */
1385 if (!tape_rewind(self->fd)) {
1386 device_set_error(d_self,
1387 vstrallocf(_("Could not rewind device while emulating BSF")),
1388 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1392 if (!tape_device_fsf(self, file)) {
1393 tape_rewind(self->fd);
1394 device_set_error(d_self,
1395 vstrallocf(_("Could not seek forward to file %d"), file),
1396 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1402 /* double-check that we're on the right fileno, if possible. This is most
1403 * likely a programming error if it occurs, but could also be due to a weird
1404 * tape drive or driver (and that would *never* happen, right?) */
1405 got_file = tape_fileno(self->fd);
1406 if (got_file >= 0 && (guint)got_file != file) {
1407 device_set_error(d_self,
1408 vstrallocf(_("Could not seek to file %d correctly; got %d"),
1410 DEVICE_STATUS_DEVICE_ERROR);
1411 d_self->file = (guint)got_file;
1415 buffer_len = tape_device_read_size(d_self);
1416 header_buffer = malloc(buffer_len);
1417 d_self->is_eof = FALSE;
1418 result = tape_device_robust_read(self, header_buffer, &buffer_len, &msg);
1420 if (result != RESULT_SUCCESS) {
1421 free(header_buffer);
1422 tape_rewind(self->fd);
1424 case RESULT_NO_DATA:
1425 /* If we read 0 bytes, that means we encountered a double
1426 * filemark, which indicates end of tape. This should
1427 * work even with QIC tapes on operating systems with
1428 * proper support. */
1429 d_self->file = file; /* other attributes are already correct */
1430 return make_tapeend_header();
1432 case RESULT_SMALL_BUFFER:
1433 msg = stralloc(_("block size too small"));
1437 msg = stralloc(_("unknown error"));
1441 device_set_error(d_self,
1442 g_strdup_printf(_("Error reading Amanda header: %s"), msg),
1443 DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
1448 rval = g_new(dumpfile_t, 1);
1449 parse_file_header(header_buffer, rval, buffer_len);
1450 amfree(header_buffer);
1451 switch (rval->type) {
1453 case F_CONT_DUMPFILE:
1454 case F_SPLIT_DUMPFILE:
1458 /* a NOOP is written on QIC tapes to avoid writing two sequential
1459 * filemarks when closing a device in WRITE or APPEND mode. In this
1460 * case, we just seek to the next file. */
1467 tape_rewind(self->fd);
1468 device_set_error(d_self,
1469 stralloc(_("Invalid amanda header while reading file header")),
1470 DEVICE_STATUS_VOLUME_ERROR);
1475 g_mutex_lock(d_self->device_mutex);
1476 d_self->in_file = TRUE;
1477 g_mutex_unlock(d_self->device_mutex);
1478 d_self->file = file;
1484 tape_device_seek_block (Device * d_self, guint64 block) {
1488 self = TAPE_DEVICE(d_self);
1490 if (device_in_error(self)) return FALSE;
1492 difference = block - d_self->block;
1494 if (difference > 0) {
1495 if (!tape_device_fsr(self, difference)) {
1496 device_set_error(d_self,
1497 vstrallocf(_("Could not seek forward to block %ju: %s"), (uintmax_t)block, strerror(errno)),
1498 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1501 } else if (difference < 0) {
1502 if (!tape_device_bsr(self, difference, d_self->file, d_self->block)) {
1503 device_set_error(d_self,
1504 vstrallocf(_("Could not seek backward to block %ju: %s"), (uintmax_t)block, strerror(errno)),
1505 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1510 d_self->block = block;
1515 tape_device_eject (Device * d_self) {
1518 self = TAPE_DEVICE(d_self);
1520 if (device_in_error(self)) return FALSE;
1522 /* Open the device if not already opened */
1523 if (self->fd == -1) {
1524 self->fd = try_open_tape_device(self, self->private->device_filename);
1525 /* if the open failed, then try_open_tape_device already set the
1526 * approppriate error status */
1532 if (!tape_rewind(self->fd)) {
1533 device_set_error(d_self,
1534 vstrallocf(_("Error rewinding device %s before ejecting: %s"),
1535 self->private->device_filename, strerror(errno)),
1536 DEVICE_STATUS_DEVICE_ERROR
1537 | DEVICE_STATUS_VOLUME_ERROR);
1541 if (tape_offl(self->fd))
1544 device_set_error(d_self,
1545 vstrallocf(_("Error ejecting device %s: %s\n"),
1546 self->private->device_filename, strerror(errno)),
1547 DEVICE_STATUS_DEVICE_ERROR);
1553 tape_device_finish (Device * d_self) {
1557 self = TAPE_DEVICE(d_self);
1559 if (device_in_error(self))
1562 /* if we're already in ACCESS_NULL, then there are no filemarks or anything
1563 * to worry about, but we need to release the kernel device */
1564 if (d_self->access_mode == ACCESS_NULL) {
1565 robust_close(self->fd);
1570 /* Polish off this file, if relevant. */
1571 g_mutex_lock(d_self->device_mutex);
1572 if (d_self->in_file && IS_WRITABLE_ACCESS_MODE(d_self->access_mode)) {
1573 g_mutex_unlock(d_self->device_mutex);
1574 if (!device_finish_file(d_self)) {
1578 g_mutex_unlock(d_self->device_mutex);
1581 /* Straighten out the filemarks. We already wrote one in finish_file, and
1582 * the device driver will write another filemark when we rewind. This means
1583 * that, if we do nothing, we'll get two filemarks. If final_filemarks is
1584 * 1, this would be wrong, so in this case we insert a F_NOOP header between
1585 * the two filemarks. */
1586 if (self->final_filemarks == 1 &&
1587 IS_WRITABLE_ACCESS_MODE(d_self->access_mode)) {
1592 /* write a F_NOOP header */
1595 header = device_build_amanda_header(d_self, &file, NULL);
1597 device_set_error(d_self,
1598 stralloc(_("Amanda file header won't fit in a single block!")),
1599 DEVICE_STATUS_DEVICE_ERROR);
1603 result = tape_device_robust_write(self, header, d_self->block_size, &msg);
1604 if (result != RESULT_SUCCESS) {
1605 device_set_error(d_self,
1606 vstrallocf(_("Error writing file header: %s"),
1607 (result == RESULT_ERROR)? msg : _("out of space")),
1608 DEVICE_STATUS_DEVICE_ERROR);
1616 /* Rewind (the kernel will write a filemark first) */
1617 if (!tape_rewind(self->fd)) {
1618 device_set_error(d_self,
1619 vstrallocf(_("Couldn't rewind device to finish: %s"), strerror(errno)),
1620 DEVICE_STATUS_DEVICE_ERROR);
1624 d_self->is_eof = FALSE;
1625 d_self->access_mode = ACCESS_NULL;
1627 /* release the kernel's device */
1628 robust_close(self->fd);
1634 d_self->access_mode = ACCESS_NULL;
1636 /* release the kernel's device */
1637 robust_close(self->fd);
1643 /* Works just like read(), except for the following:
1644 * 1) Retries on EINTR & friends.
1645 * 2) Stores count in parameter, not return value.
1646 * 3) Provides explicit return result.
1647 * *errmsg is only set on RESULT_ERROR.
1650 tape_device_robust_read (TapeDevice * self, void * buf, int * count, char **errmsg) {
1654 d_self = (Device*)self;
1656 /* Callers should ensure this. */
1657 g_assert(*count >= 0);
1660 result = read(self->fd, buf, *count);
1662 /* Success. By definition, we read a full block. */
1663 d_self->is_eof = FALSE;
1665 return RESULT_SUCCESS;
1666 } else if (result == 0) {
1667 d_self->is_eof = TRUE;
1668 return RESULT_NO_DATA;
1675 || errno == EWOULDBLOCK
1681 /* Interrupted system call */
1685 || errno == ENOMEM /* bad user-space buffer */
1688 || errno == EOVERFLOW /* bad kernel-space buffer */
1691 || errno == EINVAL /* ??? */
1694 /* Buffer too small. */
1695 g_warning("Buffer is too small (%d bytes) from %s: %s",
1696 *count, self->private->device_filename, strerror(errno));
1697 return RESULT_SMALL_BUFFER;
1699 *errmsg = g_strdup_printf(_("Error reading %d bytes from %s: %s"),
1700 *count, self->private->device_filename, strerror(errno));
1701 return RESULT_ERROR;
1706 g_assert_not_reached();
1709 /* Kernel workaround: If needed, poke the kernel so it doesn't fail.
1710 at the 2GB boundry. Parameters are G_GNUC_UNUSED in case NEED_RESETOFS
1712 static void check_resetofs(TapeDevice * self G_GNUC_UNUSED,
1713 int count G_GNUC_UNUSED) {
1714 #ifdef NEED_RESETOFS
1718 d_self = (Device*)self;
1720 self->private->write_count += count;
1721 if (self->private->write_count < RESETOFS_THRESHOLD) {
1725 result = lseek(self->fd, 0, SEEK_SET);
1727 g_warning(_("lseek() failed during kernel 2GB workaround: %s"),
1733 /* *errmsg is only set on RESULT_ERROR */
1735 tape_device_robust_write (TapeDevice * self, void * buf, int count, char **errmsg) {
1738 gboolean retry = FALSE;
1740 d_self = (Device*)self;
1742 check_resetofs(self, count);
1745 result = write(self->fd, buf, count);
1748 if (result == count)
1749 return RESULT_SUCCESS;
1752 /* write() returned a short count. This should not happen if the block sizes
1753 * are properly aligned. */
1754 *errmsg = g_strdup_printf("Short write on tape device: Tried %d, got %d. Is "
1755 "the drive using a block size smaller than %d bytes?",
1756 count, result, count);
1757 return RESULT_ERROR;
1760 /* Detect LEOM (early warning) and handle properly
1762 * FreeBSD: 0-length write; next write will succeed
1763 * http://lists.freebsd.org/pipermail/freebsd-scsi/2010-June/004414.html
1765 * Solaris: 0-length write; next write will succeed
1766 * (from Matthew Jacob on FreeBSD thread)
1768 * Linux: -1/ENOSPC; next write will succeed
1769 * http://www.mjmwired.net/kernel/Documentation/scsi/st.txt
1771 * HP/UX: -1/ENOSPC; next write will succeed
1772 * http://www.adssasia.com/Manual/IBM%203581%20tape%20autoloader.pdf
1776 || (result < 0 && errno == ENOSPC)
1779 /* if we've retried once already, then we're probably really out of space */
1781 return RESULT_NO_SPACE;
1783 d_self->is_eom = TRUE;
1785 g_debug("empty write to tape; treating as LEOM early warning and retrying");
1789 /* at this point result < 0, so an error occurred - sort out what */
1796 || errno == EWOULDBLOCK
1802 /* Interrupted system call */
1812 /* Probably EOT. Print a message if we got EIO. */
1815 g_warning(_("Got EIO on %s, assuming end of tape"),
1816 self->private->device_filename);
1819 return RESULT_NO_SPACE;
1822 *errmsg = vstrallocf(_("Kernel gave unexpected write() result of \"%s\" on device %s"),
1823 strerror(errno), self->private->device_filename);
1824 return RESULT_ERROR;
1828 g_assert_not_reached();
1831 /* Reads some number of tape blocks into the bit-bucket. If the count
1832 is negative, then we read the rest of the entire file. Returns the
1833 number of blocks read, or -1 if an error occured. If we encounter
1834 EOF (as opposed to some other error) we return the number of blocks
1836 static int drain_tape_blocks(TapeDevice * self, int count) {
1841 buffer_size = tape_device_read_size(self);
1843 buffer = malloc(buffer_size);
1845 for (i = 0; i < count || count < 0;) {
1848 result = read(self->fd, buffer, buffer_size);
1852 } else if (result == 0) {
1856 /* First check for interrupted system call. */
1862 || errno == EWOULDBLOCK
1868 /* Interrupted system call */
1872 || errno == ENOSPC /* bad user-space buffer */
1875 || errno == EOVERFLOW /* bad kernel-space buffer */
1878 || errno == EINVAL /* ??? */
1881 /* The buffer may not be big enough. But the OS is not
1882 100% clear. We double the buffer and try again, but
1883 in no case allow a buffer bigger than 32 MB. */
1886 if (buffer_size > 32*1024*1024) {
1890 buffer = realloc(buffer, buffer_size);
1902 tape_device_fsf (TapeDevice * self, guint count) {
1904 return tape_fsf(self->fd, count);
1907 for (i = 0; i < count; i ++) {
1908 if (drain_tape_blocks(self, -1) < 0)
1917 tape_device_fsr (TapeDevice * self, guint count) {
1919 return tape_fsr(self->fd, count);
1921 int result = drain_tape_blocks(self, count);
1922 return result > 0 && (int)count == result;
1926 /* Seek back the given number of blocks to block number block within
1927 * the current file, numbered file. */
1930 tape_device_bsr (TapeDevice * self, guint count, guint file, guint block) {
1932 return tape_bsr(self->fd, count);
1933 } else if (self->bsf && self->fsf) {
1934 /* BSF, FSF to the right side of the filemark, and then FSR. */
1935 if (!tape_bsf(self->fd, 1))
1938 if (!tape_fsf(self->fd, 1))
1941 return tape_device_fsr(self, block);
1943 /* rewind, FSF, and FSR */
1944 if (!tape_rewind(self->fd))
1947 if (!tape_device_fsf(self, file))
1950 return tape_device_fsr(self, block);
1952 g_assert_not_reached();
1955 /* Go to the right place to write more data, and update the file
1956 number if possible. */
1958 tape_device_eod (TapeDevice * self) {
1962 d_self = (Device*)self;
1966 result = tape_eod(self->fd);
1967 if (result == TAPE_OP_ERROR) {
1969 } else if (result != TAPE_POSITION_UNKNOWN) {
1970 /* great - we just fast-forwarded to EOD, but don't know where we are, so
1971 * now we have to rewind and drain all of that data. Warn the user so that
1972 * we can skip the fast-forward-rewind stage on the next run */
1973 g_warning("Seek to end of tape does not give an accurate tape position; set "
1974 "the EOM property to 0 to avoid useless tape movement.");
1975 /* and set the property so that next time *this* object is opened for
1976 * append, we skip this stage */
1978 /* fall through to draining blocks, below */
1980 /* We drop by 1 because Device will increment the first
1981 time the user does start_file. */
1982 d_self->file = result - 1;
1987 if (!tape_rewind(self->fd))
1992 /* We alternately read a block and FSF. If the read is
1993 successful, then we are not there yet and should FSF
1996 result = drain_tape_blocks(self, 1);
1998 /* More data, FSF. */
1999 tape_device_fsf(self, 1);
2001 } else if (result == 0) {
2003 d_self->file = count - 1;
2012 tape_device_factory (char * device_name, char * device_type, char * device_node) {
2014 g_assert(0 == strcmp(device_type, "tape"));
2015 rval = DEVICE(g_object_new(TYPE_TAPE_DEVICE, NULL));
2016 device_open_device(rval, device_name, device_type, device_node);
2021 * Tape Operations using the POSIX interface
2024 /* Having one name for every operation would be too easy. */
2025 #if !defined(MTCOMPRESSION) && defined(MTCOMP)
2026 # define MTCOMPRESSION MTCOMP
2029 #if !defined(MTSETBLK) && defined(MTSETBSIZ)
2030 # define MTSETBLK MTSETBSIZ
2033 #if !defined(MTEOM) && defined(MTEOD)
2034 # define MTEOM MTEOD
2037 gboolean tape_rewind(int fd) {
2041 /* We will retry this for up to 30 seconds or 5 retries,
2042 whichever is less, because some hardware/software combinations
2043 (notably EXB-8200 on FreeBSD) can fail to rewind. */
2044 stop_time = time(NULL) + 30;
2046 while (--count >= 0 && time(NULL) < stop_time) {
2051 if (0 == ioctl(fd, MTIOCTOP, &mt))
2060 gboolean tape_fsf(int fd, guint count) {
2063 mt.mt_count = count;
2064 return 0 == ioctl(fd, MTIOCTOP, &mt);
2067 gboolean tape_bsf(int fd, guint count) {
2070 mt.mt_count = count;
2071 return 0 == ioctl(fd, MTIOCTOP, &mt);
2074 gboolean tape_fsr(int fd, guint count) {
2077 mt.mt_count = count;
2078 return 0 == ioctl(fd, MTIOCTOP, &mt);
2081 gboolean tape_bsr(int fd, guint count) {
2084 mt.mt_count = count;
2085 return 0 == ioctl(fd, MTIOCTOP, &mt);
2088 gint tape_fileno(int fd) {
2091 if (0 != ioctl(fd, MTIOCGET, &get))
2092 return TAPE_POSITION_UNKNOWN;
2093 if (get.mt_fileno < 0)
2094 return TAPE_POSITION_UNKNOWN;
2096 return get.mt_fileno;
2099 gint tape_eod(int fd) {
2104 if (0 != ioctl(fd, MTIOCTOP, &mt))
2105 return TAPE_OP_ERROR;
2107 /* Ignored result. This is just to flush buffers. */
2109 ioctl(fd, MTIOCTOP, &mt);
2111 if (0 != ioctl(fd, MTIOCGET, &get))
2112 return TAPE_POSITION_UNKNOWN;
2113 if (get.mt_fileno < 0)
2114 return TAPE_POSITION_UNKNOWN;
2116 return get.mt_fileno;
2119 gboolean tape_weof(int fd, guint8 count) {
2122 mt.mt_count = count;
2123 return 0 == ioctl(fd, MTIOCTOP, &mt);
2126 gboolean tape_setcompression(int fd G_GNUC_UNUSED,
2127 gboolean on G_GNUC_UNUSED) {
2128 #ifdef MTCOMPRESSION
2130 mt.mt_op = MTCOMPRESSION;
2132 return 0 == ioctl(fd, MTIOCTOP, &mt);
2138 gboolean tape_offl(int fd) {
2144 if (0 == ioctl(fd, MTIOCTOP, &mt))
2148 g_debug("tape_off: ioctl(MTIOCTOP/MTOFFL) failed: %s", strerror(errno));
2154 DeviceStatusFlags tape_is_tape_device(int fd) {
2158 if (0 == ioctl(fd, MTIOCTOP, &mt)) {
2159 return DEVICE_STATUS_SUCCESS;
2161 } else if (errno == ENOMEDIUM) {
2162 return DEVICE_STATUS_VOLUME_MISSING;
2165 g_debug("tape_is_tape_device: ioctl(MTIOCTOP/MTNOP) failed: %s",
2168 /* some devices return EIO while the drive is busy loading */
2169 return DEVICE_STATUS_DEVICE_ERROR|DEVICE_STATUS_DEVICE_BUSY;
2171 return DEVICE_STATUS_DEVICE_ERROR;
2176 DeviceStatusFlags tape_is_ready(int fd, TapeDevice *t_self G_GNUC_UNUSED) {
2178 if (0 == ioctl(fd, MTIOCGET, &get)) {
2179 #if defined(GMT_ONLINE) || defined(GMT_DR_OPEN)
2182 && (t_self->broken_gmt_online || GMT_ONLINE(get.mt_gstat))
2185 && !GMT_DR_OPEN(get.mt_gstat)
2188 return DEVICE_STATUS_SUCCESS;
2190 return DEVICE_STATUS_VOLUME_MISSING;
2192 #else /* Neither macro is defined. */
2193 return DEVICE_STATUS_SUCCESS;
2196 return DEVICE_STATUS_VOLUME_ERROR;