2 * Copyright (c) 2007-2012 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() */
27 #ifdef HAVE_SYS_TAPE_H
28 # include <sys/tape.h>
30 #ifdef HAVE_SYS_MTIO_H
31 # include <sys/mtio.h>
37 /* This is equal to 2*1024*1024*1024 - 16*1024*1024 - 1, but written
38 explicitly to avoid overflow issues. */
39 #define RESETOFS_THRESHOLD (0x7effffff)
41 /* Largest possible block size on SCSI systems. */
42 #define LARGEST_BLOCK_ESTIMATE (16 * 1024 * 1024)
45 * Type checking and casting macros
48 #define TYPE_TAPE_DEVICE (tape_device_get_type())
49 #define TAPE_DEVICE(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), tape_device_get_type(), TapeDevice)
50 #define TAPE_DEVICE_CONST(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), tape_device_get_type(), TapeDevice const)
51 #define TAPE_DEVICE_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), tape_device_get_type(), TapeDeviceClass)
52 #define IS_TAPE_DEVICE(obj) G_TYPE_CHECK_INSTANCE_TYPE((obj), tape_device_get_type ())
53 #define TAPE_DEVICE_GET_CLASS(obj) G_TYPE_INSTANCE_GET_CLASS((obj), tape_device_get_type(), TapeDeviceClass)
54 GType tape_device_get_type (void);
57 * Main object structure
59 typedef struct TapeDevicePrivate_s TapeDevicePrivate;
60 typedef struct _TapeDevice {
63 /* It should go without saying that all this stuff is
64 * look-but-don't-touch. */
66 /* characteristics of the device */
67 gboolean fsf, bsf, fsr, bsr, eom, bsf_after_eom, broken_gmt_online;
69 gboolean nonblocking_open, fsf_after_filemark;
72 /* 0 if we opened with O_RDWR; error otherwise. */
73 gboolean write_open_errno;
76 TapeDevicePrivate * private;
79 struct TapeDevicePrivate_s {
80 /* This holds the total number of bytes written to the device,
81 modulus RESETOFS_THRESHOLD. */
83 char * device_filename;
84 gsize read_block_size;
91 typedef struct _TapeDeviceClass TapeDeviceClass;
92 struct _TapeDeviceClass {
93 DeviceClass __parent__;
96 void tape_device_register(void);
98 /* useful callback for tape ops */
99 void tape_device_set_capabilities(TapeDevice *self,
100 gboolean fsf, PropertySurety fsf_surety, PropertySource fsf_source,
101 gboolean fsf_after_filemark, PropertySurety faf_surety, PropertySource faf_source,
102 gboolean bsf, PropertySurety bsf_surety, PropertySource bsf_source,
103 gboolean fsr, PropertySurety fsr_surety, PropertySource fsr_source,
104 gboolean bsr, PropertySurety bsr_surety, PropertySource bsr_source,
105 gboolean eom, PropertySurety eom_surety, PropertySource eom_source,
106 gboolean leom, PropertySurety leom_surety, PropertySource leom_source,
107 gboolean bsf_after_eom, PropertySurety bae_surety, PropertySource bae_source,
108 guint final_filemarks, PropertySurety ff_surety, PropertySource ff_source);
110 /* Real Operations (always return FALSE if not implemented) */
111 gboolean tape_rewind(int fd);
112 gboolean tape_fsf(int fd, guint count);
113 gboolean tape_bsf(int fd, guint count);
114 gboolean tape_fsr(int fd, guint count);
115 gboolean tape_bsr(int fd, guint count);
116 gint tape_fileno(int fd);
118 /* tape_fileno returns tape position file number, or one of these: */
119 #define TAPE_OP_ERROR -1
120 #define TAPE_POSITION_UNKNOWN -2
122 /* Possible (abstracted) results from a system I/O operation. */
125 RESULT_ERROR, /* Undefined error (*errmsg set) */
126 RESULT_SMALL_BUFFER, /* Tried to read with a buffer that is too
128 RESULT_NO_DATA, /* End of File, while reading */
129 RESULT_NO_SPACE, /* Out of space. Sometimes we don't know if
130 it was this or I/O error, but this is the
131 preferred explanation. */
135 /* returns a fileno like tape_fileno */
136 gint tape_eod(int fd);
138 gboolean tape_weof(int fd, guint8 count);
139 gboolean tape_setcompression(int fd, gboolean on);
141 gboolean tape_offl(int fd);
143 DeviceStatusFlags tape_is_tape_device(int fd);
144 DeviceStatusFlags tape_is_ready(int fd, TapeDevice *t_self);
146 #define tape_device_read_size(self) \
147 (((TapeDevice *)(self))->private->read_block_size? \
148 ((TapeDevice *)(self))->private->read_block_size : ((Device *)(self))->block_size)
151 * Our device-specific properties.
154 #define PROPERTY_BROKEN_GMT_ONLINE (device_property_broken_gmt_online.ID)
155 #define PROPERTY_FSF (device_property_fsf.ID)
156 #define PROPERTY_FSF_AFTER_FILEMARK (device_property_fsf_after_filemark.ID)
157 #define PROPERTY_BSF (device_property_bsf.ID)
158 #define PROPERTY_FSR (device_property_fsr.ID)
159 #define PROPERTY_BSR (device_property_bsr.ID)
160 #define PROPERTY_EOM (device_property_eom.ID)
161 #define PROPERTY_BSF_AFTER_EOM (device_property_bsf_after_eom.ID)
162 #define PROPERTY_NONBLOCKING_OPEN (device_property_nonblocking_open.ID)
163 #define PROPERTY_FINAL_FILEMARKS (device_property_final_filemarks.ID)
165 static DevicePropertyBase device_property_broken_gmt_online;
166 static DevicePropertyBase device_property_fsf;
167 static DevicePropertyBase device_property_fsf_after_filemark;
168 static DevicePropertyBase device_property_bsf;
169 static DevicePropertyBase device_property_fsr;
170 static DevicePropertyBase device_property_bsr;
171 static DevicePropertyBase device_property_eom;
172 static DevicePropertyBase device_property_bsf_after_eom;
173 static DevicePropertyBase device_property_nonblocking_open;
174 static DevicePropertyBase device_property_final_filemarks;
175 static DevicePropertyBase device_property_read_buffer_size; /* old name for READ_BLOCK_SIZE */
177 /* here are local prototypes */
178 static void tape_device_init (TapeDevice * o);
179 static void tape_device_class_init (TapeDeviceClass * c);
180 static void tape_device_base_init (TapeDeviceClass * c);
181 static gboolean tape_device_set_feature_property_fn(Device *p_self, DevicePropertyBase *base,
182 GValue *val, PropertySurety surety, PropertySource source);
183 static gboolean tape_device_set_final_filemarks_fn(Device *p_self, DevicePropertyBase *base,
184 GValue *val, PropertySurety surety, PropertySource source);
185 static gboolean tape_device_set_compression_fn(Device *p_self, DevicePropertyBase *base,
186 GValue *val, PropertySurety surety, PropertySource source);
187 static gboolean tape_device_get_read_block_size_fn(Device *p_self, DevicePropertyBase *base,
188 GValue *val, PropertySurety *surety, PropertySource *source);
189 static gboolean tape_device_set_read_block_size_fn(Device *p_self, DevicePropertyBase *base,
190 GValue *val, PropertySurety surety, PropertySource source);
191 static void tape_device_open_device (Device * self, char * device_name, char * device_type, char * device_node);
192 static Device * tape_device_factory (char * device_name, char * device_type, char * device_node);
193 static DeviceStatusFlags tape_device_read_label(Device * self);
194 static gboolean tape_device_write_block(Device * self, guint size, gpointer data);
195 static int tape_device_read_block(Device * self, gpointer buf,
197 static gboolean tape_device_start (Device * self, DeviceAccessMode mode,
198 char * label, char * timestamp);
199 static gboolean tape_device_start_file (Device * self, dumpfile_t * ji);
200 static gboolean tape_device_finish_file (Device * self);
201 static dumpfile_t * tape_device_seek_file (Device * self, guint file);
202 static gboolean tape_device_seek_block (Device * self, guint64 block);
203 static gboolean tape_device_eject (Device * self);
204 static gboolean tape_device_finish (Device * self);
205 static IoResult tape_device_robust_read (TapeDevice * self, void * buf,
206 int * count, char **errmsg);
207 static IoResult tape_device_robust_write (TapeDevice * self, void * buf, int count, char **errmsg);
208 static gboolean tape_device_fsf (TapeDevice * self, guint count);
209 static gboolean tape_device_fsr (TapeDevice * self, guint count);
210 static gboolean tape_device_bsr (TapeDevice * self, guint count, guint file, guint block);
211 static gboolean tape_device_eod (TapeDevice * self);
213 /* pointer to the class of our parent */
214 static DeviceClass *parent_class = NULL;
216 GType tape_device_get_type (void)
218 static GType type = 0;
220 if G_UNLIKELY(type == 0) {
221 static const GTypeInfo info = {
222 sizeof (TapeDeviceClass),
223 (GBaseInitFunc) tape_device_base_init,
224 (GBaseFinalizeFunc) NULL,
225 (GClassInitFunc) tape_device_class_init,
226 (GClassFinalizeFunc) NULL,
227 NULL /* class_data */,
230 (GInstanceInitFunc) tape_device_init,
234 type = g_type_register_static (TYPE_DEVICE, "TapeDevice",
235 &info, (GTypeFlags)0);
242 tape_device_init (TapeDevice * self) {
246 d_self = DEVICE(self);
247 bzero(&response, sizeof(response));
249 self->private = g_new0(TapeDevicePrivate, 1);
251 /* Clear all fields. */
252 d_self->block_size = 32768;
253 d_self->min_block_size = 32768;
254 d_self->max_block_size = LARGEST_BLOCK_ESTIMATE;
255 self->broken_gmt_online = FALSE;
259 /* set all of the feature properties to an unsure default of FALSE */
260 self->broken_gmt_online = FALSE;
267 self->bsf_after_eom = FALSE;
269 g_value_init(&response, G_TYPE_BOOLEAN);
270 g_value_set_boolean(&response, FALSE);
271 device_set_simple_property(d_self, PROPERTY_BROKEN_GMT_ONLINE,
272 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
273 device_set_simple_property(d_self, PROPERTY_FSF,
274 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
275 device_set_simple_property(d_self, PROPERTY_FSF_AFTER_FILEMARK,
276 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
277 device_set_simple_property(d_self, PROPERTY_BSF,
278 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
279 device_set_simple_property(d_self, PROPERTY_FSR,
280 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
281 device_set_simple_property(d_self, PROPERTY_BSR,
282 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
283 device_set_simple_property(d_self, PROPERTY_EOM,
284 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
285 device_set_simple_property(d_self, PROPERTY_LEOM,
286 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
287 device_set_simple_property(d_self, PROPERTY_BSF_AFTER_EOM,
288 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
290 #ifdef DEFAULT_TAPE_NON_BLOCKING_OPEN
291 self->nonblocking_open = TRUE;
293 self->nonblocking_open = FALSE;
295 g_value_set_boolean(&response, self->nonblocking_open);
296 device_set_simple_property(d_self, PROPERTY_NONBLOCKING_OPEN,
297 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
298 g_value_unset(&response);
300 self->final_filemarks = 2;
301 g_value_init(&response, G_TYPE_UINT);
302 g_value_set_uint(&response, self->final_filemarks);
303 device_set_simple_property(d_self, PROPERTY_FINAL_FILEMARKS,
304 &response, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
305 g_value_unset(&response);
307 self->private->read_block_size = 0;
308 g_value_init(&response, G_TYPE_UINT);
309 g_value_set_uint(&response, self->private->read_block_size);
310 device_set_simple_property(d_self, PROPERTY_READ_BLOCK_SIZE,
311 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DEFAULT);
312 g_value_unset(&response);
314 self->private->write_count = 0;
315 self->private->device_filename = NULL;
317 /* Static properites */
318 g_value_init(&response, CONCURRENCY_PARADIGM_TYPE);
319 g_value_set_enum(&response, CONCURRENCY_PARADIGM_EXCLUSIVE);
320 device_set_simple_property(d_self, PROPERTY_CONCURRENCY,
321 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
322 g_value_unset(&response);
324 g_value_init(&response, STREAMING_REQUIREMENT_TYPE);
325 g_value_set_enum(&response, STREAMING_REQUIREMENT_DESIRED);
326 device_set_simple_property(d_self, PROPERTY_STREAMING,
327 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
328 g_value_unset(&response);
330 g_value_init(&response, G_TYPE_BOOLEAN);
331 g_value_set_boolean(&response, TRUE);
332 device_set_simple_property(d_self, PROPERTY_APPENDABLE,
333 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
334 g_value_unset(&response);
336 g_value_init(&response, G_TYPE_BOOLEAN);
337 g_value_set_boolean(&response, FALSE);
338 device_set_simple_property(d_self, PROPERTY_PARTIAL_DELETION,
339 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
340 g_value_unset(&response);
342 g_value_init(&response, G_TYPE_BOOLEAN);
343 g_value_set_boolean(&response, FALSE);
344 device_set_simple_property(d_self, PROPERTY_FULL_DELETION,
345 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
346 g_value_unset(&response);
348 g_value_init(&response, MEDIA_ACCESS_MODE_TYPE);
349 g_value_set_enum(&response, MEDIA_ACCESS_MODE_READ_WRITE);
350 device_set_simple_property(d_self, PROPERTY_MEDIUM_ACCESS_TYPE,
351 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
352 g_value_unset(&response);
355 static void tape_device_finalize(GObject * obj_self) {
356 TapeDevice * self = TAPE_DEVICE(obj_self);
358 if(G_OBJECT_CLASS(parent_class)->finalize) \
359 (* G_OBJECT_CLASS(parent_class)->finalize)(obj_self);
361 robust_close(self->fd);
363 amfree(self->private->device_filename);
364 amfree(self->private);
368 tape_device_class_init (TapeDeviceClass * c)
370 DeviceClass *device_class = (DeviceClass *)c;
371 GObjectClass *g_object_class = (GObjectClass *)c;
373 parent_class = g_type_class_ref (TYPE_DEVICE);
375 device_class->open_device = tape_device_open_device;
376 device_class->read_label = tape_device_read_label;
377 device_class->write_block = tape_device_write_block;
378 device_class->read_block = tape_device_read_block;
379 device_class->start = tape_device_start;
380 device_class->start_file = tape_device_start_file;
381 device_class->finish_file = tape_device_finish_file;
382 device_class->seek_file = tape_device_seek_file;
383 device_class->seek_block = tape_device_seek_block;
384 device_class->eject = tape_device_eject;
385 device_class->finish = tape_device_finish;
387 g_object_class->finalize = tape_device_finalize;
391 tape_device_base_init (TapeDeviceClass * c)
393 DeviceClass *device_class = (DeviceClass *)c;
395 device_class_register_property(device_class, PROPERTY_BROKEN_GMT_ONLINE,
396 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
397 device_simple_property_get_fn,
398 tape_device_set_feature_property_fn);
400 device_class_register_property(device_class, PROPERTY_FSF,
401 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
402 device_simple_property_get_fn,
403 tape_device_set_feature_property_fn);
405 device_class_register_property(device_class, PROPERTY_FSF_AFTER_FILEMARK,
406 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
407 device_simple_property_get_fn,
408 tape_device_set_feature_property_fn);
410 device_class_register_property(device_class, PROPERTY_BSF,
411 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
412 device_simple_property_get_fn,
413 tape_device_set_feature_property_fn);
415 device_class_register_property(device_class, PROPERTY_FSR,
416 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
417 device_simple_property_get_fn,
418 tape_device_set_feature_property_fn);
420 device_class_register_property(device_class, PROPERTY_BSR,
421 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
422 device_simple_property_get_fn,
423 tape_device_set_feature_property_fn);
425 device_class_register_property(device_class, PROPERTY_EOM,
426 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
427 device_simple_property_get_fn,
428 tape_device_set_feature_property_fn);
430 device_class_register_property(device_class, PROPERTY_BSF_AFTER_EOM,
431 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
432 device_simple_property_get_fn,
433 tape_device_set_feature_property_fn);
435 device_class_register_property(device_class, PROPERTY_NONBLOCKING_OPEN,
436 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
437 device_simple_property_get_fn,
438 tape_device_set_feature_property_fn);
440 device_class_register_property(device_class, PROPERTY_FINAL_FILEMARKS,
441 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
442 device_simple_property_get_fn,
443 tape_device_set_final_filemarks_fn);
445 /* We don't (yet?) support reading the device's compression state, so not
447 device_class_register_property(device_class, PROPERTY_COMPRESSION,
448 PROPERTY_ACCESS_SET_MASK,
450 tape_device_set_compression_fn);
452 device_class_register_property(device_class, PROPERTY_READ_BLOCK_SIZE,
453 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
454 tape_device_get_read_block_size_fn,
455 tape_device_set_read_block_size_fn);
457 device_class_register_property(device_class, device_property_read_buffer_size.ID,
458 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
459 tape_device_get_read_block_size_fn,
460 tape_device_set_read_block_size_fn);
462 /* add the ability to set LEOM to FALSE, for testing purposes */
463 device_class_register_property(device_class, PROPERTY_LEOM,
464 PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_BEFORE_START,
465 device_simple_property_get_fn,
466 tape_device_set_feature_property_fn);
470 tape_device_set_feature_property_fn(Device *p_self, DevicePropertyBase *base,
471 GValue *val, PropertySurety surety, PropertySource source)
473 TapeDevice *self = TAPE_DEVICE(p_self);
475 gboolean old_bool, new_bool;
476 PropertySurety old_surety;
477 PropertySource old_source;
479 new_bool = g_value_get_boolean(val);
481 /* get the old source and surety and see if we're willing to make this change */
482 bzero(&old_val, sizeof(old_val));
483 if (device_get_simple_property(p_self, base->ID, &old_val, &old_surety, &old_source)) {
484 old_bool = g_value_get_boolean(&old_val);
486 if (old_surety == PROPERTY_SURETY_GOOD && old_source == PROPERTY_SOURCE_DETECTED) {
487 if (new_bool != old_bool) {
488 device_set_error(p_self, vstrallocf(_(
489 "Value for property '%s' was autodetected and cannot be changed"),
491 DEVICE_STATUS_DEVICE_ERROR);
494 /* pretend we set it, but don't change surety/source */
500 /* (note: PROPERTY_* are not constants, so we can't use switch) */
501 if (base->ID == PROPERTY_BROKEN_GMT_ONLINE)
502 self->broken_gmt_online = new_bool;
503 else if (base->ID == PROPERTY_FSF)
504 self->fsf = new_bool;
505 else if (base->ID == PROPERTY_FSF_AFTER_FILEMARK)
506 self->fsf_after_filemark = new_bool;
507 else if (base->ID == PROPERTY_BSF)
508 self->bsf = new_bool;
509 else if (base->ID == PROPERTY_FSR)
510 self->fsr = new_bool;
511 else if (base->ID == PROPERTY_BSR)
512 self->bsr = new_bool;
513 else if (base->ID == PROPERTY_EOM)
514 self->eom = new_bool;
515 else if (base->ID == PROPERTY_BSF_AFTER_EOM)
516 self->bsf_after_eom = new_bool;
517 else if (base->ID == PROPERTY_NONBLOCKING_OPEN)
518 self->nonblocking_open = new_bool;
519 else if (base->ID == PROPERTY_LEOM)
520 self->leom = new_bool;
522 return FALSE; /* shouldn't happen */
524 return device_simple_property_set_fn(p_self, base, val, surety, source);
528 tape_device_set_final_filemarks_fn(Device *p_self, DevicePropertyBase *base,
529 GValue *val, PropertySurety surety, PropertySource source)
531 TapeDevice *self = TAPE_DEVICE(p_self);
533 gboolean old_int, new_int;
534 PropertySurety old_surety;
535 PropertySource old_source;
537 new_int = g_value_get_uint(val);
539 /* get the old source and surety and see if we're willing to make this change */
540 bzero(&old_val, sizeof(old_val));
541 if (device_get_simple_property(p_self, base->ID, &old_val, &old_surety, &old_source)) {
542 old_int = g_value_get_uint(&old_val);
544 if (old_surety == PROPERTY_SURETY_GOOD && old_source == PROPERTY_SOURCE_DETECTED) {
545 if (new_int != old_int) {
546 device_set_error(p_self, vstrallocf(_(
547 "Value for property '%s' was autodetected and cannot be changed"),
549 DEVICE_STATUS_DEVICE_ERROR);
552 /* pretend we set it, but don't change surety/source */
558 self->final_filemarks = new_int;
560 return device_simple_property_set_fn(p_self, base, val, surety, source);
564 tape_device_set_compression_fn(Device *p_self, DevicePropertyBase *base,
565 GValue *val, PropertySurety surety, PropertySource source)
567 TapeDevice *self = TAPE_DEVICE(p_self);
568 gboolean request = g_value_get_boolean(val);
570 /* We allow this property to be set at any time. This is mostly
571 * because setting compression is a hit-and-miss proposition
572 * at any time; some drives accept the mode setting but don't
573 * actually support compression, while others do support
574 * compression but do it via density settings or some other
575 * way. Set this property whenever you want, but all we'll do
576 * is report whether or not the ioctl succeeded. */
577 if (tape_setcompression(self->fd, request)) {
578 /* looks good .. let's start the device over, though */
579 device_clear_volume_details(p_self);
581 device_set_error(p_self,
582 g_strdup("Error setting COMPRESION property"),
583 DEVICE_STATUS_DEVICE_ERROR);
587 return device_simple_property_set_fn(p_self, base, val, surety, source);
591 tape_device_get_read_block_size_fn(Device *p_self, DevicePropertyBase *base G_GNUC_UNUSED,
592 GValue *val, PropertySurety *surety, PropertySource *source)
594 /* use the READ_BLOCK_SIZE, even if we're invoked to get the old READ_BUFFER_SIZE */
595 return device_simple_property_get_fn(p_self, &device_property_read_block_size,
596 val, surety, source);
600 tape_device_set_read_block_size_fn(Device *p_self, DevicePropertyBase *base G_GNUC_UNUSED,
601 GValue *val, PropertySurety surety, PropertySource source)
603 TapeDevice *self = TAPE_DEVICE(p_self);
604 guint read_block_size = g_value_get_uint(val);
606 if (read_block_size != 0 &&
607 ((gsize)read_block_size < p_self->block_size ||
608 (gsize)read_block_size > p_self->max_block_size))
609 device_set_error(p_self,
610 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),
611 DEVICE_STATUS_DEVICE_ERROR);
614 self->private->read_block_size = read_block_size;
616 /* use the READ_BLOCK_SIZE, even if we're invoked to get the old READ_BUFFER_SIZE */
617 return device_simple_property_set_fn(p_self, &device_property_read_block_size,
618 val, surety, source);
621 void tape_device_register(void) {
622 static const char * device_prefix_list[] = { "tape", NULL };
624 /* First register tape-specific properties */
625 device_property_fill_and_register(&device_property_broken_gmt_online,
626 G_TYPE_BOOLEAN, "broken_gmt_online",
627 "Does this drive support the GMT_ONLINE macro?");
629 device_property_fill_and_register(&device_property_fsf,
630 G_TYPE_BOOLEAN, "fsf",
631 "Does this drive support the MTFSF command?");
633 device_property_fill_and_register(&device_property_fsf_after_filemark,
634 G_TYPE_BOOLEAN, "fsf_after_filemark",
635 "Does this drive needs a FSF if a filemark is already read?");
637 device_property_fill_and_register(&device_property_bsf,
638 G_TYPE_BOOLEAN, "bsf",
639 "Does this drive support the MTBSF command?" );
641 device_property_fill_and_register(&device_property_fsr,
642 G_TYPE_BOOLEAN, "fsr",
643 "Does this drive support the MTFSR command?");
645 device_property_fill_and_register(&device_property_bsr,
646 G_TYPE_BOOLEAN, "bsr",
647 "Does this drive support the MTBSR command?");
649 device_property_fill_and_register(&device_property_eom,
650 G_TYPE_BOOLEAN, "eom",
651 "Does this drive support the MTEOM command?");
653 device_property_fill_and_register(&device_property_bsf_after_eom,
656 "Does this drive require an MTBSF after MTEOM in order to append?" );
658 device_property_fill_and_register(&device_property_nonblocking_open,
661 "Does this drive require a open with O_NONBLOCK?" );
663 device_property_fill_and_register(&device_property_final_filemarks,
664 G_TYPE_UINT, "final_filemarks",
665 "How many filemarks to write after the last tape file?" );
667 device_property_fill_and_register(&device_property_read_buffer_size,
668 G_TYPE_UINT, "read_buffer_size",
669 "(deprecated name for READ_BLOCK_SIZE)");
671 /* Then the device itself */
672 register_device(tape_device_factory, device_prefix_list);
675 /* Open the tape device, trying various combinations of O_RDWR and
676 O_NONBLOCK. Returns -1 and calls device_set_error for errors
677 On Linux, with O_NONBLOCK, the kernel just checks the state once,
678 whereas it checks it every second for ST_BLOCK_SECONDS if O_NONBLOCK is
679 not given. Amanda already have the code to poll, we want open to check
680 the state only once. */
682 static int try_open_tape_device(TapeDevice * self, char * device_filename) {
685 DeviceStatusFlags new_status;
690 if (self->nonblocking_open) {
691 nonblocking = O_NONBLOCK;
696 fd = robust_open(device_filename, O_RDWR | nonblocking, 0);
698 if (fd < 0 && nonblocking && (save_errno == EWOULDBLOCK || save_errno == EINVAL)) {
699 /* Maybe we don't support O_NONBLOCK for tape devices. */
700 fd = robust_open(device_filename, O_RDWR, 0);
704 fd = robust_open(device_filename, O_RDWR, 0);
708 self->write_open_errno = 0;
710 if (errno == EACCES || errno == EPERM
715 /* Device is write-protected. */
716 self->write_open_errno = errno;
718 fd = robust_open(device_filename, O_RDONLY | nonblocking, 0);
720 if (fd < 0 && nonblocking && (save_errno == EWOULDBLOCK || save_errno == EINVAL)) {
721 fd = robust_open(device_filename, O_RDONLY, 0);
725 fd = robust_open(device_filename, O_RDONLY, 0);
731 /* Clear O_NONBLOCK for operations from now on. */
732 if (fd >= 0 && nonblocking)
733 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
735 /* function continues after #endif */
737 #endif /* O_NONBLOCK */
740 DeviceStatusFlags status_flag = 0;
742 status_flag = DEVICE_STATUS_DEVICE_BUSY;
744 status_flag = DEVICE_STATUS_DEVICE_ERROR;
745 device_set_error(DEVICE(self),
746 vstrallocf(_("Can't open tape device %s: %s"), self->private->device_filename, strerror(errno)),
751 /* Check that this is actually a tape device. */
752 new_status = tape_is_tape_device(fd);
753 if (new_status & DEVICE_STATUS_DEVICE_ERROR) {
754 device_set_error(DEVICE(self),
755 vstrallocf(_("File %s is not a tape device"), self->private->device_filename),
760 if (new_status & DEVICE_STATUS_VOLUME_MISSING) {
761 device_set_error(DEVICE(self),
762 vstrallocf(_("Tape device %s is not ready or is empty"), self->private->device_filename),
768 new_status = tape_is_ready(fd, self);
769 if (new_status & DEVICE_STATUS_VOLUME_MISSING) {
770 device_set_error(DEVICE(self),
771 vstrallocf(_("Tape device %s is empty"), self->private->device_filename),
776 if (new_status != DEVICE_STATUS_SUCCESS) {
777 device_set_error(DEVICE(self),
778 vstrallocf(_("Tape device %s is not ready or is empty"), self->private->device_filename),
788 tape_device_open_device (Device * dself, char * device_name,
789 char * device_type, char * device_node) {
793 self = TAPE_DEVICE(dself);
796 self->private->device_filename = stralloc(device_node);
798 /* Set tape drive/OS info */
799 bzero(&val, sizeof(val));
800 g_value_init(&val, G_TYPE_BOOLEAN);
803 g_value_set_boolean(&val, self->fsf);
804 device_set_simple_property(dself, PROPERTY_FSF, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
806 self->fsf_after_filemark = DEFAULT_FSF_AFTER_FILEMARK;
807 g_value_set_boolean(&val, self->fsf_after_filemark);
808 device_set_simple_property(dself, PROPERTY_FSF_AFTER_FILEMARK, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
811 g_value_set_boolean(&val, self->bsf);
812 device_set_simple_property(dself, PROPERTY_BSF, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
815 g_value_set_boolean(&val, self->fsr);
816 device_set_simple_property(dself, PROPERTY_FSR, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
819 g_value_set_boolean(&val, self->bsr);
820 device_set_simple_property(dself, PROPERTY_BSR, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
823 g_value_set_boolean(&val, self->eom);
824 device_set_simple_property(dself, PROPERTY_EOM, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
827 g_value_set_boolean(&val, self->leom);
828 device_set_simple_property(dself, PROPERTY_LEOM, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
830 self->bsf_after_eom = FALSE;
831 g_value_set_boolean(&val, self->bsf_after_eom);
832 device_set_simple_property(dself, PROPERTY_BSF_AFTER_EOM, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
835 g_value_init(&val, G_TYPE_UINT);
837 self->final_filemarks = 2;
838 g_value_set_uint(&val, self->final_filemarks);
839 device_set_simple_property(dself, PROPERTY_FINAL_FILEMARKS, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
844 if (parent_class->open_device) {
845 parent_class->open_device(dself, device_name, device_type, device_node);
850 static DeviceStatusFlags tape_device_read_label(Device * dself) {
852 char * header_buffer;
856 DeviceStatusFlags new_status;
859 self = TAPE_DEVICE(dself);
861 amfree(dself->volume_label);
862 amfree(dself->volume_time);
863 dumpfile_free(dself->volume_header);
864 dself->volume_header = NULL;
866 if (device_in_error(self)) return dself->status;
868 if (self->fd == -1) {
869 self->fd = try_open_tape_device(self, self->private->device_filename);
870 /* if the open failed, then try_open_tape_device already set the
871 * approppriate error status */
873 return dself->status;
877 if (!tape_rewind(self->fd)) {
878 device_set_error(dself,
879 vstrallocf(_("Error rewinding device %s to read label: %s"),
880 self->private->device_filename, strerror(errno)),
881 DEVICE_STATUS_DEVICE_ERROR
882 | DEVICE_STATUS_VOLUME_ERROR);
883 return dself->status;
886 buffer_len = tape_device_read_size(self);
887 header_buffer = malloc(buffer_len);
888 result = tape_device_robust_read(self, header_buffer, &buffer_len, &msg);
890 if (result != RESULT_SUCCESS) {
892 tape_rewind(self->fd);
896 msg = stralloc(_("no data"));
897 new_status = (DEVICE_STATUS_VOLUME_ERROR |
898 DEVICE_STATUS_VOLUME_UNLABELED);
899 header = dself->volume_header = g_new(dumpfile_t, 1);
903 case RESULT_SMALL_BUFFER:
904 msg = stralloc(_("block size too small"));
905 new_status = (DEVICE_STATUS_DEVICE_ERROR |
906 DEVICE_STATUS_VOLUME_ERROR);
907 header = dself->volume_header = g_new(dumpfile_t, 1);
909 header->type = F_WEIRD;
913 msg = stralloc(_("unknown error"));
915 new_status = (DEVICE_STATUS_DEVICE_ERROR |
916 DEVICE_STATUS_VOLUME_ERROR |
917 DEVICE_STATUS_VOLUME_UNLABELED);
920 device_set_error(dself,
921 g_strdup_printf(_("Error reading Amanda header: %s"),
922 msg? msg : _("unknown error")),
925 return dself->status;
928 dself->header_block_size = buffer_len;
929 header = dself->volume_header = g_new(dumpfile_t, 1);
932 parse_file_header(header_buffer, header, buffer_len);
933 amfree(header_buffer);
934 if (header->type != F_TAPESTART) {
935 device_set_error(dself,
936 stralloc(_("No tapestart header -- unlabeled device?")),
937 DEVICE_STATUS_VOLUME_UNLABELED);
938 return dself->status;
941 dself->volume_label = g_strdup(header->name);
942 dself->volume_time = g_strdup(header->datestamp);
943 /* dself->volume_header is already set */
945 device_set_error(dself, NULL, DEVICE_STATUS_SUCCESS);
947 return dself->status;
951 tape_device_write_block(Device * pself, guint size, gpointer data) {
953 char *replacement_buffer = NULL;
957 self = TAPE_DEVICE(pself);
959 g_assert(self->fd >= 0);
960 if (device_in_error(self)) return FALSE;
962 /* zero out to the end of a short block -- tape devices only write
964 if (size < pself->block_size) {
965 replacement_buffer = malloc(pself->block_size);
966 memcpy(replacement_buffer, data, size);
967 bzero(replacement_buffer+size, pself->block_size-size);
969 data = replacement_buffer;
970 size = pself->block_size;
973 result = tape_device_robust_write(self, data, size, &msg);
974 amfree(replacement_buffer);
980 case RESULT_NO_SPACE:
981 device_set_error(pself,
982 stralloc(_("No space left on device")),
983 DEVICE_STATUS_VOLUME_ERROR);
984 pself->is_eom = TRUE;
988 msg = stralloc(_("unknown error"));
990 device_set_error(pself,
991 g_strdup_printf(_("Error writing block: %s"), msg),
992 DEVICE_STATUS_DEVICE_ERROR);
998 g_mutex_lock(pself->device_mutex);
999 pself->bytes_written += size;
1000 g_mutex_unlock(pself->device_mutex);
1005 static int tape_device_read_block (Device * pself, gpointer buf,
1010 gssize read_block_size = tape_device_read_size(pself);
1013 self = TAPE_DEVICE(pself);
1015 g_assert(self->fd >= 0);
1016 if (device_in_error(self)) return -1;
1018 g_assert(read_block_size < INT_MAX); /* data type mismatch */
1019 if (buf == NULL || *size_req < (int)read_block_size) {
1020 /* Just a size query. */
1021 *size_req = (int)read_block_size;
1026 result = tape_device_robust_read(self, buf, &size, &msg);
1028 case RESULT_SUCCESS:
1031 g_mutex_lock(pself->device_mutex);
1032 pself->bytes_read += size;
1033 g_mutex_unlock(pself->device_mutex);
1035 case RESULT_SMALL_BUFFER: {
1039 /* If this happens, it means that we have:
1040 * (next block size) > (buffer size) >= (read_block_size)
1041 * The solution is to ask for an even bigger buffer. We also play
1042 * some games to refrain from reading above the SCSI limit or from
1043 * integer overflow. Note that not all devices will tell us about
1044 * this problem -- some will just discard the "extra" data. */
1045 new_size = MIN(INT_MAX/2 - 1, *size_req) * 2;
1046 if (new_size > LARGEST_BLOCK_ESTIMATE &&
1047 *size_req < LARGEST_BLOCK_ESTIMATE) {
1048 new_size = LARGEST_BLOCK_ESTIMATE;
1050 g_assert (new_size > (gsize)*size_req);
1052 g_info("Device %s indicated blocksize %zd was too small; using %zd.",
1053 pself->device_name, (gsize)*size_req, new_size);
1054 *size_req = (int)new_size;
1055 self->private->read_block_size = new_size;
1057 bzero(&newval, sizeof(newval));
1058 g_value_init(&newval, G_TYPE_UINT);
1059 g_value_set_uint(&newval, self->private->read_block_size);
1060 device_set_simple_property(pself, PROPERTY_READ_BLOCK_SIZE,
1061 &newval, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
1062 g_value_unset(&newval);
1066 case RESULT_NO_DATA:
1067 pself->is_eof = TRUE;
1068 g_mutex_lock(pself->device_mutex);
1069 pself->in_file = FALSE;
1070 g_mutex_unlock(pself->device_mutex);
1071 device_set_error(pself,
1073 DEVICE_STATUS_SUCCESS);
1077 msg = stralloc(_("unknown error"));
1079 device_set_error(pself,
1080 vstrallocf(_("Error reading from tape device: %s"), msg),
1081 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1086 g_assert_not_reached();
1089 /* Just a helper function for tape_device_start(). */
1090 static gboolean write_tapestart_header(TapeDevice * self, char * label,
1093 dumpfile_t * header;
1095 Device * d_self = (Device*)self;
1098 tape_rewind(self->fd);
1100 header = make_tapestart_header(d_self, label, timestamp);
1101 g_assert(header != NULL);
1102 header_buf = device_build_amanda_header(d_self, header, NULL);
1103 if (header_buf == NULL) {
1104 device_set_error(d_self,
1105 stralloc(_("Tapestart header won't fit in a single block!")),
1106 DEVICE_STATUS_DEVICE_ERROR);
1107 dumpfile_free(header);
1110 dumpfile_free(d_self->volume_header);
1111 d_self->volume_header = NULL;
1113 result = tape_device_robust_write(self, header_buf, d_self->block_size, &msg);
1114 if (result != RESULT_SUCCESS) {
1115 device_set_error(d_self,
1116 g_strdup_printf(_("Error writing tapestart header: %s"),
1117 (result == RESULT_ERROR)? msg : _("out of space")),
1118 DEVICE_STATUS_DEVICE_ERROR);
1120 if (result == RESULT_NO_SPACE)
1121 d_self->is_eom = TRUE;
1124 dumpfile_free(header);
1129 d_self->header_block_size = d_self->block_size;
1132 if (!tape_weof(self->fd, 1)) {
1133 device_set_error(d_self,
1134 vstrallocf(_("Error writing filemark: %s"),
1136 DEVICE_STATUS_DEVICE_ERROR|DEVICE_STATUS_VOLUME_ERROR);
1137 /* can't tell if this was EOM or not, so assume it is */
1138 d_self->is_eom = TRUE;
1139 dumpfile_free(header);
1143 d_self->volume_header = header;
1148 tape_device_start (Device * d_self, DeviceAccessMode mode, char * label,
1152 self = TAPE_DEVICE(d_self);
1154 if (device_in_error(self)) return FALSE;
1156 if (self->fd == -1) {
1157 self->fd = try_open_tape_device(self, self->private->device_filename);
1158 /* if the open failed, then try_open_tape_device already set the
1159 * approppriate error status */
1164 if (mode != ACCESS_WRITE && d_self->volume_label == NULL) {
1165 /* we need a labeled volume for APPEND and READ */
1166 if (tape_device_read_label(d_self) != DEVICE_STATUS_SUCCESS)
1170 d_self->access_mode = mode;
1171 g_mutex_lock(d_self->device_mutex);
1172 d_self->in_file = FALSE;
1173 g_mutex_unlock(d_self->device_mutex);
1175 if (IS_WRITABLE_ACCESS_MODE(mode)) {
1176 if (self->write_open_errno != 0) {
1177 /* We tried and failed to open the device in write mode. */
1178 device_set_error(d_self,
1179 vstrallocf(_("Can't open tape device %s for writing: %s"),
1180 self->private->device_filename, strerror(self->write_open_errno)),
1181 DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
1183 } else if (!tape_rewind(self->fd)) {
1184 device_set_error(d_self,
1185 vstrallocf(_("Error rewinding device to start: %s"), strerror(errno)),
1186 DEVICE_STATUS_DEVICE_ERROR);
1191 /* Position the tape */
1194 if (d_self->volume_label == NULL && device_read_label(d_self) != DEVICE_STATUS_SUCCESS) {
1195 /* device_read_label already set our error message */
1199 if (!tape_device_eod(self)) {
1200 device_set_error(d_self,
1201 vstrallocf(_("Couldn't seek to end of tape: %s"), strerror(errno)),
1202 DEVICE_STATUS_DEVICE_ERROR);
1208 if (d_self->volume_label == NULL && device_read_label(d_self) != DEVICE_STATUS_SUCCESS) {
1209 /* device_read_label already set our error message */
1213 if (!tape_rewind(self->fd)) {
1214 device_set_error(d_self,
1215 vstrallocf(_("Error rewinding device after reading label: %s"), strerror(errno)),
1216 DEVICE_STATUS_DEVICE_ERROR);
1223 if (!write_tapestart_header(self, label, timestamp)) {
1224 /* write_tapestart_header already set the error status */
1228 d_self->volume_label = newstralloc(d_self->volume_label, label);
1229 d_self->volume_time = newstralloc(d_self->volume_time, timestamp);
1231 /* unset the VOLUME_UNLABELED flag, if it was set */
1232 device_set_error(d_self, NULL, DEVICE_STATUS_SUCCESS);
1237 g_assert_not_reached();
1243 static gboolean tape_device_start_file(Device * d_self,
1244 dumpfile_t * info) {
1247 char * amanda_header;
1250 self = TAPE_DEVICE(d_self);
1252 g_assert(self->fd >= 0);
1253 if (device_in_error(self)) return FALSE;
1255 /* set the blocksize in the header properly */
1256 info->blocksize = d_self->block_size;
1258 /* Make the Amanda header suitable for writing to the device. */
1259 /* Then write the damn thing. */
1260 amanda_header = device_build_amanda_header(d_self, info, NULL);
1261 if (amanda_header == NULL) {
1262 device_set_error(d_self,
1263 stralloc(_("Amanda file header won't fit in a single block!")),
1264 DEVICE_STATUS_DEVICE_ERROR);
1268 result = tape_device_robust_write(self, amanda_header, d_self->block_size, &msg);
1269 if (result != RESULT_SUCCESS) {
1270 device_set_error(d_self,
1271 vstrallocf(_("Error writing file header: %s"),
1272 (result == RESULT_ERROR)? msg : _("out of space")),
1273 DEVICE_STATUS_DEVICE_ERROR);
1275 if (result == RESULT_NO_SPACE)
1276 d_self->is_eom = TRUE;
1278 amfree(amanda_header);
1282 amfree(amanda_header);
1284 /* arrange the file numbers correctly */
1286 if (d_self->file >= 0)
1288 g_mutex_lock(d_self->device_mutex);
1289 d_self->in_file = TRUE;
1290 d_self->bytes_written = 0;
1291 g_mutex_unlock(d_self->device_mutex);
1296 tape_device_finish_file (Device * d_self) {
1299 self = TAPE_DEVICE(d_self);
1300 if (device_in_error(d_self)) return FALSE;
1302 if (!tape_weof(self->fd, 1)) {
1303 device_set_error(d_self,
1304 vstrallocf(_("Error writing filemark: %s"), strerror(errno)),
1305 DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
1306 /* can't tell if this was EOM or not, so assume it is */
1307 d_self->is_eom = TRUE;
1311 g_mutex_lock(d_self->device_mutex);
1312 d_self->in_file = FALSE;
1313 g_mutex_unlock(d_self->device_mutex);
1318 tape_device_seek_file (Device * d_self, guint file) {
1322 char * header_buffer;
1328 self = TAPE_DEVICE(d_self);
1330 if (device_in_error(self)) return NULL;
1332 difference = file - d_self->file;
1334 /* Check if we already read a filemark. */
1335 /* If we already read a filemark and the drive automaticaly goes to the
1336 next file, then we must reduce the difference by one. */
1337 if (d_self->is_eof && !self->fsf_after_filemark) {
1341 d_self->is_eof = FALSE;
1343 g_mutex_lock(d_self->device_mutex);
1344 d_self->in_file = FALSE;
1345 d_self->bytes_read = 0;
1346 g_mutex_unlock(d_self->device_mutex);
1349 if (difference > 0) {
1350 /* Seeking forwards */
1351 if (!tape_device_fsf(self, difference)) {
1352 tape_rewind(self->fd);
1353 device_set_error(d_self,
1354 vstrallocf(_("Could not seek forward to file %d"), file),
1355 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1358 } else { /* (difference <= 0) */
1359 /* Seeking backwards, or to this file itself */
1361 /* if the drive supports bsf, we can do this the fancy way */
1363 /* bsf one more than the difference */
1364 if (!tape_bsf(self->fd, -difference + 1)) {
1365 tape_rewind(self->fd);
1366 device_set_error(d_self,
1367 vstrallocf(_("Could not seek backward to file %d"), file),
1368 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1372 /* now we are on the BOT side of the desired filemark, so FSF to get to the
1374 if (!tape_device_fsf(self, 1)) {
1375 tape_rewind(self->fd);
1376 device_set_error(d_self,
1377 vstrallocf(_("Could not seek forward to file %d"), file),
1378 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1382 /* no BSF, so just rewind and seek forward */
1383 if (!tape_rewind(self->fd)) {
1384 device_set_error(d_self,
1385 vstrallocf(_("Could not rewind device while emulating BSF")),
1386 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1390 if (!tape_device_fsf(self, file)) {
1391 tape_rewind(self->fd);
1392 device_set_error(d_self,
1393 vstrallocf(_("Could not seek forward to file %d"), file),
1394 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1400 /* double-check that we're on the right fileno, if possible. This is most
1401 * likely a programming error if it occurs, but could also be due to a weird
1402 * tape drive or driver (and that would *never* happen, right?) */
1403 got_file = tape_fileno(self->fd);
1404 if (got_file >= 0 && (guint)got_file != file) {
1405 device_set_error(d_self,
1406 vstrallocf(_("Could not seek to file %d correctly; got %d"),
1408 DEVICE_STATUS_DEVICE_ERROR);
1409 d_self->file = (guint)got_file;
1413 buffer_len = tape_device_read_size(d_self);
1414 header_buffer = malloc(buffer_len);
1415 d_self->is_eof = FALSE;
1416 result = tape_device_robust_read(self, header_buffer, &buffer_len, &msg);
1418 if (result != RESULT_SUCCESS) {
1419 free(header_buffer);
1420 tape_rewind(self->fd);
1422 case RESULT_NO_DATA:
1423 /* If we read 0 bytes, that means we encountered a double
1424 * filemark, which indicates end of tape. This should
1425 * work even with QIC tapes on operating systems with
1426 * proper support. */
1427 d_self->file = file; /* other attributes are already correct */
1428 return make_tapeend_header();
1430 case RESULT_SMALL_BUFFER:
1431 msg = stralloc(_("block size too small"));
1435 msg = stralloc(_("unknown error"));
1439 device_set_error(d_self,
1440 g_strdup_printf(_("Error reading Amanda header: %s"), msg),
1441 DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
1446 rval = g_new(dumpfile_t, 1);
1447 parse_file_header(header_buffer, rval, buffer_len);
1448 amfree(header_buffer);
1449 switch (rval->type) {
1451 case F_CONT_DUMPFILE:
1452 case F_SPLIT_DUMPFILE:
1456 /* a NOOP is written on QIC tapes to avoid writing two sequential
1457 * filemarks when closing a device in WRITE or APPEND mode. In this
1458 * case, we just seek to the next file. */
1465 tape_rewind(self->fd);
1466 device_set_error(d_self,
1467 stralloc(_("Invalid amanda header while reading file header")),
1468 DEVICE_STATUS_VOLUME_ERROR);
1473 g_mutex_lock(d_self->device_mutex);
1474 d_self->in_file = TRUE;
1475 g_mutex_unlock(d_self->device_mutex);
1476 d_self->file = file;
1482 tape_device_seek_block (Device * d_self, guint64 block) {
1486 self = TAPE_DEVICE(d_self);
1488 if (device_in_error(self)) return FALSE;
1490 difference = block - d_self->block;
1492 if (difference > 0) {
1493 if (!tape_device_fsr(self, difference)) {
1494 device_set_error(d_self,
1495 vstrallocf(_("Could not seek forward to block %ju: %s"), (uintmax_t)block, strerror(errno)),
1496 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1499 } else if (difference < 0) {
1500 if (!tape_device_bsr(self, difference, d_self->file, d_self->block)) {
1501 device_set_error(d_self,
1502 vstrallocf(_("Could not seek backward to block %ju: %s"), (uintmax_t)block, strerror(errno)),
1503 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1508 d_self->block = block;
1513 tape_device_eject (Device * d_self) {
1516 self = TAPE_DEVICE(d_self);
1518 if (device_in_error(self)) return FALSE;
1520 /* Open the device if not already opened */
1521 if (self->fd == -1) {
1522 self->fd = try_open_tape_device(self, self->private->device_filename);
1523 /* if the open failed, then try_open_tape_device already set the
1524 * approppriate error status */
1530 if (!tape_rewind(self->fd)) {
1531 device_set_error(d_self,
1532 vstrallocf(_("Error rewinding device %s before ejecting: %s"),
1533 self->private->device_filename, strerror(errno)),
1534 DEVICE_STATUS_DEVICE_ERROR
1535 | DEVICE_STATUS_VOLUME_ERROR);
1539 if (tape_offl(self->fd))
1542 device_set_error(d_self,
1543 vstrallocf(_("Error ejecting device %s: %s\n"),
1544 self->private->device_filename, strerror(errno)),
1545 DEVICE_STATUS_DEVICE_ERROR);
1551 tape_device_finish (Device * d_self) {
1555 self = TAPE_DEVICE(d_self);
1557 if (device_in_error(self))
1560 /* if we're already in ACCESS_NULL, then there are no filemarks or anything
1561 * to worry about, but we need to release the kernel device */
1562 if (d_self->access_mode == ACCESS_NULL) {
1563 robust_close(self->fd);
1568 /* Polish off this file, if relevant. */
1569 g_mutex_lock(d_self->device_mutex);
1570 if (d_self->in_file && IS_WRITABLE_ACCESS_MODE(d_self->access_mode)) {
1571 g_mutex_unlock(d_self->device_mutex);
1572 if (!device_finish_file(d_self)) {
1576 g_mutex_unlock(d_self->device_mutex);
1579 /* Straighten out the filemarks. We already wrote one in finish_file, and
1580 * the device driver will write another filemark when we rewind. This means
1581 * that, if we do nothing, we'll get two filemarks. If final_filemarks is
1582 * 1, this would be wrong, so in this case we insert a F_NOOP header between
1583 * the two filemarks. */
1584 if (self->final_filemarks == 1 &&
1585 IS_WRITABLE_ACCESS_MODE(d_self->access_mode)) {
1590 /* write a F_NOOP header */
1593 header = device_build_amanda_header(d_self, &file, NULL);
1595 device_set_error(d_self,
1596 stralloc(_("Amanda file header won't fit in a single block!")),
1597 DEVICE_STATUS_DEVICE_ERROR);
1601 result = tape_device_robust_write(self, header, d_self->block_size, &msg);
1602 if (result != RESULT_SUCCESS) {
1603 device_set_error(d_self,
1604 vstrallocf(_("Error writing file header: %s"),
1605 (result == RESULT_ERROR)? msg : _("out of space")),
1606 DEVICE_STATUS_DEVICE_ERROR);
1614 /* Rewind (the kernel will write a filemark first) */
1615 if (!tape_rewind(self->fd)) {
1616 device_set_error(d_self,
1617 vstrallocf(_("Couldn't rewind device to finish: %s"), strerror(errno)),
1618 DEVICE_STATUS_DEVICE_ERROR);
1622 d_self->is_eof = FALSE;
1623 d_self->access_mode = ACCESS_NULL;
1625 /* release the kernel's device */
1626 robust_close(self->fd);
1632 d_self->access_mode = ACCESS_NULL;
1634 /* release the kernel's device */
1635 robust_close(self->fd);
1641 /* Works just like read(), except for the following:
1642 * 1) Retries on EINTR & friends.
1643 * 2) Stores count in parameter, not return value.
1644 * 3) Provides explicit return result.
1645 * *errmsg is only set on RESULT_ERROR.
1648 tape_device_robust_read (TapeDevice * self, void * buf, int * count, char **errmsg) {
1652 d_self = (Device*)self;
1654 /* Callers should ensure this. */
1655 g_assert(*count >= 0);
1658 result = read(self->fd, buf, *count);
1660 /* Success. By definition, we read a full block. */
1661 d_self->is_eof = FALSE;
1663 return RESULT_SUCCESS;
1664 } else if (result == 0) {
1665 d_self->is_eof = TRUE;
1666 return RESULT_NO_DATA;
1673 || errno == EWOULDBLOCK
1679 /* Interrupted system call */
1683 || errno == ENOMEM /* bad user-space buffer */
1686 || errno == EOVERFLOW /* bad kernel-space buffer */
1689 || errno == EINVAL /* ??? */
1692 /* Buffer too small. */
1693 g_warning("Buffer is too small (%d bytes) from %s: %s",
1694 *count, self->private->device_filename, strerror(errno));
1695 return RESULT_SMALL_BUFFER;
1697 *errmsg = g_strdup_printf(_("Error reading %d bytes from %s: %s"),
1698 *count, self->private->device_filename, strerror(errno));
1699 return RESULT_ERROR;
1704 g_assert_not_reached();
1707 /* Kernel workaround: If needed, poke the kernel so it doesn't fail.
1708 at the 2GB boundry. Parameters are G_GNUC_UNUSED in case NEED_RESETOFS
1710 static void check_resetofs(TapeDevice * self G_GNUC_UNUSED,
1711 int count G_GNUC_UNUSED) {
1712 #ifdef NEED_RESETOFS
1716 d_self = (Device*)self;
1718 self->private->write_count += count;
1719 if (self->private->write_count < RESETOFS_THRESHOLD) {
1723 result = lseek(self->fd, 0, SEEK_SET);
1725 g_warning(_("lseek() failed during kernel 2GB workaround: %s"),
1731 /* *errmsg is only set on RESULT_ERROR */
1733 tape_device_robust_write (TapeDevice * self, void * buf, int count, char **errmsg) {
1736 gboolean retry = FALSE;
1738 d_self = (Device*)self;
1740 check_resetofs(self, count);
1743 result = write(self->fd, buf, count);
1746 if (result == count)
1747 return RESULT_SUCCESS;
1750 /* write() returned a short count. This should not happen if the block sizes
1751 * are properly aligned. */
1752 *errmsg = g_strdup_printf("Short write on tape device: Tried %d, got %d. Is "
1753 "the drive using a block size smaller than %d bytes?",
1754 count, result, count);
1755 return RESULT_ERROR;
1758 /* Detect LEOM (early warning) and handle properly
1760 * FreeBSD: 0-length write; next write will succeed
1761 * http://lists.freebsd.org/pipermail/freebsd-scsi/2010-June/004414.html
1763 * Solaris: 0-length write; next write will succeed
1764 * (from Matthew Jacob on FreeBSD thread)
1766 * Linux: -1/ENOSPC; next write will succeed
1767 * http://www.mjmwired.net/kernel/Documentation/scsi/st.txt
1769 * HP/UX: -1/ENOSPC; next write will succeed
1770 * http://www.adssasia.com/Manual/IBM%203581%20tape%20autoloader.pdf
1774 || (result < 0 && errno == ENOSPC)
1777 /* if we've retried once already, then we're probably really out of space */
1779 return RESULT_NO_SPACE;
1781 d_self->is_eom = TRUE;
1783 g_debug("empty write to tape; treating as LEOM early warning and retrying");
1787 /* at this point result < 0, so an error occurred - sort out what */
1794 || errno == EWOULDBLOCK
1800 /* Interrupted system call */
1810 /* Probably EOT. Print a message if we got EIO. */
1813 g_warning(_("Got EIO on %s, assuming end of tape"),
1814 self->private->device_filename);
1817 return RESULT_NO_SPACE;
1820 *errmsg = vstrallocf(_("Kernel gave unexpected write() result of \"%s\" on device %s"),
1821 strerror(errno), self->private->device_filename);
1822 return RESULT_ERROR;
1826 g_assert_not_reached();
1829 /* Reads some number of tape blocks into the bit-bucket. If the count
1830 is negative, then we read the rest of the entire file. Returns the
1831 number of blocks read, or -1 if an error occured. If we encounter
1832 EOF (as opposed to some other error) we return the number of blocks
1834 static int drain_tape_blocks(TapeDevice * self, int count) {
1839 buffer_size = tape_device_read_size(self);
1841 buffer = malloc(buffer_size);
1843 for (i = 0; i < count || count < 0;) {
1846 result = read(self->fd, buffer, buffer_size);
1850 } else if (result == 0) {
1854 /* First check for interrupted system call. */
1860 || errno == EWOULDBLOCK
1866 /* Interrupted system call */
1870 || errno == ENOSPC /* bad user-space buffer */
1873 || errno == EOVERFLOW /* bad kernel-space buffer */
1876 || errno == EINVAL /* ??? */
1879 /* The buffer may not be big enough. But the OS is not
1880 100% clear. We double the buffer and try again, but
1881 in no case allow a buffer bigger than 32 MB. */
1884 if (buffer_size > 32*1024*1024) {
1888 buffer = realloc(buffer, buffer_size);
1900 tape_device_fsf (TapeDevice * self, guint count) {
1902 return tape_fsf(self->fd, count);
1905 for (i = 0; i < count; i ++) {
1906 if (drain_tape_blocks(self, -1) < 0)
1915 tape_device_fsr (TapeDevice * self, guint count) {
1917 return tape_fsr(self->fd, count);
1919 int result = drain_tape_blocks(self, count);
1920 return result > 0 && (int)count == result;
1924 /* Seek back the given number of blocks to block number block within
1925 * the current file, numbered file. */
1928 tape_device_bsr (TapeDevice * self, guint count, guint file, guint block) {
1930 return tape_bsr(self->fd, count);
1931 } else if (self->bsf && self->fsf) {
1932 /* BSF, FSF to the right side of the filemark, and then FSR. */
1933 if (!tape_bsf(self->fd, 1))
1936 if (!tape_fsf(self->fd, 1))
1939 return tape_device_fsr(self, block);
1941 /* rewind, FSF, and FSR */
1942 if (!tape_rewind(self->fd))
1945 if (!tape_device_fsf(self, file))
1948 return tape_device_fsr(self, block);
1950 g_assert_not_reached();
1953 /* Go to the right place to write more data, and update the file
1954 number if possible. */
1956 tape_device_eod (TapeDevice * self) {
1960 d_self = (Device*)self;
1964 result = tape_eod(self->fd);
1965 if (result == TAPE_OP_ERROR) {
1967 } else if (result != TAPE_POSITION_UNKNOWN) {
1968 /* great - we just fast-forwarded to EOD, but don't know where we are, so
1969 * now we have to rewind and drain all of that data. Warn the user so that
1970 * we can skip the fast-forward-rewind stage on the next run */
1971 g_warning("Seek to end of tape does not give an accurate tape position; set "
1972 "the EOM property to 0 to avoid useless tape movement.");
1973 /* and set the property so that next time *this* object is opened for
1974 * append, we skip this stage */
1976 /* fall through to draining blocks, below */
1978 /* We drop by 1 because Device will increment the first
1979 time the user does start_file. */
1980 d_self->file = result - 1;
1985 if (!tape_rewind(self->fd))
1990 /* We alternately read a block and FSF. If the read is
1991 successful, then we are not there yet and should FSF
1994 result = drain_tape_blocks(self, 1);
1996 /* More data, FSF. */
1997 tape_device_fsf(self, 1);
1999 } else if (result == 0) {
2001 d_self->file = count - 1;
2010 tape_device_factory (char * device_name, char * device_type, char * device_node) {
2012 g_assert(0 == strcmp(device_type, "tape"));
2013 rval = DEVICE(g_object_new(TYPE_TAPE_DEVICE, NULL));
2014 device_open_device(rval, device_name, device_type, device_node);
2019 * Tape Operations using the POSIX interface
2022 /* Having one name for every operation would be too easy. */
2023 #if !defined(MTCOMPRESSION) && defined(MTCOMP)
2024 # define MTCOMPRESSION MTCOMP
2027 #if !defined(MTSETBLK) && defined(MTSETBSIZ)
2028 # define MTSETBLK MTSETBSIZ
2031 #if !defined(MTEOM) && defined(MTEOD)
2032 # define MTEOM MTEOD
2035 gboolean tape_rewind(int fd) {
2039 /* We will retry this for up to 30 seconds or 5 retries,
2040 whichever is less, because some hardware/software combinations
2041 (notably EXB-8200 on FreeBSD) can fail to rewind. */
2042 stop_time = time(NULL) + 30;
2044 while (--count >= 0 && time(NULL) < stop_time) {
2049 if (0 == ioctl(fd, MTIOCTOP, &mt))
2058 gboolean tape_fsf(int fd, guint count) {
2061 mt.mt_count = count;
2062 return 0 == ioctl(fd, MTIOCTOP, &mt);
2065 gboolean tape_bsf(int fd, guint count) {
2068 mt.mt_count = count;
2069 return 0 == ioctl(fd, MTIOCTOP, &mt);
2072 gboolean tape_fsr(int fd, guint count) {
2075 mt.mt_count = count;
2076 return 0 == ioctl(fd, MTIOCTOP, &mt);
2079 gboolean tape_bsr(int fd, guint count) {
2082 mt.mt_count = count;
2083 return 0 == ioctl(fd, MTIOCTOP, &mt);
2086 gint tape_fileno(int fd) {
2089 if (0 != ioctl(fd, MTIOCGET, &get))
2090 return TAPE_POSITION_UNKNOWN;
2091 if (get.mt_fileno < 0)
2092 return TAPE_POSITION_UNKNOWN;
2094 return get.mt_fileno;
2097 gint tape_eod(int fd) {
2102 if (0 != ioctl(fd, MTIOCTOP, &mt))
2103 return TAPE_OP_ERROR;
2105 /* Ignored result. This is just to flush buffers. */
2107 ioctl(fd, MTIOCTOP, &mt);
2109 if (0 != ioctl(fd, MTIOCGET, &get))
2110 return TAPE_POSITION_UNKNOWN;
2111 if (get.mt_fileno < 0)
2112 return TAPE_POSITION_UNKNOWN;
2114 return get.mt_fileno;
2117 gboolean tape_weof(int fd, guint8 count) {
2120 mt.mt_count = count;
2121 return 0 == ioctl(fd, MTIOCTOP, &mt);
2124 gboolean tape_setcompression(int fd G_GNUC_UNUSED,
2125 gboolean on G_GNUC_UNUSED) {
2126 #ifdef MTCOMPRESSION
2128 mt.mt_op = MTCOMPRESSION;
2130 return 0 == ioctl(fd, MTIOCTOP, &mt);
2136 gboolean tape_offl(int fd) {
2142 if (0 == ioctl(fd, MTIOCTOP, &mt))
2146 g_debug("tape_off: ioctl(MTIOCTOP/MTOFFL) failed: %s", strerror(errno));
2152 DeviceStatusFlags tape_is_tape_device(int fd) {
2156 if (0 == ioctl(fd, MTIOCTOP, &mt)) {
2157 return DEVICE_STATUS_SUCCESS;
2159 } else if (errno == ENOMEDIUM) {
2160 return DEVICE_STATUS_VOLUME_MISSING;
2163 g_debug("tape_is_tape_device: ioctl(MTIOCTOP/MTNOP) failed: %s",
2166 /* some devices return EIO while the drive is busy loading */
2167 return DEVICE_STATUS_DEVICE_ERROR|DEVICE_STATUS_DEVICE_BUSY;
2169 return DEVICE_STATUS_DEVICE_ERROR;
2174 DeviceStatusFlags tape_is_ready(int fd, TapeDevice *t_self G_GNUC_UNUSED) {
2176 if (0 == ioctl(fd, MTIOCGET, &get)) {
2177 #if defined(GMT_ONLINE) || defined(GMT_DR_OPEN)
2180 && (t_self->broken_gmt_online || GMT_ONLINE(get.mt_gstat))
2183 && !GMT_DR_OPEN(get.mt_gstat)
2186 return DEVICE_STATUS_SUCCESS;
2188 return DEVICE_STATUS_VOLUME_MISSING;
2190 #else /* Neither macro is defined. */
2191 return DEVICE_STATUS_SUCCESS;
2194 return DEVICE_STATUS_VOLUME_ERROR;