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