Imported Upstream version 3.2.0
[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 "device.h"
26
27 #ifdef HAVE_SYS_TAPE_H
28 # include <sys/tape.h>
29 #endif
30 #ifdef HAVE_SYS_MTIO_H
31 # include <sys/mtio.h>
32 #endif
33 #ifdef HAVE_LIMITS_H
34 # include <limits.h>
35 #endif
36
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)
40
41 /* Largest possible block size on SCSI systems. */
42 #define LARGEST_BLOCK_ESTIMATE (16 * 1024 * 1024)
43
44 /*
45  * Type checking and casting macros
46  */
47
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);
55
56 /*
57  * Main object structure
58  */
59 typedef struct TapeDevicePrivate_s TapeDevicePrivate;
60 typedef struct _TapeDevice {
61     Device __parent__;
62
63     /* It should go without saying that all this stuff is
64      * look-but-don't-touch. */
65
66     /* characteristics of the device */
67     gboolean fsf, bsf, fsr, bsr, eom, bsf_after_eom, broken_gmt_online;
68     gboolean leom;
69     gboolean nonblocking_open, fsf_after_filemark;
70     int final_filemarks;
71
72     /* 0 if we opened with O_RDWR; error otherwise. */
73     gboolean write_open_errno;
74     int fd;
75
76     TapeDevicePrivate * private;
77 } TapeDevice;
78
79 struct TapeDevicePrivate_s {
80     /* This holds the total number of bytes written to the device,
81        modulus RESETOFS_THRESHOLD. */
82     int write_count;
83     char * device_filename;
84     gsize read_block_size;
85 };
86
87 /*
88  * Class definition
89  */
90
91 typedef struct _TapeDeviceClass TapeDeviceClass;
92 struct _TapeDeviceClass {
93         DeviceClass __parent__;
94 };
95
96 void tape_device_register(void);
97
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);
109
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);
117
118 /* tape_fileno returns tape position file number, or one of these: */
119 #define TAPE_OP_ERROR -1
120 #define TAPE_POSITION_UNKNOWN -2
121
122 /* Possible (abstracted) results from a system I/O operation. */
123 typedef enum {
124     RESULT_SUCCESS,
125     RESULT_ERROR,        /* Undefined error (*errmsg set) */
126     RESULT_SMALL_BUFFER, /* Tried to read with a buffer that is too
127                             small. */
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. */
132     RESULT_MAX
133 } IoResult;
134
135 /* returns a fileno like tape_fileno */
136 gint tape_eod(int fd);
137
138 gboolean tape_weof(int fd, guint8 count);
139 gboolean tape_setcompression(int fd, gboolean on);
140
141 gboolean tape_offl(int fd);
142
143 DeviceStatusFlags tape_is_tape_device(int fd);
144 DeviceStatusFlags tape_is_ready(int fd, TapeDevice *t_self);
145
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)
149
150 /*
151  * Our device-specific properties.
152  */
153
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)
164
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 */
176
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,
196                                        int * size_req);
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);
212
213 /* pointer to the class of our parent */
214 static DeviceClass *parent_class = NULL;
215
216 GType tape_device_get_type (void)
217 {
218     static GType type = 0;
219
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 */,
228             sizeof (TapeDevice),
229             0 /* n_preallocs */,
230             (GInstanceInitFunc) tape_device_init,
231             NULL
232         };
233
234         type = g_type_register_static (TYPE_DEVICE, "TapeDevice",
235                                        &info, (GTypeFlags)0);
236     }
237
238     return type;
239 }
240
241 static void
242 tape_device_init (TapeDevice * self) {
243     Device * d_self;
244     GValue response;
245
246     d_self = DEVICE(self);
247     bzero(&response, sizeof(response));
248
249     self->private = g_new0(TapeDevicePrivate, 1);
250
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;
256
257     self->fd = -1;
258
259     /* set all of the feature properties to an unsure default of FALSE */
260     self->broken_gmt_online = FALSE;
261     self->fsf = FALSE;
262     self->bsf = FALSE;
263     self->fsr = FALSE;
264     self->bsr = FALSE;
265     self->eom = FALSE;
266     self->leom = FALSE;
267     self->bsf_after_eom = FALSE;
268
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);
289
290 #ifdef DEFAULT_TAPE_NON_BLOCKING_OPEN
291     self->nonblocking_open = TRUE;
292 #else
293     self->nonblocking_open = FALSE;
294 #endif
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);
299
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);
306
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);
313
314     self->private->write_count = 0;
315     self->private->device_filename = NULL;
316
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);
323
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);
329
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);
335
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);
341
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);
347
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);
353 }
354
355 static void tape_device_finalize(GObject * obj_self) {
356     TapeDevice * self = TAPE_DEVICE(obj_self);
357
358     if(G_OBJECT_CLASS(parent_class)->finalize) \
359            (* G_OBJECT_CLASS(parent_class)->finalize)(obj_self);
360
361     robust_close(self->fd);
362     self->fd = -1;
363     amfree(self->private->device_filename);
364     amfree(self->private);
365 }
366
367 static void
368 tape_device_class_init (TapeDeviceClass * c)
369 {
370     DeviceClass *device_class = (DeviceClass *)c;
371     GObjectClass *g_object_class = (GObjectClass *)c;
372
373     parent_class = g_type_class_ref (TYPE_DEVICE);
374
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;
386
387     g_object_class->finalize = tape_device_finalize;
388 }
389
390 static void
391 tape_device_base_init (TapeDeviceClass * c)
392 {
393     DeviceClass *device_class = (DeviceClass *)c;
394
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);
399
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);
404
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);
409
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);
414
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);
419
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);
424
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);
429
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);
434
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);
439
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);
444
445     /* We don't (yet?) support reading the device's compression state, so not
446      * gettable. */
447     device_class_register_property(device_class, PROPERTY_COMPRESSION,
448             PROPERTY_ACCESS_SET_MASK,
449             NULL,
450             tape_device_set_compression_fn);
451
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);
456
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);
461 }
462
463 static gboolean
464 tape_device_set_feature_property_fn(Device *p_self, DevicePropertyBase *base,
465     GValue *val, PropertySurety surety, PropertySource source)
466 {
467     TapeDevice *self = TAPE_DEVICE(p_self);
468     GValue old_val;
469     gboolean old_bool, new_bool;
470     PropertySurety old_surety;
471     PropertySource old_source;
472
473     new_bool = g_value_get_boolean(val);
474
475     /* get the old source and surety and see if we're willing to make this change */
476     bzero(&old_val, sizeof(old_val));
477     if (device_get_simple_property(p_self, base->ID, &old_val, &old_surety, &old_source)) {
478         old_bool = g_value_get_boolean(&old_val);
479
480         if (old_surety == PROPERTY_SURETY_GOOD && old_source == PROPERTY_SOURCE_DETECTED) {
481             if (new_bool != old_bool) {
482                 device_set_error(p_self, vstrallocf(_(
483                            "Value for property '%s' was autodetected and cannot be changed"),
484                            base->name),
485                     DEVICE_STATUS_DEVICE_ERROR);
486                 return FALSE;
487             } else {
488                 /* pretend we set it, but don't change surety/source */
489                 return TRUE;
490             }
491         }
492     }
493
494     /* (note: PROPERTY_* are not constants, so we can't use switch) */
495     if (base->ID == PROPERTY_BROKEN_GMT_ONLINE)
496         self->broken_gmt_online = new_bool;
497     else if (base->ID == PROPERTY_FSF)
498         self->fsf = new_bool;
499     else if (base->ID == PROPERTY_FSF_AFTER_FILEMARK)
500         self->fsf_after_filemark = new_bool;
501     else if (base->ID == PROPERTY_BSF)
502         self->bsf = new_bool;
503     else if (base->ID == PROPERTY_FSR)
504         self->fsr = new_bool;
505     else if (base->ID == PROPERTY_BSR)
506         self->bsr = new_bool;
507     else if (base->ID == PROPERTY_EOM)
508         self->eom = new_bool;
509     else if (base->ID == PROPERTY_BSF_AFTER_EOM)
510         self->bsf_after_eom = new_bool;
511     else if (base->ID == PROPERTY_NONBLOCKING_OPEN)
512         self->nonblocking_open = new_bool;
513     else
514         return FALSE; /* shouldn't happen */
515
516     return device_simple_property_set_fn(p_self, base, val, surety, source);
517 }
518
519 static gboolean
520 tape_device_set_final_filemarks_fn(Device *p_self, DevicePropertyBase *base,
521     GValue *val, PropertySurety surety, PropertySource source)
522 {
523     TapeDevice *self = TAPE_DEVICE(p_self);
524     GValue old_val;
525     gboolean old_int, new_int;
526     PropertySurety old_surety;
527     PropertySource old_source;
528
529     new_int = g_value_get_uint(val);
530
531     /* get the old source and surety and see if we're willing to make this change */
532     bzero(&old_val, sizeof(old_val));
533     if (device_get_simple_property(p_self, base->ID, &old_val, &old_surety, &old_source)) {
534         old_int = g_value_get_uint(&old_val);
535
536         if (old_surety == PROPERTY_SURETY_GOOD && old_source == PROPERTY_SOURCE_DETECTED) {
537             if (new_int != old_int) {
538                 device_set_error(p_self, vstrallocf(_(
539                            "Value for property '%s' was autodetected and cannot be changed"),
540                            base->name),
541                     DEVICE_STATUS_DEVICE_ERROR);
542                 return FALSE;
543             } else {
544                 /* pretend we set it, but don't change surety/source */
545                 return TRUE;
546             }
547         }
548     }
549
550     self->final_filemarks = new_int;
551
552     return device_simple_property_set_fn(p_self, base, val, surety, source);
553 }
554
555 static gboolean
556 tape_device_set_compression_fn(Device *p_self, DevicePropertyBase *base,
557     GValue *val, PropertySurety surety, PropertySource source)
558 {
559     TapeDevice *self = TAPE_DEVICE(p_self);
560     gboolean request = g_value_get_boolean(val);
561
562     /* We allow this property to be set at any time. This is mostly
563      * because setting compression is a hit-and-miss proposition
564      * at any time; some drives accept the mode setting but don't
565      * actually support compression, while others do support
566      * compression but do it via density settings or some other
567      * way. Set this property whenever you want, but all we'll do
568      * is report whether or not the ioctl succeeded. */
569     if (tape_setcompression(self->fd, request)) {
570         /* looks good .. let's start the device over, though */
571         device_clear_volume_details(p_self);
572     } else {
573         return FALSE;
574     }
575
576     return device_simple_property_set_fn(p_self, base, val, surety, source);
577 }
578
579 static gboolean
580 tape_device_get_read_block_size_fn(Device *p_self, DevicePropertyBase *base G_GNUC_UNUSED,
581     GValue *val, PropertySurety *surety, PropertySource *source)
582 {
583     /* use the READ_BLOCK_SIZE, even if we're invoked to get the old READ_BUFFER_SIZE */
584     return device_simple_property_get_fn(p_self, &device_property_read_block_size,
585                                         val, surety, source);
586 }
587
588 static gboolean
589 tape_device_set_read_block_size_fn(Device *p_self, DevicePropertyBase *base G_GNUC_UNUSED,
590     GValue *val, PropertySurety surety, PropertySource source)
591 {
592     TapeDevice *self = TAPE_DEVICE(p_self);
593     guint read_block_size = g_value_get_uint(val);
594
595     if (read_block_size != 0 &&
596             ((gsize)read_block_size < p_self->block_size ||
597              (gsize)read_block_size > p_self->max_block_size))
598         return FALSE;
599
600     self->private->read_block_size = read_block_size;
601
602     /* use the READ_BLOCK_SIZE, even if we're invoked to get the old READ_BUFFER_SIZE */
603     return device_simple_property_set_fn(p_self, &device_property_read_block_size,
604                                         val, surety, source);
605 }
606
607 void tape_device_register(void) {
608     static const char * device_prefix_list[] = { "tape", NULL };
609
610     /* First register tape-specific properties */
611     device_property_fill_and_register(&device_property_broken_gmt_online,
612                                       G_TYPE_BOOLEAN, "broken_gmt_online",
613       "Does this drive support the GMT_ONLINE macro?");
614
615     device_property_fill_and_register(&device_property_fsf,
616                                       G_TYPE_BOOLEAN, "fsf",
617       "Does this drive support the MTFSF command?");
618
619     device_property_fill_and_register(&device_property_fsf_after_filemark,
620                                       G_TYPE_BOOLEAN, "fsf_after_filemark",
621       "Does this drive needs a FSF if a filemark is already read?");
622
623     device_property_fill_and_register(&device_property_bsf,
624                                       G_TYPE_BOOLEAN, "bsf",
625       "Does this drive support the MTBSF command?" );
626
627     device_property_fill_and_register(&device_property_fsr,
628                                       G_TYPE_BOOLEAN, "fsr",
629       "Does this drive support the MTFSR command?");
630
631     device_property_fill_and_register(&device_property_bsr,
632                                       G_TYPE_BOOLEAN, "bsr",
633       "Does this drive support the MTBSR command?");
634
635     device_property_fill_and_register(&device_property_eom,
636                                       G_TYPE_BOOLEAN, "eom",
637       "Does this drive support the MTEOM command?");
638
639     device_property_fill_and_register(&device_property_bsf_after_eom,
640                                       G_TYPE_BOOLEAN,
641                                       "bsf_after_eom",
642       "Does this drive require an MTBSF after MTEOM in order to append?" );
643
644     device_property_fill_and_register(&device_property_nonblocking_open,
645                                       G_TYPE_BOOLEAN,
646                                       "nonblocking_open",
647       "Does this drive require a open with O_NONBLOCK?" );
648
649     device_property_fill_and_register(&device_property_final_filemarks,
650                                       G_TYPE_UINT, "final_filemarks",
651       "How many filemarks to write after the last tape file?" );
652
653     device_property_fill_and_register(&device_property_read_buffer_size,
654                                       G_TYPE_UINT, "read_buffer_size",
655       "(deprecated name for READ_BLOCK_SIZE)");
656
657     /* Then the device itself */
658     register_device(tape_device_factory, device_prefix_list);
659 }
660
661 /* Open the tape device, trying various combinations of O_RDWR and
662    O_NONBLOCK.  Returns -1 and calls device_set_error for errors
663    On Linux, with O_NONBLOCK, the kernel just checks the state once,
664    whereas it checks it every second for ST_BLOCK_SECONDS if O_NONBLOCK is
665    not given.  Amanda already have the code to poll, we want open to check
666    the state only once. */
667
668 static int try_open_tape_device(TapeDevice * self, char * device_filename) {
669     int fd;
670     int save_errno;
671     DeviceStatusFlags new_status;
672
673 #ifdef O_NONBLOCK
674     int nonblocking = 0;
675
676     if (self->nonblocking_open) {
677         nonblocking = O_NONBLOCK;
678     }
679 #endif
680
681 #ifdef O_NONBLOCK
682     fd  = robust_open(device_filename, O_RDWR | nonblocking, 0);
683     save_errno = errno;
684     if (fd < 0 && nonblocking && (save_errno == EWOULDBLOCK || save_errno == EINVAL)) {
685         /* Maybe we don't support O_NONBLOCK for tape devices. */
686         fd = robust_open(device_filename, O_RDWR, 0);
687         save_errno = errno;
688     }
689 #else
690     fd = robust_open(device_filename, O_RDWR, 0);
691     save_errno = errno;
692 #endif
693     if (fd >= 0) {
694         self->write_open_errno = 0;
695     } else {
696         if (errno == EACCES || errno == EPERM
697 #ifdef EROFS
698                             || errno == EROFS
699 #endif
700            ) {
701             /* Device is write-protected. */
702             self->write_open_errno = errno;
703 #ifdef O_NONBLOCK
704             fd = robust_open(device_filename, O_RDONLY | nonblocking, 0);
705             save_errno = errno;
706             if (fd < 0 && nonblocking && (save_errno == EWOULDBLOCK || save_errno == EINVAL)) {
707                 fd = robust_open(device_filename, O_RDONLY, 0);
708                 save_errno = errno;
709             }
710 #else
711             fd = robust_open(device_filename, O_RDONLY, 0);
712             save_errno = errno;
713 #endif
714         }
715     }
716 #ifdef O_NONBLOCK
717     /* Clear O_NONBLOCK for operations from now on. */
718     if (fd >= 0 && nonblocking)
719         fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
720     errno = save_errno;
721     /* function continues after #endif */
722
723 #endif /* O_NONBLOCK */
724
725     if (fd < 0) {
726         DeviceStatusFlags status_flag = 0;
727         if (errno == EBUSY)
728             status_flag = DEVICE_STATUS_DEVICE_BUSY;
729         else
730             status_flag = DEVICE_STATUS_DEVICE_ERROR;
731         device_set_error(DEVICE(self),
732             vstrallocf(_("Can't open tape device %s: %s"), self->private->device_filename, strerror(errno)),
733             status_flag);
734         return -1;
735     }
736
737     /* Check that this is actually a tape device. */
738     new_status = tape_is_tape_device(fd);
739     if (new_status & DEVICE_STATUS_DEVICE_ERROR) {
740         device_set_error(DEVICE(self),
741             vstrallocf(_("File %s is not a tape device"), self->private->device_filename),
742             new_status);
743         robust_close(fd);
744         return -1;
745     }
746     if (new_status & DEVICE_STATUS_VOLUME_MISSING) {
747         device_set_error(DEVICE(self),
748             vstrallocf(_("Tape device %s is not ready or is empty"), self->private->device_filename),
749             new_status);
750         robust_close(fd);
751         return -1;
752     }
753
754     new_status = tape_is_ready(fd, self);
755     if (new_status & DEVICE_STATUS_VOLUME_MISSING) {
756         device_set_error(DEVICE(self),
757             vstrallocf(_("Tape device %s is empty"), self->private->device_filename),
758             new_status);
759         robust_close(fd);
760         return -1;
761     }
762     if (new_status != DEVICE_STATUS_SUCCESS) {
763         device_set_error(DEVICE(self),
764             vstrallocf(_("Tape device %s is not ready or is empty"), self->private->device_filename),
765             new_status);
766         robust_close(fd);
767         return -1;
768     }
769
770     return fd;
771 }
772
773 static void
774 tape_device_open_device (Device * dself, char * device_name,
775                         char * device_type, char * device_node) {
776     TapeDevice * self;
777     GValue val;
778
779     self = TAPE_DEVICE(dself);
780
781     self->fd = -1;
782     self->private->device_filename = stralloc(device_node);
783
784     /* Set tape drive/OS info */
785     bzero(&val, sizeof(val));
786     g_value_init(&val, G_TYPE_BOOLEAN);
787
788     self->fsf = TRUE;
789     g_value_set_boolean(&val, self->fsf);
790     device_set_simple_property(dself, PROPERTY_FSF, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
791
792     self->fsf_after_filemark = DEFAULT_FSF_AFTER_FILEMARK;
793     g_value_set_boolean(&val, self->fsf_after_filemark);
794     device_set_simple_property(dself, PROPERTY_FSF_AFTER_FILEMARK, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
795
796     self->bsf = TRUE;
797     g_value_set_boolean(&val, self->bsf);
798     device_set_simple_property(dself, PROPERTY_BSF, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
799
800     self->fsr = TRUE;
801     g_value_set_boolean(&val, self->fsr);
802     device_set_simple_property(dself, PROPERTY_FSR, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
803
804     self->bsr = TRUE;
805     g_value_set_boolean(&val, self->bsr);
806     device_set_simple_property(dself, PROPERTY_BSR, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
807
808     self->eom = TRUE;
809     g_value_set_boolean(&val, self->eom);
810     device_set_simple_property(dself, PROPERTY_EOM, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
811
812     self->leom = FALSE;
813     g_value_set_boolean(&val, self->leom);
814     device_set_simple_property(dself, PROPERTY_LEOM, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
815
816     self->bsf_after_eom = FALSE;
817     g_value_set_boolean(&val, self->bsf_after_eom);
818     device_set_simple_property(dself, PROPERTY_BSF_AFTER_EOM, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
819
820     g_value_unset(&val);
821     g_value_init(&val, G_TYPE_UINT);
822
823     self->final_filemarks = 2;
824     g_value_set_uint(&val, self->final_filemarks);
825     device_set_simple_property(dself, PROPERTY_FINAL_FILEMARKS, &val, PROPERTY_SURETY_BAD, PROPERTY_SOURCE_DEFAULT);
826
827     g_value_unset(&val);
828
829     /* Chain up */
830     if (parent_class->open_device) {
831         parent_class->open_device(dself, device_name, device_type, device_node);
832     }
833 }
834
835
836 static DeviceStatusFlags tape_device_read_label(Device * dself) {
837     TapeDevice * self;
838     char * header_buffer;
839     int buffer_len;
840     IoResult result;
841     dumpfile_t *header;
842     DeviceStatusFlags new_status;
843     char *msg = NULL;
844
845     self = TAPE_DEVICE(dself);
846
847     amfree(dself->volume_label);
848     amfree(dself->volume_time);
849     dumpfile_free(dself->volume_header);
850     dself->volume_header = NULL;
851
852     if (device_in_error(self)) return dself->status;
853
854     if (self->fd == -1) {
855         self->fd = try_open_tape_device(self, self->private->device_filename);
856         /* if the open failed, then try_open_tape_device already set the
857          * approppriate error status */
858         if (self->fd == -1)
859             return dself->status;
860     }
861
862     /* Rewind it. */
863     if (!tape_rewind(self->fd)) {
864         device_set_error(dself,
865             vstrallocf(_("Error rewinding device %s to read label: %s"),
866                     self->private->device_filename, strerror(errno)),
867               DEVICE_STATUS_DEVICE_ERROR
868             | DEVICE_STATUS_VOLUME_ERROR);
869         return dself->status;
870     }
871
872     buffer_len = tape_device_read_size(self);
873     header_buffer = malloc(buffer_len);
874     result = tape_device_robust_read(self, header_buffer, &buffer_len, &msg);
875
876     if (result != RESULT_SUCCESS) {
877         free(header_buffer);
878         tape_rewind(self->fd);
879         /* I/O error. */
880         switch (result) {
881         case RESULT_NO_DATA:
882             msg = stralloc(_("no data"));
883             new_status = (DEVICE_STATUS_VOLUME_ERROR |
884                           DEVICE_STATUS_VOLUME_UNLABELED);
885             header = dself->volume_header = g_new(dumpfile_t, 1);
886             fh_init(header);
887             break;
888
889         case RESULT_SMALL_BUFFER:
890             msg = stralloc(_("block size too small"));
891             new_status = (DEVICE_STATUS_DEVICE_ERROR |
892                           DEVICE_STATUS_VOLUME_ERROR);
893             header = dself->volume_header = g_new(dumpfile_t, 1);
894             fh_init(header);
895             header->type = F_WEIRD;
896             break;
897
898         default:
899             msg = stralloc(_("unknown error"));
900         case RESULT_ERROR:
901             new_status = (DEVICE_STATUS_DEVICE_ERROR |
902                           DEVICE_STATUS_VOLUME_ERROR |
903                           DEVICE_STATUS_VOLUME_UNLABELED);
904             break;
905         }
906         device_set_error(dself,
907                  g_strdup_printf(_("Error reading Amanda header: %s"),
908                         msg? msg : _("unknown error")),
909                  new_status);
910         amfree(msg);
911         return dself->status;
912     }
913
914     header = dself->volume_header = g_new(dumpfile_t, 1);
915     fh_init(header);
916
917     parse_file_header(header_buffer, header, buffer_len);
918     amfree(header_buffer);
919     if (header->type != F_TAPESTART) {
920         device_set_error(dself,
921                 stralloc(_("No tapestart header -- unlabeled device?")),
922                 DEVICE_STATUS_VOLUME_UNLABELED);
923         return dself->status;
924     }
925
926     dself->volume_label = g_strdup(header->name);
927     dself->volume_time = g_strdup(header->datestamp);
928     /* dself->volume_header is already set */
929
930     device_set_error(dself, NULL, DEVICE_STATUS_SUCCESS);
931
932     return dself->status;
933 }
934
935 static gboolean
936 tape_device_write_block(Device * pself, guint size, gpointer data) {
937     TapeDevice * self;
938     char *replacement_buffer = NULL;
939     IoResult result;
940     char *msg = NULL;
941
942     self = TAPE_DEVICE(pself);
943
944     g_assert(self->fd >= 0);
945     if (device_in_error(self)) return FALSE;
946
947     /* zero out to the end of a short block -- tape devices only write
948      * whole blocks. */
949     if (size < pself->block_size) {
950         replacement_buffer = malloc(pself->block_size);
951         memcpy(replacement_buffer, data, size);
952         bzero(replacement_buffer+size, pself->block_size-size);
953
954         data = replacement_buffer;
955         size = pself->block_size;
956     }
957
958     result = tape_device_robust_write(self, data, size, &msg);
959     amfree(replacement_buffer);
960
961     switch (result) {
962         case RESULT_SUCCESS:
963             break;
964
965         case RESULT_NO_SPACE:
966             device_set_error(pself,
967                 stralloc(_("No space left on device")),
968                 DEVICE_STATUS_VOLUME_ERROR);
969             pself->is_eom = TRUE;
970             return FALSE;
971
972         default:
973             msg = stralloc(_("unknown error"));
974         case RESULT_ERROR:
975             device_set_error(pself,
976                 g_strdup_printf(_("Error writing block: %s"), msg),
977                 DEVICE_STATUS_DEVICE_ERROR);
978             amfree(msg);
979             return FALSE;
980     }
981
982     pself->block++;
983
984     return TRUE;
985 }
986
987 static int tape_device_read_block (Device * pself, gpointer buf,
988                                    int * size_req) {
989     TapeDevice * self;
990     int size;
991     IoResult result;
992     gssize read_block_size = tape_device_read_size(pself);
993     char *msg = NULL;
994
995     self = TAPE_DEVICE(pself);
996
997     g_assert(self->fd >= 0);
998     if (device_in_error(self)) return -1;
999
1000     g_assert(read_block_size < INT_MAX); /* data type mismatch */
1001     if (buf == NULL || *size_req < (int)read_block_size) {
1002         /* Just a size query. */
1003         *size_req = (int)read_block_size;
1004         return 0;
1005     }
1006
1007     size = *size_req;
1008     result = tape_device_robust_read(self, buf, &size, &msg);
1009     switch (result) {
1010     case RESULT_SUCCESS:
1011         *size_req = size;
1012         pself->block++;
1013         return size;
1014     case RESULT_SMALL_BUFFER: {
1015         gsize new_size;
1016         GValue newval;
1017
1018         /* If this happens, it means that we have:
1019          *     (next block size) > (buffer size) >= (read_block_size)
1020          * The solution is to ask for an even bigger buffer. We also play
1021          * some games to refrain from reading above the SCSI limit or from
1022          * integer overflow.  Note that not all devices will tell us about
1023          * this problem -- some will just discard the "extra" data. */
1024         new_size = MIN(INT_MAX/2 - 1, *size_req) * 2;
1025         if (new_size > LARGEST_BLOCK_ESTIMATE &&
1026             *size_req < LARGEST_BLOCK_ESTIMATE) {
1027             new_size = LARGEST_BLOCK_ESTIMATE;
1028         }
1029         g_assert (new_size > (gsize)*size_req);
1030
1031         g_info("Device %s indicated blocksize %zd was too small; using %zd.",
1032             pself->device_name, (gsize)*size_req, new_size);
1033         *size_req = (int)new_size;
1034         self->private->read_block_size = new_size;
1035
1036         bzero(&newval, sizeof(newval));
1037         g_value_init(&newval, G_TYPE_UINT);
1038         g_value_set_uint(&newval, self->private->read_block_size);
1039         device_set_simple_property(pself, PROPERTY_READ_BLOCK_SIZE,
1040                 &newval, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
1041         g_value_unset(&newval);
1042
1043         return 0;
1044     }
1045     case RESULT_NO_DATA:
1046         pself->is_eof = TRUE;
1047         pself->in_file = FALSE;
1048         device_set_error(pself,
1049             stralloc(_("EOF")),
1050             DEVICE_STATUS_SUCCESS);
1051         return -1;
1052
1053     default:
1054         msg = stralloc(_("unknown error"));
1055     case RESULT_ERROR:
1056         device_set_error(pself,
1057             vstrallocf(_("Error reading from tape device: %s"), msg),
1058             DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1059         amfree(msg);
1060         return -1;
1061     }
1062
1063     g_assert_not_reached();
1064 }
1065
1066 /* Just a helper function for tape_device_start(). */
1067 static gboolean write_tapestart_header(TapeDevice * self, char * label,
1068                                        char * timestamp) {
1069      IoResult result;
1070      dumpfile_t * header;
1071      char * header_buf;
1072      Device * d_self = (Device*)self;
1073      char *msg = NULL;
1074
1075      tape_rewind(self->fd);
1076
1077      header = make_tapestart_header(d_self, label, timestamp);
1078      g_assert(header != NULL);
1079      header_buf = device_build_amanda_header(d_self, header, NULL);
1080      if (header_buf == NULL) {
1081          device_set_error(d_self,
1082             stralloc(_("Tapestart header won't fit in a single block!")),
1083             DEVICE_STATUS_DEVICE_ERROR);
1084          dumpfile_free(header);
1085          return FALSE;
1086      }
1087      dumpfile_free(d_self->volume_header);
1088      d_self->volume_header = NULL;
1089
1090      result = tape_device_robust_write(self, header_buf, d_self->block_size, &msg);
1091      if (result != RESULT_SUCCESS) {
1092         device_set_error(d_self,
1093             g_strdup_printf(_("Error writing tapestart header: %s"),
1094                         (result == RESULT_ERROR)? msg : _("out of space")),
1095             DEVICE_STATUS_DEVICE_ERROR);
1096
1097         if (result == RESULT_NO_SPACE)
1098             d_self->is_eom = TRUE;
1099
1100         amfree(msg);
1101         dumpfile_free(header);
1102         amfree(header_buf);
1103         return FALSE;
1104      }
1105
1106      amfree(header_buf);
1107
1108      if (!tape_weof(self->fd, 1)) {
1109         device_set_error(d_self,
1110                          vstrallocf(_("Error writing filemark: %s"),
1111                                     strerror(errno)),
1112                          DEVICE_STATUS_DEVICE_ERROR|DEVICE_STATUS_VOLUME_ERROR);
1113         /* can't tell if this was EOM or not, so assume it is */
1114         d_self->is_eom = TRUE;
1115         dumpfile_free(header);
1116         return FALSE;
1117      }
1118
1119      d_self->volume_header = header;
1120      return TRUE;
1121 }
1122
1123 static gboolean
1124 tape_device_start (Device * d_self, DeviceAccessMode mode, char * label,
1125                    char * timestamp) {
1126     TapeDevice * self;
1127
1128     self = TAPE_DEVICE(d_self);
1129
1130     if (device_in_error(self)) return FALSE;
1131
1132     if (self->fd == -1) {
1133         self->fd = try_open_tape_device(self, self->private->device_filename);
1134         /* if the open failed, then try_open_tape_device already set the
1135          * approppriate error status */
1136         if (self->fd == -1)
1137             return FALSE;
1138     }
1139
1140     if (mode != ACCESS_WRITE && d_self->volume_label == NULL) {
1141         /* we need a labeled volume for APPEND and READ */
1142         if (tape_device_read_label(d_self) != DEVICE_STATUS_SUCCESS)
1143             return FALSE;
1144     }
1145
1146     d_self->access_mode = mode;
1147     d_self->in_file = FALSE;
1148
1149     if (IS_WRITABLE_ACCESS_MODE(mode)) {
1150         if (self->write_open_errno != 0) {
1151             /* We tried and failed to open the device in write mode. */
1152             device_set_error(d_self,
1153                 vstrallocf(_("Can't open tape device %s for writing: %s"),
1154                             self->private->device_filename, strerror(self->write_open_errno)),
1155                 DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
1156             return FALSE;
1157         } else if (!tape_rewind(self->fd)) {
1158             device_set_error(d_self,
1159                 vstrallocf(_("Error rewinding device to start: %s"), strerror(errno)),
1160                 DEVICE_STATUS_DEVICE_ERROR);
1161             return FALSE;
1162         }
1163     }
1164
1165     /* Position the tape */
1166     switch (mode) {
1167     case ACCESS_APPEND:
1168         if (d_self->volume_label == NULL && device_read_label(d_self) != DEVICE_STATUS_SUCCESS) {
1169             /* device_read_label already set our error message */
1170             return FALSE;
1171         }
1172
1173         if (!tape_device_eod(self)) {
1174             device_set_error(d_self,
1175                 vstrallocf(_("Couldn't seek to end of tape: %s"), strerror(errno)),
1176                 DEVICE_STATUS_DEVICE_ERROR);
1177             return FALSE;
1178         }
1179         break;
1180
1181     case ACCESS_READ:
1182         if (d_self->volume_label == NULL && device_read_label(d_self) != DEVICE_STATUS_SUCCESS) {
1183             /* device_read_label already set our error message */
1184             return FALSE;
1185         }
1186
1187         if (!tape_rewind(self->fd)) {
1188             device_set_error(d_self,
1189                 vstrallocf(_("Error rewinding device after reading label: %s"), strerror(errno)),
1190                 DEVICE_STATUS_DEVICE_ERROR);
1191             return FALSE;
1192         }
1193         d_self->file = 0;
1194         break;
1195
1196     case ACCESS_WRITE:
1197         if (!write_tapestart_header(self, label, timestamp)) {
1198             /* write_tapestart_header already set the error status */
1199             return FALSE;
1200         }
1201
1202         d_self->volume_label = newstralloc(d_self->volume_label, label);
1203         d_self->volume_time = newstralloc(d_self->volume_time, timestamp);
1204
1205         /* unset the VOLUME_UNLABELED flag, if it was set */
1206         device_set_error(d_self, NULL, DEVICE_STATUS_SUCCESS);
1207         d_self->file = 0;
1208         break;
1209
1210     default:
1211         g_assert_not_reached();
1212     }
1213
1214     return TRUE;
1215 }
1216
1217 static gboolean tape_device_start_file(Device * d_self,
1218                                        dumpfile_t * info) {
1219     TapeDevice * self;
1220     IoResult result;
1221     char * amanda_header;
1222     char *msg = NULL;
1223
1224     self = TAPE_DEVICE(d_self);
1225
1226     g_assert(self->fd >= 0);
1227     if (device_in_error(self)) return FALSE;
1228
1229     /* set the blocksize in the header properly */
1230     info->blocksize = d_self->block_size;
1231
1232     /* Make the Amanda header suitable for writing to the device. */
1233     /* Then write the damn thing. */
1234     amanda_header = device_build_amanda_header(d_self, info, NULL);
1235     if (amanda_header == NULL) {
1236         device_set_error(d_self,
1237             stralloc(_("Amanda file header won't fit in a single block!")),
1238             DEVICE_STATUS_DEVICE_ERROR);
1239         return FALSE;
1240     }
1241
1242     result = tape_device_robust_write(self, amanda_header, d_self->block_size, &msg);
1243     if (result != RESULT_SUCCESS) {
1244         device_set_error(d_self,
1245             vstrallocf(_("Error writing file header: %s"),
1246                         (result == RESULT_ERROR)? msg : _("out of space")),
1247             DEVICE_STATUS_DEVICE_ERROR);
1248
1249         if (result == RESULT_NO_SPACE)
1250             d_self->is_eom = TRUE;
1251
1252         amfree(amanda_header);
1253         amfree(msg);
1254         return FALSE;
1255     }
1256     amfree(amanda_header);
1257
1258     /* arrange the file numbers correctly */
1259     d_self->in_file = TRUE;
1260     d_self->block = 0;
1261     if (d_self->file >= 0)
1262         d_self->file ++;
1263     return TRUE;
1264 }
1265
1266 static gboolean
1267 tape_device_finish_file (Device * d_self) {
1268     TapeDevice * self;
1269
1270     self = TAPE_DEVICE(d_self);
1271     if (device_in_error(d_self)) return FALSE;
1272
1273     if (!tape_weof(self->fd, 1)) {
1274         device_set_error(d_self,
1275                 vstrallocf(_("Error writing filemark: %s"), strerror(errno)),
1276                 DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
1277         /* can't tell if this was EOM or not, so assume it is */
1278         d_self->is_eom = TRUE;
1279         return FALSE;
1280     }
1281
1282     d_self->in_file = FALSE;
1283     return TRUE;
1284 }
1285
1286 static dumpfile_t *
1287 tape_device_seek_file (Device * d_self, guint file) {
1288     TapeDevice * self;
1289     gint got_file;
1290     int difference;
1291     char * header_buffer;
1292     dumpfile_t * rval;
1293     int buffer_len;
1294     IoResult result;
1295     char *msg;
1296
1297     self = TAPE_DEVICE(d_self);
1298
1299     if (device_in_error(self)) return NULL;
1300
1301     difference = file - d_self->file;
1302
1303     /* Check if we already read a filemark. */
1304     /* If we already read a filemark and the drive automaticaly goes to the
1305        next file, then we must reduce the difference by one. */
1306     if (d_self->is_eof && !self->fsf_after_filemark) {
1307         difference --;
1308     }
1309
1310     d_self->in_file = FALSE;
1311     d_self->is_eof = FALSE;
1312     d_self->block = 0;
1313
1314 reseek:
1315     if (difference > 0) {
1316         /* Seeking forwards */
1317         if (!tape_device_fsf(self, difference)) {
1318             tape_rewind(self->fd);
1319             device_set_error(d_self,
1320                 vstrallocf(_("Could not seek forward to file %d"), file),
1321                 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1322             return NULL;
1323         }
1324     } else { /* (difference <= 0) */
1325         /* Seeking backwards, or to this file itself */
1326
1327         /* if the drive supports bsf, we can do this the fancy way */
1328         if (self->bsf) {
1329             /* bsf one more than the difference */
1330             if (!tape_bsf(self->fd, -difference + 1)) {
1331                 tape_rewind(self->fd);
1332                 device_set_error(d_self,
1333                     vstrallocf(_("Could not seek backward to file %d"), file),
1334                     DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1335                 return NULL;
1336             }
1337
1338             /* now we are on the BOT side of the desired filemark, so FSF to get to the
1339              * EOT side of it */
1340             if (!tape_device_fsf(self, 1)) {
1341                 tape_rewind(self->fd);
1342                 device_set_error(d_self,
1343                     vstrallocf(_("Could not seek forward to file %d"), file),
1344                     DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1345                 return NULL;
1346             }
1347         } else {
1348             /* no BSF, so just rewind and seek forward */
1349             if (!tape_rewind(self->fd)) {
1350                 device_set_error(d_self,
1351                     vstrallocf(_("Could not rewind device while emulating BSF")),
1352                     DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1353                 return FALSE;
1354             }
1355
1356             if (!tape_device_fsf(self, file)) {
1357                 tape_rewind(self->fd);
1358                 device_set_error(d_self,
1359                     vstrallocf(_("Could not seek forward to file %d"), file),
1360                     DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1361                 return NULL;
1362             }
1363         }
1364     }
1365
1366     /* double-check that we're on the right fileno, if possible.  This is most
1367      * likely a programming error if it occurs, but could also be due to a weird
1368      * tape drive or driver (and that would *never* happen, right?) */
1369     got_file = tape_fileno(self->fd);
1370     if (got_file >= 0 && (guint)got_file != file) {
1371         device_set_error(d_self,
1372                 vstrallocf(_("Could not seek to file %d correctly; got %d"),
1373                             file, got_file),
1374                 DEVICE_STATUS_DEVICE_ERROR);
1375         d_self->file = (guint)got_file;
1376         return NULL;
1377     }
1378
1379     buffer_len = tape_device_read_size(d_self);
1380     header_buffer = malloc(buffer_len);
1381     d_self->is_eof = FALSE;
1382     result = tape_device_robust_read(self, header_buffer, &buffer_len, &msg);
1383
1384     if (result != RESULT_SUCCESS) {
1385         free(header_buffer);
1386         tape_rewind(self->fd);
1387         switch (result) {
1388         case RESULT_NO_DATA:
1389             /* If we read 0 bytes, that means we encountered a double
1390              * filemark, which indicates end of tape. This should
1391              * work even with QIC tapes on operating systems with
1392              * proper support. */
1393             d_self->file = file; /* other attributes are already correct */
1394             return make_tapeend_header();
1395
1396         case RESULT_SMALL_BUFFER:
1397             msg = stralloc(_("block size too small"));
1398             break;
1399
1400         default:
1401             msg = stralloc(_("unknown error"));
1402         case RESULT_ERROR:
1403             break;
1404         }
1405         device_set_error(d_self,
1406             g_strdup_printf(_("Error reading Amanda header: %s"), msg),
1407             DEVICE_STATUS_DEVICE_ERROR | DEVICE_STATUS_VOLUME_ERROR);
1408         amfree(msg);
1409         return NULL;
1410     }
1411
1412     rval = g_new(dumpfile_t, 1);
1413     parse_file_header(header_buffer, rval, buffer_len);
1414     amfree(header_buffer);
1415     switch (rval->type) {
1416     case F_DUMPFILE:
1417     case F_CONT_DUMPFILE:
1418     case F_SPLIT_DUMPFILE:
1419         break;
1420
1421     case F_NOOP:
1422         /* a NOOP is written on QIC tapes to avoid writing two sequential
1423          * filemarks when closing a device in WRITE or APPEND mode.  In this
1424          * case, we just seek to the next file. */
1425         amfree(rval);
1426         file++;
1427         difference = 1;
1428         goto reseek;
1429
1430     default:
1431         tape_rewind(self->fd);
1432         device_set_error(d_self,
1433             stralloc(_("Invalid amanda header while reading file header")),
1434             DEVICE_STATUS_VOLUME_ERROR);
1435         amfree(rval);
1436         return NULL;
1437     }
1438
1439     d_self->in_file = TRUE;
1440     d_self->file = file;
1441
1442     return rval;
1443 }
1444
1445 static gboolean
1446 tape_device_seek_block (Device * d_self, guint64 block) {
1447     TapeDevice * self;
1448     int difference;
1449
1450     self = TAPE_DEVICE(d_self);
1451
1452     if (device_in_error(self)) return FALSE;
1453
1454     difference = block - d_self->block;
1455
1456     if (difference > 0) {
1457         if (!tape_device_fsr(self, difference)) {
1458             device_set_error(d_self,
1459                 vstrallocf(_("Could not seek forward to block %ju: %s"), (uintmax_t)block, strerror(errno)),
1460                 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1461             return FALSE;
1462         }
1463     } else if (difference < 0) {
1464         if (!tape_device_bsr(self, difference, d_self->file, d_self->block)) {
1465             device_set_error(d_self,
1466                 vstrallocf(_("Could not seek backward to block %ju: %s"), (uintmax_t)block, strerror(errno)),
1467                 DEVICE_STATUS_VOLUME_ERROR | DEVICE_STATUS_DEVICE_ERROR);
1468             return FALSE;
1469         }
1470     }
1471
1472     d_self->block = block;
1473     return TRUE;
1474 }
1475
1476 static gboolean
1477 tape_device_eject (Device * d_self) {
1478     TapeDevice * self;
1479
1480     self = TAPE_DEVICE(d_self);
1481
1482     if (device_in_error(self)) return FALSE;
1483
1484     /* Open the device if not already opened */
1485     if (self->fd == -1) {
1486         self->fd = try_open_tape_device(self, self->private->device_filename);
1487         /* if the open failed, then try_open_tape_device already set the
1488          * approppriate error status */
1489         if (self->fd == -1)
1490             return FALSE;
1491     }
1492
1493     /* Rewind it. */
1494     if (!tape_rewind(self->fd)) {
1495         device_set_error(d_self,
1496             vstrallocf(_("Error rewinding device %s before ejecting: %s"),
1497                        self->private->device_filename, strerror(errno)),
1498               DEVICE_STATUS_DEVICE_ERROR
1499             | DEVICE_STATUS_VOLUME_ERROR);
1500         return FALSE;
1501     }
1502
1503     if (tape_offl(self->fd))
1504         return TRUE;
1505
1506     device_set_error(d_self,
1507         vstrallocf(_("Error ejecting device %s: %s\n"),
1508                    self->private->device_filename, strerror(errno)),
1509           DEVICE_STATUS_DEVICE_ERROR);
1510
1511     return FALSE;
1512 }
1513
1514 static gboolean
1515 tape_device_finish (Device * d_self) {
1516     TapeDevice * self;
1517     char *msg = NULL;
1518
1519     self = TAPE_DEVICE(d_self);
1520
1521     if (device_in_error(self))
1522         goto finish_error;
1523
1524     /* if we're already in ACCESS_NULL, then there are no filemarks or anything
1525      * to worry about, but we need to release the kernel device */
1526     if (d_self->access_mode == ACCESS_NULL) {
1527         robust_close(self->fd);
1528         self->fd = -1;
1529         return TRUE;
1530     }
1531
1532     /* Polish off this file, if relevant. */
1533     if (d_self->in_file && IS_WRITABLE_ACCESS_MODE(d_self->access_mode)) {
1534         if (!device_finish_file(d_self))
1535             goto finish_error;
1536     }
1537
1538     /* Straighten out the filemarks.  We already wrote one in finish_file, and
1539      * the device driver will write another filemark when we rewind.  This means
1540      * that, if we do nothing, we'll get two filemarks.  If final_filemarks is
1541      * 1, this would be wrong, so in this case we insert a F_NOOP header between
1542      * the two filemarks. */
1543     if (self->final_filemarks == 1 &&
1544         IS_WRITABLE_ACCESS_MODE(d_self->access_mode)) {
1545         dumpfile_t file;
1546         char *header;
1547         int result;
1548
1549         /* write a F_NOOP header */
1550         fh_init(&file);
1551         file.type = F_NOOP;
1552         header = device_build_amanda_header(d_self, &file, NULL);
1553         if (!header) {
1554             device_set_error(d_self,
1555                 stralloc(_("Amanda file header won't fit in a single block!")),
1556                 DEVICE_STATUS_DEVICE_ERROR);
1557             goto finish_error;
1558         }
1559
1560         result = tape_device_robust_write(self, header, d_self->block_size, &msg);
1561         if (result != RESULT_SUCCESS) {
1562             device_set_error(d_self,
1563                 vstrallocf(_("Error writing file header: %s"),
1564                             (result == RESULT_ERROR)? msg : _("out of space")),
1565                 DEVICE_STATUS_DEVICE_ERROR);
1566             amfree(header);
1567             amfree(msg);
1568             goto finish_error;
1569         }
1570         amfree(header);
1571     }
1572
1573     /* Rewind (the kernel will write a filemark first) */
1574     if (!tape_rewind(self->fd)) {
1575         device_set_error(d_self,
1576             vstrallocf(_("Couldn't rewind device to finish: %s"), strerror(errno)),
1577             DEVICE_STATUS_DEVICE_ERROR);
1578         goto finish_error;
1579     }
1580
1581     d_self->is_eof = FALSE;
1582     d_self->access_mode = ACCESS_NULL;
1583
1584     /* release the kernel's device */
1585     robust_close(self->fd);
1586     self->fd = -1;
1587
1588     return TRUE;
1589
1590 finish_error:
1591     d_self->access_mode = ACCESS_NULL;
1592
1593     /* release the kernel's device */
1594     robust_close(self->fd);
1595     self->fd = -1;
1596
1597     return FALSE;
1598 }
1599
1600 /* Works just like read(), except for the following:
1601  * 1) Retries on EINTR & friends.
1602  * 2) Stores count in parameter, not return value.
1603  * 3) Provides explicit return result.
1604  * *errmsg is only set on RESULT_ERROR.
1605  */
1606 static IoResult
1607 tape_device_robust_read (TapeDevice * self, void * buf, int * count, char **errmsg) {
1608     Device * d_self;
1609     int result;
1610
1611     d_self = (Device*)self;
1612
1613     /* Callers should ensure this. */
1614     g_assert(*count >= 0);
1615
1616     for (;;) {
1617         result = read(self->fd, buf, *count);
1618         if (result > 0) {
1619             /* Success. By definition, we read a full block. */
1620             d_self->is_eof = FALSE;
1621             *count = result;
1622             return RESULT_SUCCESS;
1623         } else if (result == 0) {
1624             d_self->is_eof = TRUE;
1625             return RESULT_NO_DATA;
1626         } else {
1627             if (0
1628 #ifdef EAGAIN
1629                 || errno == EAGAIN
1630 #endif
1631 #ifdef EWOULDBLOCK
1632                 || errno == EWOULDBLOCK
1633 #endif
1634 #ifdef EINTR
1635                 || errno == EINTR
1636 #endif
1637                 ) {
1638                 /* Interrupted system call */
1639                 continue;
1640             } else if ((0
1641 #ifdef ENOMEM
1642                         || errno == ENOMEM /* bad user-space buffer */
1643 #endif
1644 #ifdef EOVERFLOW
1645                         || errno == EOVERFLOW /* bad kernel-space buffer */
1646 #endif
1647 #ifdef EINVAL
1648                         || errno == EINVAL /* ??? */
1649 #endif
1650                         )) {
1651                 /* Buffer too small. */
1652                 g_warning("Buffer is too small (%d bytes) from %s: %s",
1653                         *count, self->private->device_filename, strerror(errno));
1654                 return RESULT_SMALL_BUFFER;
1655             } else {
1656                 *errmsg = g_strdup_printf(_("Error reading %d bytes from %s: %s"),
1657                         *count, self->private->device_filename, strerror(errno));
1658                 return RESULT_ERROR;
1659             }
1660         }
1661     }
1662
1663     g_assert_not_reached();
1664 }
1665
1666 /* Kernel workaround: If needed, poke the kernel so it doesn't fail.
1667    at the 2GB boundry. Parameters are G_GNUC_UNUSED in case NEED_RESETOFS
1668    is not defined. */
1669 static void check_resetofs(TapeDevice * self G_GNUC_UNUSED,
1670                            int count G_GNUC_UNUSED) {
1671 #ifdef NEED_RESETOFS
1672     Device * d_self;
1673     int result;
1674
1675     d_self = (Device*)self;
1676
1677     self->private->write_count += count;
1678     if (self->private->write_count < RESETOFS_THRESHOLD) {
1679         return;
1680     }
1681
1682     result = lseek(self->fd, 0, SEEK_SET);
1683     if (result < 0) {
1684         g_warning(_("lseek() failed during kernel 2GB workaround: %s"),
1685                strerror(errno));
1686     }
1687 #endif
1688 }
1689
1690 /* *errmsg is only set on RESULT_ERROR */
1691 static IoResult
1692 tape_device_robust_write (TapeDevice * self, void * buf, int count, char **errmsg) {
1693     Device * d_self;
1694     int result;
1695     gboolean retry = FALSE;
1696
1697     d_self = (Device*)self;
1698
1699     check_resetofs(self, count);
1700
1701     for (;;) {
1702         result = write(self->fd, buf, count);
1703
1704         /* Success. */
1705         if (result == count)
1706             return RESULT_SUCCESS;
1707
1708         if (result > 0) {
1709             /* write() returned a short count. This should not happen if the block sizes
1710              * are properly aligned. */
1711             *errmsg = g_strdup_printf("Short write on tape device: Tried %d, got %d.  Is "
1712                             "the drive using a block size smaller than %d bytes?",
1713                                 count, result, count);
1714             return RESULT_ERROR;
1715         }
1716
1717         /* Detect LEOM (early warning) and handle properly
1718          *
1719          * FreeBSD: 0-length write; next write will succeed
1720          *   http://lists.freebsd.org/pipermail/freebsd-scsi/2010-June/004414.html
1721          *
1722          * Solaris: 0-length write; next write will succeed
1723          *   (from Matthew Jacob on FreeBSD thread)
1724          *
1725          * Linux: -1/ENOSPC; next write will succeed
1726          *   http://www.mjmwired.net/kernel/Documentation/scsi/st.txt
1727          *
1728          * HP/UX: -1/ENOSPC; next write will succeed
1729          *   http://www.adssasia.com/Manual/IBM%203581%20tape%20autoloader.pdf
1730          */
1731         if (result == 0
1732 #ifdef ENOSPC
1733                         || (result < 0 && errno == ENOSPC)
1734 #endif
1735         ) {
1736             /* if we've retried once already, then we're probably really out of space */
1737             if (retry)
1738                 return RESULT_NO_SPACE;
1739             retry = TRUE;
1740             d_self->is_eom = TRUE;
1741
1742             g_debug("empty write to tape; treating as LEOM early warning and retrying");
1743             continue;
1744         }
1745
1746         /* at this point result < 0, so an error occurred - sort out what */
1747
1748         if (0
1749 #ifdef EAGAIN
1750                    || errno == EAGAIN
1751 #endif
1752 #ifdef EWOULDBLOCK
1753                    || errno == EWOULDBLOCK
1754 #endif
1755 #ifdef EINTR
1756                    || errno == EINTR
1757 #endif
1758                    ) {
1759                 /* Interrupted system call */
1760             continue;
1761         } else if (0
1762 #ifdef ENOSPC
1763                    || errno == ENOSPC
1764 #endif
1765 #ifdef EIO
1766                    || errno == EIO
1767 #endif
1768                    ) {
1769             /* Probably EOT. Print a message if we got EIO. */
1770 #ifdef EIO
1771             if (errno == EIO) {
1772                 g_warning(_("Got EIO on %s, assuming end of tape"),
1773                         self->private->device_filename);
1774             }
1775 #endif
1776             return RESULT_NO_SPACE;
1777         } else {
1778             /* WTF */
1779             *errmsg = vstrallocf(_("Kernel gave unexpected write() result of \"%s\" on device %s"),
1780                             strerror(errno), self->private->device_filename);
1781             return RESULT_ERROR;
1782         }
1783     }
1784
1785     g_assert_not_reached();
1786 }
1787
1788 /* Reads some number of tape blocks into the bit-bucket. If the count
1789    is negative, then we read the rest of the entire file. Returns the
1790    number of blocks read, or -1 if an error occured. If we encounter
1791    EOF (as opposed to some other error) we return the number of blocks
1792    actually read. */
1793 static int drain_tape_blocks(TapeDevice * self, int count) {
1794     char * buffer;
1795     gsize buffer_size;
1796     int i;
1797
1798     buffer_size = tape_device_read_size(self);
1799
1800     buffer = malloc(buffer_size);
1801
1802     for (i = 0; i < count || count < 0;) {
1803         int result;
1804
1805         result = read(self->fd, buffer, buffer_size);
1806         if (result > 0) {
1807             i ++;
1808             continue;
1809         } else if (result == 0) {
1810             amfree(buffer);
1811             return i;
1812         } else {
1813             /* First check for interrupted system call. */
1814             if (0
1815 #ifdef EAGAIN
1816                 || errno == EAGAIN
1817 #endif
1818 #ifdef EWOULDBLOCK
1819                 || errno == EWOULDBLOCK
1820 #endif
1821 #ifdef EINTR
1822                 || errno == EINTR
1823 #endif
1824                 ) {
1825                 /* Interrupted system call */
1826                 continue;
1827             } else if (0
1828 #ifdef ENOSPC
1829                        || errno == ENOSPC /* bad user-space buffer */
1830 #endif
1831 #ifdef EOVERFLOW
1832                        || errno == EOVERFLOW /* bad kernel-space buffer */
1833 #endif
1834 #ifdef EINVAL
1835                        || errno == EINVAL /* ??? */
1836 #endif
1837                        ) {
1838                 /* The buffer may not be big enough. But the OS is not
1839                    100% clear. We double the buffer and try again, but
1840                    in no case allow a buffer bigger than 32 MB. */
1841                 buffer_size *= 2;
1842
1843                 if (buffer_size > 32*1024*1024) {
1844                     amfree(buffer);
1845                     return -1;
1846                 } else {
1847                     buffer = realloc(buffer, buffer_size);
1848                     continue;
1849                 }
1850             }
1851         }
1852     }
1853
1854     amfree(buffer);
1855     return count;
1856 }
1857
1858 static gboolean
1859 tape_device_fsf (TapeDevice * self, guint count) {
1860     if (self->fsf) {
1861         return tape_fsf(self->fd, count);
1862     } else {
1863         guint i;
1864         for (i = 0; i < count; i ++) {
1865             if (drain_tape_blocks(self, -1) < 0)
1866                 return FALSE;
1867         }
1868         return TRUE;
1869     }
1870 }
1871
1872
1873 static gboolean
1874 tape_device_fsr (TapeDevice * self, guint count) {
1875     if (self->fsr) {
1876         return tape_fsr(self->fd, count);
1877     } else {
1878         int result = drain_tape_blocks(self, count);
1879         return result > 0 && (int)count == result;
1880     }
1881 }
1882
1883 /* Seek back the given number of blocks to block number block within
1884  * the current file, numbered file. */
1885
1886 static gboolean
1887 tape_device_bsr (TapeDevice * self, guint count, guint file, guint block) {
1888     if (self->bsr) {
1889         return tape_bsr(self->fd, count);
1890     } else if (self->bsf && self->fsf) {
1891         /* BSF, FSF to the right side of the filemark, and then FSR. */
1892         if (!tape_bsf(self->fd, 1))
1893             return FALSE;
1894
1895         if (!tape_fsf(self->fd, 1))
1896             return FALSE;
1897
1898         return tape_device_fsr(self, block);
1899     } else {
1900         /* rewind, FSF, and FSR */
1901         if (!tape_rewind(self->fd))
1902             return FALSE;
1903
1904         if (!tape_device_fsf(self, file))
1905             return FALSE;
1906
1907         return tape_device_fsr(self, block);
1908     }
1909     g_assert_not_reached();
1910 }
1911
1912 /* Go to the right place to write more data, and update the file
1913    number if possible. */
1914 static gboolean
1915 tape_device_eod (TapeDevice * self) {
1916     Device * d_self;
1917     int count;
1918
1919     d_self = (Device*)self;
1920
1921     if (self->eom) {
1922         int result;
1923         result = tape_eod(self->fd);
1924         if (result == TAPE_OP_ERROR) {
1925             return FALSE;
1926         } else if (result != TAPE_POSITION_UNKNOWN) {
1927             /* great - we just fast-forwarded to EOD, but don't know where we are, so
1928              * now we have to rewind and drain all of that data.  Warn the user so that
1929              * we can skip the fast-forward-rewind stage on the next run */
1930             g_warning("Seek to end of tape does not give an accurate tape position; set "
1931                       "the EOM property to 0 to avoid useless tape movement.");
1932             /* and set the property so that next time *this* object is opened for
1933              * append, we skip this stage */
1934             self->eom = FALSE;
1935             /* fall through to draining blocks, below */
1936         } else {
1937             /* We drop by 1 because Device will increment the first
1938                time the user does start_file. */
1939             d_self->file = result - 1;
1940             return TRUE;
1941         }
1942     }
1943
1944     if (!tape_rewind(self->fd))
1945         return FALSE;
1946
1947     count = 0;
1948     for (;;) {
1949         /* We alternately read a block and FSF. If the read is
1950            successful, then we are not there yet and should FSF
1951            again. */
1952         int result;
1953         result = drain_tape_blocks(self, 1);
1954         if (result == 1) {
1955             /* More data, FSF. */
1956             tape_device_fsf(self, 1);
1957             count ++;
1958         } else if (result == 0) {
1959             /* Finished. */
1960             d_self->file = count - 1;
1961             return TRUE;
1962         } else {
1963             return FALSE;
1964         }
1965     }
1966 }
1967
1968 static Device *
1969 tape_device_factory (char * device_name, char * device_type, char * device_node) {
1970     Device * rval;
1971     g_assert(0 == strcmp(device_type, "tape"));
1972     rval = DEVICE(g_object_new(TYPE_TAPE_DEVICE, NULL));
1973     device_open_device(rval, device_name, device_type, device_node);
1974     return rval;
1975 }
1976
1977 /*
1978  * Tape Operations using the POSIX interface
1979  */
1980
1981 /* Having one name for every operation would be too easy. */
1982 #if !defined(MTCOMPRESSION) && defined(MTCOMP)
1983 # define MTCOMPRESSION MTCOMP
1984 #endif
1985
1986 #if !defined(MTSETBLK) && defined(MTSETBSIZ)
1987 # define MTSETBLK MTSETBSIZ
1988 #endif
1989
1990 #if !defined(MTEOM) && defined(MTEOD)
1991 # define MTEOM MTEOD
1992 #endif
1993
1994 gboolean tape_rewind(int fd) {
1995     int count = 5;
1996     time_t stop_time;
1997
1998     /* We will retry this for up to 30 seconds or 5 retries,
1999        whichever is less, because some hardware/software combinations
2000        (notably EXB-8200 on FreeBSD) can fail to rewind. */
2001     stop_time = time(NULL) + 30;
2002
2003     while (--count >= 0 && time(NULL) < stop_time) {
2004         struct mtop mt;
2005         mt.mt_op = MTREW;
2006         mt.mt_count = 1;
2007
2008         if (0 == ioctl(fd, MTIOCTOP, &mt))
2009             return TRUE;
2010
2011         sleep(3);
2012     }
2013
2014     return FALSE;
2015 }
2016
2017 gboolean tape_fsf(int fd, guint count) {
2018     struct mtop mt;
2019     mt.mt_op = MTFSF;
2020     mt.mt_count = count;
2021     return 0 == ioctl(fd, MTIOCTOP, &mt);
2022 }
2023
2024 gboolean tape_bsf(int fd, guint count) {
2025     struct mtop mt;
2026     mt.mt_op = MTBSF;
2027     mt.mt_count = count;
2028     return 0 == ioctl(fd, MTIOCTOP, &mt);
2029 }
2030
2031 gboolean tape_fsr(int fd, guint count) {
2032     struct mtop mt;
2033     mt.mt_op = MTFSR;
2034     mt.mt_count = count;
2035     return 0 == ioctl(fd, MTIOCTOP, &mt);
2036 }
2037
2038 gboolean tape_bsr(int fd, guint count) {
2039     struct mtop mt;
2040     mt.mt_op = MTBSR;
2041     mt.mt_count = count;
2042     return 0 == ioctl(fd, MTIOCTOP, &mt);
2043 }
2044
2045 gint tape_fileno(int fd) {
2046     struct mtget get;
2047
2048     if (0 != ioctl(fd, MTIOCGET, &get))
2049         return TAPE_POSITION_UNKNOWN;
2050     if (get.mt_fileno < 0)
2051         return TAPE_POSITION_UNKNOWN;
2052     else
2053         return get.mt_fileno;
2054 }
2055
2056 gint tape_eod(int fd) {
2057     struct mtop mt;
2058     struct mtget get;
2059     mt.mt_op = MTEOM;
2060     mt.mt_count = 1;
2061     if (0 != ioctl(fd, MTIOCTOP, &mt))
2062         return TAPE_OP_ERROR;
2063
2064     /* Ignored result. This is just to flush buffers. */
2065     mt.mt_op = MTNOP;
2066     ioctl(fd, MTIOCTOP, &mt);
2067
2068     if (0 != ioctl(fd, MTIOCGET, &get))
2069         return TAPE_POSITION_UNKNOWN;
2070     if (get.mt_fileno < 0)
2071         return TAPE_POSITION_UNKNOWN;
2072     else
2073         return get.mt_fileno;
2074 }
2075
2076 gboolean tape_weof(int fd, guint8 count) {
2077     struct mtop mt;
2078     mt.mt_op = MTWEOF;
2079     mt.mt_count = count;
2080     return 0 == ioctl(fd, MTIOCTOP, &mt);
2081 }
2082
2083 gboolean tape_setcompression(int fd G_GNUC_UNUSED, 
2084         gboolean on G_GNUC_UNUSED) {
2085 #ifdef MTCOMPRESSION
2086     struct mtop mt;
2087     mt.mt_op = MTCOMPRESSION;
2088     mt.mt_count = on;
2089     return 0 == ioctl(fd, MTIOCTOP, &mt);
2090 #else
2091     return 0;
2092 #endif
2093 }
2094
2095 gboolean tape_offl(int fd) {
2096     struct mtop mt;
2097     int safe_errno;
2098
2099     mt.mt_op = MTOFFL;
2100     mt.mt_count = 1;
2101     if (0 == ioctl(fd, MTIOCTOP, &mt))
2102         return TRUE;
2103
2104     safe_errno = errno;
2105     g_debug("tape_off: ioctl(MTIOCTOP/MTOFFL) failed: %s", strerror(errno));
2106     errno = safe_errno;
2107
2108     return FALSE;
2109 }
2110
2111 DeviceStatusFlags tape_is_tape_device(int fd) {
2112     struct mtop mt;
2113     mt.mt_op = MTNOP;
2114     mt.mt_count = 1;
2115     if (0 == ioctl(fd, MTIOCTOP, &mt)) {
2116         return DEVICE_STATUS_SUCCESS;
2117 #ifdef ENOMEDIUM
2118     } else if (errno == ENOMEDIUM) {
2119         return DEVICE_STATUS_VOLUME_MISSING;
2120 #endif
2121     } else {
2122         g_debug("tape_is_tape_device: ioctl(MTIOCTOP/MTNOP) failed: %s",
2123                  strerror(errno));
2124         if (errno == EIO) {
2125             /* some devices return EIO while the drive is busy loading */
2126             return DEVICE_STATUS_DEVICE_ERROR|DEVICE_STATUS_DEVICE_BUSY;
2127         } else {
2128             return DEVICE_STATUS_DEVICE_ERROR;
2129         }
2130     }
2131 }
2132
2133 DeviceStatusFlags tape_is_ready(int fd, TapeDevice *t_self G_GNUC_UNUSED) {
2134     struct mtget get;
2135     if (0 == ioctl(fd, MTIOCGET, &get)) {
2136 #if defined(GMT_ONLINE) || defined(GMT_DR_OPEN)
2137         if (1
2138 #ifdef GMT_ONLINE
2139             && (t_self->broken_gmt_online || GMT_ONLINE(get.mt_gstat))
2140 #endif
2141 #ifdef GMT_DR_OPEN
2142             && !GMT_DR_OPEN(get.mt_gstat)
2143 #endif
2144             ) {
2145             return DEVICE_STATUS_SUCCESS;
2146         } else {
2147             return DEVICE_STATUS_VOLUME_MISSING;
2148         }
2149 #else /* Neither macro is defined. */
2150         return DEVICE_STATUS_SUCCESS;
2151 #endif
2152     } else {
2153         return DEVICE_STATUS_VOLUME_ERROR;
2154     }
2155 }
2156