2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
5 Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
7 The original author of Bacula is Kern Sibbald, with contributions
8 from many others, a complete list can be found in the file AUTHORS.
10 You may use this file and others of this release according to the
11 license defined in the LICENSE file, which includes the Affero General
12 Public License, v3.0 ("AGPLv3") and some additional permissions and
13 terms pursuant to its AGPLv3 Section 7.
15 This notice must be preserved when any source code is
16 conveyed and/or propagated.
18 Bacula(R) is a registered trademark of Kern Sibbald.
22 * os.c -- Operating System dependent dev.c routines
24 * written by, Kern Sibbald, MM
25 * separated from dev.c February 2014
27 * Note, this is the device dependent code, and may have
28 * to be modified for each system.
35 /* Returns file position on tape or -1 */
36 int32_t DEVICE::get_os_tape_file()
40 if (has_cap(CAP_MTIOCGET) &&
41 d_ioctl(m_fd, MTIOCGET, (char *)&mt_stat) == 0) {
42 return mt_stat.mt_fileno;
48 void set_os_device_parameters(DCR *dcr)
50 DEVICE *dev = dcr->dev;
52 if (strcmp(dev->dev_name, "/dev/null") == 0) {
53 return; /* no use trying to set /dev/null */
56 #if defined(HAVE_LINUX_OS) || defined(HAVE_WIN32)
59 Dmsg0(100, "In set_os_device_parameters\n");
61 if (dev->min_block_size == dev->max_block_size &&
62 dev->min_block_size == 0) { /* variable block mode */
63 mt_com.mt_op = MTSETBLK;
65 Dmsg0(100, "Set block size to zero\n");
66 if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
67 dev->clrerror(MTSETBLK);
71 #if defined(MTSETDRVBUFFER)
72 if (getuid() == 0) { /* Only root can do this */
73 mt_com.mt_op = MTSETDRVBUFFER;
74 mt_com.mt_count = MT_ST_CLEARBOOLEANS;
75 if (!dev->has_cap(CAP_TWOEOF)) {
76 mt_com.mt_count |= MT_ST_TWO_FM;
78 if (dev->has_cap(CAP_EOM)) {
79 mt_com.mt_count |= MT_ST_FAST_MTEOM;
81 Dmsg0(100, "MTSETDRVBUFFER\n");
82 if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
83 dev->clrerror(MTSETDRVBUFFER);
92 if (dev->min_block_size == dev->max_block_size &&
93 dev->min_block_size == 0) { /* variable block mode */
94 mt_com.mt_op = MTSETBSIZ;
96 if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
97 dev->clrerror(MTSETBSIZ);
99 /* Get notified at logical end of tape */
100 mt_com.mt_op = MTEWARN;
102 if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
103 dev->clrerror(MTEWARN);
109 #if HAVE_FREEBSD_OS || HAVE_OPENBSD_OS
111 if (dev->min_block_size == dev->max_block_size &&
112 dev->min_block_size == 0) { /* variable block mode */
113 mt_com.mt_op = MTSETBSIZ;
115 if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
116 dev->clrerror(MTSETBSIZ);
119 #if defined(MTIOCSETEOTMODEL)
121 if (dev->has_cap(CAP_TWOEOF)) {
126 if (dev->d_ioctl(dev->fd(), MTIOCSETEOTMODEL, (caddr_t)&neof) < 0) {
128 dev->dev_errno = errno; /* save errno */
129 Mmsg2(dev->errmsg, _("Unable to set eotmodel on device %s: ERR=%s\n"),
130 dev->print_name(), be.bstrerror(dev->dev_errno));
131 Jmsg(dcr->jcr, M_FATAL, 0, dev->errmsg);
139 if (dev->min_block_size == dev->max_block_size &&
140 dev->min_block_size == 0) { /* variable block mode */
141 mt_com.mt_op = MTSRSZ;
143 if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
144 dev->clrerror(MTSRSZ);
151 bool dev_get_os_pos(DEVICE *dev, struct mtget *mt_stat)
153 Dmsg0(100, "dev_get_os_pos\n");
154 return dev->has_cap(CAP_MTIOCGET) &&
155 dev->d_ioctl(dev->fd(), MTIOCGET, (char *)mt_stat) == 0 &&
156 mt_stat->mt_fileno >= 0;
160 * Return the status of the device. This was meant
161 * to be a generic routine. Unfortunately, it doesn't
162 * seem possible (at least I do not know how to do it
163 * currently), which means that for the moment, this
164 * routine has very little value.
168 uint32_t status_dev(DEVICE *dev)
170 struct mtget mt_stat;
173 if (dev->state & (ST_EOT | ST_WEOT)) {
177 if (dev->state & ST_EOF) {
181 if (dev->is_tape()) {
183 Pmsg0(-20,_(" Bacula status:"));
184 Pmsg2(-20,_(" file=%d block=%d\n"), dev->file, dev->block_num);
185 if (dev->d_ioctl(dev->fd(), MTIOCGET, (char *)&mt_stat) < 0) {
187 dev->dev_errno = errno;
188 Mmsg2(dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"),
189 dev->print_name(), be.bstrerror());
192 Pmsg0(-20, _(" Device status:"));
194 #if defined(HAVE_LINUX_OS)
195 if (GMT_EOF(mt_stat.mt_gstat)) {
199 if (GMT_BOT(mt_stat.mt_gstat)) {
203 if (GMT_EOT(mt_stat.mt_gstat)) {
207 if (GMT_SM(mt_stat.mt_gstat)) {
211 if (GMT_EOD(mt_stat.mt_gstat)) {
215 if (GMT_WR_PROT(mt_stat.mt_gstat)) {
217 Pmsg0(-20, " WR_PROT");
219 if (GMT_ONLINE(mt_stat.mt_gstat)) {
221 Pmsg0(-20, " ONLINE");
223 if (GMT_DR_OPEN(mt_stat.mt_gstat)) {
225 Pmsg0(-20, " DR_OPEN");
227 if (GMT_IM_REP_EN(mt_stat.mt_gstat)) {
228 stat |= BMT_IM_REP_EN;
229 Pmsg0(-20, " IM_REP_EN");
231 #elif defined(HAVE_WIN32)
232 if (GMT_EOF(mt_stat.mt_gstat)) {
236 if (GMT_BOT(mt_stat.mt_gstat)) {
240 if (GMT_EOT(mt_stat.mt_gstat)) {
244 if (GMT_EOD(mt_stat.mt_gstat)) {
248 if (GMT_WR_PROT(mt_stat.mt_gstat)) {
250 Pmsg0(-20, " WR_PROT");
252 if (GMT_ONLINE(mt_stat.mt_gstat)) {
254 Pmsg0(-20, " ONLINE");
256 if (GMT_DR_OPEN(mt_stat.mt_gstat)) {
258 Pmsg0(-20, " DR_OPEN");
260 if (GMT_IM_REP_EN(mt_stat.mt_gstat)) {
261 stat |= BMT_IM_REP_EN;
262 Pmsg0(-20, " IM_REP_EN");
265 #endif /* !SunOS && !OSF */
266 if (dev->has_cap(CAP_MTIOCGET)) {
267 Pmsg2(-20, _(" file=%d block=%d\n"), mt_stat.mt_fileno, mt_stat.mt_blkno);
269 Pmsg2(-20, _(" file=%d block=%d\n"), -1, -1);
272 stat |= BMT_ONLINE | BMT_BOT;
278 * If implemented in system, clear the tape
281 void DEVICE::clrerror(int func)
283 const char *msg = NULL;
286 dev_errno = errno; /* save errno */
288 VolCatInfo.VolCatErrors++;
295 if (errno == ENOTTY || errno == ENOSYS) { /* Function not implemented */
298 break; /* ignore message printed later */
301 clear_cap(CAP_EOF); /* turn off feature */
306 clear_cap(CAP_EOM); /* turn off feature */
311 clear_cap(CAP_FSF); /* turn off feature */
315 clear_cap(CAP_BSF); /* turn off feature */
319 clear_cap(CAP_FSR); /* turn off feature */
323 clear_cap(CAP_BSR); /* turn off feature */
333 #ifdef MTSETDRVBUFFER
335 msg = "MTSETDRVBUFFER";
368 bsnprintf(buf, sizeof(buf), _("unknown func code %d"), func);
374 Mmsg1(errmsg, _("I/O function \"%s\" not supported on this device.\n"), msg);
375 Emsg0(M_ERROR, 0, errmsg);
380 * Now we try different methods of clearing the error
381 * status on the drive so that it is not locked for
382 * further operations.
385 /* On some systems such as NetBSD, this clears all errors */
388 /* Found on Solaris */
391 d_ioctl(m_fd, MTIOCLRERR);
392 Dmsg0(200, "Did MTIOCLRERR\n");
396 /* Typically on FreeBSD */
400 /* Read and clear SCSI error status */
401 union mterrstat mt_errstat;
402 Dmsg2(200, "Doing MTIOCERRSTAT errno=%d ERR=%s\n", dev_errno,
403 be.bstrerror(dev_errno));
404 d_ioctl(m_fd, MTIOCERRSTAT, (char *)&mt_errstat);
408 /* Clear Subsystem Exception TRU64 */
412 mt_com.mt_op = MTCSE;
414 /* Clear any error condition on the tape */
415 d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
416 Dmsg0(200, "Did MTCSE\n");