2 * Copyright (c) 2005-2008 Zmanda Inc. All Rights Reserved.
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 2.1 as
6 * published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
11 * License for more details.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17 * Contact information: Zmanda Inc., 465 S Mathlida Ave, Suite 300
18 * Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
21 #include <string.h> /* memset() */
23 #include "tape-device.h"
26 /* This is equal to 2*1024*1024*1024 - 16*1024*1024 - 1, but written
27 explicitly to avoid overflow issues. */
28 #define RESETOFS_THRESHOLD (0x7effffff)
30 /* Largest possible block size on SCSI systems. */
31 #define LARGEST_BLOCK_ESTIMATE (16 * 1024 * 1024)
33 struct TapeDevicePrivate_s {
34 /* This holds the total number of bytes written to the device,
35 modulus RESETOFS_THRESHOLD. */
37 char * device_filename;
38 gsize read_buffer_size;
41 /* Possible (abstracted) results from a system I/O operation. */
44 RESULT_ERROR, /* Undefined error. */
45 RESULT_SMALL_BUFFER, /* Tried to read with a buffer that is too
47 RESULT_NO_DATA, /* End of File, while reading */
48 RESULT_NO_SPACE, /* Out of space. Sometimes we don't know if
49 it was this or I/O error, but this is the
50 preferred explanation. */
55 * Our device-specific properties. These are not static because they are
56 * accessed from the OS-specific tape-*.c files.
58 DevicePropertyBase device_property_broken_gmt_online;
59 DevicePropertyBase device_property_fsf;
60 DevicePropertyBase device_property_bsf;
61 DevicePropertyBase device_property_fsr;
62 DevicePropertyBase device_property_bsr;
63 DevicePropertyBase device_property_eom;
64 DevicePropertyBase device_property_bsf_after_eom;
65 DevicePropertyBase device_property_final_filemarks;
67 void tape_device_register(void);
69 #define tape_device_read_size(self) \
70 (((TapeDevice *)(self))->private->read_buffer_size? \
71 ((TapeDevice *)(self))->private->read_buffer_size : ((Device *)(self))->block_size)
73 /* here are local prototypes */
74 static void tape_device_init (TapeDevice * o);
75 static void tape_device_class_init (TapeDeviceClass * c);
76 static void tape_device_base_init (TapeDeviceClass * c);
77 static gboolean tape_device_set_feature_property_fn(Device *p_self, DevicePropertyBase *base,
78 GValue *val, PropertySurety surety, PropertySource source);
79 static gboolean tape_device_set_final_filemarks_fn(Device *p_self, DevicePropertyBase *base,
80 GValue *val, PropertySurety surety, PropertySource source);
81 static gboolean tape_device_set_compression_fn(Device *p_self, DevicePropertyBase *base,
82 GValue *val, PropertySurety surety, PropertySource source);
83 static gboolean tape_device_set_read_buffer_size_fn(Device *p_self, DevicePropertyBase *base,
84 GValue *val, PropertySurety surety, PropertySource source);
85 static void tape_device_open_device (Device * self, char * device_name, char * device_type, char * device_node);
86 static Device * tape_device_factory (char * device_name, char * device_type, char * device_node);
87 static DeviceStatusFlags tape_device_read_label(Device * self);
88 static gboolean tape_device_write_block(Device * self, guint size, gpointer data);
89 static int tape_device_read_block(Device * self, gpointer buf,
91 static gboolean tape_device_start (Device * self, DeviceAccessMode mode,
92 char * label, char * timestamp);
93 static gboolean tape_device_start_file (Device * self, dumpfile_t * ji);
94 static gboolean tape_device_finish_file (Device * self);
95 static dumpfile_t * tape_device_seek_file (Device * self, guint file);
96 static gboolean tape_device_seek_block (Device * self, guint64 block);
97 static gboolean tape_device_finish (Device * self);
98 static IoResult tape_device_robust_read (TapeDevice * self, void * buf,
100 static IoResult tape_device_robust_write (TapeDevice * self, void * buf, int count);
101 static gboolean tape_device_fsf (TapeDevice * self, guint count);
102 static gboolean tape_device_bsf (TapeDevice * self, guint count, guint file);
103 static gboolean tape_device_fsr (TapeDevice * self, guint count);
104 static gboolean tape_device_bsr (TapeDevice * self, guint count, guint file, guint block);
105 static gboolean tape_device_eod (TapeDevice * self);
107 /* pointer to the class of our parent */
108 static DeviceClass *parent_class = NULL;
110 GType tape_device_get_type (void)
112 static GType type = 0;
114 if G_UNLIKELY(type == 0) {
115 static const GTypeInfo info = {
116 sizeof (TapeDeviceClass),
117 (GBaseInitFunc) tape_device_base_init,
118 (GBaseFinalizeFunc) NULL,
119 (GClassInitFunc) tape_device_class_init,
120 (GClassFinalizeFunc) NULL,
121 NULL /* class_data */,
124 (GInstanceInitFunc) tape_device_init,
128 type = g_type_register_static (TYPE_DEVICE, "TapeDevice",
129 &info, (GTypeFlags)0);
136 tape_device_init (TapeDevice * self) {
140 d_self = DEVICE(self);
141 bzero(&response, sizeof(response));
143 self->private = g_new0(TapeDevicePrivate, 1);
145 /* Clear all fields. */
146 d_self->block_size = 32768;
147 d_self->min_block_size = 32768;
148 d_self->max_block_size = LARGEST_BLOCK_ESTIMATE;
149 self->broken_gmt_online = FALSE;
153 /* set all of the feature properties to an unsure default of FALSE */
154 self->broken_gmt_online = FALSE;
160 self->bsf_after_eom = FALSE;
162 g_value_init(&response, G_TYPE_BOOLEAN);
163 g_value_set_boolean(&response, FALSE);
164 device_set_simple_property(d_self, PROPERTY_BROKEN_GMT_ONLINE,
165 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
166 device_set_simple_property(d_self, PROPERTY_FSF,
167 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
168 device_set_simple_property(d_self, PROPERTY_BSF,
169 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
170 device_set_simple_property(d_self, PROPERTY_FSR,
171 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
172 device_set_simple_property(d_self, PROPERTY_BSR,
173 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
174 device_set_simple_property(d_self, PROPERTY_EOM,
175 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
176 device_set_simple_property(d_self, PROPERTY_BSF_AFTER_EOM,
177 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
178 g_value_unset(&response);
180 self->final_filemarks = 2;
181 g_value_init(&response, G_TYPE_UINT);
182 g_value_set_uint(&response, self->final_filemarks);
183 device_set_simple_property(d_self, PROPERTY_FINAL_FILEMARKS,
184 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
185 g_value_unset(&response);
187 self->private->read_buffer_size = 0;
188 g_value_init(&response, G_TYPE_UINT);
189 g_value_set_uint(&response, self->private->read_buffer_size);
190 device_set_simple_property(d_self, PROPERTY_READ_BUFFER_SIZE,
191 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DEFAULT);
192 g_value_unset(&response);
194 self->private->write_count = 0;
195 self->private->device_filename = NULL;
197 /* Static properites */
198 g_value_init(&response, CONCURRENCY_PARADIGM_TYPE);
199 g_value_set_enum(&response, CONCURRENCY_PARADIGM_EXCLUSIVE);
200 device_set_simple_property(d_self, PROPERTY_CONCURRENCY,
201 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
202 g_value_unset(&response);
204 g_value_init(&response, STREAMING_REQUIREMENT_TYPE);
205 g_value_set_enum(&response, STREAMING_REQUIREMENT_DESIRED);
206 device_set_simple_property(d_self, PROPERTY_STREAMING,
207 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
208 g_value_unset(&response);
210 g_value_init(&response, G_TYPE_BOOLEAN);
211 g_value_set_boolean(&response, FALSE);
212 device_set_simple_property(d_self, PROPERTY_APPENDABLE,
213 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
214 g_value_unset(&response);
216 g_value_init(&response, G_TYPE_BOOLEAN);
217 g_value_set_boolean(&response, FALSE);
218 device_set_simple_property(d_self, PROPERTY_PARTIAL_DELETION,
219 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
220 g_value_unset(&response);
222 g_value_init(&response, MEDIA_ACCESS_MODE_TYPE);
223 g_value_set_enum(&response, MEDIA_ACCESS_MODE_READ_WRITE);
224 device_set_simple_property(d_self, PROPERTY_MEDIUM_ACCESS_TYPE,
225 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
226 g_value_unset(&response);
229 static void tape_device_finalize(GObject * obj_self) {
230 TapeDevice * self = TAPE_DEVICE(obj_self);
232 if(G_OBJECT_CLASS(parent_class)->finalize) \
233 (* G_OBJECT_CLASS(parent_class)->finalize)(obj_self);
235 robust_close(self->fd);
237 amfree(self->private->device_filename);
238 amfree(self->private);
242 tape_device_class_init (TapeDeviceClass * c)
244 DeviceClass *device_class = (DeviceClass *)c;
245 GObjectClass *g_object_class = (GObjectClass *)c;
247 parent_class = g_type_class_ref (TYPE_DEVICE);
249 device_class->open_device = tape_device_open_device;
250 device_class->read_label = tape_device_read_label;
251 device_class->write_block = tape_device_write_block;
252 device_class->read_block = tape_device_read_block;
253 device_class->start = tape_device_start;
254 device_class->start_file = tape_device_start_file;
255 device_class->finish_file = tape_device_finish_file;
256 device_class->seek_file = tape_device_seek_file;
257 device_class->seek_block = tape_device_seek_block;
258 device_class->finish = tape_device_finish;
260 g_object_class->finalize = tape_device_finalize;
264 tape_device_base_init (TapeDeviceClass * c)
266 DeviceClass *device_class = (DeviceClass *)c;
268 device_class_register_property(device_class, PROPERTY_BROKEN_GMT_ONLINE,
269 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
270 device_simple_property_get_fn,
271 tape_device_set_feature_property_fn);
273 device_class_register_property(device_class, PROPERTY_FSF,
274 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
275 device_simple_property_get_fn,
276 tape_device_set_feature_property_fn);
278 device_class_register_property(device_class, PROPERTY_BSF,
279 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
280 device_simple_property_get_fn,
281 tape_device_set_feature_property_fn);
283 device_class_register_property(device_class, PROPERTY_FSR,
284 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
285 device_simple_property_get_fn,
286 tape_device_set_feature_property_fn);
288 device_class_register_property(device_class, PROPERTY_BSR,
289 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
290 device_simple_property_get_fn,
291 tape_device_set_feature_property_fn);
293 device_class_register_property(device_class, PROPERTY_EOM,
294 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
295 device_simple_property_get_fn,
296 tape_device_set_feature_property_fn);
298 device_class_register_property(device_class, PROPERTY_BSF_AFTER_EOM,
299 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
300 device_simple_property_get_fn,
301 tape_device_set_feature_property_fn);
303 device_class_register_property(device_class, PROPERTY_FINAL_FILEMARKS,
304 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
305 device_simple_property_get_fn,
306 tape_device_set_final_filemarks_fn);
308 /* We don't (yet?) support reading the device's compression state, so not
310 device_class_register_property(device_class, PROPERTY_COMPRESSION,
311 PROPERTY_ACCESS_SET_MASK,
313 tape_device_set_compression_fn);
315 device_class_register_property(device_class, PROPERTY_READ_BUFFER_SIZE,
316 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
317 device_simple_property_get_fn,
318 tape_device_set_read_buffer_size_fn);
322 tape_device_set_feature_property_fn(Device *p_self, DevicePropertyBase *base,
323 GValue *val, PropertySurety surety, PropertySource source)
325 TapeDevice *self = TAPE_DEVICE(p_self);
327 gboolean old_bool, new_bool;
328 PropertySurety old_surety;
329 PropertySource old_source;
331 new_bool = g_value_get_boolean(val);
333 /* get the old source and surety and see if we're willing to make this change */
334 bzero(&old_val, sizeof(old_val));
335 if (device_get_simple_property(p_self, base->ID, &old_val, &old_surety, &old_source)) {
336 old_bool = g_value_get_boolean(&old_val);
338 if (old_surety == PROPERTY_SURETY_GOOD && old_source == PROPERTY_SOURCE_DETECTED) {
339 if (new_bool != old_bool) {
340 device_set_error(p_self, vstrallocf(_(
341 "Value for property '%s' was autodetected and cannot be changed"),
343 DEVICE_STATUS_DEVICE_ERROR);
346 /* pretend we set it, but don't change surety/source */
352 /* (note: PROPERTY_* are not constants, so we can't use switch) */
353 if (base->ID == PROPERTY_BROKEN_GMT_ONLINE)
354 self->broken_gmt_online = new_bool;
355 else if (base->ID == PROPERTY_FSF)
356 self->fsf = new_bool;
357 else if (base->ID == PROPERTY_BSF)
358 self->bsf = new_bool;
359 else if (base->ID == PROPERTY_FSR)
360 self->fsr = new_bool;
361 else if (base->ID == PROPERTY_BSR)
362 self->bsr = new_bool;
363 else if (base->ID == PROPERTY_EOM)
364 self->eom = new_bool;
365 else if (base->ID == PROPERTY_BSF_AFTER_EOM)
366 self->bsf_after_eom = new_bool;
368 return FALSE; /* shouldn't happen */
370 return device_simple_property_set_fn(p_self, base, val, surety, source);
374 tape_device_set_final_filemarks_fn(Device *p_self, DevicePropertyBase *base,
375 GValue *val, PropertySurety surety, PropertySource source)
377 TapeDevice *self = TAPE_DEVICE(p_self);
379 gboolean old_int, new_int;
380 PropertySurety old_surety;
381 PropertySource old_source;
383 new_int = g_value_get_uint(val);
385 /* get the old source and surety and see if we're willing to make this change */
386 bzero(&old_val, sizeof(old_val));
387 if (device_get_simple_property(p_self, base->ID, &old_val, &old_surety, &old_source)) {
388 old_int = g_value_get_uint(&old_val);
390 if (old_surety == PROPERTY_SURETY_GOOD && old_source == PROPERTY_SOURCE_DETECTED) {
391 if (new_int != old_int) {
392 device_set_error(p_self, vstrallocf(_(
393 "Value for property '%s' was autodetected and cannot be changed"),
395 DEVICE_STATUS_DEVICE_ERROR);
398 /* pretend we set it, but don't change surety/source */
404 self->final_filemarks = new_int;
406 return device_simple_property_set_fn(p_self, base, val, surety, source);
410 tape_device_set_compression_fn(Device *p_self, DevicePropertyBase *base,
411 GValue *val, PropertySurety surety, PropertySource source)
413 TapeDevice *self = TAPE_DEVICE(p_self);
414 gboolean request = g_value_get_boolean(val);
416 /* We allow this property to be set at any time. This is mostly
417 * because setting compression is a hit-and-miss proposition
418 * at any time; some drives accept the mode setting but don't
419 * actually support compression, while others do support
420 * compression but do it via density settings or some other
421 * way. Set this property whenever you want, but all we'll do
422 * is report whether or not the ioctl succeeded. */
423 if (tape_setcompression(self->fd, request)) {
424 /* looks good .. let's start the device over, though */
425 device_clear_volume_details(p_self);
430 return device_simple_property_set_fn(p_self, base, val, surety, source);
434 tape_device_set_read_buffer_size_fn(Device *p_self, DevicePropertyBase *base,
435 GValue *val, PropertySurety surety, PropertySource source)
437 TapeDevice *self = TAPE_DEVICE(p_self);
438 guint buffer_size = g_value_get_uint(val);
440 if (buffer_size != 0 &&
441 ((gsize)buffer_size < p_self->block_size ||
442 (gsize)buffer_size > p_self->max_block_size))
445 self->private->read_buffer_size = buffer_size;
447 return device_simple_property_set_fn(p_self, base, val, surety, source);
450 void tape_device_register(void) {
451 static const char * device_prefix_list[] = { "tape", NULL };
453 /* First register tape-specific properties */
454 device_property_fill_and_register(&device_property_broken_gmt_online,
455 G_TYPE_BOOLEAN, "broken_gmt_online",
456 "Does this drive support the GMT_ONLINE macro?");
458 device_property_fill_and_register(&device_property_fsf,
459 G_TYPE_BOOLEAN, "fsf",
460 "Does this drive support the MTFSF command?");
462 device_property_fill_and_register(&device_property_bsf,
463 G_TYPE_BOOLEAN, "bsf",
464 "Does this drive support the MTBSF command?" );
466 device_property_fill_and_register(&device_property_fsr,
467 G_TYPE_BOOLEAN, "fsr",
468 "Does this drive support the MTFSR command?");
470 device_property_fill_and_register(&device_property_bsr,
471 G_TYPE_BOOLEAN, "bsr",
472 "Does this drive support the MTBSR command?");
474 /* FIXME: Is this feature even useful? */
475 device_property_fill_and_register(&device_property_eom,
476 G_TYPE_BOOLEAN, "eom",
477 "Does this drive support the MTEOM command?");
479 device_property_fill_and_register(&device_property_bsf_after_eom,
482 "Does this drive require an MTBSF after MTEOM in order to append?" );
484 device_property_fill_and_register(&device_property_final_filemarks,
485 G_TYPE_UINT, "final_filemarks",
486 "How many filemarks to write after the last tape file?" );
488 /* Then the device itself */
489 register_device(tape_device_factory, device_prefix_list);
492 static int try_open_tape_device(TapeDevice * self, char * device_filename) {
495 DeviceStatusFlags new_status;
497 fd = robust_open(device_filename, O_RDWR,0);
500 self->write_open_errno = 0;
502 if (errno == EACCES || errno == EPERM) {
503 /* Device is write-protected. */
504 self->write_open_errno = errno;
505 fd = robust_open(device_filename, O_RDONLY,0);
511 DeviceStatusFlags status_flag = 0;
513 status_flag = DEVICE_STATUS_DEVICE_BUSY;
515 status_flag = DEVICE_STATUS_DEVICE_ERROR;
516 device_set_error(DEVICE(self),
517 vstrallocf(_("Can't open tape device %s: %s"), self->private->device_filename, strerror(errno)),
522 /* Check that this is actually a tape device. */
523 new_status = tape_is_tape_device(fd);
524 if (new_status & DEVICE_STATUS_DEVICE_ERROR) {
525 device_set_error(DEVICE(self),
526 vstrallocf(_("File %s is not a tape device"), self->private->device_filename),
531 if (new_status & DEVICE_STATUS_VOLUME_MISSING) {
532 device_set_error(DEVICE(self),
533 vstrallocf(_("Tape device %s is not ready or is empty"), self->private->device_filename),
539 new_status = tape_is_ready(fd, self);
540 if (new_status & DEVICE_STATUS_VOLUME_MISSING) {
541 device_set_error(DEVICE(self),
542 vstrallocf(_("Tape device %s is empty"), self->private->device_filename),
547 if (new_status != DEVICE_STATUS_SUCCESS) {
548 device_set_error(DEVICE(self),
549 vstrallocf(_("Tape device %s is not ready or is empty"), self->private->device_filename),
559 tape_device_open_device (Device * d_self, char * device_name G_GNUC_UNUSED,
560 char * device_type G_GNUC_UNUSED, char * device_node) {
563 self = TAPE_DEVICE(d_self);
566 self->private->device_filename = stralloc(device_node);
568 /* Get tape drive/OS info */
569 tape_device_detect_capabilities(self);
572 if (parent_class->open_device) {
573 parent_class->open_device(d_self, device_node, device_type, device_node);
578 tape_device_set_capabilities(TapeDevice *self,
579 gboolean fsf, PropertySurety fsf_surety, PropertySource fsf_source,
580 gboolean bsf, PropertySurety bsf_surety, PropertySource bsf_source,
581 gboolean fsr, PropertySurety fsr_surety, PropertySource fsr_source,
582 gboolean bsr, PropertySurety bsr_surety, PropertySource bsr_source,
583 gboolean eom, PropertySurety eom_surety, PropertySource eom_source,
584 gboolean bsf_after_eom, PropertySurety bae_surety, PropertySource bae_source,
585 guint final_filemarks, PropertySurety ff_surety, PropertySource ff_source)
587 Device *dself = DEVICE(self);
590 /* this function is called by tape_device_detect_capabilities, and basically
591 * exists to take care of the GValue mechanics in one place */
593 g_assert(final_filemarks == 1 || final_filemarks == 2);
595 bzero(&val, sizeof(val));
596 g_value_init(&val, G_TYPE_BOOLEAN);
599 g_value_set_boolean(&val, fsf);
600 device_set_simple_property(dself, PROPERTY_FSF, &val, fsf_surety, fsf_source);
603 g_value_set_boolean(&val, bsf);
604 device_set_simple_property(dself, PROPERTY_BSF, &val, bsf_surety, bsf_source);
607 g_value_set_boolean(&val, fsr);
608 device_set_simple_property(dself, PROPERTY_FSR, &val, fsr_surety, fsr_source);
611 g_value_set_boolean(&val, bsr);
612 device_set_simple_property(dself, PROPERTY_BSR, &val, bsr_surety, bsr_source);
615 g_value_set_boolean(&val, eom);
616 device_set_simple_property(dself, PROPERTY_EOM, &val, eom_surety, eom_source);
618 self->bsf_after_eom = bsf_after_eom;
619 g_value_set_boolean(&val, bsf_after_eom);
620 device_set_simple_property(dself, PROPERTY_BSF_AFTER_EOM, &val, bae_surety, bae_source);
623 g_value_init(&val, G_TYPE_UINT);
625 self->final_filemarks = final_filemarks;
626 g_value_set_uint(&val, final_filemarks);
627 device_set_simple_property(dself, PROPERTY_FINAL_FILEMARKS, &val, ff_surety, ff_source);
632 static DeviceStatusFlags tape_device_read_label(Device * dself) {
634 char * header_buffer;
638 DeviceStatusFlags new_status;
640 self = TAPE_DEVICE(dself);
642 amfree(dself->volume_label);
643 amfree(dself->volume_time);
644 amfree(dself->volume_header);
646 if (device_in_error(self)) return dself->status;
648 header = dself->volume_header = g_new(dumpfile_t, 1);
651 if (self->fd == -1) {
652 self->fd = try_open_tape_device(self, self->private->device_filename);
653 /* if the open failed, then try_open_tape_device already set the
654 * approppriate error status */
656 return dself->status;
660 if (!tape_rewind(self->fd)) {
661 device_set_error(dself,
662 vstrallocf(_("Error rewinding device %s"), self->private->device_filename),
663 DEVICE_STATUS_DEVICE_ERROR
664 | DEVICE_STATUS_VOLUME_ERROR);
665 robust_close(self->fd);
666 return dself->status;
669 buffer_len = tape_device_read_size(self);
670 header_buffer = malloc(buffer_len);
671 result = tape_device_robust_read(self, header_buffer, &buffer_len);
673 if (result != RESULT_SUCCESS) {
675 tape_rewind(self->fd);
677 if (result == RESULT_NO_DATA) {
678 new_status = (DEVICE_STATUS_VOLUME_ERROR |
679 DEVICE_STATUS_VOLUME_UNLABELED);
681 new_status = (DEVICE_STATUS_DEVICE_ERROR |
682 DEVICE_STATUS_VOLUME_ERROR |
683 DEVICE_STATUS_VOLUME_UNLABELED);
685 device_set_error(dself, stralloc(_("Error reading Amanda header")), new_status);
686 return dself->status;
689 parse_file_header(header_buffer, header, buffer_len);
690 amfree(header_buffer);
691 if (header->type != F_TAPESTART) {
692 device_set_error(dself,
693 stralloc(_("No tapestart header -- unlabeled device?")),
694 DEVICE_STATUS_VOLUME_UNLABELED);
695 return dself->status;
698 dself->volume_label = g_strdup(header->name);
699 dself->volume_time = g_strdup(header->datestamp);
700 /* dself->volume_header is already set */
702 device_set_error(dself, NULL, DEVICE_STATUS_SUCCESS);
704 return dself->status;
708 tape_device_write_block(Device * pself, guint size, gpointer data) {
710 char *replacement_buffer = NULL;
713 self = TAPE_DEVICE(pself);
715 g_assert(self->fd >= 0);
716 if (device_in_error(self)) return FALSE;
718 /* zero out to the end of a short block -- tape devices only write
720 if (size < pself->block_size) {
721 replacement_buffer = malloc(pself->block_size);
722 memcpy(replacement_buffer, data, size);
723 bzero(replacement_buffer+size, pself->block_size-size);
725 data = replacement_buffer;
726 size = pself->block_size;
729 result = tape_device_robust_write(self, data, size);
730 amfree(replacement_buffer);
736 case RESULT_NO_SPACE:
737 device_set_error(pself,
738 stralloc(_("No space left on device")),
739 DEVICE_STATUS_VOLUME_ERROR);
740 pself->is_eof = TRUE;
745 device_set_error(pself,
746 vstrallocf(_("Error writing block: %s"), strerror(errno)),
747 DEVICE_STATUS_DEVICE_ERROR);
756 static int tape_device_read_block (Device * pself, gpointer buf,
761 gssize read_block_size = tape_device_read_size(pself);
763 self = TAPE_DEVICE(pself);
765 g_assert(self->fd >= 0);
766 if (device_in_error(self)) return -1;
768 g_assert(read_block_size < INT_MAX); /* data type mismatch */
769 if (buf == NULL || *size_req < (int)read_block_size) {
770 /* Just a size query. */
771 *size_req = (int)read_block_size;
776 result = tape_device_robust_read(self, buf, &size);
782 case RESULT_SMALL_BUFFER: {
786 /* If this happens, it means that we have:
787 * (next block size) > (buffer size) >= (read_block_size)
788 * The solution is to ask for an even bigger buffer. We also play
789 * some games to refrain from reading above the SCSI limit or from
790 * integer overflow. Note that not all devices will tell us about
791 * this problem -- some will just discard the "extra" data. */
792 new_size = MIN(INT_MAX/2 - 1, *size_req) * 2;
793 if (new_size > LARGEST_BLOCK_ESTIMATE &&
794 *size_req < LARGEST_BLOCK_ESTIMATE) {
795 new_size = LARGEST_BLOCK_ESTIMATE;
797 g_assert (new_size > (gsize)*size_req);
799 g_warning("Device %s indicated blocksize %zd was too small; using %zd.",
800 pself->device_name, (gsize)*size_req, new_size);
801 *size_req = (int)new_size;
802 self->private->read_buffer_size = new_size;
804 bzero(&newval, sizeof(newval));
805 g_value_init(&newval, G_TYPE_UINT);
806 g_value_set_uint(&newval, self->private->read_buffer_size);
807 device_set_simple_property(pself, PROPERTY_READ_BUFFER_SIZE,
808 &newval, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
809 g_value_unset(&newval);
814 pself->is_eof = TRUE;
815 pself->in_file = FALSE;
816 device_set_error(pself,
818 DEVICE_STATUS_SUCCESS);
822 device_set_error(pself,
823 vstrallocf(_("Error reading from tape device: %s"), strerror(errno)),
824 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
828 g_assert_not_reached();
831 /* Just a helper function for tape_device_start(). */
832 static gboolean write_tapestart_header(TapeDevice * self, char * label,
838 gboolean header_fits;
839 Device * d_self = (Device*)self;
840 tape_rewind(self->fd);
842 header = make_tapestart_header(d_self, label, timestamp);
843 g_assert(header != NULL);
844 header_buf = device_build_amanda_header(d_self, header, &header_size,
847 g_assert(header_buf != NULL);
851 device_set_error(d_self,
852 stralloc(_("Tapestart header won't fit in a single block!")),
853 DEVICE_STATUS_DEVICE_ERROR);
857 g_assert(header_size >= (int)d_self->min_block_size);
858 result = tape_device_robust_write(self, header_buf, header_size);
859 if (result != RESULT_SUCCESS) {
860 device_set_error(d_self,
861 vstrallocf(_("Error writing tapestart header: %s"), strerror(errno)),
862 DEVICE_STATUS_DEVICE_ERROR);
869 if (!tape_weof(self->fd, 1)) {
870 device_set_error(d_self,
871 vstrallocf(_("Error writing filemark: %s"),
873 DEVICE_STATUS_DEVICE_ERROR|DEVICE_STATUS_VOLUME_ERROR);
882 tape_device_start (Device * d_self, DeviceAccessMode mode, char * label,
886 self = TAPE_DEVICE(d_self);
888 if (device_in_error(self)) return FALSE;
890 if (self->fd == -1) {
891 self->fd = try_open_tape_device(self, self->private->device_filename);
892 /* if the open failed, then try_open_tape_device already set the
893 * approppriate error status */
898 if (mode != ACCESS_WRITE && d_self->volume_label == NULL) {
899 /* we need a labeled volume for APPEND and READ */
900 if (tape_device_read_label(d_self) != DEVICE_STATUS_SUCCESS)
904 d_self->access_mode = mode;
905 d_self->in_file = FALSE;
907 if (IS_WRITABLE_ACCESS_MODE(mode)) {
908 if (self->write_open_errno != 0) {
909 /* We tried and failed to open the device in write mode. */
910 device_set_error(d_self,
911 vstrallocf(_("Can't open tape device %s for writing: %s"),
912 self->private->device_filename, strerror(self->write_open_errno)),
913 DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
915 } else if (!tape_rewind(self->fd)) {
916 device_set_error(d_self,
917 vstrallocf(_("Couldn't rewind device: %s"), strerror(errno)),
918 DEVICE_STATUS_DEVICE_ERROR);
923 /* Position the tape */
926 if (d_self->volume_label == NULL && device_read_label(d_self) != DEVICE_STATUS_SUCCESS) {
927 /* device_read_label already set our error message */
931 if (!tape_device_eod(self)) {
932 device_set_error(d_self,
933 vstrallocf(_("Couldn't seek to end of tape: %s"), strerror(errno)),
934 DEVICE_STATUS_DEVICE_ERROR);
940 if (d_self->volume_label == NULL && device_read_label(d_self) != DEVICE_STATUS_SUCCESS) {
941 /* device_read_label already set our error message */
945 if (!tape_rewind(self->fd)) {
946 device_set_error(d_self,
947 vstrallocf(_("Couldn't rewind device: %s"), strerror(errno)),
948 DEVICE_STATUS_DEVICE_ERROR);
955 if (!write_tapestart_header(self, label, timestamp)) {
956 /* write_tapestart_header already set the error status */
960 d_self->volume_label = newstralloc(d_self->volume_label, label);
961 d_self->volume_time = newstralloc(d_self->volume_time, timestamp);
963 /* unset the VOLUME_UNLABELED flag, if it was set */
964 device_set_error(d_self, NULL, DEVICE_STATUS_SUCCESS);
969 g_assert_not_reached();
975 static gboolean tape_device_start_file(Device * d_self,
979 char * amanda_header;
981 gboolean header_fits;
983 self = TAPE_DEVICE(d_self);
985 g_assert(self->fd >= 0);
986 if (device_in_error(self)) return FALSE;
988 /* set the blocksize in the header properly */
989 info->blocksize = d_self->block_size;
991 /* Make the Amanda header suitable for writing to the device. */
992 /* Then write the damn thing. */
993 amanda_header = device_build_amanda_header(d_self, info,
994 &header_size, &header_fits);
996 device_set_error(d_self,
997 stralloc(_("Amanda file header won't fit in a single block!")),
998 DEVICE_STATUS_DEVICE_ERROR);
1001 result = tape_device_robust_write(self, amanda_header, header_size);
1002 if (result != RESULT_SUCCESS) {
1003 device_set_error(d_self,
1004 vstrallocf(_("Error writing file header: %s"), strerror(errno)),
1005 DEVICE_STATUS_DEVICE_ERROR);
1006 amfree(amanda_header);
1009 amfree(amanda_header);
1011 /* arrange the file numbers correctly */
1012 d_self->in_file = TRUE;
1014 if (d_self->file >= 0)
1020 tape_device_finish_file (Device * d_self) {
1023 self = TAPE_DEVICE(d_self);
1024 if (device_in_error(d_self)) return FALSE;
1026 if (!tape_weof(self->fd, 1)) {
1027 device_set_error(d_self,
1028 vstrallocf(_("Error writing filemark: %s"), strerror(errno)),
1029 DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
1033 d_self->in_file = FALSE;
1038 tape_device_seek_file (Device * d_self, guint file) {
1041 char * header_buffer;
1046 self = TAPE_DEVICE(d_self);
1048 if (device_in_error(self)) return NULL;
1050 difference = file - d_self->file;
1052 /* Check if we already read a filemark. */
1053 if (d_self->is_eof) {
1057 d_self->in_file = FALSE;
1058 d_self->is_eof = FALSE;
1061 if (difference > 0) {
1062 /* Seeking forwards */
1063 if (!tape_device_fsf(self, difference)) {
1064 tape_rewind(self->fd);
1065 device_set_error(d_self,
1066 vstrallocf(_("Could not seek forward to file %d"), file),
1067 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1070 } else if (difference < 0) {
1071 /* Seeking backwards */
1072 if (!tape_device_bsf(self, -difference, d_self->file)) {
1073 tape_rewind(self->fd);
1074 device_set_error(d_self,
1075 vstrallocf(_("Could not seek backward to file %d"), file),
1076 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1081 buffer_len = tape_device_read_size(d_self);
1082 header_buffer = malloc(buffer_len);
1083 d_self->is_eof = FALSE;
1084 result = tape_device_robust_read(self, header_buffer, &buffer_len);
1086 if (result != RESULT_SUCCESS) {
1087 free(header_buffer);
1088 tape_rewind(self->fd);
1089 if (result == RESULT_NO_DATA) {
1090 /* If we read 0 bytes, that means we encountered a double
1091 * filemark, which indicates end of tape. This should
1092 * work even with QIC tapes on operating systems with
1093 * proper support. */
1094 d_self->file = file; /* other attributes are already correct */
1095 return make_tapeend_header();
1098 device_set_error(d_self,
1099 stralloc(_("Error reading Amanda header")),
1100 DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
1104 rval = g_new(dumpfile_t, 1);
1105 parse_file_header(header_buffer, rval, buffer_len);
1106 amfree(header_buffer);
1107 switch (rval->type) {
1109 case F_CONT_DUMPFILE:
1110 case F_SPLIT_DUMPFILE:
1114 tape_rewind(self->fd);
1115 device_set_error(d_self,
1116 stralloc(_("Invalid amanda header while reading file header")),
1117 DEVICE_STATUS_VOLUME_ERROR);
1122 d_self->in_file = TRUE;
1123 d_self->file = file;
1129 tape_device_seek_block (Device * d_self, guint64 block) {
1133 self = TAPE_DEVICE(d_self);
1135 if (device_in_error(self)) return FALSE;
1137 difference = block - d_self->block;
1139 if (difference > 0) {
1140 if (!tape_device_fsr(self, difference)) {
1141 device_set_error(d_self,
1142 vstrallocf(_("Could not seek forward to block %ju"), (uintmax_t)block),
1143 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1146 } else if (difference < 0) {
1147 if (!tape_device_bsr(self, difference, d_self->file, d_self->block)) {
1148 device_set_error(d_self,
1149 vstrallocf(_("Could not seek backward to block %ju"), (uintmax_t)block),
1150 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1155 d_self->block = block;
1160 tape_device_finish (Device * d_self) {
1163 self = TAPE_DEVICE(d_self);
1165 if (device_in_error(self)) return FALSE;
1167 if (d_self->access_mode == ACCESS_NULL)
1170 /* Polish off this file, if relevant. */
1171 if (d_self->in_file && IS_WRITABLE_ACCESS_MODE(d_self->access_mode)) {
1172 if (!device_finish_file(d_self))
1176 /* Write an extra filemark, if needed. The OS will give us one for
1178 /* device_finish_file already wrote one for us */
1180 if (self->final_filemarks > 1 &&
1181 IS_WRITABLE_ACCESS_MODE(d_self->access_mode)) {
1182 if (!tape_weof(self->fd, 1)) {
1183 device_set_error(d_self,
1184 vstrallocf(_("Error writing final filemark: %s"), strerror(errno)),
1185 DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
1192 if (!tape_rewind(self->fd)) {
1193 device_set_error(d_self,
1194 vstrallocf(_("Couldn't rewind device: %s"), strerror(errno)),
1195 DEVICE_STATUS_DEVICE_ERROR);
1199 d_self->access_mode = ACCESS_NULL;
1204 /* Works just like read(), except for the following:
1205 * 1) Retries on EINTR & friends.
1206 * 2) Stores count in parameter, not return value.
1207 * 3) Provides explicit return result. */
1209 tape_device_robust_read (TapeDevice * self, void * buf, int * count) {
1213 d_self = (Device*)self;
1215 /* Callers should ensure this. */
1216 g_assert(*count >= 0);
1219 result = read(self->fd, buf, *count);
1221 /* Success. By definition, we read a full block. */
1223 return RESULT_SUCCESS;
1224 } else if (result == 0) {
1225 return RESULT_NO_DATA;
1232 || errno == EWOULDBLOCK
1238 /* Interrupted system call */
1242 || errno == ENOMEM /* bad user-space buffer */
1245 || errno == EOVERFLOW /* bad kernel-space buffer */
1248 || errno == EINVAL /* ??? */
1251 /* Buffer too small. */
1252 return RESULT_SMALL_BUFFER;
1254 device_set_error(d_self,
1255 vstrallocf(_("Error reading %d bytes from %s: %s"),
1256 *count, self->private->device_filename, strerror(errno)),
1257 DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
1258 return RESULT_ERROR;
1264 g_assert_not_reached();
1267 /* Kernel workaround: If needed, poke the kernel so it doesn't fail.
1268 at the 2GB boundry. Parameters are G_GNUC_UNUSED in case NEED_RESETOFS
1270 static void check_resetofs(TapeDevice * self G_GNUC_UNUSED,
1271 int count G_GNUC_UNUSED) {
1272 #ifdef NEED_RESETOFS
1276 d_self = (Device*)self;
1278 self->private->write_count += count;
1279 if (self->private->write_count < RESETOFS_THRESHOLD) {
1283 result = lseek(self->fd, 0, SEEK_SET);
1285 g_warning(_("lseek() failed during kernel 2GB workaround: %s"),
1292 tape_device_robust_write (TapeDevice * self, void * buf, int count) {
1296 d_self = (Device*)self;
1298 check_resetofs(self, count);
1301 result = write(self->fd, buf, count);
1303 if (result == count) {
1306 self->private->write_count ++;
1307 return RESULT_SUCCESS;
1308 } else if (result >= 0) {
1309 /* write() returned a short count. This should not happen. */
1310 device_set_error(d_self,
1311 vstrallocf(_("Mysterious short write on tape device: Tried %d, got %d"),
1313 DEVICE_STATUS_DEVICE_ERROR);
1314 return RESULT_ERROR;
1320 || errno == EWOULDBLOCK
1326 /* Interrupted system call */
1336 /* Probably EOT. Print a message if we got EIO. */
1339 g_warning(_("Got EIO on %s, assuming end of tape"),
1340 self->private->device_filename);
1343 return RESULT_NO_SPACE;
1346 device_set_error(d_self,
1347 vstrallocf(_("Kernel gave unexpected write() result of \"%s\" on device %s"),
1348 strerror(errno), self->private->device_filename),
1349 DEVICE_STATUS_DEVICE_ERROR);
1350 return RESULT_ERROR;
1354 g_assert_not_reached();
1357 /* Reads some number of tape blocks into the bit-bucket. If the count
1358 is negative, then we read the rest of the entire file. Returns the
1359 number of blocks read, or -1 if an error occured. If we encounter
1360 EOF (as opposed to some other error) we return the number of blocks
1362 static int drain_tape_blocks(TapeDevice * self, int count) {
1367 buffer_size = tape_device_read_size(self);
1369 buffer = malloc(sizeof(buffer_size));
1371 for (i = 0; i < count || count < 0;) {
1374 result = read(self->fd, buffer, buffer_size);
1378 } else if (result == 0) {
1382 /* First check for interrupted system call. */
1388 || errno == EWOULDBLOCK
1394 /* Interrupted system call */
1398 || errno == ENOSPC /* bad user-space buffer */
1401 || errno == EOVERFLOW /* bad kernel-space buffer */
1404 || errno == EINVAL /* ??? */
1407 /* The buffer may not be big enough. But the OS is not
1408 100% clear. We double the buffer and try again, but
1409 in no case allow a buffer bigger than 32 MB. */
1412 if (buffer_size > 32*1024*1024) {
1416 buffer = realloc(buffer, buffer_size);
1427 /* FIXME: Make sure that there are no cycles in reimplementation
1431 tape_device_fsf (TapeDevice * self, guint count) {
1433 return tape_fsf(self->fd, count);
1436 for (i = 0; i < count; i ++) {
1437 if (drain_tape_blocks(self, -1) < 0)
1444 /* Seek back over count + 1 filemarks to the start of the given file. */
1446 tape_device_bsf (TapeDevice * self, guint count, guint file) {
1448 /* The BSF operation is not very smart; it includes the
1449 filemark of the present file as part of the count, and seeks
1450 to the wrong (BOT) side of the filemark. We compensate for
1451 this by seeking one filemark too many, then FSFing back over
1454 If this procedure fails for some reason, we can still try
1456 if (tape_bsf(self->fd, count + 1) &&
1457 tape_device_fsf(self, 1))
1459 } /* Fall through to backup plan. */
1461 /* We rewind the tape, then seek forward the given number of
1463 if (!tape_rewind(self->fd))
1466 return tape_device_fsf(self, file);
1471 tape_device_fsr (TapeDevice * self, guint count) {
1473 return tape_fsr(self->fd, count);
1475 int result = drain_tape_blocks(self, count);
1476 return result > 0 && (int)count == result;
1480 /* Seek back the given number of blocks to block number block within
1481 * the current file, numbered file. */
1484 tape_device_bsr (TapeDevice * self, guint count, guint file, guint block) {
1486 return tape_bsr(self->fd, count);
1488 /* We BSF, then FSR. */
1489 if (!tape_device_bsf(self, 0, file))
1492 return tape_device_fsr(self, block);
1494 g_assert_not_reached();
1497 /* Go to the right place to write more data, and update the file
1498 number if possible. */
1500 tape_device_eod (TapeDevice * self) {
1502 d_self = (Device*)self;
1506 result = tape_eod(self->fd);
1507 if (result == TAPE_OP_ERROR) {
1509 } else if (result == TAPE_POSITION_UNKNOWN) {
1512 /* We drop by 1 because Device will increment the first
1513 time the user does start_file. */
1514 d_self->file = result - 1;
1519 if (!tape_rewind(self->fd))
1523 /* We alternately read a block and FSF. If the read is
1524 successful, then we are not there yet and should FSF
1527 result = drain_tape_blocks(self, 1);
1529 /* More data, FSF. */
1530 tape_device_fsf(self, 1);
1532 } else if (result == 0) {
1534 d_self->file = count;
1544 tape_device_factory (char * device_name, char * device_type, char * device_node) {
1546 g_assert(0 == strcmp(device_type, "tape"));
1547 rval = DEVICE(g_object_new(TYPE_TAPE_DEVICE, NULL));
1548 device_open_device(rval, device_name, device_type, device_node);