static void check_tape(int boot_flag) { size_t status, buflen; int action; static char *fid = "check_tape"; MUTEX_LOCK(&Status->lock); Status->output.state = ISP_OUTPUT_CHECK; MUTEX_UNLOCK(&Status->lock); /* Check for data by trying to read from the tape */ if (mtio_rew(tp) < 0) { util_log(1, "%s: mtio_rew: %s", fid, syserrmsg(errno)); eject_tape(0); return; } status = mtio_read(tp, tmpbuf, MAXBUFLEN); if (mtio_rew(tp) < 0) { util_log(1, "%s: mtio_rew: %s", fid, syserrmsg(errno)); eject_tape(0); return; } if (status > 0) { util_log(1, "tape contains data", fid); if (boot_flag) { action = ISP_MEDIA_APPEND; } else { action = media_alert(0); } switch (action) { case ISP_MEDIA_EJECT: eject_tape(0); break; case ISP_MEDIA_OVERWRITE: util_log(1, "OVERWRITTING TAPE"); MUTEX_LOCK(&Status->lock); Status->output.state = ISP_OUTPUT_ONLINE; MUTEX_UNLOCK(&Status->lock); break; default: util_log(1, "skipping to end of data"); MUTEX_LOCK(&Status->lock); Status->output.state = ISP_OUTPUT_SKIP; MUTEX_UNLOCK(&Status->lock); mtio_eom(tp); MUTEX_LOCK(&Status->lock); Status->output.state = ISP_OUTPUT_ONLINE; MUTEX_UNLOCK(&Status->lock); break; } } return; }
void check_eject_flag() { MUTEX_LOCK(&mp); if (eject_flag) eject_tape(0); eject_flag = 0; MUTEX_UNLOCK(&mp); }
/* main program */ int main(int argc, char **argv) { char *device = NULL; char *disk = NULL; char *mountpoint = NULL; int worked = 0; /* set to 1 when successfully ejected */ int fd; /* file descriptor for device */ setlocale(LC_ALL,""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); atexit(close_stdout); /* parse the command line arguments */ parse_args(argc, argv, &device); /* handle -d option */ if (d_option) { info(_("default device: `%s'"), EJECT_DEFAULT_DEVICE); return EXIT_SUCCESS; } if (!device) { device = mnt_resolve_path(EJECT_DEFAULT_DEVICE, NULL); verbose(_("using default device `%s'"), device); } else { char *p; if (device[strlen(device)-1] == '/') device[strlen(device)-1] = '\0'; /* figure out full device or mount point name */ p = find_device(device); if (p) free(device); else p = device; device = mnt_resolve_spec(p, NULL); free(p); } if (!device) errx(EXIT_FAILURE, _("%s: unable to find device"), device); verbose(_("device name is `%s'"), device); device_get_mountpoint(&device, &mountpoint); if (mountpoint) verbose(_("%s: mounted on %s"), device, mountpoint); else verbose(_("%s: not mounted"), device); disk = get_disk_devname(device); if (disk) { verbose(_("%s: disc device: %s (disk device will be used for eject)"), device, disk); free(device); device = disk; disk = NULL; } else { struct stat st; if (stat(device, &st) != 0 || !S_ISBLK(st.st_mode)) errx(EXIT_FAILURE, _("%s: not found mountpoint or device " "with the given name"), device); verbose(_("%s: is whole-disk device"), device); } if (F_option == 0 && is_hotpluggable(device) == 0) errx(EXIT_FAILURE, _("%s: is not hot-pluggable device"), device); /* handle -n option */ if (n_option) { info(_("device is `%s'"), device); verbose(_("exiting due to -n/--noop option")); return EXIT_SUCCESS; } /* handle -i option */ if (i_option) { fd = open_device(device); manual_eject(fd, i_arg); return EXIT_SUCCESS; } /* handle -a option */ if (a_option) { if (a_arg) verbose(_("%s: enabling auto-eject mode"), device); else verbose(_("%s: disabling auto-eject mode"), device); fd = open_device(device); auto_eject(fd, a_arg); return EXIT_SUCCESS; } /* handle -t option */ if (t_option) { verbose(_("%s: closing tray"), device); fd = open_device(device); close_tray(fd); set_device_speed(device); return EXIT_SUCCESS; } /* handle -T option */ if (T_option) { verbose(_("%s: toggling tray"), device); fd = open_device(device); toggle_tray(fd); set_device_speed(device); return EXIT_SUCCESS; } /* handle -X option */ if (X_option) { verbose(_("%s: listing CD-ROM speed"), device); fd = open_device(device); list_speeds(device, fd); return EXIT_SUCCESS; } /* handle -x option only */ if (!c_option) set_device_speed(device); /* * Unmount all partitions if -m is not specified; or umount given * mountpoint if -M is specified, otherwise print error of another * partition is mounted. */ if (!m_option) { int ct = umount_partitions(device, M_option); if (ct == 0 && mountpoint) umount_one(mountpoint); /* probably whole-device */ if (M_option) { if (ct == 1 && mountpoint) umount_one(mountpoint); else if (ct) errx(EXIT_FAILURE, _("error: %s: device in use"), device); } } /* handle -c option */ if (c_option) { verbose(_("%s: selecting CD-ROM disc #%ld"), device, c_arg); fd = open_device(device); changer_select(fd, c_arg); set_device_speed(device); return EXIT_SUCCESS; } /* if user did not specify type of eject, try all four methods */ if (r_option + s_option + f_option + q_option == 0) r_option = s_option = f_option = q_option = 1; /* open device */ fd = open_device(device); /* try various methods of ejecting until it works */ if (r_option) { verbose(_("%s: trying to eject using CD-ROM eject command"), device); worked = eject_cdrom(fd); verbose(worked ? _("CD-ROM eject command succeeded") : _("CD-ROM eject command failed")); } if (s_option && !worked) { verbose(_("%s: trying to eject using SCSI commands"), device); worked = eject_scsi(fd); verbose(worked ? _("SCSI eject succeeded") : _("SCSI eject failed")); } if (f_option && !worked) { verbose(_("%s: trying to eject using floppy eject command"), device); worked = eject_floppy(fd); verbose(worked ? _("floppy eject command succeeded") : _("floppy eject command failed")); } if (q_option && !worked) { verbose(_("%s: trying to eject using tape offline command"), device); worked = eject_tape(fd); verbose(worked ? _("tape offline command succeeded") : _("tape offline command failed")); } if (!worked) errx(EXIT_FAILURE, _("unable to eject")); /* cleanup */ close(fd); free(device); free(mountpoint); mnt_unref_table(mtab); return EXIT_SUCCESS; }
static THREAD_FUNC TapeWriteThread(void *dummy) { int status; size_t blen, remain, want, put, nrec; char *ptr; OLD_MSGQ_MSG *obuf; static char *fid = "TapeWriteThread"; blen = Params->bfact * IDA_BUFSIZ; /* IDA10 OK */ MUTEX_LOCK(&mp); ioerr = 0; MUTEX_UNLOCK(&mp); while (1) { obuf = msgq_get(&Q->obuf, OLD_MSGQ_WAITFOREVER); if (!msgq_chkmsg2(fid, obuf)) { util_log(1, "%s: corrupt message received", fid); ispd_die(MY_MOD_ID + 1); } nrec = *((size_t *) obuf->data); util_log(1, "dumping %ld records to %s", nrec, Params->odev); ptr = obuf->data + sizeof(size_t); remain = nrec * IDA_BUFSIZ; /* IDA10 OK */ while (remain > 0) { want = remain > blen ? blen : remain; nrec = want / IDA_BUFSIZ; /* IDA10 OK */ do { lock_device(); put = mtio_write(tp, ptr, want); if (put == want) { MUTEX_LOCK(&Status->lock); Status->output.nrec += nrec; status = Status->output.state; MUTEX_UNLOCK(&Status->lock); ptr += put; if (ioerr) { clear_alarm(ISP_ALARM_IOERR); ioerr = 0; } } else { if (put != 0) { if (++ioerr == 1) { set_alarm(ISP_ALARM_IOERR); util_log(1, "%s: %s", Params->odev, syserrmsg(errno) ); } MUTEX_LOCK(&Status->lock); ++Status->output.err; MUTEX_UNLOCK(&Status->lock); eject_tape(0); } } release_device(); if (put != want) { if (shutting_down()) { complete_shutdown(); THREAD_EXIT(0); } else { sleep(5); } } } while (put != want); remain -= put; } util_log(1, "tape dump completed OK"); if (shutting_down()) { complete_shutdown(); THREAD_EXIT(0); } MUTEX_LOCK(&mp); if (eject_flag) eject_tape(0); eject_flag = 0; MUTEX_UNLOCK(&mp); msgq_put(&Heap->obuf, obuf); } }
int main( int argc, char ** argv) { int loaded; int target = -1; int oldtarget; command com; /* a little DOS joke */ /* * drive_num really should be something from the config file, but.. * for now, it is set to zero, since most of the common changers * used by amanda only have one drive ( until someone wants to * use an EXB60/120, or a Breece Hill Q45.. ) */ int drive_num = 0; int need_eject = 0; /* Does the drive need an eject command ? */ unsigned need_sleep = 0; /* How many seconds to wait for the drive to get ready */ int clean_slot = -1; int maxclean = 0; char *clean_file=NULL; char *time_file=NULL; int use_slots; int slot_offset; int confnum; int fd, slotcnt, drivecnt; int endstatus = 0; char *changer_dev = NULL; char *tape_device = NULL; char *changer_file = NULL; char *scsitapedevice = NULL; /* * Configure program for internationalization: * 1) Only set the message locale for now. * 2) Set textdomain for all amanda related programs to "amanda" * We don't want to be forced to support dozens of message catalogs. */ setlocale(LC_MESSAGES, "C"); textdomain("amanda"); set_pname("chg-scsi"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); dbopen(DBG_SUBDIR_SERVER); parse_args(argc,argv,&com); changer = alloc(SIZEOF(changer_t)); config_init(CONFIG_INIT_USE_CWD, NULL); if (config_errors(NULL) >= CFGERR_WARNINGS) { config_print_errors(); if (config_errors(NULL) >= CFGERR_ERRORS) { g_critical(_("errors processing config file")); } } changer_dev = getconf_str(CNF_CHANGERDEV); changer_file = getconf_str(CNF_CHANGERFILE); tape_device = getconf_str(CNF_TAPEDEV); /* Get the configuration parameters */ if (strlen(tape_device)==1){ read_config(changer_file, changer); confnum=atoi(tape_device); use_slots = changer->conf[confnum].end-changer->conf[confnum].start+1; slot_offset = changer->conf[confnum].start; drive_num = changer->conf[confnum].drivenum; need_eject = changer->eject; need_sleep = changer->sleep; clean_file = stralloc(changer->conf[confnum].cleanfile); clean_slot = changer->conf[confnum].cleanslot; maxclean = changer->cleanmax; if (NULL != changer->conf[confnum].timefile) time_file = stralloc(changer->conf[confnum].timefile); if (NULL != changer->conf[confnum].slotfile) changer_file = stralloc(changer->conf[confnum].slotfile); else changer_file = NULL; if (NULL != changer->conf[confnum].device) tape_device = stralloc(changer->conf[confnum].device); if (NULL != changer->device) changer_dev = stralloc(changer->device); if (NULL != changer->conf[confnum].scsitapedev) scsitapedevice = stralloc(changer->conf[confnum].scsitapedev); if (NULL != changer->conf[confnum].tapestatfile) tapestatfile = stralloc(changer->conf[confnum].tapestatfile); dump_changer_struct(changer); /* get info about the changer */ fd = OpenDevice(INDEX_CHANGER , changer_dev, "changer_dev", changer->conf[confnum].changerident); if (fd == -1) { int localerr = errno; g_fprintf(stderr, _("%s: open: %s: %s\n"), get_pname(), changer_dev, strerror(localerr)); g_printf(_("%s open: %s: %s\n"), "<none>", changer_dev, strerror(localerr)); dbprintf(_("open: %s: %s\n"), changer_dev, strerror(localerr)); return 2; } if (tape_device == NULL) { tape_device = stralloc(changer_dev); } if (scsitapedevice == NULL) { scsitapedevice = stralloc(tape_device); } if ((changer->conf[confnum].end == -1) || (changer->conf[confnum].start == -1)){ slotcnt = get_slot_count(fd); use_slots = slotcnt; slot_offset = 0; } free_changer_struct(&changer); } else { /* get info about the changer */ confnum = 0; fd = OpenDevice(INDEX_CHANGER , changer_dev, "changer_dev", changer->conf[confnum].changerident); if (fd == -1) { int localerr = errno; g_fprintf(stderr, _("%s: open: %s: %s\n"), get_pname(), changer_dev, strerror(localerr)); g_printf(_("%s open: %s: %s\n"), _("<none>"), changer_dev, strerror(localerr)); dbprintf(_("open: %s: %s\n"), changer_dev, strerror(localerr)); return 2; } slotcnt = get_slot_count(fd); use_slots = slotcnt; slot_offset = 0; drive_num = 0; need_eject = 0; need_sleep = 0; } drivecnt = get_drive_count(fd); if (drive_num > drivecnt) { g_printf(_("%s drive number error (%d > %d)\n"), _("<none>"), drive_num, drivecnt); g_fprintf(stderr, _("%s: requested drive number (%d) greater than " "number of supported drives (%d)\n"), get_pname(), drive_num, drivecnt); dbprintf(_("requested drive number (%d) greater than " "number of supported drives (%d)\n"), drive_num, drivecnt); CloseDevice("", fd); return 2; } loaded = drive_loaded(fd, drive_num); switch(com.command_code) { case COM_SLOT: /* slot changing command */ if (is_positive_number(com.parameter)) { if ((target = atoi(com.parameter))>=use_slots) { g_printf(_("<none> no slot `%d'\n"),target); close(fd); endstatus = 2; break; } else { target = target+slot_offset; } } else target=get_relative_target(fd, use_slots, com.parameter, loaded, changer_file,slot_offset,slot_offset+use_slots); if (loaded) { if (changer_file != NULL) { oldtarget=get_current_slot(changer_file); } else { oldtarget = GetCurrentSlot(fd, drive_num); } if ((oldtarget)!=target) { if (need_eject) eject_tape(scsitapedevice, need_eject); (void)unload(fd, drive_num, oldtarget); if (ask_clean(scsitapedevice)) clean_tape(fd,tape_device,clean_file,drive_num, clean_slot,maxclean,time_file); loaded=0; } } if (changer_file != NULL) { put_current_slot(changer_file, target); } if (!loaded && isempty(fd, target)) { g_printf(_("%d slot %d is empty\n"),target-slot_offset, target-slot_offset); close(fd); endstatus = 1; break; } if (!loaded) if (load(fd, drive_num, target) != 0) { g_printf(_("%d slot %d move failed\n"),target-slot_offset, target-slot_offset); close(fd); endstatus = 2; break; } if (need_sleep) Tape_Ready1(scsitapedevice, need_sleep); g_printf(_("%d %s\n"), target-slot_offset, tape_device); break; case COM_INFO: if (changer_file != NULL) { g_printf("%d ", get_current_slot(changer_file)-slot_offset); } else { g_printf("%d ", GetCurrentSlot(fd, drive_num)-slot_offset); } g_printf("%d 1\n", use_slots); break; case COM_RESET: if (changer_file != NULL) { target=get_current_slot(changer_file); } else { target = GetCurrentSlot(fd, drive_num); } if (loaded) { if (!isempty(fd, target)) target=find_empty(fd,0 ,0); if (need_eject) eject_tape(scsitapedevice, need_eject); (void)unload(fd, drive_num, target); if (ask_clean(scsitapedevice)) clean_tape(fd,tape_device,clean_file,drive_num,clean_slot, maxclean,time_file); } if (isempty(fd, slot_offset)) { g_printf(_("0 slot 0 is empty\n")); close(fd); endstatus = 1; break; } if (load(fd, drive_num, slot_offset) != 0) { g_printf(_("%d slot %d move failed\n"),slot_offset, slot_offset); close(fd); endstatus = 2; break; } if (changer_file != NULL) { put_current_slot(changer_file, slot_offset); } if (need_sleep) Tape_Ready1(scsitapedevice, need_sleep); if (changer_file != NULL) { g_printf("%d %s\n", get_current_slot(changer_file), tape_device); } else { g_printf("%d %s\n", GetCurrentSlot(fd, drive_num), tape_device); } break; case COM_EJECT: if (loaded) { if (changer_file != NULL) { target=get_current_slot(changer_file); } else { target = GetCurrentSlot(fd, drive_num); } if (need_eject) eject_tape(scsitapedevice, need_eject); (void)unload(fd, drive_num, target); if (ask_clean(scsitapedevice)) clean_tape(fd,tape_device,clean_file,drive_num,clean_slot, maxclean,time_file); g_printf("%d %s\n", target, tape_device); } else { g_printf(_("%d drive was not loaded\n"), target); endstatus = 1; } break; case COM_CLEAN: if (loaded) { if (changer_file != NULL) { target=get_current_slot(changer_file); } else { target = GetCurrentSlot(fd, drive_num); } if (need_eject) eject_tape(scsitapedevice, need_eject); (void)unload(fd, drive_num, target); } clean_tape(fd,tape_device,clean_file,drive_num,clean_slot, maxclean,time_file); g_printf(_("%s cleaned\n"), tape_device); break; }; CloseDevice("", 0); dbclose(); return endstatus; }