Exemple #1
0
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);
}
Exemple #2
0
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);
}
Exemple #3
0
/*
 * 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);
}
Exemple #4
0
/* 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);
}
Exemple #5
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);
}
Exemple #6
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);
}
Exemple #7
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);
}
Exemple #8
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);
}
Exemple #9
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);
}
Exemple #10
0
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);
}
Exemple #11
0
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);
}