/* * Write an ANSI or IBM 80 character tape label * Type determines whether we are writing HDR, EOF, or EOV labels * Assume we are positioned to write the labels * Returns: true of OK * false if error */ bool write_ansi_ibm_labels(DCR *dcr, int type, const char *VolName) { DEVICE *dev = dcr->dev; JCR *jcr = dcr->jcr; char ansi_volname[7]; /* 6 char + \0 */ char label[80]; /* tape label */ char date[20]; /* ansi date buffer */ time_t now; int len, stat, label_type; /* * If the Device requires a specific label type use it, * otherwise, use the type requested by the Director */ if (dcr->device->label_type != B_BACULA_LABEL) { label_type = dcr->device->label_type; /* force label type */ } else { label_type = dcr->VolCatInfo.LabelType; /* accept Dir type */ } switch (label_type) { case B_BACULA_LABEL: return true; case B_ANSI_LABEL: case B_IBM_LABEL: ser_declare; Dmsg1(100, "Write ANSI label type=%d\n", label_type); len = strlen(VolName); if (len > 6) { Jmsg1(jcr, M_FATAL, 0, _("ANSI Volume label name \"%s\" longer than 6 chars.\n"), VolName); return false; } /* ANSI labels have 6 characters, and are padded with spaces * 'vol1\0' => 'vol1 \0' */ strcpy(ansi_volname, VolName); for(int i=len; i < 6; i++) { ansi_volname[i]=' '; } ansi_volname[6]='\0'; /* only for debug */ if (type == ANSI_VOL_LABEL) { ser_begin(label, sizeof(label)); ser_bytes("VOL1", 4); ser_bytes(ansi_volname, 6); /* Write VOL1 label */ if (label_type == B_IBM_LABEL) { ascii_to_ebcdic(label, label, sizeof(label)); } else { label[79] = '3'; /* ANSI label flag */ } stat = dev->write(label, sizeof(label)); if (stat != sizeof(label)) { berrno be; Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI VOL1 label. ERR=%s\n"), be.bstrerror()); return false; } } /* Now construct HDR1 label */ memset(label, ' ', sizeof(label)); ser_begin(label, sizeof(label)); ser_bytes(labels[type], 3); ser_bytes("1", 1); ser_bytes("BACULA.DATA", 11); /* Filename field */ ser_begin(&label[21], sizeof(label)-21); /* fileset field */ ser_bytes(ansi_volname, 6); /* write Vol Ser No. */ ser_begin(&label[27], sizeof(label)-27); ser_bytes("00010001000100", 14); /* File section, File seq no, Generation no */ now = time(NULL); ser_bytes(ansi_date(now, date), 6); /* current date */ ser_bytes(ansi_date(now - 24 * 3600, date), 6); /* created yesterday */ ser_bytes(" 000000Bacula ", 27); /* Write HDR1 label */ if (label_type == B_IBM_LABEL) { ascii_to_ebcdic(label, label, sizeof(label)); } /* * This could come at the end of a tape, ignore * EOT errors. */ stat = dev->write(label, sizeof(label)); if (stat != sizeof(label)) { berrno be; if (stat == -1) { dev->clrerror(-1); if (dev->dev_errno == 0) { dev->dev_errno = ENOSPC; /* out of space */ } if (dev->dev_errno != ENOSPC) { Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"), be.bstrerror()); return false; } } else { Jmsg(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label.\n")); return false; } } /* Now construct HDR2 label */ memset(label, ' ', sizeof(label)); ser_begin(label, sizeof(label)); ser_bytes(labels[type], 3); ser_bytes("2D3200032000", 12); /* Write HDR2 label */ if (label_type == B_IBM_LABEL) { label[4] = 'V'; ascii_to_ebcdic(label, label, sizeof(label)); } stat = dev->write(label, sizeof(label)); if (stat != sizeof(label)) { berrno be; if (stat == -1) { dev->clrerror(-1); if (dev->dev_errno == 0) { dev->dev_errno = ENOSPC; /* out of space */ } if (dev->dev_errno != ENOSPC) { Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"), be.bstrerror()); return false; } dev->weof(1); return true; } else { Jmsg(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label.\n")); return false; } } if (!dev->weof(1)) { Jmsg(jcr, M_FATAL, 0, _("Error writing EOF to tape. ERR=%s"), dev->errmsg); return false; } return true; default: Jmsg0(jcr, M_ABORT, 0, _("write_ansi_ibm_label called for non-ANSI/IBM type\n")); return false; /* should not get here */ } }
void set_os_device_parameters(DCR *dcr) { DEVICE *dev = dcr->dev; if (strcmp(dev->dev_name, "/dev/null") == 0) { return; /* no use trying to set /dev/null */ } #if defined(HAVE_LINUX_OS) || defined(HAVE_WIN32) struct mtop mt_com; Dmsg0(100, "In set_os_device_parameters\n"); #if defined(MTSETBLK) if (dev->min_block_size == dev->max_block_size && dev->min_block_size == 0) { /* variable block mode */ mt_com.mt_op = MTSETBLK; mt_com.mt_count = 0; Dmsg0(100, "Set block size to zero\n"); if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { dev->clrerror(MTSETBLK); } } #endif #if defined(MTSETDRVBUFFER) if (getuid() == 0) { /* Only root can do this */ mt_com.mt_op = MTSETDRVBUFFER; mt_com.mt_count = MT_ST_CLEARBOOLEANS; if (!dev->has_cap(CAP_TWOEOF)) { mt_com.mt_count |= MT_ST_TWO_FM; } if (dev->has_cap(CAP_EOM)) { mt_com.mt_count |= MT_ST_FAST_MTEOM; } Dmsg0(100, "MTSETDRVBUFFER\n"); if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { dev->clrerror(MTSETDRVBUFFER); } } #endif return; #endif #ifdef HAVE_NETBSD_OS struct mtop mt_com; if (dev->min_block_size == dev->max_block_size && dev->min_block_size == 0) { /* variable block mode */ mt_com.mt_op = MTSETBSIZ; mt_com.mt_count = 0; if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { dev->clrerror(MTSETBSIZ); } /* Get notified at logical end of tape */ mt_com.mt_op = MTEWARN; mt_com.mt_count = 1; if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { dev->clrerror(MTEWARN); } } return; #endif #if HAVE_FREEBSD_OS || HAVE_OPENBSD_OS struct mtop mt_com; if (dev->min_block_size == dev->max_block_size && dev->min_block_size == 0) { /* variable block mode */ mt_com.mt_op = MTSETBSIZ; mt_com.mt_count = 0; if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { dev->clrerror(MTSETBSIZ); } } #if defined(MTIOCSETEOTMODEL) uint32_t neof; if (dev->has_cap(CAP_TWOEOF)) { neof = 2; } else { neof = 1; } if (dev->d_ioctl(dev->fd(), MTIOCSETEOTMODEL, (caddr_t)&neof) < 0) { berrno be; dev->dev_errno = errno; /* save errno */ Mmsg2(dev->errmsg, _("Unable to set eotmodel on device %s: ERR=%s\n"), dev->print_name(), be.bstrerror(dev->dev_errno)); Jmsg(dcr->jcr, M_FATAL, 0, dev->errmsg); } #endif return; #endif #ifdef HAVE_SUN_OS struct mtop mt_com; if (dev->min_block_size == dev->max_block_size && dev->min_block_size == 0) { /* variable block mode */ mt_com.mt_op = MTSRSZ; mt_com.mt_count = 0; if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) { dev->clrerror(MTSRSZ); } } return; #endif }