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 + -
显示快捷键?