1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
5    Copyright (C) 2014-2014 Planets Communications B.V.
6    Copyright (C) 2014-2021 Bareos GmbH & Co. KG
7 
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12 
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17 
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22 */
23 /*
24  * Kern Sibbald, MM
25  *
26  * Extracted from other source files Marco van Wieringen, June 2014
27  */
28 /**
29  * @file
30  * Generic Tape API device abstraction.
31  */
32 
33 #include "include/bareos.h"
34 #include "stored/device_control_record.h"
35 #include "stored/stored.h"
36 #include "generic_tape_device.h"
37 #include "stored/autochanger.h"
38 #include "lib/scsi_lli.h"
39 #include "lib/berrno.h"
40 #include "lib/util.h"
41 
42 #include <string>
43 
44 namespace storagedaemon {
45 
46 /**
47  * Open a tape device
48  */
OpenDevice(DeviceControlRecord * dcr,DeviceMode omode)49 void generic_tape_device::OpenDevice(DeviceControlRecord* dcr, DeviceMode omode)
50 {
51   file_size = 0;
52   int timeout = max_open_wait;
53 #if !defined(HAVE_WIN32)
54   mtop mt_com{};
55   utime_t start_time = time(NULL);
56 #endif
57 
58   mount(dcr, 1); /* do mount if required */
59 
60   Dmsg0(100, "Open dev: device is tape\n");
61 
62   GetAutochangerLoadedSlot(dcr);
63 
64   open_mode = omode;
65   set_mode(omode);
66 
67   if (timeout < 1) { timeout = 1; }
68   errno = 0;
69   Dmsg2(100, "Try open %s mode=%s\n", prt_name, mode_to_str(omode));
70 #if defined(HAVE_WIN32)
71   /*
72    * Windows Code
73    */
74   if ((fd = d_open(archive_device_string, oflags, 0)) < 0) {
75     dev_errno = errno;
76   }
77 #else
78   /*
79    * UNIX Code
80    *
81    * If busy retry each second for max_open_wait seconds
82    */
83   for (;;) {
84     /*
85      * Try non-blocking open
86      */
87     fd = d_open(archive_device_string, oflags | O_NONBLOCK, 0);
88     if (fd < 0) {
89       BErrNo be;
90       dev_errno = errno;
91       Dmsg5(100, "Open error on %s omode=%d oflags=%x errno=%d: ERR=%s\n",
92             prt_name, omode, oflags, errno, be.bstrerror());
93     } else {
94       /*
95        * Tape open, now rewind it
96        */
97       Dmsg0(100, "Rewind after open\n");
98       mt_com.mt_op = MTREW;
99       mt_com.mt_count = 1;
100 
101       /*
102        * Rewind only if dev is a tape
103        */
104       if (d_ioctl(fd, MTIOCTOP, (char*)&mt_com) < 0) {
105         BErrNo be;
106         dev_errno = errno; /* set error status from rewind */
107         d_close(fd);
108         ClearOpened();
109         Dmsg2(100, "Rewind error on %s close: ERR=%s\n", prt_name,
110               be.bstrerror(dev_errno));
111         /*
112          * If we get busy, device is probably rewinding, try again
113          */
114         if (dev_errno != EBUSY) { break; /* error -- no medium */ }
115       } else {
116         /*
117          * Got fd and rewind worked, so we must have medium in drive
118          */
119         d_close(fd);
120         fd = d_open(archive_device_string, oflags, 0); /* open normally */
121         if (fd < 0) {
122           BErrNo be;
123           dev_errno = errno;
124           Dmsg5(100, "Open error on %s omode=%d oflags=%x errno=%d: ERR=%s\n",
125                 prt_name, omode, oflags, errno, be.bstrerror());
126           break;
127         }
128         dev_errno = 0;
129         LockDoor();
130         SetOsDeviceParameters(dcr); /* do system dependent stuff */
131         break;                      /* Successfully opened and rewound */
132       }
133     }
134     Bmicrosleep(5, 0);
135 
136     /*
137      * Exceed wait time ?
138      */
139     if (time(NULL) - start_time >= max_open_wait) { break; /* yes, get out */ }
140   }
141 #endif
142 
143   if (!IsOpen()) {
144     BErrNo be;
145     Mmsg2(errmsg, _("Unable to open device %s: ERR=%s\n"), prt_name,
146           be.bstrerror(dev_errno));
147     Dmsg1(100, "%s", errmsg);
148   }
149 
150   Dmsg1(100, "open dev: tape %d opened\n", fd);
151 }
152 
153 /**
154  * Position device to end of medium (end of data)
155  *
156  * Returns: true  on succes
157  *          false on error
158  */
eod(DeviceControlRecord * dcr)159 bool generic_tape_device::eod(DeviceControlRecord* dcr)
160 {
161   mtop mt_com{};
162   bool ok = true;
163   int32_t os_file;
164 
165   if (fd < 0) {
166     dev_errno = EBADF;
167     Mmsg1(errmsg, _("Bad call to eod. Device %s not open\n"), prt_name);
168     return false;
169   }
170 
171 #if defined(__digital__) && defined(__unix__)
172   return fsf(VolCatInfo.VolCatFiles);
173 #endif
174 
175   Dmsg0(100, "Enter eod\n");
176   if (AtEot()) { return true; }
177 
178   ClearEof(); /* remove EOF flag */
179   block_num = file = 0;
180   file_size = 0;
181   file_addr = 0;
182 
183 #ifdef MTEOM
184   if (HasCap(CAP_FASTFSF) && !HasCap(CAP_EOM)) {
185     Dmsg0(100, "Using FAST FSF for EOM\n");
186     /*
187      * If unknown position, rewind
188      */
189     if (GetOsTapeFile() < 0) {
190       if (!rewind(NULL)) {
191         Dmsg0(100, "Rewind error\n");
192         return false;
193       }
194     }
195     mt_com.mt_op = MTFSF;
196     /*
197      * ***FIXME*** fix code to handle case that INT16_MAX is not large enough.
198      */
199     mt_com.mt_count = INT16_MAX; /* use big positive number */
200     if (mt_com.mt_count < 0) {
201       mt_com.mt_count = INT16_MAX; /* brain damaged system */
202     }
203   }
204 
205   if (HasCap(CAP_MTIOCGET) && (HasCap(CAP_FASTFSF) || HasCap(CAP_EOM))) {
206     if (HasCap(CAP_EOM)) {
207       Dmsg0(100, "Using EOM for EOM\n");
208       mt_com.mt_op = MTEOM;
209       mt_com.mt_count = 1;
210     }
211 
212     if (d_ioctl(fd, MTIOCTOP, (char*)&mt_com) < 0) {
213       BErrNo be;
214       clrerror(mt_com.mt_op);
215       Dmsg1(50, "ioctl error: %s\n", be.bstrerror());
216       UpdatePos(dcr);
217       Mmsg2(errmsg, _("ioctl MTEOM error on %s. ERR=%s.\n"), prt_name,
218             be.bstrerror());
219       Dmsg0(100, errmsg);
220       return false;
221     }
222 
223     os_file = GetOsTapeFile();
224     if (os_file < 0) {
225       BErrNo be;
226       clrerror(-1);
227       Mmsg2(errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"), prt_name,
228             be.bstrerror());
229       Dmsg0(100, errmsg);
230       return false;
231     }
232     Dmsg1(100, "EOD file=%d\n", os_file);
233     SetAteof();
234     file = os_file;
235   } else {
236 #endif
237     /*
238      * Rewind then use FSF until EOT reached
239      */
240     if (!rewind(NULL)) {
241       Dmsg0(100, "Rewind error.\n");
242       return false;
243     }
244 
245     /*
246      * Move file by file to the end of the tape
247      */
248     int file_num;
249     for (file_num = file; !AtEot(); file_num++) {
250       Dmsg0(200, "eod: doing fsf 1\n");
251       if (!fsf(1)) {
252         Dmsg0(100, "fsf error.\n");
253         return false;
254       }
255       /*
256        * Avoid infinite loop by ensuring we advance.
257        */
258       if (!AtEot() && file_num == (int)file) {
259         Dmsg1(100, "fsf did not advance from file %d\n", file_num);
260         SetAteof();
261         os_file = GetOsTapeFile();
262         if (os_file >= 0) {
263           Dmsg2(100, "Adjust file from %d to %d\n", file_num, os_file);
264           file = os_file;
265         }
266         break;
267       }
268     }
269 #ifdef MTEOM
270   }
271 #endif
272 
273   /*
274    * Some drivers leave us after second EOF when doing MTEOM, so we must backup
275    * so that appending overwrites the second EOF.
276    */
277   if (HasCap(CAP_BSFATEOM)) {
278     /*
279      * Backup over EOF
280      */
281     ok = bsf(1);
282 
283     /*
284      * If BSF worked and fileno is known (not -1), set file
285      */
286     os_file = GetOsTapeFile();
287     if (os_file >= 0) {
288       Dmsg2(100, "BSFATEOF adjust file from %d to %d\n", file, os_file);
289       file = os_file;
290     } else {
291       file++; /* wing it -- not correct on all OSes */
292     }
293   } else {
294     UpdatePos(dcr); /* update position */
295   }
296   Dmsg1(200, "EOD dev->file=%d\n", file);
297 
298   return ok;
299 }
300 
301 /**
302  * Called to indicate that we have just read an EOF from the device.
303  */
SetAteof()304 void generic_tape_device::SetAteof()
305 {
306   SetEof();
307   file++;
308   file_addr = 0;
309   file_size = 0;
310   block_num = 0;
311 }
312 
313 /**
314  * Called to indicate we are now at the end of the volume, and writing is not
315  * possible.
316  */
SetAteot()317 void generic_tape_device::SetAteot()
318 {
319   /*
320    * Make volume effectively read-only
321    */
322   SetBit(ST_EOF, state);
323   SetBit(ST_EOT, state);
324   SetBit(ST_WEOT, state);
325   ClearAppend();
326 }
327 
328 /**
329  * Rewind device and put it offline
330  *
331  * Returns: true  on success
332  *          false on failure
333  */
offline()334 bool generic_tape_device::offline()
335 {
336   mtop mt_com{};
337 
338   /*
339    * Remove EOF/EOT flags.
340    */
341   ClearBit(ST_APPENDREADY, state);
342   ClearBit(ST_READREADY, state);
343   ClearBit(ST_EOT, state);
344   ClearBit(ST_EOF, state);
345   ClearBit(ST_WEOT, state);
346 
347   block_num = file = 0;
348   file_size = 0;
349   file_addr = 0;
350   UnlockDoor();
351   mt_com.mt_op = MTOFFL;
352   mt_com.mt_count = 1;
353 
354   if (d_ioctl(fd, MTIOCTOP, (char*)&mt_com) < 0) {
355     BErrNo be;
356     dev_errno = errno;
357     Mmsg2(errmsg, _("ioctl MTOFFL error on %s. ERR=%s.\n"), prt_name,
358           be.bstrerror());
359     return false;
360   }
361   Dmsg1(100, "Offlined device %s\n", prt_name);
362 
363   return true;
364 }
365 
366 /**
367  * Write an end of file on the device
368  *
369  * Returns: true on success
370  *          false on failure
371  */
weof(int num)372 bool generic_tape_device::weof(int num)
373 {
374   mtop mt_com{};
375   int status;
376   Dmsg1(129, "=== weof_dev=%s\n", prt_name);
377 
378   if (!IsOpen()) {
379     dev_errno = EBADF;
380     Mmsg0(errmsg, _("Bad call to weof_dev. Device not open\n"));
381     Emsg0(M_FATAL, 0, errmsg);
382     return false;
383   }
384   file_size = 0;
385 
386   if (!CanAppend()) {
387     Mmsg0(errmsg, _("Attempt to WEOF on non-appendable Volume\n"));
388     Emsg0(M_FATAL, 0, errmsg);
389     return false;
390   }
391 
392   ClearEof();
393   ClearEot();
394   mt_com.mt_op = MTWEOF;
395   mt_com.mt_count = num;
396   status = d_ioctl(fd, MTIOCTOP, (char*)&mt_com);
397   if (status == 0) {
398     block_num = 0;
399     file += num;
400     file_addr = 0;
401   } else {
402     BErrNo be;
403 
404     clrerror(mt_com.mt_op);
405     if (status == -1) {
406       Mmsg2(errmsg, _("ioctl MTWEOF error on %s. ERR=%s.\n"), prt_name,
407             be.bstrerror());
408     }
409   }
410 
411   return status == 0;
412 }
413 
414 /**
415  * Foward space a file
416  *
417  * Returns: true  on success
418  *          false on failure
419  */
fsf(int num)420 bool generic_tape_device::fsf(int num)
421 {
422   int32_t os_file = 0;
423   mtop mt_com{};
424   int status = 0;
425 
426   if (!IsOpen()) {
427     dev_errno = EBADF;
428     Mmsg0(errmsg, _("Bad call to fsf. Device not open\n"));
429     Emsg0(M_FATAL, 0, errmsg);
430     return false;
431   }
432 
433   if (AtEot()) {
434     dev_errno = 0;
435     Mmsg1(errmsg, _("Device %s at End of Tape.\n"), prt_name);
436     return false;
437   }
438 
439   if (AtEof()) { Dmsg0(200, "ST_EOF set on entry to FSF\n"); }
440 
441   Dmsg0(100, "fsf\n");
442   block_num = 0;
443 
444   /*
445    * If Fast forward space file is set, then we
446    * use MTFSF to forward space and MTIOCGET
447    * to get the file position. We assume that
448    * the SCSI driver will ensure that we do not
449    * forward space past the end of the medium.
450    */
451   if (HasCap(CAP_FSF) && HasCap(CAP_MTIOCGET) && HasCap(CAP_FASTFSF)) {
452     int my_errno = 0;
453     mt_com.mt_op = MTFSF;
454     mt_com.mt_count = num;
455     status = d_ioctl(fd, MTIOCTOP, (char*)&mt_com);
456     if (status < 0) {
457       my_errno = errno; /* save errno */
458     } else if ((os_file = GetOsTapeFile()) < 0) {
459       my_errno = errno; /* save errno */
460     }
461     if (my_errno != 0) {
462       BErrNo be;
463 
464       SetEot();
465       Dmsg0(200, "Set ST_EOT\n");
466       clrerror(mt_com.mt_op);
467       Mmsg2(errmsg, _("ioctl MTFSF error on %s. ERR=%s.\n"), prt_name,
468             be.bstrerror(my_errno));
469       Dmsg1(200, "%s", errmsg);
470       return false;
471     }
472 
473     Dmsg1(200, "fsf file=%d\n", os_file);
474     SetAteof();
475     file = os_file;
476     return true;
477 
478     /*
479      * Here if CAP_FSF is set, and virtually all drives
480      * these days support it, we read a record, then forward
481      * space one file. Using this procedure, which is slow,
482      * is the only way we can be sure that we don't read
483      * two consecutive EOF marks, which means End of Data.
484      */
485   } else if (HasCap(CAP_FSF)) {
486     POOLMEM* rbuf;
487     int rbuf_len;
488     Dmsg0(200, "FSF has cap_fsf\n");
489     if (max_block_size == 0) {
490       rbuf_len = DEFAULT_BLOCK_SIZE;
491     } else {
492       rbuf_len = max_block_size;
493     }
494     rbuf = GetMemory(rbuf_len);
495     mt_com.mt_op = MTFSF;
496     mt_com.mt_count = 1;
497     while (num-- && !AtEot()) {
498       Dmsg0(100, "Doing read before fsf\n");
499       if ((status = this->read((char*)rbuf, rbuf_len)) < 0) {
500         if (errno == ENOMEM) { /* tape record exceeds buf len */
501           status = rbuf_len;   /* This is OK */
502           /*
503            * On IBM drives, they return ENOSPC at EOM instead of EOF status
504            */
505         } else if (AtEof() && errno == ENOSPC) {
506           status = 0;
507         } else if (HasCap(CAP_IOERRATEOM) && AtEof() && errno == EIO) {
508           if (HasCap(CAP_IBMLINTAPE)) {
509             Dmsg0(100, "Got EIO on read, checking lin_tape sense data\n");
510             if (CheckScsiAtEod(fd)) {
511               Dmsg0(100, "Sense data confirms it's EOD\n");
512               status = 0;
513             } else {
514               Dmsg0(100,
515                     "Not at EOD, might be a real error. Check sense trace from "
516                     "lin_taped logs.\n");
517               SetEot();
518               clrerror(-1);
519               Mmsg1(errmsg, _("read error on %s. ERR=Input/Output error.\n"),
520                     prt_name);
521               break;
522             }
523           } else {
524             Dmsg0(100, "Got EIO on read, assuming that's due to EOD\n");
525             status = 0;
526           }
527         } else {
528           BErrNo be;
529 
530           SetEot();
531           clrerror(-1);
532           Dmsg2(100, "Set ST_EOT read errno=%d. ERR=%s\n", dev_errno,
533                 be.bstrerror());
534           Mmsg2(errmsg, _("read error on %s. ERR=%s.\n"), prt_name,
535                 be.bstrerror());
536           Dmsg1(100, "%s", errmsg);
537           break;
538         }
539       }
540       if (status == 0) { /* EOF */
541         Dmsg1(100, "End of File mark from read. File=%d\n", file + 1);
542         /*
543          * Two reads of zero means end of tape
544          */
545         if (AtEof()) {
546           SetEot();
547           Dmsg0(100, "Set ST_EOT\n");
548           break;
549         } else {
550           SetAteof();
551           continue;
552         }
553       } else { /* Got data */
554         ClearEot();
555         ClearEof();
556       }
557 
558       Dmsg0(100, "Doing MTFSF\n");
559       status = d_ioctl(fd, MTIOCTOP, (char*)&mt_com);
560       if (status < 0) { /* error => EOT */
561         BErrNo be;
562 
563         SetEot();
564         Dmsg0(100, "Set ST_EOT\n");
565         clrerror(mt_com.mt_op);
566         Mmsg2(errmsg, _("ioctl MTFSF error on %s. ERR=%s.\n"), prt_name,
567               be.bstrerror());
568         Dmsg0(100, "Got < 0 for MTFSF\n");
569         Dmsg1(100, "%s", errmsg);
570       } else {
571         SetAteof();
572       }
573     }
574     FreeMemory(rbuf);
575 
576     /*
577      * No FSF, so use FSR to simulate it
578      */
579   } else {
580     Dmsg0(200, "Doing FSR for FSF\n");
581     while (num-- && !AtEot()) { fsr(INT32_MAX); /* returns -1 on EOF or EOT */ }
582     if (AtEot()) {
583       dev_errno = 0;
584       Mmsg1(errmsg, _("Device %s at End of Tape.\n"), prt_name);
585       status = -1;
586     } else {
587       status = 0;
588     }
589   }
590   Dmsg1(200, "Return %d from FSF\n", status);
591   if (AtEof()) { Dmsg0(200, "ST_EOF set on exit FSF\n"); }
592   if (AtEot()) { Dmsg0(200, "ST_EOT set on exit FSF\n"); }
593   Dmsg1(200, "Return from FSF file=%d\n", file);
594 
595   return status == 0;
596 }
597 
598 /**
599  * Backward space a file
600  *
601  * Returns: false on failure
602  *          true  on success
603  */
bsf(int num)604 bool generic_tape_device::bsf(int num)
605 {
606   mtop mt_com{};
607   int status;
608 
609   if (!IsOpen()) {
610     dev_errno = EBADF;
611     Mmsg0(errmsg, _("Bad call to bsf. Device not open\n"));
612     Emsg0(M_FATAL, 0, errmsg);
613     return false;
614   }
615 
616   Dmsg0(100, "bsf\n");
617   ClearEot();
618   ClearEof();
619   file -= num;
620   file_addr = 0;
621   file_size = 0;
622   mt_com.mt_op = MTBSF;
623   mt_com.mt_count = num;
624 
625   status = d_ioctl(fd, MTIOCTOP, (char*)&mt_com);
626   if (status < 0) {
627     BErrNo be;
628 
629     clrerror(mt_com.mt_op);
630     Mmsg2(errmsg, _("ioctl MTBSF error on %s. ERR=%s.\n"), prt_name,
631           be.bstrerror());
632   }
633 
634   return status == 0;
635 }
636 
DevGetOsPos(Device * dev,struct mtget * mt_stat)637 static inline bool DevGetOsPos(Device* dev, struct mtget* mt_stat)
638 {
639   Dmsg0(100, "DevGetOsPos\n");
640   return dev->HasCap(CAP_MTIOCGET)
641          && dev->d_ioctl(dev->fd, MTIOCGET, (char*)mt_stat) == 0
642          && mt_stat->mt_fileno >= 0;
643 }
644 
645 /**
646  * Foward space num records
647  *
648  * Returns: false on failure
649  *          true  on success
650  */
fsr(int num)651 bool generic_tape_device::fsr(int num)
652 {
653   mtop mt_com{};
654   int status;
655 
656   if (!IsOpen()) {
657     dev_errno = EBADF;
658     Mmsg0(errmsg, _("Bad call to fsr. Device not open\n"));
659     Emsg0(M_FATAL, 0, errmsg);
660     return false;
661   }
662 
663   if (!HasCap(CAP_FSR)) {
664     Mmsg1(errmsg, _("ioctl MTFSR not permitted on %s.\n"), prt_name);
665     return false;
666   }
667 
668   Dmsg1(100, "fsr %d\n", num);
669   mt_com.mt_op = MTFSR;
670   mt_com.mt_count = num;
671 
672   status = d_ioctl(fd, MTIOCTOP, (char*)&mt_com);
673   if (status == 0) {
674     ClearEof();
675     block_num += num;
676   } else {
677     BErrNo be;
678     struct mtget mt_stat;
679 
680     clrerror(mt_com.mt_op);
681     Dmsg1(100, "FSF fail: ERR=%s\n", be.bstrerror());
682     if (DevGetOsPos(this, &mt_stat)) {
683       Dmsg4(100, "Adjust from %d:%d to %d:%d\n", file, block_num,
684             mt_stat.mt_fileno, mt_stat.mt_blkno);
685       file = mt_stat.mt_fileno;
686       block_num = mt_stat.mt_blkno;
687     } else {
688       if (AtEof()) {
689         SetEot();
690       } else {
691         SetAteof();
692       }
693     }
694     Mmsg3(errmsg, _("ioctl MTFSR %d error on %s. ERR=%s.\n"), num, prt_name,
695           be.bstrerror());
696   }
697 
698   return status == 0;
699 }
700 
701 /**
702  * Backward space a record
703  *
704  * Returns:  false on failure
705  *           true  on success
706  */
bsr(int num)707 bool generic_tape_device::bsr(int num)
708 {
709   mtop mt_com{};
710   int status;
711 
712   if (!IsOpen()) {
713     dev_errno = EBADF;
714     Mmsg0(errmsg, _("Bad call to bsr_dev. Device not open\n"));
715     Emsg0(M_FATAL, 0, errmsg);
716     return false;
717   }
718 
719   if (!HasCap(CAP_BSR)) {
720     Mmsg1(errmsg, _("ioctl MTBSR not permitted on %s.\n"), prt_name);
721     return false;
722   }
723 
724   Dmsg0(100, "bsr_dev\n");
725   block_num -= num;
726   ClearEof();
727   ClearEot();
728   mt_com.mt_op = MTBSR;
729   mt_com.mt_count = num;
730 
731   status = d_ioctl(fd, MTIOCTOP, (char*)&mt_com);
732   if (status < 0) {
733     BErrNo be;
734 
735     clrerror(mt_com.mt_op);
736     Mmsg2(errmsg, _("ioctl MTBSR error on %s. ERR=%s.\n"), prt_name,
737           be.bstrerror());
738   }
739 
740   return status == 0;
741 }
742 
743 /**
744  * Load medium in device
745  *
746  * Returns: true  on success
747  *          false on failure
748  */
LoadDev()749 bool generic_tape_device::LoadDev()
750 {
751 #ifdef MTLOAD
752   mtop mt_com{};
753 #endif
754 
755   if (fd < 0) {
756     dev_errno = EBADF;
757     Mmsg0(errmsg, _("Bad call to LoadDev. Device not open\n"));
758     Emsg0(M_FATAL, 0, errmsg);
759     return false;
760   }
761 
762 #ifndef MTLOAD
763   Dmsg0(200, "stored: MTLOAD command not available\n");
764   BErrNo be;
765   dev_errno = ENOTTY; /* function not available */
766   Mmsg2(errmsg, _("ioctl MTLOAD error on %s. ERR=%s.\n"), prt_name,
767         be.bstrerror());
768   return false;
769 #else
770   block_num = file = 0;
771   file_size = 0;
772   file_addr = 0;
773   mt_com.mt_op = MTLOAD;
774   mt_com.mt_count = 1;
775   if (d_ioctl(fd, MTIOCTOP, (char*)&mt_com) < 0) {
776     BErrNo be;
777     dev_errno = errno;
778     Mmsg2(errmsg, _("ioctl MTLOAD error on %s. ERR=%s.\n"), prt_name,
779           be.bstrerror());
780     return false;
781   }
782 
783   return true;
784 #endif
785 }
786 
LockDoor()787 void generic_tape_device::LockDoor()
788 {
789 #ifdef MTLOCK
790   mtop mt_com{};
791 
792   mt_com.mt_op = MTLOCK;
793   mt_com.mt_count = 1;
794   if (d_ioctl(fd, MTIOCTOP, (char*)&mt_com) < 0) { clrerror(mt_com.mt_op); }
795 #endif
796 }
797 
UnlockDoor()798 void generic_tape_device::UnlockDoor()
799 {
800 #ifdef MTUNLOCK
801   mtop mt_com{};
802 
803   mt_com.mt_op = MTUNLOCK;
804   mt_com.mt_count = 1;
805   if (d_ioctl(fd, MTIOCTOP, (char*)&mt_com) < 0) { clrerror(mt_com.mt_op); }
806 #endif
807 }
808 
OsClrError()809 void generic_tape_device::OsClrError()
810 {
811 #if defined(MTIOCLRERR)
812   // Found on Solaris
813   if (d_ioctl(fd, MTIOCLRERR) < 0) { HandleError(MTIOCLRERR); }
814   Dmsg0(200, "Did MTIOCLRERR\n");
815 #elif defined(MTIOCERRSTAT)
816   // Typically on FreeBSD
817   BErrNo be;
818   union mterrstat mt_errstat;
819 
820   // Read and clear SCSI error status
821   Dmsg2(200, "Doing MTIOCERRSTAT errno=%d ERR=%s\n", dev_errno,
822         be.bstrerror(dev_errno));
823   if (d_ioctl(fd, MTIOCERRSTAT, (char*)&mt_errstat) < 0) {
824     HandleError(MTIOCERRSTAT);
825   }
826 #elif defined(MTCSE)
827   // Clear Subsystem Exception TRU64
828   mtop mt_com{};
829 
830   /*
831    * Clear any error condition on the tape
832    */
833   mt_com.mt_op = MTCSE;
834   mt_com.mt_count = 1;
835   if (d_ioctl(fd, MTIOCTOP, (char*)&mt_com) < 0) { HandleError(mt_com.mt_op); }
836   Dmsg0(200, "Did MTCSE\n");
837 #endif
838 }
839 
HandleError(int func)840 void generic_tape_device::HandleError(int func)
841 {
842   dev_errno = errno;
843   if (errno == EIO) {
844     VolCatInfo.VolCatErrors++;
845   } else if (errno == ENOTTY
846              || errno == ENOSYS) { /* Function not implemented */
847     std::string msg;
848     switch (func) {
849       case -1:
850         break; /* ignore message printed later */
851       case MTWEOF:
852         msg = "WTWEOF";
853         ClearCap(CAP_EOF); /* turn off feature */
854         break;
855 #ifdef MTEOM
856       case MTEOM:
857         msg = "WTEOM";
858         ClearCap(CAP_EOM); /* turn off feature */
859         break;
860 #endif
861       case MTFSF:
862         msg = "MTFSF";
863         ClearCap(CAP_FSF); /* turn off feature */
864         break;
865       case MTBSF:
866         msg = "MTBSF";
867         ClearCap(CAP_BSF); /* turn off feature */
868         break;
869       case MTFSR:
870         msg = "MTFSR";
871         ClearCap(CAP_FSR); /* turn off feature */
872         break;
873       case MTBSR:
874         msg = "MTBSR";
875         ClearCap(CAP_BSR); /* turn off feature */
876         break;
877       case MTREW:
878         msg = "MTREW";
879         break;
880 #ifdef MTSETBLK
881       case MTSETBLK:
882         msg = "MTSETBLK";
883         break;
884 #endif
885 #ifdef MTSETDRVBUFFER
886       case MTSETDRVBUFFER:
887         msg = "MTSETDRVBUFFER";
888         break;
889 #endif
890 #ifdef MTRESET
891       case MTRESET:
892         msg = "MTRESET";
893         break;
894 #endif
895 #ifdef MTSETBSIZ
896       case MTSETBSIZ:
897         msg = "MTSETBSIZ";
898         break;
899 #endif
900 #ifdef MTSRSZ
901       case MTSRSZ:
902         msg = "MTSRSZ";
903         break;
904 #endif
905 #ifdef MTLOAD
906       case MTLOAD:
907         msg = "MTLOAD";
908         break;
909 #endif
910 #ifdef MTLOCK
911       case MTLOCK:
912         msg = "MTLOCK";
913         break;
914 #endif
915 #ifdef MTUNLOCK
916       case MTUNLOCK:
917         msg = "MTUNLOCK";
918         break;
919 #endif
920       case MTOFFL:
921         msg = "MTOFFL";
922         break;
923 #ifdef MTIOCLRERR
924       case MTIOCLRERR:
925         msg = "MTIOCLRERR";
926         break;
927 #endif
928 #ifdef MTIOCERRSTAT
929       case MTIOCERRSTAT:
930         msg = "MTIOCERRSTAT";
931         break;
932 #endif
933 #ifdef MTCSE
934       case MTCSE:
935         msg = "MTCSE";
936         break;
937 #endif
938       default:
939         char buf[100];
940         Bsnprintf(buf, sizeof(buf), _("unknown func code %d"), func);
941         msg = buf;
942         break;
943     }
944     if (!msg.empty()) {
945       dev_errno = ENOSYS;
946       Mmsg1(errmsg, _("I/O function \"%s\" not supported on this device.\n"),
947             msg.c_str());
948       Emsg0(M_ERROR, 0, errmsg);
949     }
950   }
951 }
952 
clrerror(int func)953 void generic_tape_device::clrerror(int func)
954 {
955   HandleError(func);
956 
957   /*
958    * Now we try different methods of clearing the error status on the drive
959    * so that it is not locked for further operations.
960    */
961 
962   /*
963    * On some systems such as NetBSD, this clears all errors
964    */
965   GetOsTapeFile();
966 
967   // OS specific clear function.
968   OsClrError();
969 }
970 
SetOsDeviceParameters(DeviceControlRecord * dcr)971 void generic_tape_device::SetOsDeviceParameters(DeviceControlRecord* dcr)
972 {
973   Device* dev = dcr->dev;
974 
975   if (bstrcmp(dev->archive_device_string, "/dev/null")) {
976     return; /* no use trying to set /dev/null */
977   }
978 
979 #if defined(HAVE_LINUX_OS) || defined(HAVE_WIN32)
980   mtop mt_com{};
981 
982   Dmsg0(100, "In SetOsDeviceParameters\n");
983 #  if defined(MTSETBLK)
984   if (dev->min_block_size == dev->max_block_size
985       && dev->min_block_size == 0) { /* variable block mode */
986     mt_com.mt_op = MTSETBLK;
987     mt_com.mt_count = 0;
988     Dmsg0(100, "Set block size to zero\n");
989     if (dev->d_ioctl(dev->fd, MTIOCTOP, (char*)&mt_com) < 0) {
990       dev->clrerror(mt_com.mt_op);
991     }
992   }
993 #  endif
994 #  if defined(MTSETDRVBUFFER)
995   if (getuid() == 0) { /* Only root can do this */
996     mt_com.mt_op = MTSETDRVBUFFER;
997     mt_com.mt_count = MT_ST_CLEARBOOLEANS;
998     if (!dev->HasCap(CAP_TWOEOF)) { mt_com.mt_count |= MT_ST_TWO_FM; }
999     if (dev->HasCap(CAP_EOM)) { mt_com.mt_count |= MT_ST_FAST_MTEOM; }
1000     Dmsg0(100, "MTSETDRVBUFFER\n");
1001     if (dev->d_ioctl(dev->fd, MTIOCTOP, (char*)&mt_com) < 0) {
1002       dev->clrerror(mt_com.mt_op);
1003     }
1004   }
1005 #  endif
1006   return;
1007 #endif
1008 
1009 #ifdef HAVE_NETBSD_OS
1010   mtop mt_com{};
1011   if (dev->min_block_size == dev->max_block_size
1012       && dev->min_block_size == 0) { /* variable block mode */
1013     mt_com.mt_op = MTSETBSIZ;
1014     mt_com.mt_count = 0;
1015     if (dev->d_ioctl(dev->fd, MTIOCTOP, (char*)&mt_com) < 0) {
1016       dev->clrerror(mt_com.mt_op);
1017     }
1018     /* Get notified at logical end of tape */
1019     mt_com.mt_op = MTEWARN;
1020     mt_com.mt_count = 1;
1021     if (dev->d_ioctl(dev->fd, MTIOCTOP, (char*)&mt_com) < 0) {
1022       dev->clrerror(mt_com.mt_op);
1023     }
1024   }
1025   return;
1026 #endif
1027 
1028 #if HAVE_FREEBSD_OS || HAVE_OPENBSD_OS
1029   mtop mt_com{};
1030   if (dev->min_block_size == dev->max_block_size
1031       && dev->min_block_size == 0) { /* variable block mode */
1032     mt_com.mt_op = MTSETBSIZ;
1033     mt_com.mt_count = 0;
1034     if (dev->d_ioctl(dev->fd, MTIOCTOP, (char*)&mt_com) < 0) {
1035       dev->clrerror(mt_com.mt_op);
1036     }
1037   }
1038 #  if defined(MTIOCSETEOTMODEL)
1039   uint32_t neof;
1040   if (dev->HasCap(CAP_TWOEOF)) {
1041     neof = 2;
1042   } else {
1043     neof = 1;
1044   }
1045   if (dev->d_ioctl(dev->fd, MTIOCSETEOTMODEL, (caddr_t)&neof) < 0) {
1046     BErrNo be;
1047     dev->dev_errno = errno; /* save errno */
1048     Mmsg2(dev->errmsg, _("Unable to set eotmodel on device %s: ERR=%s\n"),
1049           dev->print_name(), be.bstrerror(dev->dev_errno));
1050     Jmsg(dcr->jcr, M_FATAL, 0, dev->errmsg);
1051   }
1052 #  endif
1053   return;
1054 #endif
1055 
1056 #ifdef HAVE_SUN_OS
1057   mtop mt_com{};
1058   if (dev->min_block_size == dev->max_block_size
1059       && dev->min_block_size == 0) { /* variable block mode */
1060     mt_com.mt_op = MTSRSZ;
1061     mt_com.mt_count = 0;
1062     if (dev->d_ioctl(dev->fd, MTIOCTOP, (char*)&mt_com) < 0) {
1063       dev->clrerror(mt_com.mt_op);
1064     }
1065   }
1066   return;
1067 #endif
1068 }
1069 
1070 /**
1071  * Returns file position on tape or -1
1072  */
GetOsTapeFile()1073 int32_t generic_tape_device::GetOsTapeFile()
1074 {
1075   struct mtget mt_stat;
1076 
1077   if (HasCap(CAP_MTIOCGET) && d_ioctl(fd, MTIOCGET, (char*)&mt_stat) == 0) {
1078     return mt_stat.mt_fileno;
1079   }
1080 
1081   return -1;
1082 }
1083 
1084 /**
1085  * Rewind the device.
1086  *
1087  * Returns: true  on success
1088  *          false on failure
1089  */
rewind(DeviceControlRecord * dcr)1090 bool generic_tape_device::rewind(DeviceControlRecord* dcr)
1091 {
1092   mtop mt_com{};
1093   unsigned int i;
1094   bool first = true;
1095 
1096   Dmsg3(400, "rewind res=%d fd=%d %s\n", NumReserved(), fd, prt_name);
1097 
1098   /*
1099    * Remove EOF/EOT flags.
1100    */
1101   ClearBit(ST_EOT, state);
1102   ClearBit(ST_EOF, state);
1103   ClearBit(ST_WEOT, state);
1104 
1105   block_num = file = 0;
1106   file_size = 0;
1107   file_addr = 0;
1108   if (fd < 0) { return false; }
1109 
1110   mt_com.mt_op = MTREW;
1111   mt_com.mt_count = 1;
1112 
1113   /*
1114    * If we get an I/O error on rewind, it is probably because
1115    * the drive is actually busy. We loop for (about 5 minutes)
1116    * retrying every 5 seconds.
1117    */
1118   for (i = max_rewind_wait;; i -= 5) {
1119     if (d_ioctl(fd, MTIOCTOP, (char*)&mt_com) < 0) {
1120       BErrNo be;
1121 
1122       clrerror(mt_com.mt_op);
1123       if (i == max_rewind_wait) {
1124         Dmsg1(200, "Rewind error, %s. retrying ...\n", be.bstrerror());
1125       }
1126       /*
1127        * This is a gross hack, because if the user has the
1128        * device mounted (i.e. open), then uses mtx to load
1129        * a tape, the current open file descriptor is invalid.
1130        * So, we close the drive and re-open it.
1131        */
1132       if (first && dcr) {
1133         DeviceMode oo_mode = open_mode;
1134         d_close(fd);
1135         ClearOpened();
1136         open(dcr, oo_mode);
1137         if (fd < 0) { return false; }
1138         first = false;
1139         continue;
1140       }
1141 #ifdef HAVE_SUN_OS
1142       if (dev_errno == EIO) {
1143         Mmsg1(errmsg, _("No tape loaded or drive offline on %s.\n"), prt_name);
1144         return false;
1145       }
1146 #else
1147       if (dev_errno == EIO && i > 0) {
1148         Dmsg0(200, "Sleeping 5 seconds.\n");
1149         Bmicrosleep(5, 0);
1150         continue;
1151       }
1152 #endif
1153       Mmsg2(errmsg, _("Rewind error on %s. ERR=%s.\n"), prt_name,
1154             be.bstrerror());
1155       return false;
1156     }
1157     break;
1158   }
1159 
1160   return true;
1161 }
1162 
1163 // (Un)mount the device (for tape devices)
do_mount(DeviceControlRecord * dcr,int mount,int dotimeout)1164 bool generic_tape_device::do_mount(DeviceControlRecord* dcr, int mount, int dotimeout)
1165 {
1166   PoolMem ocmd(PM_FNAME);
1167   POOLMEM* results;
1168   char* icmd;
1169   int status, tries;
1170   BErrNo be;
1171 
1172   if (mount) {
1173     icmd = device_resource->mount_command;
1174   } else {
1175     icmd = device_resource->unmount_command;
1176   }
1177 
1178   EditMountCodes(ocmd, icmd);
1179   Dmsg2(100, "do_mount: cmd=%s mounted=%d\n", ocmd.c_str(),
1180         IsMounted());
1181 
1182   if (dotimeout) {
1183     /* Try at most 10 times to (un)mount the device. This should perhaps be
1184      * configurable. */
1185     tries = 10;
1186   } else {
1187     tries = 1;
1188   }
1189   results = GetMemory(4000);
1190 
1191   /* If busy retry each second */
1192   Dmsg1(100, "do_mount run_prog=%s\n", ocmd.c_str());
1193   while ((status = RunProgramFullOutput(ocmd.c_str(),
1194                                         max_open_wait / 2, results))
1195          != 0) {
1196     if (tries-- > 0) { continue; }
1197 
1198     Dmsg5(100, "Device %s cannot be %smounted. stat=%d result=%s ERR=%s\n",
1199           print_name(), (mount ? "" : "un"), status, results,
1200           be.bstrerror(status));
1201     Mmsg(errmsg, _("Device %s cannot be %smounted. ERR=%s\n"),
1202          print_name(), (mount ? "" : "un"), be.bstrerror(status));
1203 
1204     FreePoolMemory(results);
1205     Dmsg0(200, "============ mount=0\n");
1206     return false;
1207   }
1208 
1209   FreePoolMemory(results);
1210   Dmsg1(200, "============ mount=%d\n", mount);
1211   return true;
1212 }
1213 
StatusDev()1214 char* generic_tape_device::StatusDev()
1215 {
1216   struct mtget mt_stat;
1217   char* status;
1218 
1219   status = (char*)malloc(BMT_BYTES);
1220   ClearAllBits(BMT_MAX, status);
1221 
1222   if (BitIsSet(ST_EOT, state) || BitIsSet(ST_WEOT, state)) {
1223     SetBit(BMT_EOD, status);
1224     Pmsg0(-20, " EOD");
1225   }
1226 
1227   if (BitIsSet(ST_EOF, state)) {
1228     SetBit(BMT_EOF, status);
1229     Pmsg0(-20, " EOF");
1230   }
1231 
1232   SetBit(BMT_TAPE, status);
1233   Pmsg0(-20, _(" Bareos status:"));
1234   Pmsg2(-20, _(" file=%d block=%d\n"), file, block_num);
1235   if (d_ioctl(fd, MTIOCGET, (char*)&mt_stat) < 0) {
1236     BErrNo be;
1237 
1238     dev_errno = errno;
1239     Mmsg2(errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"), print_name(),
1240           be.bstrerror());
1241     free(status);
1242     return 0;
1243   }
1244   Pmsg0(-20, _(" Device status:"));
1245 
1246 #if defined(HAVE_LINUX_OS)
1247   if (GMT_EOF(mt_stat.mt_gstat)) {
1248     SetBit(BMT_EOF, status);
1249     Pmsg0(-20, " EOF");
1250   }
1251   if (GMT_BOT(mt_stat.mt_gstat)) {
1252     SetBit(BMT_BOT, status);
1253     Pmsg0(-20, " BOT");
1254   }
1255   if (GMT_EOT(mt_stat.mt_gstat)) {
1256     SetBit(BMT_EOT, status);
1257     Pmsg0(-20, " EOT");
1258   }
1259   if (GMT_SM(mt_stat.mt_gstat)) {
1260     SetBit(BMT_SM, status);
1261     Pmsg0(-20, " SM");
1262   }
1263   if (GMT_EOD(mt_stat.mt_gstat)) {
1264     SetBit(BMT_EOD, status);
1265     Pmsg0(-20, " EOD");
1266   }
1267   if (GMT_WR_PROT(mt_stat.mt_gstat)) {
1268     SetBit(BMT_WR_PROT, status);
1269     Pmsg0(-20, " WR_PROT");
1270   }
1271   if (GMT_ONLINE(mt_stat.mt_gstat)) {
1272     SetBit(BMT_ONLINE, status);
1273     Pmsg0(-20, " ONLINE");
1274   }
1275   if (GMT_DR_OPEN(mt_stat.mt_gstat)) {
1276     SetBit(BMT_DR_OPEN, status);
1277     Pmsg0(-20, " DR_OPEN");
1278   }
1279   if (GMT_IM_REP_EN(mt_stat.mt_gstat)) {
1280     SetBit(BMT_IM_REP_EN, status);
1281     Pmsg0(-20, " IM_REP_EN");
1282   }
1283 #elif defined(HAVE_WIN32)
1284   if (GMT_EOF(mt_stat.mt_gstat)) {
1285     SetBit(BMT_EOF, status);
1286     Pmsg0(-20, " EOF");
1287   }
1288   if (GMT_BOT(mt_stat.mt_gstat)) {
1289     SetBit(BMT_BOT, status);
1290     Pmsg0(-20, " BOT");
1291   }
1292   if (GMT_EOT(mt_stat.mt_gstat)) {
1293     SetBit(BMT_EOT, status);
1294     Pmsg0(-20, " EOT");
1295   }
1296   if (GMT_EOD(mt_stat.mt_gstat)) {
1297     SetBit(BMT_EOD, status);
1298     Pmsg0(-20, " EOD");
1299   }
1300   if (GMT_WR_PROT(mt_stat.mt_gstat)) {
1301     SetBit(BMT_WR_PROT, status);
1302     Pmsg0(-20, " WR_PROT");
1303   }
1304   if (GMT_ONLINE(mt_stat.mt_gstat)) {
1305     SetBit(BMT_ONLINE, status);
1306     Pmsg0(-20, " ONLINE");
1307   }
1308   if (GMT_DR_OPEN(mt_stat.mt_gstat)) {
1309     SetBit(BMT_DR_OPEN, status);
1310     Pmsg0(-20, " DR_OPEN");
1311   }
1312   if (GMT_IM_REP_EN(mt_stat.mt_gstat)) {
1313     SetBit(BMT_IM_REP_EN, status);
1314     Pmsg0(-20, " IM_REP_EN");
1315   }
1316 #endif /* HAVE_LINUX_OS || HAVE_WIN32 */
1317 
1318   if (HasCap(CAP_MTIOCGET)) {
1319     Pmsg2(-20, _(" file=%d block=%d\n"), mt_stat.mt_fileno, mt_stat.mt_blkno);
1320   } else {
1321     Pmsg2(-20, _(" file=%d block=%d\n"), -1, -1);
1322   }
1323 
1324   return status;
1325 }
1326 
1327 /**
1328  * Set the position of the device.
1329  *
1330  * Returns: true  on succes
1331  *          false on error
1332  */
UpdatePos(DeviceControlRecord * dcr)1333 bool generic_tape_device::UpdatePos(DeviceControlRecord* dcr) { return true; }
1334 
1335 /**
1336  * Reposition the device to file, block
1337  *
1338  * Returns: false on failure
1339  *          true  on success
1340  */
Reposition(DeviceControlRecord * dcr,uint32_t rfile,uint32_t rblock)1341 bool generic_tape_device::Reposition(DeviceControlRecord* dcr,
1342                                      uint32_t rfile,
1343                                      uint32_t rblock)
1344 {
1345   Dmsg4(100, "Reposition from %u:%u to %u:%u\n", file, block_num, rfile,
1346         rblock);
1347   if (rfile < file) {
1348     Dmsg0(100, "Rewind\n");
1349     if (!rewind(NULL)) { return false; }
1350   }
1351 
1352   if (rfile > file) {
1353     Dmsg1(100, "fsf %d\n", rfile - file);
1354     if (!fsf(rfile - file)) {
1355       Dmsg1(100, "fsf failed! ERR=%s\n", bstrerror());
1356       return false;
1357     }
1358     Dmsg2(100, "wanted_file=%d at_file=%d\n", rfile, file);
1359   }
1360 
1361   if (rblock < block_num) {
1362     Dmsg2(100, "wanted_blk=%d at_blk=%d\n", rblock, block_num);
1363     Dmsg0(100, "bsf 1\n");
1364     bsf(1);
1365     Dmsg0(100, "fsf 1\n");
1366     fsf(1);
1367     Dmsg2(100, "wanted_blk=%d at_blk=%d\n", rblock, block_num);
1368   }
1369 
1370   if (HasCap(CAP_POSITIONBLOCKS) && rblock > block_num) {
1371     /*
1372      * Ignore errors as Bareos can read to the correct block.
1373      */
1374     Dmsg1(100, "fsr %d\n", rblock - block_num);
1375     return fsr(rblock - block_num);
1376   } else {
1377     while (rblock > block_num) {
1378       if (DeviceControlRecord::ReadStatus::Ok
1379           != dcr->ReadBlockFromDev(NO_BLOCK_NUMBER_CHECK)) {
1380         BErrNo be;
1381         dev_errno = errno;
1382         Dmsg2(30, "Failed to find requested block on %s: ERR=%s", prt_name,
1383               be.bstrerror());
1384         return false;
1385       }
1386       Dmsg2(300, "moving forward wanted_blk=%d at_blk=%d\n", rblock, block_num);
1387     }
1388   }
1389 
1390   return true;
1391 }
1392 
1393 /**
1394  * Mount the device.
1395  *
1396  * If timeout, wait until the mount command returns 0.
1397  * If !timeout, try to mount the device only once.
1398  */
MountBackend(DeviceControlRecord * dcr,int timeout)1399 bool generic_tape_device::MountBackend(DeviceControlRecord* dcr, int timeout)
1400 {
1401   bool retval = true;
1402 
1403   if (RequiresMount() && device_resource->mount_command) {
1404     retval = do_mount(dcr, true, timeout);
1405   }
1406 
1407   return retval;
1408 }
1409 
1410 /**
1411  * Unmount the device
1412  *
1413  * If timeout, wait until the unmount command returns 0.
1414  * If !timeout, try to unmount the device only once.
1415  */
UnmountBackend(DeviceControlRecord * dcr,int timeout)1416 bool generic_tape_device::UnmountBackend(DeviceControlRecord* dcr, int timeout)
1417 {
1418   bool retval = true;
1419 
1420   if (RequiresMount() && device_resource->unmount_command) {
1421     retval = do_mount(dcr, false, timeout);
1422   }
1423 
1424   return retval;
1425 }
1426 
d_open(const char * pathname,int flags,int mode)1427 int generic_tape_device::d_open(const char* pathname, int flags, int mode)
1428 {
1429   return ::open(pathname, flags, mode);
1430 }
1431 
d_read(int fd,void * buffer,size_t count)1432 ssize_t generic_tape_device::d_read(int fd, void* buffer, size_t count)
1433 {
1434   return ::read(fd, buffer, count);
1435 }
1436 
d_write(int fd,const void * buffer,size_t count)1437 ssize_t generic_tape_device::d_write(int fd, const void* buffer, size_t count)
1438 {
1439   return ::write(fd, buffer, count);
1440 }
1441 
d_close(int fd)1442 int generic_tape_device::d_close(int fd) { return ::close(fd); }
1443 
d_ioctl(int fd,ioctl_req_t request,char * op)1444 int generic_tape_device::d_ioctl(int fd, ioctl_req_t request, char* op)
1445 {
1446   return -1;
1447 }
1448 
d_lseek(DeviceControlRecord * dcr,boffset_t offset,int whence)1449 boffset_t generic_tape_device::d_lseek(DeviceControlRecord* dcr,
1450                                        boffset_t offset,
1451                                        int whence)
1452 {
1453   return -1;
1454 }
1455 
d_truncate(DeviceControlRecord * dcr)1456 bool generic_tape_device::d_truncate(DeviceControlRecord* dcr)
1457 {
1458   /*
1459    * Maybe we should rewind and write and eof ????
1460    */
1461   return true; /* We don't really truncate tapes */
1462 }
1463 
1464 } /* namespace storagedaemon  */
1465