📄 stinit.c
字号:
/* This program initializes Linux SCSI tape drives using the inquiry data from the devices and a text database. Copyright 1996-2005 by Kai M鋕isara (email Kai.Makisara@kolumbus.fi) Distribution of this program is allowed according to the GNU Public Licence. Last modified: Sun Aug 21 21:47:51 2005 by kai.makisara*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <unistd.h>#include <errno.h>#include <fcntl.h>#include <dirent.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <sys/sysmacros.h>#include <linux/major.h>#include <scsi/sg.h>#include "mtio.h"#ifndef FALSE#define TRUE 1#define FALSE 0#endif#define SKIP_WHITE(p) for ( ; *p == ' ' || *p == '\t'; p++)#define VERSION "0.9b"typedef struct _modepar_tr { int defined; int blocksize; int density; int buffer_writes; int async_writes; int read_ahead; int two_fm; int compression; int auto_lock; int fast_eod; int can_bsr; int no_blklimits; int can_partitions; int scsi2logical; int sysv; int defs_for_writes;} modepar_tr;typedef struct _devdef_tr { int do_rewind; int drive_buffering; int timeout; int long_timeout; int cleaning; int nowait; modepar_tr modedefs[4];} devdef_tr;#define DEFMAX 2048#define LINEMAX 256#define MAX_TAPES 32#define NBR_MODES 4static int verbose = 0;/* The device directories being searched */typedef struct { char dir[PATH_MAX]; int selective_scan;} devdir;static devdir devdirs[] = { {"/dev/scsi", 0}, {"/dev", 1}, {"", 0}};#define DEVFS_PATH "/dev/tapes"#define DEVFS_TAPEFMT DEVFS_PATH "/tape%d"/* The partial names of the tape devices being included in the search in selective scan */static char *tape_name_bases[] = { "st", "nst", "rmt", "nrmt", "tape", NULL};/* The list of standard definition files being searched */static char *std_databases[] = { "/etc/stinit.def", NULL}; static FILE *open_database(char *base){ int i; FILE *f; if (base != NULL) { if ((f = fopen(base, "r")) == NULL) fprintf(stderr, "stinit: Can't find SCSI tape database '%s'.\n", base); return f; } for (i=0; std_databases[i] != NULL; i++) { if (verbose > 1) fprintf(stderr, "Trying to open database '%s'.\n", std_databases[i]); if ((f = fopen(std_databases[i], "r")) != NULL) { if (verbose > 1) fprintf(stderr, "Open succeeded.\n"); return f; } } fprintf(stderr, "Can't find the tape characteristics database.\n"); return NULL;} static char *find_string(char *s, char *target, char *buf, int buflen){ int have_arg; char *cp, *cp2, c, *argp; if (buf != NULL && buflen > 0) *buf = '\0'; for ( ; *s != '\0'; ) { SKIP_WHITE(s); if (isalpha(*s)) { for (cp=s ; isalnum(*cp) || *cp == '-'; cp++) ; cp2 = cp; SKIP_WHITE(cp); if (*cp == '=') { cp++; SKIP_WHITE(cp); if (*cp == '"') { cp++; for (cp2=cp; *cp2 != '"' && *cp2 != '\0'; cp2++) ; } else for (cp2=cp+1; isalnum(*cp2) || *cp2 == '-'; cp2++) ; if (cp2 == '\0') return NULL; have_arg = TRUE; argp = cp; } else { have_arg = FALSE; argp = "1"; } if (!strncmp(target, s, strlen(target))) { c = *cp2; *cp2 = '\0'; if (buf == NULL) buf = strdup(argp); else { if (strlen(argp) < buflen) strcpy(buf, argp); else { strncpy(buf, argp, buflen); buf[buflen - 1] = '\0'; } } if (have_arg && c == '"') cp2++; else *cp2 = c; if (*cp2 != '\0') memmove(s, cp2, strlen(cp2) + 1); else *s = '\0'; return buf; } s = cp2; } else for ( ; *s != '\0' && *s != ' ' && *s != '\t'; s++) ; } return NULL;} static intnum_arg(char *t){ int nbr; char *tt; nbr = strtol(t, &tt, 0); if (t != tt) { if (*tt == 'k') nbr *= 1024; else if (*tt == 'M') nbr *= 1024 * 1024; } return nbr;} static intnext_block(FILE *dbf, char *buf, int buflen, int limiter){ int len; char *cp, *bp; static char lbuf[LINEMAX]; if (limiter == 0) { /* Restart */ rewind(dbf); lbuf[0] = '\0'; return TRUE; } for (len = 0 ; ; ) { bp = buf + len; if ((cp = strchr(lbuf, limiter)) != NULL) { *cp = '\0'; strcpy(bp, lbuf); cp++; SKIP_WHITE(cp); memmove(lbuf, cp, strlen(cp) + 1); return TRUE; } if (len + strlen(lbuf) >= DEFMAX) { fprintf(stderr, "Too long definition: '%s'\n", buf); return FALSE; } cp = lbuf; SKIP_WHITE(cp); strcpy(bp, cp); strcat(bp, " "); len += strlen(cp) + 1; if (fgets(lbuf, LINEMAX, dbf) == NULL) return FALSE; if ((cp = strchr(lbuf, '#')) != NULL) *cp = '\0'; else lbuf[strlen(lbuf) - 1] = '\0'; }} static intfind_pars(FILE *dbf, char *company, char *product, char *rev, devdef_tr *defs, int parse_only){ int i, mode, modes_defined, errors; char line[LINEMAX], defstr[DEFMAX], comdef[DEFMAX]; char tmpcomp[LINEMAX], tmpprod[LINEMAX], tmprev[LINEMAX], *cp, c, *t; char *nextdef, *curdef, *comptr; static int call_nbr = 0; call_nbr++; defs->drive_buffering = (-1); defs->timeout = (-1); defs->long_timeout = (-1); defs->cleaning = (-1); defs->nowait = (-1); for (i=0; i < NBR_MODES; i++) { defs->modedefs[i].defined = FALSE; defs->modedefs[i].blocksize = (-1); defs->modedefs[i].density = (-1); defs->modedefs[i].buffer_writes = (-1); defs->modedefs[i].async_writes = (-1); defs->modedefs[i].read_ahead = (-1); defs->modedefs[i].two_fm = (-1); defs->modedefs[i].compression = (-1); defs->modedefs[i].auto_lock = (-1); defs->modedefs[i].fast_eod = (-1); defs->modedefs[i].can_bsr = (-1); defs->modedefs[i].no_blklimits = (-1); defs->modedefs[i].can_partitions = (-1); defs->modedefs[i].scsi2logical = (-1); defs->modedefs[i].sysv = (-1); defs->modedefs[i].defs_for_writes = (-1); } next_block(dbf, NULL, 0, 0); /* Find matching inquiry block */ for (errors=0 ; ; ) { if (!next_block(dbf, defstr, DEFMAX, '{')) break; find_string(defstr, "manuf", tmpcomp, LINEMAX); find_string(defstr, "model", tmpprod, LINEMAX); find_string(defstr, "rev", tmprev, LINEMAX); if (!next_block(dbf, defstr, DEFMAX, '}')) { fprintf(stderr, "End of definition block not found for ('%s', '%s', '%s').\n", tmpcomp, tmpprod, tmprev); return FALSE; } if (!parse_only) { if (tmpcomp[0] != '\0' && strncmp(company, tmpcomp, strlen(tmpcomp))) continue; if (tmpprod[0] != '\0' && strncmp(product, tmpprod, strlen(tmpprod))) continue; if (tmprev[0] != '\0' && strncmp(rev, tmprev, strlen(tmprev))) continue; } else if (verbose > 0) printf("\nParsing modes for ('%s', '%s', '%s').\n", tmpcomp, tmpprod, tmprev); /* Block found, get the characteristics */ for (nextdef=defstr; *nextdef != '\0' && (*nextdef != 'm' || strncmp(nextdef, "mode", 2)); nextdef++) ; c = *nextdef; *nextdef = '\0'; strcpy(comdef, defstr); *nextdef = c; comptr = comdef; SKIP_WHITE(comptr); for ( ; *nextdef != '\0'; ) { curdef = nextdef; SKIP_WHITE(curdef); for (nextdef++ ; *nextdef != '\0' && (*nextdef != 'm' || strncmp(nextdef, "mode", 2)); nextdef++) ; c = *nextdef; *nextdef = '\0'; mode = strtol(curdef + 4, &cp, 0) - 1; if (mode < 0 || mode >= NBR_MODES) { fprintf(stderr, "Illegal mode for ('%s', '%s', '%s'):\n'%s'\n", tmpcomp, tmpprod, tmprev, curdef); *nextdef = c; errors++; continue; } strcpy(defstr, comptr); strcat(defstr, cp); *nextdef = c; if (verbose > 1) fprintf(stderr, "Mode %d definition: %s\n", mode + 1, defstr); if ((t = find_string(defstr, "disab", line, LINEMAX)) != NULL && strtol(t, NULL, 0) != 0) { defs->modedefs[mode].defined = FALSE; continue; } if ((t = find_string(defstr, "drive-", line, LINEMAX)) != NULL) defs->drive_buffering = num_arg(t); if ((t = find_string(defstr, "timeout", line, LINEMAX)) != NULL) defs->timeout = num_arg(t); if ((t = find_string(defstr, "long-time", line, LINEMAX)) != NULL) defs->long_timeout = num_arg(t); if ((t = find_string(defstr, "clean", line, LINEMAX)) != NULL) defs->cleaning = num_arg(t); if ((t = find_string(defstr, "no-w", line, LINEMAX)) != NULL) defs->nowait = num_arg(t); defs->modedefs[mode].defined = TRUE; if ((t = find_string(defstr, "block", line, LINEMAX)) != NULL) defs->modedefs[mode].blocksize = num_arg(t); if ((t = find_string(defstr, "dens", line, LINEMAX)) != NULL) defs->modedefs[mode].density = num_arg(t); if ((t = find_string(defstr, "buff", line, LINEMAX)) != NULL) defs->modedefs[mode].buffer_writes = num_arg(t); if ((t = find_string(defstr, "async", line, LINEMAX)) != NULL) defs->modedefs[mode].async_writes = num_arg(t); if ((t = find_string(defstr, "read", line, LINEMAX)) != NULL) defs->modedefs[mode].read_ahead = num_arg(t); if ((t = find_string(defstr, "two", line, LINEMAX)) != NULL) defs->modedefs[mode].two_fm = num_arg(t); if ((t = find_string(defstr, "comp", line, LINEMAX)) != NULL) defs->modedefs[mode].compression = num_arg(t); if ((t = find_string(defstr, "auto", line, LINEMAX)) != NULL) defs->modedefs[mode].auto_lock = num_arg(t); if ((t = find_string(defstr, "fast", line, LINEMAX)) != NULL) defs->modedefs[mode].fast_eod = num_arg(t); if ((t = find_string(defstr, "can-b", line, LINEMAX)) != NULL) defs->modedefs[mode].can_bsr = num_arg(t); if ((t = find_string(defstr, "noblk", line, LINEMAX)) != NULL) defs->modedefs[mode].no_blklimits = num_arg(t); if ((t = find_string(defstr, "can-p", line, LINEMAX)) != NULL) defs->modedefs[mode].can_partitions = num_arg(t); if ((t = find_string(defstr, "scsi2", line, LINEMAX)) != NULL) defs->modedefs[mode].scsi2logical = num_arg(t); if ((t = find_string(defstr, "sysv", line, LINEMAX)) != NULL) defs->modedefs[mode].sysv = num_arg(t); if ((t = find_string(defstr, "defs-for-w", line, LINEMAX)) != NULL) defs->modedefs[mode].defs_for_writes = num_arg(t); for (t=defstr; *t == ' ' || *t == '\t'; t++) ; if (*t != '\0' && call_nbr <= 1) { fprintf(stderr, "Warning: errors in definition for ('%s', '%s', '%s'):\n%s\n", tmpcomp, tmpprod, tmprev, defstr); errors++; } } } if (parse_only) { if (verbose > 0) printf("\n"); printf("Definition parse completed. "); if (errors) { printf("Errors found!\n"); return FALSE; } else { printf("No errors found.\n"); return TRUE; } } else { for (i=modes_defined=0; i < NBR_MODES; i++) if (defs->modedefs[i].defined) modes_defined++; if (modes_defined == 0) { fprintf(stderr, "Warning: No modes in definition for ('%s', '%s', '%s').\n", tmpcomp, tmpprod, tmprev); errors++; } } if (modes_defined) return TRUE; return FALSE;}static int sg_io_errcheck(struct sg_io_hdr *hdp){ int status; status = hdp->status & 0x7e; if ((hdp->status & 0x7e) == 0 || hdp->host_status == 0 || hdp->driver_status == 0) return 0; return EIO;}#define INQUIRY 0x12#define INQUIRY_CMDLEN 6#define SENSE_BUFF_LEN 32#define DEF_TIMEOUT 60000#ifndef SCSI_IOCTL_SEND_COMMAND#define SCSI_IOCTL_SEND_COMMAND 1#endif#define IOCTL_HEADER_LENGTH 8 static intdo_inquiry(char *tname, char *company, char *product, char *rev, int print_non_found){ int fn; int result, *ip, i;#define BUFLEN 256 unsigned char buffer[BUFLEN], *cmd, *inqptr; struct sg_io_hdr io_hdr; unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY, 0, 0, 0, 200, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; if ((fn = open(tname, O_RDONLY | O_NONBLOCK)) < 0) { if (print_non_found || verbose > 0) { if (errno == ENXIO)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -