mt.c

来自「mt 是linux下得磁带机」· C语言 代码 · 共 713 行 · 第 1/2 页

C
713
字号
	if (i) {	    if (errno == ENOSYS)		fprintf(stderr, "mt: Command not supported by this kernel.\n");	    else if (comp->error_tests != 0)		test_error(mtfd, comp);	}    }    else {	fprintf(stderr, "mt: Internal error: command without function.\n");	i = 1;    }    if (mtfd >= 0)	close(mtfd);    return i;}	static voidusage(int explain){    int ind;    char line[100];    fprintf(stderr, "usage: mt [-v] [--version] [-h] [ -f device ] command [ count ]\n");    if (explain) {	for (ind=0; cmds[ind].cmd_name != NULL; ) {	    if (ind == 0)		strcpy(line, "commands: ");	    else		strcpy(line, "          ");	    for ( ; cmds[ind].cmd_name != NULL; ind++) {		strcat(line, cmds[ind].cmd_name);		if (cmds[ind+1].cmd_name != NULL)		    strcat(line, ", ");		else		    strcat(line, ".");		if (strlen(line) >= 70 || cmds[ind+1].cmd_name == NULL) {		    fprintf(stderr, "%s\n", line);		    ind++;		    break;		}	    }	}    }}/* Do a command that simply feeds an argument to the MTIOCTOP ioctl */	static intdo_standard(int mtfd, cmdef_tr *cmd, int argc, char **argv){    struct mtop mt_com;    char *endp;    mt_com.mt_op = cmd->cmd_code;    mt_com.mt_count = (argc > 0 ? strtol(*argv, &endp, 0) : 1);    if (argc > 0 && endp != *argv) {	if (*endp == 'k')	    mt_com.mt_count *= 1024;	else if (*endp == 'M')	    mt_com.mt_count *= 1024 * 1024;	else if (*endp == 'G')	    mt_com.mt_count *= 1024 * 1024 * 1024;    }    mt_com.mt_count |= cmd->cmd_count_bits;    if (mt_com.mt_count < 0) {	fprintf(stderr, "mt: negative repeat count\n");	return 1;    }    if (ioctl(mtfd, MTIOCTOP, (char *)&mt_com) < 0) {	perror(tape_name);	return 2;    }    return 0;}/* The the drive buffering and other things with this (highly overloaded)   ioctl function. (See also do_options below.) */	static intdo_drvbuffer(int mtfd, cmdef_tr *cmd, int argc, char **argv){    struct mtop mt_com;    mt_com.mt_op = MTSETDRVBUFFER;    mt_com.mt_count = (argc > 0 ? strtol(*argv, NULL, 0) : 1);    if ((cmd->cmd_count_bits & MT_ST_OPTIONS) == MT_ST_DEF_OPTIONS)	mt_com.mt_count &= 0xfffff;#ifdef MT_ST_TIMEOUTS    else if ((cmd->cmd_count_bits & MT_ST_OPTIONS) == MT_ST_TIMEOUTS)	mt_com.mt_count &= 0x7ffffff;#endif    else	mt_com.mt_count &= 0xfffffff;    mt_com.mt_count |= cmd->cmd_count_bits;    if (ioctl(mtfd, MTIOCTOP, (char *)&mt_com) < 0) {	perror(tape_name);	return 2;    }    return 0;}/* Set the tape driver options */	static intdo_options(int mtfd, cmdef_tr *cmd, int argc, char **argv){    int i, an, len;    struct mtop mt_com;    mt_com.mt_op = MTSETDRVBUFFER;    if (argc == 0)	mt_com.mt_count = 0;    else if (isdigit(**argv))	mt_com.mt_count = strtol(*argv, NULL, 0) & ~MT_ST_OPTIONS;    else	for (an = 0, mt_com.mt_count = 0; an < argc; an++) {	    len = strlen(argv[an]);	    for (i=0; boolean_tbl[i].name != NULL; i++)		if (!strncmp(boolean_tbl[i].name, argv[an], len)) {		    mt_com.mt_count |= boolean_tbl[i].bitmask;		    break;		}	    if (boolean_tbl[i].name == NULL) {		fprintf(stderr, "Illegal property name '%s'.\n", argv[an]);		fprintf(stderr, "The implemented property names are:\n");		for (i=0; boolean_tbl[i].name != NULL; i++)		    fprintf(stderr, "  %9s -> %s\n", boolean_tbl[i].name,			    boolean_tbl[i].expl);		return 1;	    }	    if (len != strlen(boolean_tbl[i].name))		for (i++ ; boolean_tbl[i].name != NULL; i++)		    if (!strncmp(boolean_tbl[i].name, argv[an], len)) {			fprintf(stderr, "Property name '%s' ambiguous.\n",				argv[an]);			return 1;		    }	}    switch (cmd->cmd_code) {    case DO_BOOLEANS:	mt_com.mt_count |= MT_ST_BOOLEANS;	break;    case SET_BOOLEANS:	mt_com.mt_count |= MT_ST_SETBOOLEANS;	break;    case CLEAR_BOOLEANS:	mt_com.mt_count |= MT_ST_CLEARBOOLEANS;	break;    }    if (ioctl(mtfd, MTIOCTOP, (char *)&mt_com) < 0) {	perror(tape_name);	return 2;    }    return 0;}/* Tell where the tape is */	static intdo_tell(int mtfd, cmdef_tr *cmd, int argc, char **argv){    struct mtpos mt_pos;    if (ioctl(mtfd, MTIOCPOS, (char *)&mt_pos) < 0) {	perror(tape_name);	return 2;    }    printf("At block %ld.\n", mt_pos.mt_blkno);    return 0;}/* Position the tape to a specific location within a specified partition */	static intdo_partseek(int mtfd, cmdef_tr *cmd, int argc, char **argv){    struct mtop mt_com;    mt_com.mt_op = MTSETPART;    mt_com.mt_count = (argc > 0 ? strtol(*argv, NULL, 0) : 0);    if (ioctl(mtfd, MTIOCTOP, (char *)&mt_com) < 0) {	perror(tape_name);	return 2;    }    mt_com.mt_op = MTSEEK;    mt_com.mt_count = (argc > 1 ? strtol(argv[1], NULL, 0) : 0);    if (ioctl(mtfd, MTIOCTOP, (char *)&mt_com) < 0) {	perror(tape_name);	return 2;    }    return 0;}/* Position to start of file n. This might be implemented more intelligently   some day. */	static intdo_asf(int mtfd, cmdef_tr *cmd, int argc, char **argv){    struct mtop mt_com;    mt_com.mt_op = MTREW;    mt_com.mt_count = 1;    if (ioctl(mtfd, MTIOCTOP, (char *)&mt_com) < 0) {	perror(tape_name);	return 2;    }    mt_com.mt_count = (argc > 0 ? strtol(*argv, NULL, 0) : 0);    if (mt_com.mt_count > 0) {	mt_com.mt_op = MTFSF;	if (ioctl(mtfd, MTIOCTOP, (char *)&mt_com) < 0) {	    perror(tape_name);	    return 2;	}    }    return 0;}/*** Decipher the status ***/	static intdo_status(int mtfd, cmdef_tr *cmd, int argc, char **argv){    struct mtget status;    int dens, i;    char *type, *density;    if (ioctl(mtfd, MTIOCGET, (char *)&status) < 0) {	perror(tape_name);	return 2;    }    if (status.mt_type == MT_ISSCSI1)	type = "SCSI 1";    else if (status.mt_type == MT_ISSCSI2)	type = "SCSI 2";    else if (status.mt_type == MT_ISONSTREAM_SC)	type = "OnStream SC-, DI-, DP-, or USB";    else	type = NULL;    if (type == NULL) {	if (status.mt_type & 0x800000)	    printf ("qic-117 drive type = 0x%05lx\n", status.mt_type & 0x1ffff);	else if (status.mt_type == 0)	    printf("IDE-Tape (type code 0) ?\n");	else	    printf("Unknown tape drive type (type code %ld)\n", status.mt_type);	printf("File number=%d, block number=%d.\n",	       status.mt_fileno, status.mt_blkno);	printf("mt_resid: %ld, mt_erreg: 0x%lx\n",	       status.mt_resid, status.mt_erreg);	printf("mt_dsreg: 0x%lx, mt_gstat: 0x%lx\n",	       status.mt_dsreg, status.mt_gstat);    }    else {	printf("%s tape drive:\n", type);	if (status.mt_type == MT_ISSCSI2)	    printf("File number=%d, block number=%d, partition=%ld.\n",		   status.mt_fileno, status.mt_blkno, (status.mt_resid & 0xff));	else	    printf("File number=%d, block number=%d.\n",		   status.mt_fileno, status.mt_blkno);	if (status.mt_type == MT_ISSCSI1 ||	    status.mt_type == MT_ISSCSI2 ||	    status.mt_type == MT_ISONSTREAM_SC) {	    dens = (status.mt_dsreg & MT_ST_DENSITY_MASK) >> MT_ST_DENSITY_SHIFT;	    density = "no translation";	    for (i=0; i < NBR_DENSITIES; i++)		if (density_tbl[i].code == dens) {		    density = density_tbl[i].name;		    break;		}	    printf("Tape block size %ld bytes. Density code 0x%x (%s).\n",		   ((status.mt_dsreg & MT_ST_BLKSIZE_MASK) >> MT_ST_BLKSIZE_SHIFT),		   dens, density);	    printf("Soft error count since last status=%ld\n",		   (status.mt_erreg & MT_ST_SOFTERR_MASK) >> MT_ST_SOFTERR_SHIFT);	}    }    printf("General status bits on (%lx):\n", status.mt_gstat);    if (GMT_EOF(status.mt_gstat))	printf(" EOF");    if (GMT_BOT(status.mt_gstat))	printf(" BOT");    if (GMT_EOT(status.mt_gstat))	printf(" EOT");    if (GMT_SM(status.mt_gstat))	printf(" SM");    if (GMT_EOD(status.mt_gstat))	printf(" EOD");    if (GMT_WR_PROT(status.mt_gstat))	printf(" WR_PROT");    if (GMT_ONLINE(status.mt_gstat))	printf(" ONLINE");    if (GMT_D_6250(status.mt_gstat))	printf(" D_6250");    if (GMT_D_1600(status.mt_gstat))	printf(" D_1600");    if (GMT_D_800(status.mt_gstat))	printf(" D_800");    if (GMT_DR_OPEN(status.mt_gstat))	printf(" DR_OPEN");	      if (GMT_IM_REP_EN(status.mt_gstat))	printf(" IM_REP_EN");    if (GMT_CLN(status.mt_gstat))	printf(" CLN");    printf("\n");    return 0;}/* Print a list of possible density codes */	static intprint_densities(int fd, cmdef_tr *cmd, int argc, char **argv){    int i, offset;    printf("Some SCSI tape density codes:\ncode   explanation                   code   explanation\n");    offset = (NBR_DENSITIES + 1) / 2;    for (i=0; i < offset; i++) {	printf("0x%02x   %-28s", density_tbl[i].code, density_tbl[i].name);	if (i + offset < NBR_DENSITIES)	    printf("  0x%02x   %s\n", density_tbl[i + offset].code, density_tbl[i + offset].name);	else	    printf("\n");    }    return 0;}/* Try to find out why the command failed */	static voidtest_error(int mtfd, cmdef_tr *cmd){    struct mtget status;    if (ioctl(mtfd, MTIOCGET, (char *)&status) < 0)	return;    if (status.mt_type != MT_ISSCSI1 && status.mt_type != MT_ISSCSI2)	return;    if ((cmd->error_tests & ET_ONLINE) && !GMT_ONLINE(status.mt_gstat))	fprintf(stderr, "mt: The device is offline (not powered on, no tape ?).\n");    if ((cmd->error_tests & ET_WPROT) && !GMT_WR_PROT(status.mt_gstat))	fprintf(stderr, "mt: The tape is write-protected.\n");}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?