2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from many
7 others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 Bacula® is a registered trademark of Kern Sibbald.
18 * os.c -- Operating System dependent dev.c routines
20 * written by, Kern Sibbald, MM
21 * separated from dev.c February 2014
23 * Note, this is the device dependent code, and may have
24 * to be modified for each system.
31 /* Returns file position on tape or -1 */
32 int32_t DEVICE::get_os_tape_file()
36 if (has_cap(CAP_MTIOCGET) &&
37 d_ioctl(m_fd, MTIOCGET, (char *)&mt_stat) == 0) {
38 return mt_stat.mt_fileno;
44 void set_os_device_parameters(DCR *dcr)
46 DEVICE *dev = dcr->dev;
48 if (strcmp(dev->dev_name, "/dev/null") == 0) {
49 return; /* no use trying to set /dev/null */
52 #if defined(HAVE_LINUX_OS) || defined(HAVE_WIN32)
55 Dmsg0(100, "In set_os_device_parameters\n");
57 if (dev->min_block_size == dev->max_block_size &&
58 dev->min_block_size == 0) { /* variable block mode */
59 mt_com.mt_op = MTSETBLK;
61 Dmsg0(100, "Set block size to zero\n");
62 if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
63 dev->clrerror(MTSETBLK);
67 #if defined(MTSETDRVBUFFER)
68 if (getuid() == 0) { /* Only root can do this */
69 mt_com.mt_op = MTSETDRVBUFFER;
70 mt_com.mt_count = MT_ST_CLEARBOOLEANS;
71 if (!dev->has_cap(CAP_TWOEOF)) {
72 mt_com.mt_count |= MT_ST_TWO_FM;
74 if (dev->has_cap(CAP_EOM)) {
75 mt_com.mt_count |= MT_ST_FAST_MTEOM;
77 Dmsg0(100, "MTSETDRVBUFFER\n");
78 if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
79 dev->clrerror(MTSETDRVBUFFER);
88 if (dev->min_block_size == dev->max_block_size &&
89 dev->min_block_size == 0) { /* variable block mode */
90 mt_com.mt_op = MTSETBSIZ;
92 if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
93 dev->clrerror(MTSETBSIZ);
95 /* Get notified at logical end of tape */
96 mt_com.mt_op = MTEWARN;
98 if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
99 dev->clrerror(MTEWARN);
105 #if HAVE_FREEBSD_OS || HAVE_OPENBSD_OS
107 if (dev->min_block_size == dev->max_block_size &&
108 dev->min_block_size == 0) { /* variable block mode */
109 mt_com.mt_op = MTSETBSIZ;
111 if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
112 dev->clrerror(MTSETBSIZ);
115 #if defined(MTIOCSETEOTMODEL)
117 if (dev->has_cap(CAP_TWOEOF)) {
122 if (dev->d_ioctl(dev->fd(), MTIOCSETEOTMODEL, (caddr_t)&neof) < 0) {
124 dev->dev_errno = errno; /* save errno */
125 Mmsg2(dev->errmsg, _("Unable to set eotmodel on device %s: ERR=%s\n"),
126 dev->print_name(), be.bstrerror(dev->dev_errno));
127 Jmsg(dcr->jcr, M_FATAL, 0, dev->errmsg);
135 if (dev->min_block_size == dev->max_block_size &&
136 dev->min_block_size == 0) { /* variable block mode */
137 mt_com.mt_op = MTSRSZ;
139 if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
140 dev->clrerror(MTSRSZ);
147 bool dev_get_os_pos(DEVICE *dev, struct mtget *mt_stat)
149 Dmsg0(100, "dev_get_os_pos\n");
150 return dev->has_cap(CAP_MTIOCGET) &&
151 dev->d_ioctl(dev->fd(), MTIOCGET, (char *)mt_stat) == 0 &&
152 mt_stat->mt_fileno >= 0;
156 * Return the status of the device. This was meant
157 * to be a generic routine. Unfortunately, it doesn't
158 * seem possible (at least I do not know how to do it
159 * currently), which means that for the moment, this
160 * routine has very little value.
164 uint32_t status_dev(DEVICE *dev)
166 struct mtget mt_stat;
169 if (dev->state & (ST_EOT | ST_WEOT)) {
173 if (dev->state & ST_EOF) {
177 if (dev->is_tape()) {
179 Pmsg0(-20,_(" Bacula status:"));
180 Pmsg2(-20,_(" file=%d block=%d\n"), dev->file, dev->block_num);
181 if (dev->d_ioctl(dev->fd(), MTIOCGET, (char *)&mt_stat) < 0) {
183 dev->dev_errno = errno;
184 Mmsg2(dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"),
185 dev->print_name(), be.bstrerror());
188 Pmsg0(-20, _(" Device status:"));
190 #if defined(HAVE_LINUX_OS)
191 if (GMT_EOF(mt_stat.mt_gstat)) {
195 if (GMT_BOT(mt_stat.mt_gstat)) {
199 if (GMT_EOT(mt_stat.mt_gstat)) {
203 if (GMT_SM(mt_stat.mt_gstat)) {
207 if (GMT_EOD(mt_stat.mt_gstat)) {
211 if (GMT_WR_PROT(mt_stat.mt_gstat)) {
213 Pmsg0(-20, " WR_PROT");
215 if (GMT_ONLINE(mt_stat.mt_gstat)) {
217 Pmsg0(-20, " ONLINE");
219 if (GMT_DR_OPEN(mt_stat.mt_gstat)) {
221 Pmsg0(-20, " DR_OPEN");
223 if (GMT_IM_REP_EN(mt_stat.mt_gstat)) {
224 stat |= BMT_IM_REP_EN;
225 Pmsg0(-20, " IM_REP_EN");
227 #elif defined(HAVE_WIN32)
228 if (GMT_EOF(mt_stat.mt_gstat)) {
232 if (GMT_BOT(mt_stat.mt_gstat)) {
236 if (GMT_EOT(mt_stat.mt_gstat)) {
240 if (GMT_EOD(mt_stat.mt_gstat)) {
244 if (GMT_WR_PROT(mt_stat.mt_gstat)) {
246 Pmsg0(-20, " WR_PROT");
248 if (GMT_ONLINE(mt_stat.mt_gstat)) {
250 Pmsg0(-20, " ONLINE");
252 if (GMT_DR_OPEN(mt_stat.mt_gstat)) {
254 Pmsg0(-20, " DR_OPEN");
256 if (GMT_IM_REP_EN(mt_stat.mt_gstat)) {
257 stat |= BMT_IM_REP_EN;
258 Pmsg0(-20, " IM_REP_EN");
261 #endif /* !SunOS && !OSF */
262 if (dev->has_cap(CAP_MTIOCGET)) {
263 Pmsg2(-20, _(" file=%d block=%d\n"), mt_stat.mt_fileno, mt_stat.mt_blkno);
265 Pmsg2(-20, _(" file=%d block=%d\n"), -1, -1);
268 stat |= BMT_ONLINE | BMT_BOT;
274 * If implemented in system, clear the tape
277 void DEVICE::clrerror(int func)
279 const char *msg = NULL;
282 dev_errno = errno; /* save errno */
284 VolCatInfo.VolCatErrors++;
291 if (errno == ENOTTY || errno == ENOSYS) { /* Function not implemented */
294 break; /* ignore message printed later */
297 clear_cap(CAP_EOF); /* turn off feature */
302 clear_cap(CAP_EOM); /* turn off feature */
307 clear_cap(CAP_FSF); /* turn off feature */
311 clear_cap(CAP_BSF); /* turn off feature */
315 clear_cap(CAP_FSR); /* turn off feature */
319 clear_cap(CAP_BSR); /* turn off feature */
329 #ifdef MTSETDRVBUFFER
331 msg = "MTSETDRVBUFFER";
364 bsnprintf(buf, sizeof(buf), _("unknown func code %d"), func);
370 Mmsg1(errmsg, _("I/O function \"%s\" not supported on this device.\n"), msg);
371 Emsg0(M_ERROR, 0, errmsg);
376 * Now we try different methods of clearing the error
377 * status on the drive so that it is not locked for
378 * further operations.
381 /* On some systems such as NetBSD, this clears all errors */
384 /* Found on Solaris */
387 d_ioctl(m_fd, MTIOCLRERR);
388 Dmsg0(200, "Did MTIOCLRERR\n");
392 /* Typically on FreeBSD */
396 /* Read and clear SCSI error status */
397 union mterrstat mt_errstat;
398 Dmsg2(200, "Doing MTIOCERRSTAT errno=%d ERR=%s\n", dev_errno,
399 be.bstrerror(dev_errno));
400 d_ioctl(m_fd, MTIOCERRSTAT, (char *)&mt_errstat);
404 /* Clear Subsystem Exception TRU64 */
408 mt_com.mt_op = MTCSE;
410 /* Clear any error condition on the tape */
411 d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
412 Dmsg0(200, "Did MTCSE\n");