static int do_setpicker(const char *cname, int argc, char **argv) { int picker; ++argv; --argc; if (argc < 1) { warnx("%s: too few arguments", cname); goto usage; } else if (argc > 1) { warnx("%s: too many arguments", cname); goto usage; } picker = parse_element_unit(*argv); /* Set the changer picker. */ if (ioctl(changer_fd, CHIOSPICKER, &picker)) err(1, "%s: CHIOSPICKER", changer_name); return (0); usage: (void) fprintf(stderr, "usage: %s %s <picker>\n", getprogname(), cname); return (1); }
static int do_position(const char *cname, int argc, char **argv) { struct changer_position cmd; int val; /* * On a position command, we expect the following: * * <to ET> <to EU> [inv] * * where ET == element type and EU == element unit. */ ++argv; --argc; if (argc < 2) { warnx("%s: too few arguments", cname); goto usage; } else if (argc > 3) { warnx("%s: too many arguments", cname); goto usage; } (void) memset(&cmd, 0, sizeof(cmd)); /* <to ET> */ cmd.cp_type = parse_element_type(*argv); ++argv; --argc; /* <to EU> */ cmd.cp_unit = parse_element_unit(*argv); ++argv; --argc; /* Deal with optional command modifier. */ if (argc) { val = parse_special(*argv); switch (val) { case SW_INVERT: cmd.cp_flags |= CP_INVERT; break; default: errx(1, "%s: inappropriate modifier `%s'", cname, *argv); /* NOTREACHED */ } } /* Send command to changer. */ if (ioctl(changer_fd, CHIOPOSITION, &cmd)) err(1, "%s: CHIOPOSITION", changer_name); return (0); usage: (void) fprintf(stderr, "usage: %s %s <to ET> <to EU> [inv]\n", getprogname(), cname); return (1); }
/* * do_return() * * Given an element reference, ask the changer/picker to move that * element back to its source slot. */ static int do_return(const char *cname, int argc, char **argv) { struct changer_element_status *ces; struct changer_move cmd; uint16_t type, element; ++argv; --argc; if (argc < 2) { warnx("%s: too few arguments", cname); goto usage; } else if (argc > 3) { warnx("%s: too many arguments", cname); goto usage; } type = parse_element_type(*argv); ++argv; --argc; /* Handle voltag virtual Changer Element Type */ if (CHET_VT == type) { find_element(*argv, &type, &element); } else { element = parse_element_unit(*argv); } ++argv; --argc; /* Get the status */ ces = get_element_status((unsigned int)type, (unsigned int)element, CHET_VT == type); if (NULL == ces) errx(1, "%s: null element status pointer", cname); if (!(ces->ces_flags & CES_SOURCE_VALID)) errx(1, "%s: no source information", cname); (void) memset(&cmd, 0, sizeof(cmd)); cmd.cm_fromtype = type; cmd.cm_fromunit = element; cmd.cm_totype = ces->ces_source_type; cmd.cm_tounit = ces->ces_source_addr; if (ioctl(changer_fd, CHIOMOVE, &cmd) == -1) err(1, "%s: CHIOMOVE", changer_name); free(ces); return(0); usage: (void) fprintf(stderr, "usage: %s %s " "<from ET> <from EU>\n", getprogname(), cname); return(1); }
/* ARGSUSED */ static int do_cdlu(const char *cname, int argc, char **argv) { static const struct special_word cdlu_subcmds[] = { { "load", CD_LU_LOAD }, { "unload", CD_LU_UNLOAD }, { "abort", CD_LU_ABORT }, { NULL, 0 }, }; struct ioc_load_unload cmd; int i; /* * This command is a little different, since we are mostly dealing * with ATAPI CD changers, which have a lame API (since ATAPI doesn't * have LUNs). * * We have 3 sub-commands: "load", "unload", and "abort". The * first two take a slot number. The latter does not. */ if (argc < 1 || argc > 2) usage(); /*NOTREACHED*/ for (i = 0; cdlu_subcmds[i].sw_name != NULL; i++) { if (strcmp(argv[0], cdlu_subcmds[i].sw_name) == 0) { cmd.options = cdlu_subcmds[i].sw_value; break; } } if (cdlu_subcmds[i].sw_name == NULL) usage(); /*NOTREACHED*/ if (strcmp(argv[0], "abort") == 0) cmd.slot = 0; else cmd.slot = parse_element_unit(argv[1]); /* * XXX Should maybe do something different with the device * XXX handling for cdlu; think about this some more. */ if (ioctl(changer_fd, CDIOCLOADUNLOAD, &cmd)) err(EXIT_FAILURE, "%s: CDIOCLOADUNLOAD", changer_name); /* NOTREACHED */ return (0); }
static int do_setpicker(const char *cname, int argc, char **argv) { int picker; if (argc < 1) { warnx("%s: too few arguments", cname); usage(); /*NOTREACHED*/ } else if (argc > 1) { warnx("%s: too many arguments", cname); usage(); /*NOTREACHED*/ } picker = parse_element_unit(*argv); /* Set the changer picker. */ if (ioctl(changer_fd, CHIOSPICKER, &picker)) err(EXIT_FAILURE, "%s: CHIOSPICKER", changer_name); return (0); }
static int do_status(const char *cname, int argc, char **argv) { struct changer_element_status_request cmd; struct changer_params data; struct changer_element_status *ces; int i, chet, count, echet, flags, have_ucount, have_unit; int schet, ucount, unit; size_t size; flags = 0; ucount = 0; unit = 0; have_ucount = 0; have_unit = 0; /* * On a status command, we expect the following: * * [<ET> [unit [count]]] [voltags] * * where ET == element type. * * If we get no element-related arguments, we get the status of all * known element types. */ if (argc > 4) { warnx("%s: too many arguments", cname); usage(); /*NOTREACHED*/ } /* * Get params from changer. Specifically, we need the element * counts. */ (void)memset(&data, 0, sizeof(data)); if (ioctl(changer_fd, CHIOGPARAMS, &data)) err(EXIT_FAILURE, "%s: CHIOGPARAMS", changer_name); /* NOTREACHED */ schet = CHET_MT; echet = CHET_DT; for (; argc != 0; argc--, argv++) { /* * If we have the voltags modifier, it must be the * last argument. */ if (is_special(argv[0])) { if (argc != 1) { warnx("%s: malformed command line", cname); usage(); /*NOTREACHED*/ } if (parse_special(argv[0]) != SW_VOLTAGS) errx(EXIT_FAILURE, "%s: inappropriate special word: %s", cname, argv[0]); /* NOTREACHED */ flags |= CESR_VOLTAGS; continue; } /* * If we get an element type, we can't have specified * anything else. */ if (isdigit((unsigned char)*argv[0]) == 0) { if (schet == echet || flags != 0 || have_unit || have_ucount) { warnx("%s: malformed command line", cname); usage(); /*NOTREACHED*/ } schet = echet = parse_element_type(argv[0]); continue; } /* * We know we have a digit here. If we do, we must * have specified an element type. */ if (schet != echet) { warnx("%s: malformed command line", cname); usage(); /*NOTREACHED*/ } i = parse_element_unit(argv[0]); if (have_unit == 0) { unit = i; have_unit = 1; } else if (have_ucount == 0) { ucount = i; have_ucount = 1; } else { warnx("%s: malformed command line", cname); usage(); /*NOTREACHED*/ } } for (chet = schet; chet <= echet; ++chet) { switch (chet) { case CHET_MT: count = data.cp_npickers; break; case CHET_ST: count = data.cp_nslots; break; case CHET_IE: count = data.cp_nportals; break; case CHET_DT: count = data.cp_ndrives; break; default: /* To appease gcc -Wuninitialized. */ count = 0; } if (count == 0) { if (schet != echet) continue; else { (void)printf("%s: no %s elements\n", changer_name, elements[chet].et_name); return (0); } } /* * If we have a unit, we may or may not have a count. * If we don't have a unit, we don't have a count, either. * * Make sure both are initialized. */ if (have_unit) { if (have_ucount == 0) ucount = 1; } else { unit = 0; ucount = count; } if ((unit + ucount) > count) errx(EXIT_FAILURE, "%s: unvalid unit/count %d/%d", cname, unit, ucount); /* NOTREACHED */ size = ucount * sizeof(struct changer_element_status); /* Allocate storage for the status bytes. */ if ((ces = malloc(size)) == NULL) errx(EXIT_FAILURE, "can't allocate status storage"); /* NOTREACHED */ (void)memset(ces, 0, size); (void)memset(&cmd, 0, sizeof(cmd)); cmd.cesr_type = chet; cmd.cesr_unit = unit; cmd.cesr_count = ucount; cmd.cesr_flags = flags; cmd.cesr_data = ces; /* * Should we deal with this eventually? */ cmd.cesr_vendor_data = NULL; if (ioctl(changer_fd, CHIOGSTATUS, &cmd)) { free(ces); err(EXIT_FAILURE, "%s: CHIOGSTATUS", changer_name); /* NOTREACHED */ } /* Dump the status for each element of this type. */ for (i = 0; i < ucount; i++) { (void)printf("%s %d: ", elements[chet].et_name, unit + i); if ((ces[i].ces_flags & CESTATUS_STATUS_VALID) == 0) { (void)printf("status not available\n"); continue; } (void)printf("%s", bits_to_string(ces[i].ces_flags, CESTATUS_BITS)); if (ces[i].ces_flags & CESTATUS_XNAME_VALID) (void)printf(" (%s)", ces[i].ces_xname); (void)printf("\n"); if (ces[i].ces_flags & CESTATUS_PVOL_VALID) (void)printf("\tPrimary volume tag: %s " "ver. %d\n", ces[i].ces_pvoltag.cv_tag, ces[i].ces_pvoltag.cv_serial); if (ces[i].ces_flags & CESTATUS_AVOL_VALID) (void)printf("\tAlternate volume tag: %s " "ver. %d\n", ces[i].ces_avoltag.cv_tag, ces[i].ces_avoltag.cv_serial); if (ces[i].ces_flags & CESTATUS_FROM_VALID) (void)printf("\tFrom: %s %d\n", elements[ces[i].ces_from_type].et_name, ces[i].ces_from_unit); if (ces[i].ces_vendor_len) (void)printf("\tVendor-specific data size: " "%lu\n", (u_long)ces[i].ces_vendor_len); } free(ces); } return (0); }
static int do_exchange(const char *cname, int argc, char **argv) { struct changer_exchange_request cmd; int val; /* * On an exchange command, we expect the following: * * <src ET> <src EU> <dst1 ET> <dst1 EU> [<dst2 ET> <dst2 EU>] [inv1] [inv2] * * where ET == element type and EU == element unit. */ if (argc < 4) { warnx("%s: too few arguments", cname); usage(); /*NOTREACHED*/ } else if (argc > 8) { warnx("%s: too many arguments", cname); usage(); /*NOTREACHED*/ } (void)memset(&cmd, 0, sizeof(cmd)); /* <src ET> */ cmd.ce_srctype = parse_element_type(*argv); ++argv; --argc; /* <src EU> */ cmd.ce_srcunit = parse_element_unit(*argv); ++argv; --argc; /* <dst1 ET> */ cmd.ce_fdsttype = parse_element_type(*argv); ++argv; --argc; /* <dst1 EU> */ cmd.ce_fdstunit = parse_element_unit(*argv); ++argv; --argc; /* * If the next token is a special word or there are no more * arguments, then this is a case of simple exchange. * dst2 == src. */ if ((argc == 0) || is_special(*argv)) { cmd.ce_sdsttype = cmd.ce_srctype; cmd.ce_sdstunit = cmd.ce_srcunit; goto do_special; } /* <dst2 ET> */ cmd.ce_sdsttype = parse_element_type(*argv); ++argv; --argc; /* <dst2 EU> */ cmd.ce_sdstunit = parse_element_unit(*argv); ++argv; --argc; do_special: /* Deal with optional command modifiers. */ while (argc) { val = parse_special(*argv); ++argv; --argc; switch (val) { case SW_INVERT1: cmd.ce_flags |= CE_INVERT1; break; case SW_INVERT2: cmd.ce_flags |= CE_INVERT2; break; default: errx(EXIT_FAILURE, "%s: inappropriate modifier `%s'", cname, *argv); /* NOTREACHED */ } } /* Send command to changer. */ if (ioctl(changer_fd, CHIOEXCHANGE, &cmd)) err(EXIT_FAILURE, "%s: CHIOEXCHANGE", changer_name); /* NOTREACHED */ return (0); }
static int do_move(const char *cname, int argc, char **argv) { struct changer_move_request cmd; int val; /* * On a move command, we expect the following: * * <from ET> <from EU> <to ET> <to EU> [inv] * * where ET == element type and EU == element unit. */ if (argc < 4) { warnx("%s: too few arguments", cname); usage(); /*NOTREACHED*/ } else if (argc > 5) { warnx("%s: too many arguments", cname); usage(); /*NOTREACHED*/ } (void)memset(&cmd, 0, sizeof(cmd)); /* <from ET> */ cmd.cm_fromtype = parse_element_type(*argv); ++argv; --argc; /* <from EU> */ cmd.cm_fromunit = parse_element_unit(*argv); ++argv; --argc; /* <to ET> */ cmd.cm_totype = parse_element_type(*argv); ++argv; --argc; /* <to EU> */ cmd.cm_tounit = parse_element_unit(*argv); ++argv; --argc; /* Deal with optional command modifier. */ if (argc) { val = parse_special(*argv); switch (val) { case SW_INVERT: cmd.cm_flags |= CM_INVERT; break; default: errx(EXIT_FAILURE, "%s: inappropriate modifier `%s'", cname, *argv); /* NOTREACHED */ } } /* Send command to changer. */ if (ioctl(changer_fd, CHIOMOVE, &cmd)) err(EXIT_FAILURE, "%s: CHIOMOVE", changer_name); /* NOTREACHED */ return (0); }
static int do_exchange(const char *cname, int argc, char **argv) { struct changer_exchange cmd; int val; /* * On an exchange command, we expect the following: * * <src ET> <src EU> <dst1 ET> <dst1 EU> [<dst2 ET> <dst2 EU>] [inv1] [inv2] * * where ET == element type and EU == element unit. */ ++argv; --argc; if (argc < 4) { warnx("%s: too few arguments", cname); goto usage; } else if (argc > 8) { warnx("%s: too many arguments", cname); goto usage; } (void) memset(&cmd, 0, sizeof(cmd)); /* <src ET> */ cmd.ce_srctype = parse_element_type(*argv); ++argv; --argc; /* Check for voltag virtual type */ if (CHET_VT == cmd.ce_srctype) { find_element(*argv, &cmd.ce_srctype, &cmd.ce_srcunit); } else { /* <from EU> */ cmd.ce_srcunit = parse_element_unit(*argv); } ++argv; --argc; /* <dst1 ET> */ cmd.ce_fdsttype = parse_element_type(*argv); ++argv; --argc; /* Check for voltag virtual type */ if (CHET_VT == cmd.ce_fdsttype) { find_element(*argv, &cmd.ce_fdsttype, &cmd.ce_fdstunit); } else { /* <from EU> */ cmd.ce_fdstunit = parse_element_unit(*argv); } ++argv; --argc; /* * If the next token is a special word or there are no more * arguments, then this is a case of simple exchange. * dst2 == src. */ if ((argc == 0) || is_special(*argv)) { cmd.ce_sdsttype = cmd.ce_srctype; cmd.ce_sdstunit = cmd.ce_srcunit; goto do_special; } /* <dst2 ET> */ cmd.ce_sdsttype = parse_element_type(*argv); ++argv; --argc; if (CHET_VT == cmd.ce_sdsttype) errx(1,"%s %s: voltag only makes sense as an element source", cname, *argv); /* <dst2 EU> */ cmd.ce_sdstunit = parse_element_unit(*argv); ++argv; --argc; do_special: /* Deal with optional command modifiers. */ while (argc) { val = parse_special(*argv); ++argv; --argc; switch (val) { case SW_INVERT1: cmd.ce_flags |= CE_INVERT1; break; case SW_INVERT2: cmd.ce_flags |= CE_INVERT2; break; default: errx(1, "%s: inappropriate modifier `%s'", cname, *argv); /* NOTREACHED */ } } /* Send command to changer. */ if (ioctl(changer_fd, CHIOEXCHANGE, &cmd)) err(1, "%s: CHIOEXCHANGE", changer_name); return (0); usage: (void) fprintf(stderr, "usage: %s %s <src ET> <src EU> <dst1 ET> <dst1 EU>\n" " [<dst2 ET> <dst2 EU>] [inv1] [inv2]\n", getprogname(), cname); return (1); }
static int do_move(const char *cname, int argc, char **argv) { struct changer_move cmd; int val; /* * On a move command, we expect the following: * * <from ET> <from EU> <to ET> <to EU> [inv] * * where ET == element type and EU == element unit. */ ++argv; --argc; if (argc < 4) { warnx("%s: too few arguments", cname); goto usage; } else if (argc > 5) { warnx("%s: too many arguments", cname); goto usage; } (void) memset(&cmd, 0, sizeof(cmd)); /* <from ET> */ cmd.cm_fromtype = parse_element_type(*argv); ++argv; --argc; /* Check for voltag virtual type */ if (CHET_VT == cmd.cm_fromtype) { find_element(*argv, &cmd.cm_fromtype, &cmd.cm_fromunit); } else { /* <from EU> */ cmd.cm_fromunit = parse_element_unit(*argv); } ++argv; --argc; /* <to ET> */ cmd.cm_totype = parse_element_type(*argv); ++argv; --argc; /* Check for voltag virtual type, and report error */ if (CHET_VT == cmd.cm_totype) errx(1,"%s: voltag only makes sense as an element source", cname); /* <to EU> */ cmd.cm_tounit = parse_element_unit(*argv); ++argv; --argc; /* Deal with optional command modifier. */ if (argc) { val = parse_special(*argv); switch (val) { case SW_INVERT: cmd.cm_flags |= CM_INVERT; break; default: errx(1, "%s: inappropriate modifier `%s'", cname, *argv); /* NOTREACHED */ } } /* Send command to changer. */ if (ioctl(changer_fd, CHIOMOVE, &cmd)) err(1, "%s: CHIOMOVE", changer_name); return (0); usage: (void) fprintf(stderr, "usage: %s %s " "<from ET> <from EU> <to ET> <to EU> [inv]\n", getprogname(), cname); return (1); }
static int do_move(char *cname, int argc, char *argv[]) { struct changer_move cmd; int val; /* * On a move command, we expect the following: * * <from ET> <from EU> <to ET> <to EU> [inv] * * where ET == element type and EU == element unit. */ ++argv; --argc; if (argc < 4) { warnx("%s: too few arguments", cname); goto usage; } else if (argc > 5) { warnx("%s: too many arguments", cname); goto usage; } bzero(&cmd, sizeof(cmd)); /* * Get the from ET and EU - we search for it if the ET is * "voltag", otherwise, we just use the ET and EU given to us. */ if (strcmp(*argv, "voltag") == 0) { ++argv; --argc; find_voltag(*argv, &cmd.cm_fromtype, &cmd.cm_fromunit); ++argv; --argc; } else { cmd.cm_fromtype = parse_element_type(*argv); ++argv; --argc; cmd.cm_fromunit = parse_element_unit(*argv); ++argv; --argc; } if (cmd.cm_fromtype == CHET_DT) check_source_drive(cmd.cm_fromunit); /* * Don't allow voltag on the to ET, using a volume * as a destination makes no sense on a move */ cmd.cm_totype = parse_element_type(*argv); ++argv; --argc; cmd.cm_tounit = parse_element_unit(*argv); ++argv; --argc; /* Deal with optional command modifier. */ if (argc) { val = parse_special(*argv); switch (val) { case SW_INVERT: cmd.cm_flags |= CM_INVERT; break; default: errx(1, "%s: inappropriate modifier `%s'", cname, *argv); /* NOTREACHED */ } } /* Send command to changer. */ if (ioctl(changer_fd, CHIOMOVE, &cmd)) err(1, "%s: CHIOMOVE", changer_name); return (0); usage: fprintf(stderr, "usage: %s %s " "<from ET> <from EU> <to ET> <to EU> [inv]\n", __progname, cname); return (1); }