2 * Copyright (c) 2007, 2008, 2009, 2010 Zmanda, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published
6 * by the Free Software Foundation.
8 * This program 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 General Public License
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
18 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
22 #include "pipespawn.h"
23 #include <string.h> /* memset() */
25 #include "tape-device.h"
28 /* This is equal to 2*1024*1024*1024 - 16*1024*1024 - 1, but written
29 explicitly to avoid overflow issues. */
30 #define RESETOFS_THRESHOLD (0x7effffff)
32 /* Largest possible block size on SCSI systems. */
33 #define LARGEST_BLOCK_ESTIMATE (16 * 1024 * 1024)
35 struct TapeDevicePrivate_s {
36 /* This holds the total number of bytes written to the device,
37 modulus RESETOFS_THRESHOLD. */
39 char * device_filename;
40 gsize read_block_size;
43 /* Possible (abstracted) results from a system I/O operation. */
46 RESULT_ERROR, /* Undefined error (*errmsg set) */
47 RESULT_SMALL_BUFFER, /* Tried to read with a buffer that is too
49 RESULT_NO_DATA, /* End of File, while reading */
50 RESULT_NO_SPACE, /* Out of space. Sometimes we don't know if
51 it was this or I/O error, but this is the
52 preferred explanation. */
57 * Our device-specific properties. These are not static because they are
58 * accessed from the OS-specific tape-*.c files.
60 DevicePropertyBase device_property_broken_gmt_online;
61 DevicePropertyBase device_property_fsf;
62 DevicePropertyBase device_property_fsf_after_filemark;
63 DevicePropertyBase device_property_bsf;
64 DevicePropertyBase device_property_fsr;
65 DevicePropertyBase device_property_bsr;
66 DevicePropertyBase device_property_eom;
67 DevicePropertyBase device_property_bsf_after_eom;
68 DevicePropertyBase device_property_nonblocking_open;
69 DevicePropertyBase device_property_final_filemarks;
70 DevicePropertyBase device_property_read_buffer_size; /* old name for READ_BLOCK_SIZE */
72 void tape_device_register(void);
74 #define tape_device_read_size(self) \
75 (((TapeDevice *)(self))->private->read_block_size? \
76 ((TapeDevice *)(self))->private->read_block_size : ((Device *)(self))->block_size)
78 /* here are local prototypes */
79 static void tape_device_init (TapeDevice * o);
80 static void tape_device_class_init (TapeDeviceClass * c);
81 static void tape_device_base_init (TapeDeviceClass * c);
82 static gboolean tape_device_set_feature_property_fn(Device *p_self, DevicePropertyBase *base,
83 GValue *val, PropertySurety surety, PropertySource source);
84 static gboolean tape_device_set_final_filemarks_fn(Device *p_self, DevicePropertyBase *base,
85 GValue *val, PropertySurety surety, PropertySource source);
86 static gboolean tape_device_set_compression_fn(Device *p_self, DevicePropertyBase *base,
87 GValue *val, PropertySurety surety, PropertySource source);
88 static gboolean tape_device_get_read_block_size_fn(Device *p_self, DevicePropertyBase *base,
89 GValue *val, PropertySurety *surety, PropertySource *source);
90 static gboolean tape_device_set_read_block_size_fn(Device *p_self, DevicePropertyBase *base,
91 GValue *val, PropertySurety surety, PropertySource source);
92 static void tape_device_open_device (Device * self, char * device_name, char * device_type, char * device_node);
93 static Device * tape_device_factory (char * device_name, char * device_type, char * device_node);
94 static DeviceStatusFlags tape_device_read_label(Device * self);
95 static gboolean tape_device_write_block(Device * self, guint size, gpointer data);
96 static int tape_device_read_block(Device * self, gpointer buf,
98 static gboolean tape_device_start (Device * self, DeviceAccessMode mode,
99 char * label, char * timestamp);
100 static gboolean tape_device_start_file (Device * self, dumpfile_t * ji);
101 static gboolean tape_device_finish_file (Device * self);
102 static dumpfile_t * tape_device_seek_file (Device * self, guint file);
103 static gboolean tape_device_seek_block (Device * self, guint64 block);
104 static gboolean tape_device_eject (Device * self);
105 static gboolean tape_device_finish (Device * self);
106 static IoResult tape_device_robust_read (TapeDevice * self, void * buf,
107 int * count, char **errmsg);
108 static IoResult tape_device_robust_write (TapeDevice * self, void * buf, int count, char **errmsg);
109 static gboolean tape_device_fsf (TapeDevice * self, guint count);
110 static gboolean tape_device_fsr (TapeDevice * self, guint count);
111 static gboolean tape_device_bsr (TapeDevice * self, guint count, guint file, guint block);
112 static gboolean tape_device_eod (TapeDevice * self);
114 /* pointer to the class of our parent */
115 static DeviceClass *parent_class = NULL;
117 GType tape_device_get_type (void)
119 static GType type = 0;
121 if G_UNLIKELY(type == 0) {
122 static const GTypeInfo info = {
123 sizeof (TapeDeviceClass),
124 (GBaseInitFunc) tape_device_base_init,
125 (GBaseFinalizeFunc) NULL,
126 (GClassInitFunc) tape_device_class_init,
127 (GClassFinalizeFunc) NULL,
128 NULL /* class_data */,
131 (GInstanceInitFunc) tape_device_init,
135 type = g_type_register_static (TYPE_DEVICE, "TapeDevice",
136 &info, (GTypeFlags)0);
143 tape_device_init (TapeDevice * self) {
147 d_self = DEVICE(self);
148 bzero(&response, sizeof(response));
150 self->private = g_new0(TapeDevicePrivate, 1);
152 /* Clear all fields. */
153 d_self->block_size = 32768;
154 d_self->min_block_size = 32768;
155 d_self->max_block_size = LARGEST_BLOCK_ESTIMATE;
156 self->broken_gmt_online = FALSE;
160 /* set all of the feature properties to an unsure default of FALSE */
161 self->broken_gmt_online = FALSE;
167 self->bsf_after_eom = FALSE;
169 g_value_init(&response, G_TYPE_BOOLEAN);
170 g_value_set_boolean(&response, FALSE);
171 device_set_simple_property(d_self, PROPERTY_BROKEN_GMT_ONLINE,
172 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
173 device_set_simple_property(d_self, PROPERTY_FSF,
174 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
175 device_set_simple_property(d_self, PROPERTY_FSF_AFTER_FILEMARK,
176 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
177 device_set_simple_property(d_self, PROPERTY_BSF,
178 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
179 device_set_simple_property(d_self, PROPERTY_FSR,
180 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
181 device_set_simple_property(d_self, PROPERTY_BSR,
182 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
183 device_set_simple_property(d_self, PROPERTY_EOM,
184 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
185 device_set_simple_property(d_self, PROPERTY_BSF_AFTER_EOM,
186 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
188 #ifdef DEFAULT_TAPE_NON_BLOCKING_OPEN
189 self->nonblocking_open = TRUE;
191 self->nonblocking_open = FALSE;
193 g_value_set_boolean(&response, self->nonblocking_open);
194 device_set_simple_property(d_self, PROPERTY_NONBLOCKING_OPEN,
195 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
196 g_value_unset(&response);
198 self->final_filemarks = 2;
199 g_value_init(&response, G_TYPE_UINT);
200 g_value_set_uint(&response, self->final_filemarks);
201 device_set_simple_property(d_self, PROPERTY_FINAL_FILEMARKS,
202 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
203 g_value_unset(&response);
205 self->private->read_block_size = 0;
206 g_value_init(&response, G_TYPE_UINT);
207 g_value_set_uint(&response, self->private->read_block_size);
208 device_set_simple_property(d_self, PROPERTY_READ_BLOCK_SIZE,
209 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DEFAULT);
210 g_value_unset(&response);
212 self->private->write_count = 0;
213 self->private->device_filename = NULL;
215 /* Static properites */
216 g_value_init(&response, CONCURRENCY_PARADIGM_TYPE);
217 g_value_set_enum(&response, CONCURRENCY_PARADIGM_EXCLUSIVE);
218 device_set_simple_property(d_self, PROPERTY_CONCURRENCY,
219 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
220 g_value_unset(&response);
222 g_value_init(&response, STREAMING_REQUIREMENT_TYPE);
223 g_value_set_enum(&response, STREAMING_REQUIREMENT_DESIRED);
224 device_set_simple_property(d_self, PROPERTY_STREAMING,
225 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
226 g_value_unset(&response);
228 g_value_init(&response, G_TYPE_BOOLEAN);
229 g_value_set_boolean(&response, TRUE);
230 device_set_simple_property(d_self, PROPERTY_APPENDABLE,
231 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
232 g_value_unset(&response);
234 g_value_init(&response, G_TYPE_BOOLEAN);
235 g_value_set_boolean(&response, FALSE);
236 device_set_simple_property(d_self, PROPERTY_PARTIAL_DELETION,
237 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
238 g_value_unset(&response);
240 g_value_init(&response, G_TYPE_BOOLEAN);
241 g_value_set_boolean(&response, FALSE);
242 device_set_simple_property(d_self, PROPERTY_FULL_DELETION,
243 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
244 g_value_unset(&response);
246 g_value_init(&response, MEDIA_ACCESS_MODE_TYPE);
247 g_value_set_enum(&response, MEDIA_ACCESS_MODE_READ_WRITE);
248 device_set_simple_property(d_self, PROPERTY_MEDIUM_ACCESS_TYPE,
249 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
250 g_value_unset(&response);
253 static void tape_device_finalize(GObject * obj_self) {
254 TapeDevice * self = TAPE_DEVICE(obj_self);
256 if(G_OBJECT_CLASS(parent_class)->finalize) \
257 (* G_OBJECT_CLASS(parent_class)->finalize)(obj_self);
259 robust_close(self->fd);
261 amfree(self->private->device_filename);
262 amfree(self->private);
266 tape_device_class_init (TapeDeviceClass * c)
268 DeviceClass *device_class = (DeviceClass *)c;
269 GObjectClass *g_object_class = (GObjectClass *)c;
271 parent_class = g_type_class_ref (TYPE_DEVICE);
273 device_class->open_device = tape_device_open_device;
274 device_class->read_label = tape_device_read_label;
275 device_class->write_block = tape_device_write_block;
276 device_class->read_block = tape_device_read_block;
277 device_class->start = tape_device_start;
278 device_class->start_file = tape_device_start_file;
279 device_class->finish_file = tape_device_finish_file;
280 device_class->seek_file = tape_device_seek_file;
281 device_class->seek_block = tape_device_seek_block;
282 device_class->eject = tape_device_eject;
283 device_class->finish = tape_device_finish;
285 g_object_class->finalize = tape_device_finalize;
289 tape_device_base_init (TapeDeviceClass * c)
291 DeviceClass *device_class = (DeviceClass *)c;
293 device_class_register_property(device_class, PROPERTY_BROKEN_GMT_ONLINE,
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_FSF,
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_FSF_AFTER_FILEMARK,
304 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
305 device_simple_property_get_fn,
306 tape_device_set_feature_property_fn);
308 device_class_register_property(device_class, PROPERTY_BSF,
309 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
310 device_simple_property_get_fn,
311 tape_device_set_feature_property_fn);
313 device_class_register_property(device_class, PROPERTY_FSR,
314 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
315 device_simple_property_get_fn,
316 tape_device_set_feature_property_fn);
318 device_class_register_property(device_class, PROPERTY_BSR,
319 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
320 device_simple_property_get_fn,
321 tape_device_set_feature_property_fn);
323 device_class_register_property(device_class, PROPERTY_EOM,
324 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
325 device_simple_property_get_fn,
326 tape_device_set_feature_property_fn);
328 device_class_register_property(device_class, PROPERTY_BSF_AFTER_EOM,
329 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
330 device_simple_property_get_fn,
331 tape_device_set_feature_property_fn);
333 device_class_register_property(device_class, PROPERTY_NONBLOCKING_OPEN,
334 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
335 device_simple_property_get_fn,
336 tape_device_set_feature_property_fn);
338 device_class_register_property(device_class, PROPERTY_FINAL_FILEMARKS,
339 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
340 device_simple_property_get_fn,
341 tape_device_set_final_filemarks_fn);
343 /* We don't (yet?) support reading the device's compression state, so not
345 device_class_register_property(device_class, PROPERTY_COMPRESSION,
346 PROPERTY_ACCESS_SET_MASK,
348 tape_device_set_compression_fn);
350 device_class_register_property(device_class, PROPERTY_READ_BLOCK_SIZE,
351 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
352 tape_device_get_read_block_size_fn,
353 tape_device_set_read_block_size_fn);
355 device_class_register_property(device_class, device_property_read_buffer_size.ID,
356 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
357 tape_device_get_read_block_size_fn,
358 tape_device_set_read_block_size_fn);
362 tape_device_set_feature_property_fn(Device *p_self, DevicePropertyBase *base,
363 GValue *val, PropertySurety surety, PropertySource source)
365 TapeDevice *self = TAPE_DEVICE(p_self);
367 gboolean old_bool, new_bool;
368 PropertySurety old_surety;
369 PropertySource old_source;
371 new_bool = g_value_get_boolean(val);
373 /* get the old source and surety and see if we're willing to make this change */
374 bzero(&old_val, sizeof(old_val));
375 if (device_get_simple_property(p_self, base->ID, &old_val, &old_surety, &old_source)) {
376 old_bool = g_value_get_boolean(&old_val);
378 if (old_surety == PROPERTY_SURETY_GOOD && old_source == PROPERTY_SOURCE_DETECTED) {
379 if (new_bool != old_bool) {
380 device_set_error(p_self, vstrallocf(_(
381 "Value for property '%s' was autodetected and cannot be changed"),
383 DEVICE_STATUS_DEVICE_ERROR);
386 /* pretend we set it, but don't change surety/source */
392 /* (note: PROPERTY_* are not constants, so we can't use switch) */
393 if (base->ID == PROPERTY_BROKEN_GMT_ONLINE)
394 self->broken_gmt_online = new_bool;
395 else if (base->ID == PROPERTY_FSF)
396 self->fsf = new_bool;
397 else if (base->ID == PROPERTY_FSF_AFTER_FILEMARK)
398 self->fsf_after_filemark = new_bool;
399 else if (base->ID == PROPERTY_BSF)
400 self->bsf = new_bool;
401 else if (base->ID == PROPERTY_FSR)
402 self->fsr = new_bool;
403 else if (base->ID == PROPERTY_BSR)
404 self->bsr = new_bool;
405 else if (base->ID == PROPERTY_EOM)
406 self->eom = new_bool;
407 else if (base->ID == PROPERTY_BSF_AFTER_EOM)
408 self->bsf_after_eom = new_bool;
409 else if (base->ID == PROPERTY_NONBLOCKING_OPEN)
410 self->nonblocking_open = new_bool;
412 return FALSE; /* shouldn't happen */
414 return device_simple_property_set_fn(p_self, base, val, surety, source);
418 tape_device_set_final_filemarks_fn(Device *p_self, DevicePropertyBase *base,
419 GValue *val, PropertySurety surety, PropertySource source)
421 TapeDevice *self = TAPE_DEVICE(p_self);
423 gboolean old_int, new_int;
424 PropertySurety old_surety;
425 PropertySource old_source;
427 new_int = g_value_get_uint(val);
429 /* get the old source and surety and see if we're willing to make this change */
430 bzero(&old_val, sizeof(old_val));
431 if (device_get_simple_property(p_self, base->ID, &old_val, &old_surety, &old_source)) {
432 old_int = g_value_get_uint(&old_val);
434 if (old_surety == PROPERTY_SURETY_GOOD && old_source == PROPERTY_SOURCE_DETECTED) {
435 if (new_int != old_int) {
436 device_set_error(p_self, vstrallocf(_(
437 "Value for property '%s' was autodetected and cannot be changed"),
439 DEVICE_STATUS_DEVICE_ERROR);
442 /* pretend we set it, but don't change surety/source */
448 self->final_filemarks = new_int;
450 return device_simple_property_set_fn(p_self, base, val, surety, source);
454 tape_device_set_compression_fn(Device *p_self, DevicePropertyBase *base,
455 GValue *val, PropertySurety surety, PropertySource source)
457 TapeDevice *self = TAPE_DEVICE(p_self);
458 gboolean request = g_value_get_boolean(val);
460 /* We allow this property to be set at any time. This is mostly
461 * because setting compression is a hit-and-miss proposition
462 * at any time; some drives accept the mode setting but don't
463 * actually support compression, while others do support
464 * compression but do it via density settings or some other
465 * way. Set this property whenever you want, but all we'll do
466 * is report whether or not the ioctl succeeded. */
467 if (tape_setcompression(self->fd, request)) {
468 /* looks good .. let's start the device over, though */
469 device_clear_volume_details(p_self);
474 return device_simple_property_set_fn(p_self, base, val, surety, source);
478 tape_device_get_read_block_size_fn(Device *p_self, DevicePropertyBase *base G_GNUC_UNUSED,
479 GValue *val, PropertySurety *surety, PropertySource *source)
481 /* use the READ_BLOCK_SIZE, even if we're invoked to get the old READ_BUFFER_SIZE */
482 return device_simple_property_get_fn(p_self, &device_property_read_block_size,
483 val, surety, source);
487 tape_device_set_read_block_size_fn(Device *p_self, DevicePropertyBase *base G_GNUC_UNUSED,
488 GValue *val, PropertySurety surety, PropertySource source)
490 TapeDevice *self = TAPE_DEVICE(p_self);
491 guint read_block_size = g_value_get_uint(val);
493 if (read_block_size != 0 &&
494 ((gsize)read_block_size < p_self->block_size ||
495 (gsize)read_block_size > p_self->max_block_size))
498 self->private->read_block_size = read_block_size;
500 /* use the READ_BLOCK_SIZE, even if we're invoked to get the old READ_BUFFER_SIZE */
501 return device_simple_property_set_fn(p_self, &device_property_read_block_size,
502 val, surety, source);
505 void tape_device_register(void) {
506 static const char * device_prefix_list[] = { "tape", NULL };
508 /* First register tape-specific properties */
509 device_property_fill_and_register(&device_property_broken_gmt_online,
510 G_TYPE_BOOLEAN, "broken_gmt_online",
511 "Does this drive support the GMT_ONLINE macro?");
513 device_property_fill_and_register(&device_property_fsf,
514 G_TYPE_BOOLEAN, "fsf",
515 "Does this drive support the MTFSF command?");
517 device_property_fill_and_register(&device_property_fsf_after_filemark,
518 G_TYPE_BOOLEAN, "fsf_after_filemark",
519 "Does this drive needs a FSF if a filemark is already read?");
521 device_property_fill_and_register(&device_property_bsf,
522 G_TYPE_BOOLEAN, "bsf",
523 "Does this drive support the MTBSF command?" );
525 device_property_fill_and_register(&device_property_fsr,
526 G_TYPE_BOOLEAN, "fsr",
527 "Does this drive support the MTFSR command?");
529 device_property_fill_and_register(&device_property_bsr,
530 G_TYPE_BOOLEAN, "bsr",
531 "Does this drive support the MTBSR command?");
533 device_property_fill_and_register(&device_property_eom,
534 G_TYPE_BOOLEAN, "eom",
535 "Does this drive support the MTEOM command?");
537 device_property_fill_and_register(&device_property_bsf_after_eom,
540 "Does this drive require an MTBSF after MTEOM in order to append?" );
542 device_property_fill_and_register(&device_property_nonblocking_open,
545 "Does this drive require a open with O_NONBLOCK?" );
547 device_property_fill_and_register(&device_property_final_filemarks,
548 G_TYPE_UINT, "final_filemarks",
549 "How many filemarks to write after the last tape file?" );
551 device_property_fill_and_register(&device_property_read_buffer_size,
552 G_TYPE_UINT, "read_buffer_size",
553 "(deprecated name for READ_BLOCK_SIZE)");
555 /* Then the device itself */
556 register_device(tape_device_factory, device_prefix_list);
559 /* Open the tape device, trying various combinations of O_RDWR and
560 O_NONBLOCK. Returns -1 and calls device_set_error for errors
561 On Linux, with O_NONBLOCK, the kernel just checks the state once,
562 whereas it checks it every second for ST_BLOCK_SECONDS if O_NONBLOCK is
563 not given. Amanda already have the code to poll, we want open to check
564 the state only once. */
566 static int try_open_tape_device(TapeDevice * self, char * device_filename) {
569 DeviceStatusFlags new_status;
574 if (self->nonblocking_open) {
575 nonblocking = O_NONBLOCK;
580 fd = robust_open(device_filename, O_RDWR | nonblocking, 0);
582 if (fd < 0 && nonblocking && (save_errno == EWOULDBLOCK || save_errno == EINVAL)) {
583 /* Maybe we don't support O_NONBLOCK for tape devices. */
584 fd = robust_open(device_filename, O_RDWR, 0);
588 fd = robust_open(device_filename, O_RDWR, 0);
592 self->write_open_errno = 0;
594 if (errno == EACCES || errno == EPERM
599 /* Device is write-protected. */
600 self->write_open_errno = errno;
602 fd = robust_open(device_filename, O_RDONLY | nonblocking, 0);
604 if (fd < 0 && nonblocking && (save_errno == EWOULDBLOCK || save_errno == EINVAL)) {
605 fd = robust_open(device_filename, O_RDONLY, 0);
609 fd = robust_open(device_filename, O_RDONLY, 0);
615 /* Clear O_NONBLOCK for operations from now on. */
616 if (fd >= 0 && nonblocking)
617 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
619 /* function continues after #endif */
621 #endif /* O_NONBLOCK */
624 DeviceStatusFlags status_flag = 0;
626 status_flag = DEVICE_STATUS_DEVICE_BUSY;
628 status_flag = DEVICE_STATUS_DEVICE_ERROR;
629 device_set_error(DEVICE(self),
630 vstrallocf(_("Can't open tape device %s: %s"), self->private->device_filename, strerror(errno)),
635 /* Check that this is actually a tape device. */
636 new_status = tape_is_tape_device(fd);
637 if (new_status & DEVICE_STATUS_DEVICE_ERROR) {
638 device_set_error(DEVICE(self),
639 vstrallocf(_("File %s is not a tape device"), self->private->device_filename),
644 if (new_status & DEVICE_STATUS_VOLUME_MISSING) {
645 device_set_error(DEVICE(self),
646 vstrallocf(_("Tape device %s is not ready or is empty"), self->private->device_filename),
652 new_status = tape_is_ready(fd, self);
653 if (new_status & DEVICE_STATUS_VOLUME_MISSING) {
654 device_set_error(DEVICE(self),
655 vstrallocf(_("Tape device %s is empty"), self->private->device_filename),
660 if (new_status != DEVICE_STATUS_SUCCESS) {
661 device_set_error(DEVICE(self),
662 vstrallocf(_("Tape device %s is not ready or is empty"), self->private->device_filename),
672 tape_device_open_device (Device * d_self, char * device_name,
673 char * device_type, char * device_node) {
676 self = TAPE_DEVICE(d_self);
679 self->private->device_filename = stralloc(device_node);
681 /* Get tape drive/OS info */
682 tape_device_detect_capabilities(self);
685 if (parent_class->open_device) {
686 parent_class->open_device(d_self, device_name, device_type, device_node);
691 tape_device_set_capabilities(TapeDevice *self,
692 gboolean fsf, PropertySurety fsf_surety, PropertySource fsf_source,
693 gboolean fsf_after_filemark, PropertySurety faf_surety, PropertySource faf_source,
694 gboolean bsf, PropertySurety bsf_surety, PropertySource bsf_source,
695 gboolean fsr, PropertySurety fsr_surety, PropertySource fsr_source,
696 gboolean bsr, PropertySurety bsr_surety, PropertySource bsr_source,
697 gboolean eom, PropertySurety eom_surety, PropertySource eom_source,
698 gboolean bsf_after_eom, PropertySurety bae_surety, PropertySource bae_source,
699 guint final_filemarks, PropertySurety ff_surety, PropertySource ff_source)
701 Device *dself = DEVICE(self);
704 /* this function is called by tape_device_detect_capabilities, and basically
705 * exists to take care of the GValue mechanics in one place */
707 g_assert(final_filemarks == 1 || final_filemarks == 2);
709 bzero(&val, sizeof(val));
710 g_value_init(&val, G_TYPE_BOOLEAN);
713 g_value_set_boolean(&val, fsf);
714 device_set_simple_property(dself, PROPERTY_FSF, &val, fsf_surety, fsf_source);
716 self->fsf_after_filemark = fsf_after_filemark;
717 g_value_set_boolean(&val, fsf_after_filemark);
718 device_set_simple_property(dself, PROPERTY_FSF_AFTER_FILEMARK, &val, faf_surety, faf_source);
721 g_value_set_boolean(&val, bsf);
722 device_set_simple_property(dself, PROPERTY_BSF, &val, bsf_surety, bsf_source);
725 g_value_set_boolean(&val, fsr);
726 device_set_simple_property(dself, PROPERTY_FSR, &val, fsr_surety, fsr_source);
729 g_value_set_boolean(&val, bsr);
730 device_set_simple_property(dself, PROPERTY_BSR, &val, bsr_surety, bsr_source);
733 g_value_set_boolean(&val, eom);
734 device_set_simple_property(dself, PROPERTY_EOM, &val, eom_surety, eom_source);
736 self->bsf_after_eom = bsf_after_eom;
737 g_value_set_boolean(&val, bsf_after_eom);
738 device_set_simple_property(dself, PROPERTY_BSF_AFTER_EOM, &val, bae_surety, bae_source);
741 g_value_init(&val, G_TYPE_UINT);
743 self->final_filemarks = final_filemarks;
744 g_value_set_uint(&val, final_filemarks);
745 device_set_simple_property(dself, PROPERTY_FINAL_FILEMARKS, &val, ff_surety, ff_source);
750 static DeviceStatusFlags tape_device_read_label(Device * dself) {
752 char * header_buffer;
756 DeviceStatusFlags new_status;
759 self = TAPE_DEVICE(dself);
761 amfree(dself->volume_label);
762 amfree(dself->volume_time);
763 dumpfile_free(dself->volume_header);
764 dself->volume_header = NULL;
766 if (device_in_error(self)) return dself->status;
768 header = dself->volume_header = g_new(dumpfile_t, 1);
771 if (self->fd == -1) {
772 self->fd = try_open_tape_device(self, self->private->device_filename);
773 /* if the open failed, then try_open_tape_device already set the
774 * approppriate error status */
776 return dself->status;
780 if (!tape_rewind(self->fd)) {
781 device_set_error(dself,
782 vstrallocf(_("Error rewinding device %s to read label: %s"),
783 self->private->device_filename, strerror(errno)),
784 DEVICE_STATUS_DEVICE_ERROR
785 | DEVICE_STATUS_VOLUME_ERROR);
786 return dself->status;
789 buffer_len = tape_device_read_size(self);
790 header_buffer = malloc(buffer_len);
791 result = tape_device_robust_read(self, header_buffer, &buffer_len, &msg);
793 if (result != RESULT_SUCCESS) {
795 tape_rewind(self->fd);
799 msg = stralloc(_("no data"));
800 new_status = (DEVICE_STATUS_VOLUME_ERROR |
801 DEVICE_STATUS_VOLUME_UNLABELED);
804 case RESULT_SMALL_BUFFER:
805 msg = stralloc(_("block size too small"));
806 new_status = (DEVICE_STATUS_DEVICE_ERROR |
807 DEVICE_STATUS_VOLUME_ERROR);
811 msg = stralloc(_("unknown error"));
813 new_status = (DEVICE_STATUS_DEVICE_ERROR |
814 DEVICE_STATUS_VOLUME_ERROR |
815 DEVICE_STATUS_VOLUME_UNLABELED);
818 device_set_error(dself,
819 g_strdup_printf(_("Error reading Amanda header: %s"),
820 msg? msg : _("unknown error")),
823 return dself->status;
826 parse_file_header(header_buffer, header, buffer_len);
827 amfree(header_buffer);
828 if (header->type != F_TAPESTART) {
829 device_set_error(dself,
830 stralloc(_("No tapestart header -- unlabeled device?")),
831 DEVICE_STATUS_VOLUME_UNLABELED);
832 return dself->status;
835 dself->volume_label = g_strdup(header->name);
836 dself->volume_time = g_strdup(header->datestamp);
837 /* dself->volume_header is already set */
839 device_set_error(dself, NULL, DEVICE_STATUS_SUCCESS);
841 return dself->status;
845 tape_device_write_block(Device * pself, guint size, gpointer data) {
847 char *replacement_buffer = NULL;
851 self = TAPE_DEVICE(pself);
853 g_assert(self->fd >= 0);
854 if (device_in_error(self)) return FALSE;
856 /* zero out to the end of a short block -- tape devices only write
858 if (size < pself->block_size) {
859 replacement_buffer = malloc(pself->block_size);
860 memcpy(replacement_buffer, data, size);
861 bzero(replacement_buffer+size, pself->block_size-size);
863 data = replacement_buffer;
864 size = pself->block_size;
867 result = tape_device_robust_write(self, data, size, &msg);
868 amfree(replacement_buffer);
874 case RESULT_NO_SPACE:
875 device_set_error(pself,
876 stralloc(_("No space left on device")),
877 DEVICE_STATUS_VOLUME_ERROR);
878 pself->is_eom = TRUE;
882 msg = stralloc(_("unknown error"));
884 device_set_error(pself,
885 g_strdup_printf(_("Error writing block: %s"), msg),
886 DEVICE_STATUS_DEVICE_ERROR);
896 static int tape_device_read_block (Device * pself, gpointer buf,
901 gssize read_block_size = tape_device_read_size(pself);
904 self = TAPE_DEVICE(pself);
906 g_assert(self->fd >= 0);
907 if (device_in_error(self)) return -1;
909 g_assert(read_block_size < INT_MAX); /* data type mismatch */
910 if (buf == NULL || *size_req < (int)read_block_size) {
911 /* Just a size query. */
912 *size_req = (int)read_block_size;
917 result = tape_device_robust_read(self, buf, &size, &msg);
923 case RESULT_SMALL_BUFFER: {
927 /* If this happens, it means that we have:
928 * (next block size) > (buffer size) >= (read_block_size)
929 * The solution is to ask for an even bigger buffer. We also play
930 * some games to refrain from reading above the SCSI limit or from
931 * integer overflow. Note that not all devices will tell us about
932 * this problem -- some will just discard the "extra" data. */
933 new_size = MIN(INT_MAX/2 - 1, *size_req) * 2;
934 if (new_size > LARGEST_BLOCK_ESTIMATE &&
935 *size_req < LARGEST_BLOCK_ESTIMATE) {
936 new_size = LARGEST_BLOCK_ESTIMATE;
938 g_assert (new_size > (gsize)*size_req);
940 g_info("Device %s indicated blocksize %zd was too small; using %zd.",
941 pself->device_name, (gsize)*size_req, new_size);
942 *size_req = (int)new_size;
943 self->private->read_block_size = new_size;
945 bzero(&newval, sizeof(newval));
946 g_value_init(&newval, G_TYPE_UINT);
947 g_value_set_uint(&newval, self->private->read_block_size);
948 device_set_simple_property(pself, PROPERTY_READ_BLOCK_SIZE,
949 &newval, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
950 g_value_unset(&newval);
955 pself->is_eof = TRUE;
956 pself->in_file = FALSE;
957 device_set_error(pself,
959 DEVICE_STATUS_SUCCESS);
963 msg = stralloc(_("unknown error"));
965 device_set_error(pself,
966 vstrallocf(_("Error reading from tape device: %s"), msg),
967 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
972 g_assert_not_reached();
975 /* Just a helper function for tape_device_start(). */
976 static gboolean write_tapestart_header(TapeDevice * self, char * label,
981 Device * d_self = (Device*)self;
984 tape_rewind(self->fd);
986 header = make_tapestart_header(d_self, label, timestamp);
987 g_assert(header != NULL);
988 header_buf = device_build_amanda_header(d_self, header, NULL);
989 if (header_buf == NULL) {
990 device_set_error(d_self,
991 stralloc(_("Tapestart header won't fit in a single block!")),
992 DEVICE_STATUS_DEVICE_ERROR);
993 dumpfile_free(header);
996 dumpfile_free(d_self->volume_header);
997 d_self->volume_header = NULL;
999 result = tape_device_robust_write(self, header_buf, d_self->block_size, &msg);
1000 if (result != RESULT_SUCCESS) {
1001 device_set_error(d_self,
1002 g_strdup_printf(_("Error writing tapestart header: %s"),
1003 (result == RESULT_ERROR)? msg : _("out of space")),
1004 DEVICE_STATUS_DEVICE_ERROR);
1006 if (result == RESULT_NO_SPACE)
1007 d_self->is_eom = TRUE;
1010 dumpfile_free(header);
1017 if (!tape_weof(self->fd, 1)) {
1018 device_set_error(d_self,
1019 vstrallocf(_("Error writing filemark: %s"),
1021 DEVICE_STATUS_DEVICE_ERROR|DEVICE_STATUS_VOLUME_ERROR);
1022 /* can't tell if this was EOM or not, so assume it is */
1023 d_self->is_eom = TRUE;
1024 dumpfile_free(header);
1028 d_self->volume_header = header;
1033 tape_device_start (Device * d_self, DeviceAccessMode mode, char * label,
1037 self = TAPE_DEVICE(d_self);
1039 if (device_in_error(self)) return FALSE;
1041 if (self->fd == -1) {
1042 self->fd = try_open_tape_device(self, self->private->device_filename);
1043 /* if the open failed, then try_open_tape_device already set the
1044 * approppriate error status */
1049 if (mode != ACCESS_WRITE && d_self->volume_label == NULL) {
1050 /* we need a labeled volume for APPEND and READ */
1051 if (tape_device_read_label(d_self) != DEVICE_STATUS_SUCCESS)
1055 d_self->access_mode = mode;
1056 d_self->in_file = FALSE;
1058 if (IS_WRITABLE_ACCESS_MODE(mode)) {
1059 if (self->write_open_errno != 0) {
1060 /* We tried and failed to open the device in write mode. */
1061 device_set_error(d_self,
1062 vstrallocf(_("Can't open tape device %s for writing: %s"),
1063 self->private->device_filename, strerror(self->write_open_errno)),
1064 DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
1066 } else if (!tape_rewind(self->fd)) {
1067 device_set_error(d_self,
1068 vstrallocf(_("Error rewinding device to start: %s"), strerror(errno)),
1069 DEVICE_STATUS_DEVICE_ERROR);
1074 /* Position the tape */
1077 if (d_self->volume_label == NULL && device_read_label(d_self) != DEVICE_STATUS_SUCCESS) {
1078 /* device_read_label already set our error message */
1082 if (!tape_device_eod(self)) {
1083 device_set_error(d_self,
1084 vstrallocf(_("Couldn't seek to end of tape: %s"), strerror(errno)),
1085 DEVICE_STATUS_DEVICE_ERROR);
1091 if (d_self->volume_label == NULL && device_read_label(d_self) != DEVICE_STATUS_SUCCESS) {
1092 /* device_read_label already set our error message */
1096 if (!tape_rewind(self->fd)) {
1097 device_set_error(d_self,
1098 vstrallocf(_("Error rewinding device after reading label: %s"), strerror(errno)),
1099 DEVICE_STATUS_DEVICE_ERROR);
1106 if (!write_tapestart_header(self, label, timestamp)) {
1107 /* write_tapestart_header already set the error status */
1111 d_self->volume_label = newstralloc(d_self->volume_label, label);
1112 d_self->volume_time = newstralloc(d_self->volume_time, timestamp);
1114 /* unset the VOLUME_UNLABELED flag, if it was set */
1115 device_set_error(d_self, NULL, DEVICE_STATUS_SUCCESS);
1120 g_assert_not_reached();
1126 static gboolean tape_device_start_file(Device * d_self,
1127 dumpfile_t * info) {
1130 char * amanda_header;
1133 d_self->is_eom = FALSE;
1135 self = TAPE_DEVICE(d_self);
1137 g_assert(self->fd >= 0);
1138 if (device_in_error(self)) return FALSE;
1140 /* set the blocksize in the header properly */
1141 info->blocksize = d_self->block_size;
1143 /* Make the Amanda header suitable for writing to the device. */
1144 /* Then write the damn thing. */
1145 amanda_header = device_build_amanda_header(d_self, info, NULL);
1146 if (amanda_header == NULL) {
1147 device_set_error(d_self,
1148 stralloc(_("Amanda file header won't fit in a single block!")),
1149 DEVICE_STATUS_DEVICE_ERROR);
1153 result = tape_device_robust_write(self, amanda_header, d_self->block_size, &msg);
1154 if (result != RESULT_SUCCESS) {
1155 device_set_error(d_self,
1156 vstrallocf(_("Error writing file header: %s"),
1157 (result == RESULT_ERROR)? msg : _("out of space")),
1158 DEVICE_STATUS_DEVICE_ERROR);
1160 if (result == RESULT_NO_SPACE)
1161 d_self->is_eom = TRUE;
1163 amfree(amanda_header);
1167 amfree(amanda_header);
1169 /* arrange the file numbers correctly */
1170 d_self->in_file = TRUE;
1172 if (d_self->file >= 0)
1178 tape_device_finish_file (Device * d_self) {
1181 self = TAPE_DEVICE(d_self);
1182 if (device_in_error(d_self)) return FALSE;
1184 if (!tape_weof(self->fd, 1)) {
1185 device_set_error(d_self,
1186 vstrallocf(_("Error writing filemark: %s"), strerror(errno)),
1187 DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
1188 /* can't tell if this was EOM or not, so assume it is */
1189 d_self->is_eom = TRUE;
1193 d_self->in_file = FALSE;
1198 tape_device_seek_file (Device * d_self, guint file) {
1202 char * header_buffer;
1208 self = TAPE_DEVICE(d_self);
1210 if (device_in_error(self)) return NULL;
1212 difference = file - d_self->file;
1214 /* Check if we already read a filemark. */
1215 /* If we already read a filemark and the drive automaticaly goes to the
1216 next file, then we must reduce the difference by one. */
1217 if (d_self->is_eof && !self->fsf_after_filemark) {
1221 d_self->in_file = FALSE;
1222 d_self->is_eof = FALSE;
1226 if (difference > 0) {
1227 /* Seeking forwards */
1228 if (!tape_device_fsf(self, difference)) {
1229 tape_rewind(self->fd);
1230 device_set_error(d_self,
1231 vstrallocf(_("Could not seek forward to file %d"), file),
1232 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1235 } else { /* (difference <= 0) */
1236 /* Seeking backwards, or to this file itself */
1238 /* if the drive supports bsf, we can do this the fancy way */
1240 /* bsf one more than the difference */
1241 if (!tape_bsf(self->fd, -difference + 1)) {
1242 tape_rewind(self->fd);
1243 device_set_error(d_self,
1244 vstrallocf(_("Could not seek backward to file %d"), file),
1245 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1249 /* now we are on the BOT side of the desired filemark, so FSF to get to the
1251 if (!tape_device_fsf(self, 1)) {
1252 tape_rewind(self->fd);
1253 device_set_error(d_self,
1254 vstrallocf(_("Could not seek forward to file %d"), file),
1255 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1259 /* no BSF, so just rewind and seek forward */
1260 if (!tape_rewind(self->fd)) {
1261 device_set_error(d_self,
1262 vstrallocf(_("Could not rewind device while emulating BSF")),
1263 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1267 if (!tape_device_fsf(self, file)) {
1268 tape_rewind(self->fd);
1269 device_set_error(d_self,
1270 vstrallocf(_("Could not seek forward to file %d"), file),
1271 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1277 /* double-check that we're on the right fileno, if possible. This is most
1278 * likely a programming error if it occurs, but could also be due to a weird
1279 * tape drive or driver (and that would *never* happen, right?) */
1280 got_file = tape_fileno(self->fd);
1281 if (got_file >= 0 && (guint)got_file != file) {
1282 device_set_error(d_self,
1283 vstrallocf(_("Could not seek to file %d correctly; got %d"),
1285 DEVICE_STATUS_DEVICE_ERROR);
1286 d_self->file = (guint)got_file;
1290 buffer_len = tape_device_read_size(d_self);
1291 header_buffer = malloc(buffer_len);
1292 d_self->is_eof = FALSE;
1293 result = tape_device_robust_read(self, header_buffer, &buffer_len, &msg);
1295 if (result != RESULT_SUCCESS) {
1296 free(header_buffer);
1297 tape_rewind(self->fd);
1299 case RESULT_NO_DATA:
1300 /* If we read 0 bytes, that means we encountered a double
1301 * filemark, which indicates end of tape. This should
1302 * work even with QIC tapes on operating systems with
1303 * proper support. */
1304 d_self->file = file; /* other attributes are already correct */
1305 return make_tapeend_header();
1307 case RESULT_SMALL_BUFFER:
1308 msg = stralloc(_("block size too small"));
1312 msg = stralloc(_("unknown error"));
1316 device_set_error(d_self,
1317 g_strdup_printf(_("Error reading Amanda header: %s"), msg),
1318 DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
1323 rval = g_new(dumpfile_t, 1);
1324 parse_file_header(header_buffer, rval, buffer_len);
1325 amfree(header_buffer);
1326 switch (rval->type) {
1328 case F_CONT_DUMPFILE:
1329 case F_SPLIT_DUMPFILE:
1333 /* a NOOP is written on QIC tapes to avoid writing two sequential
1334 * filemarks when closing a device in WRITE or APPEND mode. In this
1335 * case, we just seek to the next file. */
1342 tape_rewind(self->fd);
1343 device_set_error(d_self,
1344 stralloc(_("Invalid amanda header while reading file header")),
1345 DEVICE_STATUS_VOLUME_ERROR);
1350 d_self->in_file = TRUE;
1351 d_self->file = file;
1357 tape_device_seek_block (Device * d_self, guint64 block) {
1361 self = TAPE_DEVICE(d_self);
1363 if (device_in_error(self)) return FALSE;
1365 difference = block - d_self->block;
1367 if (difference > 0) {
1368 if (!tape_device_fsr(self, difference)) {
1369 device_set_error(d_self,
1370 vstrallocf(_("Could not seek forward to block %ju: %s"), (uintmax_t)block, strerror(errno)),
1371 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1374 } else if (difference < 0) {
1375 if (!tape_device_bsr(self, difference, d_self->file, d_self->block)) {
1376 device_set_error(d_self,
1377 vstrallocf(_("Could not seek backward to block %ju: %s"), (uintmax_t)block, strerror(errno)),
1378 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1383 d_self->block = block;
1388 tape_device_eject (Device * d_self) {
1391 self = TAPE_DEVICE(d_self);
1393 if (device_in_error(self)) return FALSE;
1395 /* Open the device if not already opened */
1396 if (self->fd == -1) {
1397 self->fd = try_open_tape_device(self, self->private->device_filename);
1398 /* if the open failed, then try_open_tape_device already set the
1399 * approppriate error status */
1405 if (!tape_rewind(self->fd)) {
1406 device_set_error(d_self,
1407 vstrallocf(_("Error rewinding device %s before ejecting: %s"),
1408 self->private->device_filename, strerror(errno)),
1409 DEVICE_STATUS_DEVICE_ERROR
1410 | DEVICE_STATUS_VOLUME_ERROR);
1414 if (tape_offl(self->fd))
1417 device_set_error(d_self,
1418 vstrallocf(_("Error ejecting device %s: %s\n"),
1419 self->private->device_filename, strerror(errno)),
1420 DEVICE_STATUS_DEVICE_ERROR);
1426 tape_device_finish (Device * d_self) {
1430 self = TAPE_DEVICE(d_self);
1432 if (device_in_error(self)) return FALSE;
1434 /* if we're already in ACCESS_NULL, then there are no filemarks or anything
1435 * to worry about, but we need to release the kernel device */
1436 if (d_self->access_mode == ACCESS_NULL) {
1437 robust_close(self->fd);
1442 /* Polish off this file, if relevant. */
1443 if (d_self->in_file && IS_WRITABLE_ACCESS_MODE(d_self->access_mode)) {
1444 if (!device_finish_file(d_self))
1448 /* Straighten out the filemarks. We already wrote one in finish_file, and
1449 * the device driver will write another filemark when we rewind. This means
1450 * that, if we do nothing, we'll get two filemarks. If final_filemarks is
1451 * 1, this would be wrong, so in this case we insert a F_NOOP header between
1452 * the two filemarks. */
1453 if (self->final_filemarks == 1 &&
1454 IS_WRITABLE_ACCESS_MODE(d_self->access_mode)) {
1459 /* write a F_NOOP header */
1462 header = device_build_amanda_header(d_self, &file, NULL);
1464 device_set_error(d_self,
1465 stralloc(_("Amanda file header won't fit in a single block!")),
1466 DEVICE_STATUS_DEVICE_ERROR);
1470 result = tape_device_robust_write(self, header, d_self->block_size, &msg);
1471 if (result != RESULT_SUCCESS) {
1472 device_set_error(d_self,
1473 vstrallocf(_("Error writing file header: %s"),
1474 (result == RESULT_ERROR)? msg : _("out of space")),
1475 DEVICE_STATUS_DEVICE_ERROR);
1483 /* Rewind (the kernel will write a filemark first) */
1484 if (!tape_rewind(self->fd)) {
1485 device_set_error(d_self,
1486 vstrallocf(_("Couldn't rewind device to finish: %s"), strerror(errno)),
1487 DEVICE_STATUS_DEVICE_ERROR);
1491 d_self->is_eof = FALSE;
1492 d_self->access_mode = ACCESS_NULL;
1494 /* release the kernel's device */
1495 robust_close(self->fd);
1501 /* Works just like read(), except for the following:
1502 * 1) Retries on EINTR & friends.
1503 * 2) Stores count in parameter, not return value.
1504 * 3) Provides explicit return result.
1505 * *errmsg is only set on RESULT_ERROR.
1508 tape_device_robust_read (TapeDevice * self, void * buf, int * count, char **errmsg) {
1512 d_self = (Device*)self;
1514 /* Callers should ensure this. */
1515 g_assert(*count >= 0);
1518 result = read(self->fd, buf, *count);
1520 /* Success. By definition, we read a full block. */
1521 d_self->is_eof = FALSE;
1523 return RESULT_SUCCESS;
1524 } else if (result == 0) {
1525 d_self->is_eof = TRUE;
1526 return RESULT_NO_DATA;
1533 || errno == EWOULDBLOCK
1539 /* Interrupted system call */
1543 || errno == ENOMEM /* bad user-space buffer */
1546 || errno == EOVERFLOW /* bad kernel-space buffer */
1549 || errno == EINVAL /* ??? */
1552 /* Buffer too small. */
1553 g_warning("Buffer is too small (%d bytes) from %s: %s",
1554 *count, self->private->device_filename, strerror(errno));
1555 return RESULT_SMALL_BUFFER;
1557 *errmsg = g_strdup_printf(_("Error reading %d bytes from %s: %s"),
1558 *count, self->private->device_filename, strerror(errno));
1559 return RESULT_ERROR;
1564 g_assert_not_reached();
1567 /* Kernel workaround: If needed, poke the kernel so it doesn't fail.
1568 at the 2GB boundry. Parameters are G_GNUC_UNUSED in case NEED_RESETOFS
1570 static void check_resetofs(TapeDevice * self G_GNUC_UNUSED,
1571 int count G_GNUC_UNUSED) {
1572 #ifdef NEED_RESETOFS
1576 d_self = (Device*)self;
1578 self->private->write_count += count;
1579 if (self->private->write_count < RESETOFS_THRESHOLD) {
1583 result = lseek(self->fd, 0, SEEK_SET);
1585 g_warning(_("lseek() failed during kernel 2GB workaround: %s"),
1591 /* *errmsg is only set on RESULT_ERROR */
1593 tape_device_robust_write (TapeDevice * self, void * buf, int count, char **errmsg) {
1597 d_self = (Device*)self;
1599 check_resetofs(self, count);
1602 result = write(self->fd, buf, count);
1604 if (result == count) {
1607 self->private->write_count ++;
1608 return RESULT_SUCCESS;
1609 } else if (result >= 0) {
1610 /* write() returned a short count. This should not happen. */
1611 *errmsg = g_strdup_printf("Mysterious short write on tape device: Tried %d, got %d",
1613 return RESULT_ERROR;
1619 || errno == EWOULDBLOCK
1625 /* Interrupted system call */
1635 /* Probably EOT. Print a message if we got EIO. */
1638 g_warning(_("Got EIO on %s, assuming end of tape"),
1639 self->private->device_filename);
1642 return RESULT_NO_SPACE;
1645 *errmsg = vstrallocf(_("Kernel gave unexpected write() result of \"%s\" on device %s"),
1646 strerror(errno), self->private->device_filename);
1647 return RESULT_ERROR;
1651 g_assert_not_reached();
1654 /* Reads some number of tape blocks into the bit-bucket. If the count
1655 is negative, then we read the rest of the entire file. Returns the
1656 number of blocks read, or -1 if an error occured. If we encounter
1657 EOF (as opposed to some other error) we return the number of blocks
1659 static int drain_tape_blocks(TapeDevice * self, int count) {
1664 buffer_size = tape_device_read_size(self);
1666 buffer = malloc(buffer_size);
1668 for (i = 0; i < count || count < 0;) {
1671 result = read(self->fd, buffer, buffer_size);
1675 } else if (result == 0) {
1679 /* First check for interrupted system call. */
1685 || errno == EWOULDBLOCK
1691 /* Interrupted system call */
1695 || errno == ENOSPC /* bad user-space buffer */
1698 || errno == EOVERFLOW /* bad kernel-space buffer */
1701 || errno == EINVAL /* ??? */
1704 /* The buffer may not be big enough. But the OS is not
1705 100% clear. We double the buffer and try again, but
1706 in no case allow a buffer bigger than 32 MB. */
1709 if (buffer_size > 32*1024*1024) {
1713 buffer = realloc(buffer, buffer_size);
1725 tape_device_fsf (TapeDevice * self, guint count) {
1727 return tape_fsf(self->fd, count);
1730 for (i = 0; i < count; i ++) {
1731 if (drain_tape_blocks(self, -1) < 0)
1740 tape_device_fsr (TapeDevice * self, guint count) {
1742 return tape_fsr(self->fd, count);
1744 int result = drain_tape_blocks(self, count);
1745 return result > 0 && (int)count == result;
1749 /* Seek back the given number of blocks to block number block within
1750 * the current file, numbered file. */
1753 tape_device_bsr (TapeDevice * self, guint count, guint file, guint block) {
1755 return tape_bsr(self->fd, count);
1756 } else if (self->bsf && self->fsf) {
1757 /* BSF, FSF to the right side of the filemark, and then FSR. */
1758 if (!tape_bsf(self->fd, 1))
1761 if (!tape_fsf(self->fd, 1))
1764 return tape_device_fsr(self, block);
1766 /* rewind, FSF, and FSR */
1767 if (!tape_rewind(self->fd))
1770 if (!tape_device_fsf(self, file))
1773 return tape_device_fsr(self, block);
1775 g_assert_not_reached();
1778 /* Go to the right place to write more data, and update the file
1779 number if possible. */
1781 tape_device_eod (TapeDevice * self) {
1785 d_self = (Device*)self;
1789 result = tape_eod(self->fd);
1790 if (result == TAPE_OP_ERROR) {
1792 } else if (result != TAPE_POSITION_UNKNOWN) {
1793 /* great - we just fast-forwarded to EOD, but don't know where we are, so
1794 * now we have to rewind and drain all of that data. Warn the user so that
1795 * we can skip the fast-forward-rewind stage on the next run */
1796 g_warning("Seek to end of tape does not give an accurate tape position; set "
1797 "the EOM property to 0 to avoid useless tape movement.");
1798 /* and set the property so that next time *this* object is opened for
1799 * append, we skip this stage */
1801 /* fall through to draining blocks, below */
1803 /* We drop by 1 because Device will increment the first
1804 time the user does start_file. */
1805 d_self->file = result - 1;
1810 if (!tape_rewind(self->fd))
1815 /* We alternately read a block and FSF. If the read is
1816 successful, then we are not there yet and should FSF
1819 result = drain_tape_blocks(self, 1);
1821 /* More data, FSF. */
1822 tape_device_fsf(self, 1);
1824 } else if (result == 0) {
1826 d_self->file = count - 1;
1835 tape_device_factory (char * device_name, char * device_type, char * device_node) {
1837 g_assert(0 == strcmp(device_type, "tape"));
1838 rval = DEVICE(g_object_new(TYPE_TAPE_DEVICE, NULL));
1839 device_open_device(rval, device_name, device_type, device_node);