ba8f7689f27a91d9a4684cb242c659a8de13279b
[debian/amanda] / device-src / tape-device.c
1 /*
2  * Copyright (c) 2007, 2008, 2009, 2010 Zmanda, Inc.  All Rights Reserved.
3  *
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.
7  *
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
11  * for more details.
12  *
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
16  *
17  * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
18  * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
19  */
20
21 #include "amanda.h"
22 #include "pipespawn.h"
23 #include <string.h> /* memset() */
24 #include "util.h"
25 #include "tape-device.h"
26 #include "tape-ops.h"
27
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)
31
32 /* Largest possible block size on SCSI systems. */
33 #define LARGEST_BLOCK_ESTIMATE (16 * 1024 * 1024)
34
35 struct TapeDevicePrivate_s {
36     /* This holds the total number of bytes written to the device,
37        modulus RESETOFS_THRESHOLD. */
38     int write_count;
39     char * device_filename;
40     gsize read_block_size;
41 };
42
43 /* Possible (abstracted) results from a system I/O operation. */
44 typedef enum {
45     RESULT_SUCCESS,
46     RESULT_ERROR,        /* Undefined error (*errmsg set) */
47     RESULT_SMALL_BUFFER, /* Tried to read with a buffer that is too
48                             small. */
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. */
53     RESULT_MAX
54 } IoResult;
55
56 /*
57  * Our device-specific properties.  These are not static because they are
58  * accessed from the OS-specific tape-*.c files.
59  */
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 */
71
72 void tape_device_register(void);
73
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)
77
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,
97                                        int * size_req);
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);
113
114 /* pointer to the class of our parent */
115 static DeviceClass *parent_class = NULL;
116
117 GType tape_device_get_type (void)
118 {
119     static GType type = 0;
120
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 */,
129             sizeof (TapeDevice),
130             0 /* n_preallocs */,
131             (GInstanceInitFunc) tape_device_init,
132             NULL
133         };
134
135         type = g_type_register_static (TYPE_DEVICE, "TapeDevice",
136                                        &info, (GTypeFlags)0);
137     }
138
139     return type;
140 }
141
142 static void
143 tape_device_init (TapeDevice * self) {
144     Device * d_self;
145     GValue response;
146
147     d_self = DEVICE(self);
148     bzero(&response, sizeof(response));
149
150     self->private = g_new0(TapeDevicePrivate, 1);
151
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;
157
158     self->fd = -1;
159
160     /* set all of the feature properties to an unsure default of FALSE */
161     self->broken_gmt_online = FALSE;
162     self->fsf = FALSE;
163     self->bsf = FALSE;
164     self->fsr = FALSE;
165     self->bsr = FALSE;
166     self->eom = FALSE;
167     self->bsf_after_eom = FALSE;
168
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);
187
188 #ifdef DEFAULT_TAPE_NON_BLOCKING_OPEN
189     self->nonblocking_open = TRUE;
190 #else
191     self->nonblocking_open = FALSE;
192 #endif
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);
197
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);
204
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);
211
212     self->private->write_count = 0;
213     self->private->device_filename = NULL;
214
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);
221
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);
227
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);
233
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);
239
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);
245
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);
251 }
252
253 static void tape_device_finalize(GObject * obj_self) {
254     TapeDevice * self = TAPE_DEVICE(obj_self);
255
256     if(G_OBJECT_CLASS(parent_class)->finalize) \
257            (* G_OBJECT_CLASS(parent_class)->finalize)(obj_self);
258
259     robust_close(self->fd);
260     self->fd = -1;
261     amfree(self->private->device_filename);
262     amfree(self->private);
263 }
264
265 static void
266 tape_device_class_init (TapeDeviceClass * c)
267 {
268     DeviceClass *device_class = (DeviceClass *)c;
269     GObjectClass *g_object_class = (GObjectClass *)c;
270
271     parent_class = g_type_class_ref (TYPE_DEVICE);
272
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;
284
285     g_object_class->finalize = tape_device_finalize;
286 }
287
288 static void
289 tape_device_base_init (TapeDeviceClass * c)
290 {
291     DeviceClass *device_class = (DeviceClass *)c;
292
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);
297
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);
302
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);
307
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);
312
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);
317
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);
322
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);
327
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);
332
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);
337
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);
342
343     /* We don't (yet?) support reading the device's compression state, so not
344      * gettable. */
345     device_class_register_property(device_class, PROPERTY_COMPRESSION,
346             PROPERTY_ACCESS_SET_MASK,
347             NULL,
348             tape_device_set_compression_fn);
349
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);
354
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);
359 }
360
361 static gboolean
362 tape_device_set_feature_property_fn(Device *p_self, DevicePropertyBase *base,
363     GValue *val, PropertySurety surety, PropertySource source)
364 {
365     TapeDevice *self = TAPE_DEVICE(p_self);
366     GValue old_val;
367     gboolean old_bool, new_bool;
368     PropertySurety old_surety;
369     PropertySource old_source;
370
371     new_bool = g_value_get_boolean(val);
372
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);
377
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"),
382                            base->name),
383                     DEVICE_STATUS_DEVICE_ERROR);
384                 return FALSE;
385             } else {
386                 /* pretend we set it, but don't change surety/source */
387                 return TRUE;
388             }
389         }
390     }
391
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;
411     else
412         return FALSE; /* shouldn't happen */
413
414     return device_simple_property_set_fn(p_self, base, val, surety, source);
415 }
416
417 static gboolean
418 tape_device_set_final_filemarks_fn(Device *p_self, DevicePropertyBase *base,
419     GValue *val, PropertySurety surety, PropertySource source)
420 {
421     TapeDevice *self = TAPE_DEVICE(p_self);
422     GValue old_val;
423     gboolean old_int, new_int;
424     PropertySurety old_surety;
425     PropertySource old_source;
426
427     new_int = g_value_get_uint(val);
428
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);
433
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"),
438                            base->name),
439                     DEVICE_STATUS_DEVICE_ERROR);
440                 return FALSE;
441             } else {
442                 /* pretend we set it, but don't change surety/source */
443                 return TRUE;
444             }
445         }
446     }
447
448     self->final_filemarks = new_int;
449
450     return device_simple_property_set_fn(p_self, base, val, surety, source);
451 }
452
453 static gboolean
454 tape_device_set_compression_fn(Device *p_self, DevicePropertyBase *base,
455     GValue *val, PropertySurety surety, PropertySource source)
456 {
457     TapeDevice *self = TAPE_DEVICE(p_self);
458     gboolean request = g_value_get_boolean(val);
459
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);
470     } else {
471         return FALSE;
472     }
473
474     return device_simple_property_set_fn(p_self, base, val, surety, source);
475 }
476
477 static gboolean
478 tape_device_get_read_block_size_fn(Device *p_self, DevicePropertyBase *base G_GNUC_UNUSED,
479     GValue *val, PropertySurety *surety, PropertySource *source)
480 {
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);
484 }
485
486 static gboolean
487 tape_device_set_read_block_size_fn(Device *p_self, DevicePropertyBase *base G_GNUC_UNUSED,
488     GValue *val, PropertySurety surety, PropertySource source)
489 {
490     TapeDevice *self = TAPE_DEVICE(p_self);
491     guint read_block_size = g_value_get_uint(val);
492
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))
496         return FALSE;
497
498     self->private->read_block_size = read_block_size;
499
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);
503 }
504
505 void tape_device_register(void) {
506     static const char * device_prefix_list[] = { "tape", NULL };
507
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?");
512
513     device_property_fill_and_register(&device_property_fsf,
514                                       G_TYPE_BOOLEAN, "fsf",
515       "Does this drive support the MTFSF command?");
516
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?");
520
521     device_property_fill_and_register(&device_property_bsf,
522                                       G_TYPE_BOOLEAN, "bsf",
523       "Does this drive support the MTBSF command?" );
524
525     device_property_fill_and_register(&device_property_fsr,
526                                       G_TYPE_BOOLEAN, "fsr",
527       "Does this drive support the MTFSR command?");
528
529     device_property_fill_and_register(&device_property_bsr,
530                                       G_TYPE_BOOLEAN, "bsr",
531       "Does this drive support the MTBSR command?");
532
533     device_property_fill_and_register(&device_property_eom,
534                                       G_TYPE_BOOLEAN, "eom",
535       "Does this drive support the MTEOM command?");
536
537     device_property_fill_and_register(&device_property_bsf_after_eom,
538                                       G_TYPE_BOOLEAN,
539                                       "bsf_after_eom",
540       "Does this drive require an MTBSF after MTEOM in order to append?" );
541
542     device_property_fill_and_register(&device_property_nonblocking_open,
543                                       G_TYPE_BOOLEAN,
544                                       "nonblocking_open",
545       "Does this drive require a open with O_NONBLOCK?" );
546
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?" );
550
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)");
554
555     /* Then the device itself */
556     register_device(tape_device_factory, device_prefix_list);
557 }
558
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. */
565
566 static int try_open_tape_device(TapeDevice * self, char * device_filename) {
567     int fd;
568     int save_errno;
569     DeviceStatusFlags new_status;
570
571 #ifdef O_NONBLOCK
572     int nonblocking = 0;
573
574     if (self->nonblocking_open) {
575         nonblocking = O_NONBLOCK;
576     }
577 #endif
578
579 #ifdef O_NONBLOCK
580     fd  = robust_open(device_filename, O_RDWR | nonblocking, 0);
581     save_errno = errno;
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);
585         save_errno = errno;
586     }
587 #else
588     fd = robust_open(device_filename, O_RDWR, 0);
589     save_errno = errno;
590 #endif
591     if (fd >= 0) {
592         self->write_open_errno = 0;
593     } else {
594         if (errno == EACCES || errno == EPERM
595 #ifdef EROFS
596                             || errno == EROFS
597 #endif
598            ) {
599             /* Device is write-protected. */
600             self->write_open_errno = errno;
601 #ifdef O_NONBLOCK
602             fd = robust_open(device_filename, O_RDONLY | nonblocking, 0);
603             save_errno = errno;
604             if (fd < 0 && nonblocking && (save_errno == EWOULDBLOCK || save_errno == EINVAL)) {
605                 fd = robust_open(device_filename, O_RDONLY, 0);
606                 save_errno = errno;
607             }
608 #else
609             fd = robust_open(device_filename, O_RDONLY, 0);
610             save_errno = errno;
611 #endif
612         }
613     }
614 #ifdef O_NONBLOCK
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);
618     errno = save_errno;
619     /* function continues after #endif */
620
621 #endif /* O_NONBLOCK */
622
623     if (fd < 0) {
624         DeviceStatusFlags status_flag = 0;
625         if (errno == EBUSY)
626             status_flag = DEVICE_STATUS_DEVICE_BUSY;
627         else
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)),
631             status_flag);
632         return -1;
633     }
634
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),
640             new_status);
641         robust_close(fd);
642         return -1;
643     }
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),
647             new_status);
648         robust_close(fd);
649         return -1;
650     }
651
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),
656             new_status);
657         robust_close(fd);
658         return -1;
659     }
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),
663             new_status);
664         robust_close(fd);
665         return -1;
666     }
667
668     return fd;
669 }
670
671 static void
672 tape_device_open_device (Device * d_self, char * device_name,
673                         char * device_type, char * device_node) {
674     TapeDevice * self;
675
676     self = TAPE_DEVICE(d_self);
677
678     self->fd = -1;
679     self->private->device_filename = stralloc(device_node);
680
681     /* Get tape drive/OS info */
682     tape_device_detect_capabilities(self);
683
684     /* Chain up */
685     if (parent_class->open_device) {
686         parent_class->open_device(d_self, device_name, device_type, device_node);
687     }
688 }
689
690 void
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)
700 {
701     Device *dself = DEVICE(self);
702     GValue val;
703
704     /* this function is called by tape_device_detect_capabilities, and basically
705      * exists to take care of the GValue mechanics in one place */
706
707     g_assert(final_filemarks == 1 || final_filemarks == 2);
708
709     bzero(&val, sizeof(val));
710     g_value_init(&val, G_TYPE_BOOLEAN);
711
712     self->fsf = fsf;
713     g_value_set_boolean(&val, fsf);
714     device_set_simple_property(dself, PROPERTY_FSF, &val, fsf_surety, fsf_source);
715
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);
719
720     self->bsf = bsf;
721     g_value_set_boolean(&val, bsf);
722     device_set_simple_property(dself, PROPERTY_BSF, &val, bsf_surety, bsf_source);
723
724     self->fsr = fsr;
725     g_value_set_boolean(&val, fsr);
726     device_set_simple_property(dself, PROPERTY_FSR, &val, fsr_surety, fsr_source);
727
728     self->bsr = bsr;
729     g_value_set_boolean(&val, bsr);
730     device_set_simple_property(dself, PROPERTY_BSR, &val, bsr_surety, bsr_source);
731
732     self->eom = eom;
733     g_value_set_boolean(&val, eom);
734     device_set_simple_property(dself, PROPERTY_EOM, &val, eom_surety, eom_source);
735
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);
739
740     g_value_unset(&val);
741     g_value_init(&val, G_TYPE_UINT);
742
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);
746
747     g_value_unset(&val);
748 }
749
750 static DeviceStatusFlags tape_device_read_label(Device * dself) {
751     TapeDevice * self;
752     char * header_buffer;
753     int buffer_len;
754     IoResult result;
755     dumpfile_t *header;
756     DeviceStatusFlags new_status;
757     char *msg = NULL;
758
759     self = TAPE_DEVICE(dself);
760
761     amfree(dself->volume_label);
762     amfree(dself->volume_time);
763     dumpfile_free(dself->volume_header);
764     dself->volume_header = NULL;
765
766     if (device_in_error(self)) return dself->status;
767
768     header = dself->volume_header = g_new(dumpfile_t, 1);
769     fh_init(header);
770
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 */
775         if (self->fd == -1)
776             return dself->status;
777     }
778
779     /* Rewind it. */
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;
787     }
788
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);
792
793     if (result != RESULT_SUCCESS) {
794         free(header_buffer);
795         tape_rewind(self->fd);
796         /* I/O error. */
797         switch (result) {
798         case RESULT_NO_DATA:
799             msg = stralloc(_("no data"));
800             new_status = (DEVICE_STATUS_VOLUME_ERROR |
801                           DEVICE_STATUS_VOLUME_UNLABELED);
802             break;
803
804         case RESULT_SMALL_BUFFER:
805             msg = stralloc(_("block size too small"));
806             new_status = (DEVICE_STATUS_DEVICE_ERROR |
807                           DEVICE_STATUS_VOLUME_ERROR);
808             break;
809
810         default:
811             msg = stralloc(_("unknown error"));
812         case RESULT_ERROR:
813             new_status = (DEVICE_STATUS_DEVICE_ERROR |
814                           DEVICE_STATUS_VOLUME_ERROR |
815                           DEVICE_STATUS_VOLUME_UNLABELED);
816             break;
817         }
818         device_set_error(dself,
819                  g_strdup_printf(_("Error reading Amanda header: %s"),
820                         msg? msg : _("unknown error")),
821                  new_status);
822         amfree(msg);
823         return dself->status;
824     }
825
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;
833     }
834
835     dself->volume_label = g_strdup(header->name);
836     dself->volume_time = g_strdup(header->datestamp);
837     /* dself->volume_header is already set */
838
839     device_set_error(dself, NULL, DEVICE_STATUS_SUCCESS);
840
841     return dself->status;
842 }
843
844 static gboolean
845 tape_device_write_block(Device * pself, guint size, gpointer data) {
846     TapeDevice * self;
847     char *replacement_buffer = NULL;
848     IoResult result;
849     char *msg = NULL;
850
851     self = TAPE_DEVICE(pself);
852
853     g_assert(self->fd >= 0);
854     if (device_in_error(self)) return FALSE;
855
856     /* zero out to the end of a short block -- tape devices only write
857      * whole blocks. */
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);
862
863         data = replacement_buffer;
864         size = pself->block_size;
865     }
866
867     result = tape_device_robust_write(self, data, size, &msg);
868     amfree(replacement_buffer);
869
870     switch (result) {
871         case RESULT_SUCCESS:
872             break;
873
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;
879             return FALSE;
880
881         default:
882             msg = stralloc(_("unknown error"));
883         case RESULT_ERROR:
884             device_set_error(pself,
885                 g_strdup_printf(_("Error writing block: %s"), msg),
886                 DEVICE_STATUS_DEVICE_ERROR);
887             amfree(msg);
888             return FALSE;
889     }
890
891     pself->block++;
892
893     return TRUE;
894 }
895
896 static int tape_device_read_block (Device * pself, gpointer buf,
897                                    int * size_req) {
898     TapeDevice * self;
899     int size;
900     IoResult result;
901     gssize read_block_size = tape_device_read_size(pself);
902     char *msg = NULL;
903
904     self = TAPE_DEVICE(pself);
905
906     g_assert(self->fd >= 0);
907     if (device_in_error(self)) return -1;
908
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;
913         return 0;
914     }
915
916     size = *size_req;
917     result = tape_device_robust_read(self, buf, &size, &msg);
918     switch (result) {
919     case RESULT_SUCCESS:
920         *size_req = size;
921         pself->block++;
922         return size;
923     case RESULT_SMALL_BUFFER: {
924         gsize new_size;
925         GValue newval;
926
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;
937         }
938         g_assert (new_size > (gsize)*size_req);
939
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;
944
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);
951
952         return 0;
953     }
954     case RESULT_NO_DATA:
955         pself->is_eof = TRUE;
956         pself->in_file = FALSE;
957         device_set_error(pself,
958             stralloc(_("EOF")),
959             DEVICE_STATUS_SUCCESS);
960         return -1;
961
962     default:
963         msg = stralloc(_("unknown error"));
964     case RESULT_ERROR:
965         device_set_error(pself,
966             vstrallocf(_("Error reading from tape device: %s"), msg),
967             DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
968         amfree(msg);
969         return -1;
970     }
971
972     g_assert_not_reached();
973 }
974
975 /* Just a helper function for tape_device_start(). */
976 static gboolean write_tapestart_header(TapeDevice * self, char * label,
977                                        char * timestamp) {
978      IoResult result;
979      dumpfile_t * header;
980      char * header_buf;
981      Device * d_self = (Device*)self;
982      char *msg = NULL;
983
984      tape_rewind(self->fd);
985
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);
994          return FALSE;
995      }
996      dumpfile_free(d_self->volume_header);
997      d_self->volume_header = NULL;
998
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);
1005
1006         if (result == RESULT_NO_SPACE)
1007             d_self->is_eom = TRUE;
1008
1009         amfree(msg);
1010         dumpfile_free(header);
1011         amfree(header_buf);
1012         return FALSE;
1013      }
1014
1015      amfree(header_buf);
1016
1017      if (!tape_weof(self->fd, 1)) {
1018         device_set_error(d_self,
1019                          vstrallocf(_("Error writing filemark: %s"),
1020                                     strerror(errno)),
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);
1025         return FALSE;
1026      }
1027
1028      d_self->volume_header = header;
1029      return TRUE;
1030 }
1031
1032 static gboolean
1033 tape_device_start (Device * d_self, DeviceAccessMode mode, char * label,
1034                    char * timestamp) {
1035     TapeDevice * self;
1036
1037     self = TAPE_DEVICE(d_self);
1038
1039     if (device_in_error(self)) return FALSE;
1040
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 */
1045         if (self->fd == -1)
1046             return FALSE;
1047     }
1048
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)
1052             return FALSE;
1053     }
1054
1055     d_self->access_mode = mode;
1056     d_self->in_file = FALSE;
1057
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);
1065             return FALSE;
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);
1070             return FALSE;
1071         }
1072     }
1073
1074     /* Position the tape */
1075     switch (mode) {
1076     case ACCESS_APPEND:
1077         if (d_self->volume_label == NULL && device_read_label(d_self) != DEVICE_STATUS_SUCCESS) {
1078             /* device_read_label already set our error message */
1079             return FALSE;
1080         }
1081
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);
1086             return FALSE;
1087         }
1088         break;
1089
1090     case ACCESS_READ:
1091         if (d_self->volume_label == NULL && device_read_label(d_self) != DEVICE_STATUS_SUCCESS) {
1092             /* device_read_label already set our error message */
1093             return FALSE;
1094         }
1095
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);
1100             return FALSE;
1101         }
1102         d_self->file = 0;
1103         break;
1104
1105     case ACCESS_WRITE:
1106         if (!write_tapestart_header(self, label, timestamp)) {
1107             /* write_tapestart_header already set the error status */
1108             return FALSE;
1109         }
1110
1111         d_self->volume_label = newstralloc(d_self->volume_label, label);
1112         d_self->volume_time = newstralloc(d_self->volume_time, timestamp);
1113
1114         /* unset the VOLUME_UNLABELED flag, if it was set */
1115         device_set_error(d_self, NULL, DEVICE_STATUS_SUCCESS);
1116         d_self->file = 0;
1117         break;
1118
1119     default:
1120         g_assert_not_reached();
1121     }
1122
1123     return TRUE;
1124 }
1125
1126 static gboolean tape_device_start_file(Device * d_self,
1127                                        dumpfile_t * info) {
1128     TapeDevice * self;
1129     IoResult result;
1130     char * amanda_header;
1131     char *msg = NULL;
1132
1133     d_self->is_eom = FALSE;
1134
1135     self = TAPE_DEVICE(d_self);
1136
1137     g_assert(self->fd >= 0);
1138     if (device_in_error(self)) return FALSE;
1139
1140     /* set the blocksize in the header properly */
1141     info->blocksize = d_self->block_size;
1142
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);
1150         return FALSE;
1151     }
1152
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);
1159
1160         if (result == RESULT_NO_SPACE)
1161             d_self->is_eom = TRUE;
1162
1163         amfree(amanda_header);
1164         amfree(msg);
1165         return FALSE;
1166     }
1167     amfree(amanda_header);
1168
1169     /* arrange the file numbers correctly */
1170     d_self->in_file = TRUE;
1171     d_self->block = 0;
1172     if (d_self->file >= 0)
1173         d_self->file ++;
1174     return TRUE;
1175 }
1176
1177 static gboolean
1178 tape_device_finish_file (Device * d_self) {
1179     TapeDevice * self;
1180
1181     self = TAPE_DEVICE(d_self);
1182     if (device_in_error(d_self)) return FALSE;
1183
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;
1190         return FALSE;
1191     }
1192
1193     d_self->in_file = FALSE;
1194     return TRUE;
1195 }
1196
1197 static dumpfile_t *
1198 tape_device_seek_file (Device * d_self, guint file) {
1199     TapeDevice * self;
1200     gint got_file;
1201     int difference;
1202     char * header_buffer;
1203     dumpfile_t * rval;
1204     int buffer_len;
1205     IoResult result;
1206     char *msg;
1207
1208     self = TAPE_DEVICE(d_self);
1209
1210     if (device_in_error(self)) return NULL;
1211
1212     difference = file - d_self->file;
1213
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) {
1218         difference --;
1219     }
1220
1221     d_self->in_file = FALSE;
1222     d_self->is_eof = FALSE;
1223     d_self->block = 0;
1224
1225 reseek:
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);
1233             return NULL;
1234         }
1235     } else { /* (difference <= 0) */
1236         /* Seeking backwards, or to this file itself */
1237
1238         /* if the drive supports bsf, we can do this the fancy way */
1239         if (self->bsf) {
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);
1246                 return NULL;
1247             }
1248
1249             /* now we are on the BOT side of the desired filemark, so FSF to get to the
1250              * EOT side of it */
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);
1256                 return NULL;
1257             }
1258         } else {
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);
1264                 return FALSE;
1265             }
1266
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);
1272                 return NULL;
1273             }
1274         }
1275     }
1276
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"),
1284                             file, got_file),
1285                 DEVICE_STATUS_DEVICE_ERROR);
1286         d_self->file = (guint)got_file;
1287         return NULL;
1288     }
1289
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);
1294
1295     if (result != RESULT_SUCCESS) {
1296         free(header_buffer);
1297         tape_rewind(self->fd);
1298         switch (result) {
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();
1306
1307         case RESULT_SMALL_BUFFER:
1308             msg = stralloc(_("block size too small"));
1309             break;
1310
1311         default:
1312             msg = stralloc(_("unknown error"));
1313         case RESULT_ERROR:
1314             break;
1315         }
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);
1319         amfree(msg);
1320         return NULL;
1321     }
1322
1323     rval = g_new(dumpfile_t, 1);
1324     parse_file_header(header_buffer, rval, buffer_len);
1325     amfree(header_buffer);
1326     switch (rval->type) {
1327     case F_DUMPFILE:
1328     case F_CONT_DUMPFILE:
1329     case F_SPLIT_DUMPFILE:
1330         break;
1331
1332     case F_NOOP:
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. */
1336         amfree(rval);
1337         file++;
1338         difference = 1;
1339         goto reseek;
1340
1341     default:
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);
1346         amfree(rval);
1347         return NULL;
1348     }
1349
1350     d_self->in_file = TRUE;
1351     d_self->file = file;
1352
1353     return rval;
1354 }
1355
1356 static gboolean
1357 tape_device_seek_block (Device * d_self, guint64 block) {
1358     TapeDevice * self;
1359     int difference;
1360
1361     self = TAPE_DEVICE(d_self);
1362
1363     if (device_in_error(self)) return FALSE;
1364
1365     difference = block - d_self->block;
1366
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);
1372             return FALSE;
1373         }
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);
1379             return FALSE;
1380         }
1381     }
1382
1383     d_self->block = block;
1384     return TRUE;
1385 }
1386
1387 static gboolean
1388 tape_device_eject (Device * d_self) {
1389     TapeDevice * self;
1390
1391     self = TAPE_DEVICE(d_self);
1392
1393     if (device_in_error(self)) return FALSE;
1394
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 */
1400         if (self->fd == -1)
1401             return FALSE;
1402     }
1403
1404     /* Rewind it. */
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);
1411         return FALSE;
1412     }
1413
1414     if (tape_offl(self->fd))
1415         return TRUE;
1416
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);
1421
1422     return FALSE;
1423 }
1424
1425 static gboolean
1426 tape_device_finish (Device * d_self) {
1427     TapeDevice * self;
1428     char *msg = NULL;
1429
1430     self = TAPE_DEVICE(d_self);
1431
1432     if (device_in_error(self)) return FALSE;
1433
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);
1438         self->fd = -1;
1439         return TRUE;
1440     }
1441
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))
1445             return FALSE;
1446     }
1447
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)) {
1455         dumpfile_t file;
1456         char *header;
1457         int result;
1458
1459         /* write a F_NOOP header */
1460         fh_init(&file);
1461         file.type = F_NOOP;
1462         header = device_build_amanda_header(d_self, &file, NULL);
1463         if (!header) {
1464             device_set_error(d_self,
1465                 stralloc(_("Amanda file header won't fit in a single block!")),
1466                 DEVICE_STATUS_DEVICE_ERROR);
1467             return FALSE;
1468         }
1469
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);
1476             amfree(header);
1477             amfree(msg);
1478             return FALSE;
1479         }
1480         amfree(header);
1481     }
1482
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);
1488         return FALSE;
1489     }
1490
1491     d_self->is_eof = FALSE;
1492     d_self->access_mode = ACCESS_NULL;
1493
1494     /* release the kernel's device */
1495     robust_close(self->fd);
1496     self->fd = -1;
1497
1498     return TRUE;
1499 }
1500
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.
1506  */
1507 static IoResult
1508 tape_device_robust_read (TapeDevice * self, void * buf, int * count, char **errmsg) {
1509     Device * d_self;
1510     int result;
1511
1512     d_self = (Device*)self;
1513
1514     /* Callers should ensure this. */
1515     g_assert(*count >= 0);
1516
1517     for (;;) {
1518         result = read(self->fd, buf, *count);
1519         if (result > 0) {
1520             /* Success. By definition, we read a full block. */
1521             d_self->is_eof = FALSE;
1522             *count = result;
1523             return RESULT_SUCCESS;
1524         } else if (result == 0) {
1525             d_self->is_eof = TRUE;
1526             return RESULT_NO_DATA;
1527         } else {
1528             if (0
1529 #ifdef EAGAIN
1530                 || errno == EAGAIN
1531 #endif
1532 #ifdef EWOULDBLOCK
1533                 || errno == EWOULDBLOCK
1534 #endif
1535 #ifdef EINTR
1536                 || errno == EINTR
1537 #endif
1538                 ) {
1539                 /* Interrupted system call */
1540                 continue;
1541             } else if ((0
1542 #ifdef ENOMEM
1543                         || errno == ENOMEM /* bad user-space buffer */
1544 #endif
1545 #ifdef EOVERFLOW
1546                         || errno == EOVERFLOW /* bad kernel-space buffer */
1547 #endif
1548 #ifdef EINVAL
1549                         || errno == EINVAL /* ??? */
1550 #endif
1551                         )) {
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;
1556             } else {
1557                 *errmsg = g_strdup_printf(_("Error reading %d bytes from %s: %s"),
1558                         *count, self->private->device_filename, strerror(errno));
1559                 return RESULT_ERROR;
1560             }
1561         }
1562     }
1563
1564     g_assert_not_reached();
1565 }
1566
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
1569    is not defined. */
1570 static void check_resetofs(TapeDevice * self G_GNUC_UNUSED,
1571                            int count G_GNUC_UNUSED) {
1572 #ifdef NEED_RESETOFS
1573     Device * d_self;
1574     int result;
1575
1576     d_self = (Device*)self;
1577
1578     self->private->write_count += count;
1579     if (self->private->write_count < RESETOFS_THRESHOLD) {
1580         return;
1581     }
1582
1583     result = lseek(self->fd, 0, SEEK_SET);
1584     if (result < 0) {
1585         g_warning(_("lseek() failed during kernel 2GB workaround: %s"),
1586                strerror(errno));
1587     }
1588 #endif
1589 }
1590
1591 /* *errmsg is only set on RESULT_ERROR */
1592 static IoResult
1593 tape_device_robust_write (TapeDevice * self, void * buf, int count, char **errmsg) {
1594     Device * d_self;
1595     int result;
1596
1597     d_self = (Device*)self;
1598
1599     check_resetofs(self, count);
1600
1601     for (;;) {
1602         result = write(self->fd, buf, count);
1603
1604         if (result == count) {
1605             /* Success. */
1606
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",
1612                                 count, result);
1613             return RESULT_ERROR;
1614         } else if (0
1615 #ifdef EAGAIN
1616                    || errno == EAGAIN
1617 #endif
1618 #ifdef EWOULDBLOCK
1619                    || errno == EWOULDBLOCK
1620 #endif
1621 #ifdef EINTR
1622                    || errno == EINTR
1623 #endif
1624                    ) {
1625                 /* Interrupted system call */
1626             continue;
1627         } else if (0
1628 #ifdef ENOSPC
1629                    || errno == ENOSPC
1630 #endif
1631 #ifdef EIO
1632                    || errno == EIO
1633 #endif
1634                    ) {
1635             /* Probably EOT. Print a message if we got EIO. */
1636 #ifdef EIO
1637             if (errno == EIO) {
1638                 g_warning(_("Got EIO on %s, assuming end of tape"),
1639                         self->private->device_filename);
1640             }
1641 #endif
1642             return RESULT_NO_SPACE;
1643         } else {
1644             /* WTF */
1645             *errmsg = vstrallocf(_("Kernel gave unexpected write() result of \"%s\" on device %s"),
1646                             strerror(errno), self->private->device_filename);
1647             return RESULT_ERROR;
1648         }
1649     }
1650
1651     g_assert_not_reached();
1652 }
1653
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
1658    actually read. */
1659 static int drain_tape_blocks(TapeDevice * self, int count) {
1660     char * buffer;
1661     gsize buffer_size;
1662     int i;
1663
1664     buffer_size = tape_device_read_size(self);
1665
1666     buffer = malloc(buffer_size);
1667
1668     for (i = 0; i < count || count < 0;) {
1669         int result;
1670
1671         result = read(self->fd, buffer, buffer_size);
1672         if (result > 0) {
1673             i ++;
1674             continue;
1675         } else if (result == 0) {
1676             amfree(buffer);
1677             return i;
1678         } else {
1679             /* First check for interrupted system call. */
1680             if (0
1681 #ifdef EAGAIN
1682                 || errno == EAGAIN
1683 #endif
1684 #ifdef EWOULDBLOCK
1685                 || errno == EWOULDBLOCK
1686 #endif
1687 #ifdef EINTR
1688                 || errno == EINTR
1689 #endif
1690                 ) {
1691                 /* Interrupted system call */
1692                 continue;
1693             } else if (0
1694 #ifdef ENOSPC
1695                        || errno == ENOSPC /* bad user-space buffer */
1696 #endif
1697 #ifdef EOVERFLOW
1698                        || errno == EOVERFLOW /* bad kernel-space buffer */
1699 #endif
1700 #ifdef EINVAL
1701                        || errno == EINVAL /* ??? */
1702 #endif
1703                        ) {
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. */
1707                 buffer_size *= 2;
1708
1709                 if (buffer_size > 32*1024*1024) {
1710                     amfree(buffer);
1711                     return -1;
1712                 } else {
1713                     buffer = realloc(buffer, buffer_size);
1714                     continue;
1715                 }
1716             }
1717         }
1718     }
1719
1720     amfree(buffer);
1721     return count;
1722 }
1723
1724 static gboolean
1725 tape_device_fsf (TapeDevice * self, guint count) {
1726     if (self->fsf) {
1727         return tape_fsf(self->fd, count);
1728     } else {
1729         guint i;
1730         for (i = 0; i < count; i ++) {
1731             if (drain_tape_blocks(self, -1) < 0)
1732                 return FALSE;
1733         }
1734         return TRUE;
1735     }
1736 }
1737
1738
1739 static gboolean
1740 tape_device_fsr (TapeDevice * self, guint count) {
1741     if (self->fsr) {
1742         return tape_fsr(self->fd, count);
1743     } else {
1744         int result = drain_tape_blocks(self, count);
1745         return result > 0 && (int)count == result;
1746     }
1747 }
1748
1749 /* Seek back the given number of blocks to block number block within
1750  * the current file, numbered file. */
1751
1752 static gboolean
1753 tape_device_bsr (TapeDevice * self, guint count, guint file, guint block) {
1754     if (self->bsr) {
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))
1759             return FALSE;
1760
1761         if (!tape_fsf(self->fd, 1))
1762             return FALSE;
1763
1764         return tape_device_fsr(self, block);
1765     } else {
1766         /* rewind, FSF, and FSR */
1767         if (!tape_rewind(self->fd))
1768             return FALSE;
1769
1770         if (!tape_device_fsf(self, file))
1771             return FALSE;
1772
1773         return tape_device_fsr(self, block);
1774     }
1775     g_assert_not_reached();
1776 }
1777
1778 /* Go to the right place to write more data, and update the file
1779    number if possible. */
1780 static gboolean
1781 tape_device_eod (TapeDevice * self) {
1782     Device * d_self;
1783     int count;
1784
1785     d_self = (Device*)self;
1786
1787     if (self->eom) {
1788         int result;
1789         result = tape_eod(self->fd);
1790         if (result == TAPE_OP_ERROR) {
1791             return FALSE;
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 */
1800             self->eom = FALSE;
1801             /* fall through to draining blocks, below */
1802         } else {
1803             /* We drop by 1 because Device will increment the first
1804                time the user does start_file. */
1805             d_self->file = result - 1;
1806             return TRUE;
1807         }
1808     }
1809
1810     if (!tape_rewind(self->fd))
1811         return FALSE;
1812
1813     count = 0;
1814     for (;;) {
1815         /* We alternately read a block and FSF. If the read is
1816            successful, then we are not there yet and should FSF
1817            again. */
1818         int result;
1819         result = drain_tape_blocks(self, 1);
1820         if (result == 1) {
1821             /* More data, FSF. */
1822             tape_device_fsf(self, 1);
1823             count ++;
1824         } else if (result == 0) {
1825             /* Finished. */
1826             d_self->file = count - 1;
1827             return TRUE;
1828         } else {
1829             return FALSE;
1830         }
1831     }
1832 }
1833
1834 static Device *
1835 tape_device_factory (char * device_name, char * device_type, char * device_node) {
1836     Device * rval;
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);
1840     return rval;
1841 }