stinit.c

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

C
965
字号
		fprintf(stderr, "Device '%s' not found by kernel.\n", tname);	    else		fprintf(stderr, "Can't open tape device '%s' (errno %d).\n",			tname, errno);	}	return FALSE;    }    /* Try SG_IO first, if it is not supported, use SCSI_IOCTL_SEND_COMMAND */    memset(&io_hdr, 0, sizeof(struct sg_io_hdr));    io_hdr.interface_id = 'S';    io_hdr.cmd_len = sizeof(inqCmdBlk);    io_hdr.mx_sb_len = sizeof(sense_b);    io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;    io_hdr.dxfer_len = 200;    io_hdr.dxferp = buffer;    io_hdr.cmdp = inqCmdBlk;    io_hdr.sbp = sense_b;    io_hdr.timeout = DEF_TIMEOUT;    inqptr = buffer;    result = ioctl(fn, SG_IO, &io_hdr);    if (!result)	result = sg_io_errcheck(&io_hdr);    if (result) {	if (errno == ENOTTY || errno == EINVAL) {	    memset(buffer, 0, BUFLEN);	    ip = (int *)&(buffer[0]);	    *ip = 0;	    *(ip+1) = BUFLEN - 13;	    cmd = &(buffer[8]);	    cmd[0] = INQUIRY;	    cmd[4] = 200;	    result = ioctl(fn, SCSI_IOCTL_SEND_COMMAND, buffer);	    inqptr = buffer + IOCTL_HEADER_LENGTH;	}	if (result) {	    close(fn);	    sprintf(buffer,		    "The SCSI INQUIRY for device '%s' failed (power off?)",		    tname);	    perror(buffer);	    return FALSE;	}    }    memcpy(company, inqptr + 8, 8);    for (i=8; i > 0 && company[i-1] == ' '; i--)	;    company[i] = '\0';    memcpy(product, inqptr + 16, 16);    for (i=16; i > 0 && product[i-1] == ' '; i--)	;    product[i] = '\0';    memcpy(rev, inqptr + 32, 4);    for (i=4; i > 0 && rev[i-1] == ' '; i--)	;    rev[i] = '\0';    close(fn);    return TRUE;}	static inttapenum(char *name){    int dev;    struct dirent *dent;    DIR *dirp;    char tmpname[PATH_MAX];    const char *dn;    const devdir *dvd;    struct stat statbuf;    if (strchr(name, '/') != NULL) {  /* Complete name */	if (stat(name, &statbuf) != 0) {	    fprintf(stderr, "Can't stat '%s'.\n", name);	    return (-1);	}	if (!S_ISCHR(statbuf.st_mode) ||	    major(statbuf.st_rdev) != SCSI_TAPE_MAJOR)	    return (-1);	dev = minor(statbuf.st_rdev) & 31;	return dev;    }    else { /* Search from the device directories */	for (dvd=devdirs; dvd->dir != NULL; dvd++) {	    dn = dvd->dir;	    if ((dirp = opendir(dn)) == NULL)	      continue;	    for ( ; (dent = readdir(dirp)) != NULL; )		if (!strcmp(dent->d_name, name)) {		    strcpy(tmpname, dn);		    strcat(tmpname, "/");		    strcat(tmpname, dent->d_name);		    if (stat(tmpname, &statbuf) != 0) {			fprintf(stderr, "Can't stat '%s'.\n", tmpname);			continue;		    }		    if (!S_ISCHR(statbuf.st_mode) ||			major(statbuf.st_rdev) != SCSI_TAPE_MAJOR)			continue;		    dev = minor(statbuf.st_rdev) & 31;		    closedir(dirp);		    return dev;		}	    closedir(dirp);	}    }    return (-1);}	static intaccept_tape_name(char *name){    char **npp;    for (npp=tape_name_bases; *npp; npp++)	if (!strncmp(name, *npp, strlen(*npp)))	    return TRUE;    return FALSE;}	static intfind_devfiles(int tapeno, char **names){    int dev, mode, found;    int non_rew[NBR_MODES];    struct dirent *dent;    DIR *dirp;    char tmpname[PATH_MAX];    const char *dn;    static const devdir *dvd;    const devdir *dvp;    int tmpdevdirsindex = 0;    static devdir tmpdevdirs[MAX_TAPES + 1];    struct stat statbuf;    for (found=0; found < NBR_MODES; found++) {	*names[found] = '\0';	non_rew[found] = FALSE;    }    if (dvd == NULL && !stat(DEVFS_PATH, &statbuf)) {	if (S_ISDIR(statbuf.st_mode) && (dirp=opendir(DEVFS_PATH)) != NULL) {	    /* Assume devfs, one directory for each tape */	    for ( ; (dent = readdir(dirp)) != NULL; ) {		if (!strcmp (dent->d_name, ".")		    || !strcmp (dent->d_name, ".."))		    continue;		snprintf(tmpdevdirs[tmpdevdirsindex].dir,			 sizeof(tmpdevdirs[tmpdevdirsindex].dir),			 "%s/%s", DEVFS_PATH, dent->d_name);		tmpdevdirs[tmpdevdirsindex].selective_scan = FALSE;		if (++tmpdevdirsindex == MAX_TAPES)		    break;	    }	    tmpdevdirs[tmpdevdirsindex].dir[0] = 0;	    closedir(dirp);	    dvd = &tmpdevdirs[0];	}    }    if (dvd == NULL)	dvd = devdirs;    for (found=0, dvp=dvd; found < NBR_MODES && dvp->dir[0] != 0; dvp++) {	dn = dvp->dir;	if ((dirp = opendir(dn)) == NULL)	    continue;	for ( ; (dent = readdir(dirp)) != NULL; ) {	    if (!strcmp (dent->d_name, ".") || !strcmp (dent->d_name, ".."))		continue;	    /* Ignore non-tape devices to avoid loading all the modules */	    if (dvp->selective_scan && !accept_tape_name(dent->d_name))		continue;	    strcpy(tmpname, dn);	    strcat(tmpname, "/");	    strcat(tmpname, dent->d_name);	    if (stat(tmpname, &statbuf) != 0) {		fprintf(stderr, "Can't stat '%s'.\n", tmpname);		continue;	    }	    if (!S_ISCHR(statbuf.st_mode) || major(statbuf.st_rdev) !=		SCSI_TAPE_MAJOR)		continue;	    dev = minor(statbuf.st_rdev);	    if ((dev & 31) != tapeno)		continue;	    mode = (dev & 127) >> 5;	    if (non_rew[mode])		continue;	    if (*names[mode] == '\0')		found++;	    strcpy(names[mode], tmpname);	    non_rew[mode] = (dev & 128) != 0;	}	closedir(dirp);    }    return (found > 0);}	static intset_defs(devdef_tr *defs, char **fnames){    int i, tape;    int clear_set[2];    struct mtop op;    for (i=0; i < NBR_MODES; i++) {	if (*fnames[i] == '\0' || !defs->modedefs[i].defined)	    continue;	if ((tape = open(fnames[i], O_RDONLY | O_NONBLOCK)) < 0) {	    fprintf(stderr, "Can't open the tape device '%s' for mode %d.\n",		    fnames[i], i);	    return FALSE;	}	if (i == 0) {	    if (defs->do_rewind) {		op.mt_op = MTREW;		op.mt_count = 1;		ioctl(tape, MTIOCTOP, &op);  /* Don't worry about result */	    }	    if (defs->drive_buffering >= 0) {		op.mt_op = MTSETDRVBUFFER;		op.mt_count = MT_ST_DEF_DRVBUFFER | defs->drive_buffering;		if (ioctl(tape, MTIOCTOP, &op) != 0) {		    fprintf(stderr, "Can't set drive buffering to %d.\n",			    defs->drive_buffering);		}	    }	    if (defs->timeout >= 0) {		op.mt_op = MTSETDRVBUFFER;		op.mt_count = MT_ST_SET_TIMEOUT | defs->timeout;		if (ioctl(tape, MTIOCTOP, &op) != 0) {		    fprintf(stderr, "Can't set device timeout %d s.\n",			    defs->timeout);		}	    }	    if (defs->long_timeout >= 0) {		op.mt_op = MTSETDRVBUFFER;		op.mt_count = MT_ST_SET_LONG_TIMEOUT | defs->long_timeout;		if (ioctl(tape, MTIOCTOP, &op) != 0) {		    fprintf(stderr, "Can't set device long timeout %d s.\n",			    defs->long_timeout);		}	    }	    if (defs->cleaning >= 0) {		op.mt_op = MTSETDRVBUFFER;		op.mt_count = MT_ST_SET_CLN | defs->cleaning;		if (ioctl(tape, MTIOCTOP, &op) != 0) {		    fprintf(stderr, "Can't set cleaning request parameter to %x\n",			    defs->cleaning);		}	    }	}	op.mt_op = MTSETDRVBUFFER;	clear_set[0] = clear_set[1] = 0;	if (defs->nowait >= 0)	    clear_set[defs->nowait != 0] |= MT_ST_NOWAIT;	if (defs->modedefs[i].buffer_writes >= 0)	    clear_set[defs->modedefs[i].buffer_writes != 0] |= MT_ST_BUFFER_WRITES;	if (defs->modedefs[i].async_writes >= 0)	    clear_set[defs->modedefs[i].async_writes != 0] |= MT_ST_ASYNC_WRITES;	if (defs->modedefs[i].read_ahead >= 0)	    clear_set[defs->modedefs[i].read_ahead != 0] |= MT_ST_READ_AHEAD;	if (defs->modedefs[i].two_fm >= 0)	    clear_set[defs->modedefs[i].two_fm != 0] |= MT_ST_TWO_FM;	if (defs->modedefs[i].fast_eod >= 0)	    clear_set[defs->modedefs[i].fast_eod != 0] |= MT_ST_FAST_MTEOM;	if (defs->modedefs[i].auto_lock >= 0)	    clear_set[defs->modedefs[i].auto_lock != 0] |= MT_ST_AUTO_LOCK;	if (defs->modedefs[i].can_bsr >= 0)	    clear_set[defs->modedefs[i].can_bsr != 0] |= MT_ST_CAN_BSR;	if (defs->modedefs[i].no_blklimits >= 0)	    clear_set[defs->modedefs[i].no_blklimits != 0] |= MT_ST_NO_BLKLIMS;	if (defs->modedefs[i].can_partitions >= 0)	    clear_set[defs->modedefs[i].can_partitions != 0] |= MT_ST_CAN_PARTITIONS;	if (defs->modedefs[i].scsi2logical >= 0)	    clear_set[defs->modedefs[i].scsi2logical != 0] |= MT_ST_SCSI2LOGICAL;	if (defs->modedefs[i].sysv >= 0)	    clear_set[defs->modedefs[i].sysv != 0] |= MT_ST_SYSV;	if (defs->modedefs[i].defs_for_writes >= 0)	    clear_set[defs->modedefs[i].defs_for_writes != 0] |= MT_ST_DEF_WRITES;	if (clear_set[0] != 0) {	    op.mt_count = MT_ST_CLEARBOOLEANS | clear_set[0];	    if (ioctl(tape, MTIOCTOP, &op) != 0) {		fprintf(stderr, "Can't clear the tape options (bits 0x%x, mode %d).\n",			clear_set[0], i);	    }	}	if (clear_set[1] != 0) {	    op.mt_count = MT_ST_SETBOOLEANS | clear_set[1];	    if (ioctl(tape, MTIOCTOP, &op) != 0) {		fprintf(stderr, "Can't set the tape options (bits 0x%x, mode %d).\n",			clear_set[1], i);	    }	}	if (defs->modedefs[i].blocksize >= 0) {	    op.mt_count = MT_ST_DEF_BLKSIZE | defs->modedefs[i].blocksize;	    if (ioctl(tape, MTIOCTOP, &op) != 0) {		fprintf(stderr, "Can't set blocksize %d for mode %d.\n",			defs->modedefs[i].blocksize, i);	    }	}	if (defs->modedefs[i].density >= 0) {	    op.mt_count = MT_ST_DEF_DENSITY | defs->modedefs[i].density;	    if (ioctl(tape, MTIOCTOP, &op) != 0) {		fprintf(stderr, "Can't set density %x for mode %d.\n",			defs->modedefs[i].density, i);	    }	}	if (defs->modedefs[i].compression >= 0) {	    op.mt_count = MT_ST_DEF_COMPRESSION | defs->modedefs[i].compression;	    if (ioctl(tape, MTIOCTOP, &op) != 0) {		fprintf(stderr, "Can't set compression %d for mode %d.\n",			defs->modedefs[i].compression, i);	    }	}	close(tape);    }    return TRUE;}	static intdefine_tape(int tapeno, FILE *dbf, devdef_tr *defptr, int print_non_found){    int i;    char company[10], product[20], rev[5], *tname, *fnames[NBR_MODES];    if (verbose > 0)	printf("\nstinit, processing tape %d\n", tapeno);    if ((fnames[0] = calloc(NBR_MODES, PATH_MAX)) == NULL) {	fprintf(stderr, "Can't allocate name buffers.\n");	return FALSE;    }    for (i=1; i < NBR_MODES; i++)	fnames[i] = fnames[i-1] + PATH_MAX;    if (!find_devfiles(tapeno, fnames) ||	*fnames[0] == '\0') {	if (print_non_found)	    fprintf(stderr, "Can't find any device files for tape %d.\n",		    tapeno);	free(fnames[0]);	return FALSE;    }    if (verbose > 1)	for (i=0; i < NBR_MODES; i++)	    printf("Mode %d, name '%s'\n", i, fnames[i]);    tname = fnames[0];    if (!do_inquiry(tname, company, product, rev, print_non_found)) {	free(fnames[0]);	return FALSE;    }    if (verbose > 0)	printf("The manufacturer is '%s', product is '%s', and revision '%s'.\n",	       company, product, rev);    if (!find_pars(dbf, company, product, rev, defptr, FALSE)) {	fprintf(stderr, "Can't find defaults for tape number %d.\n", tapeno);	free(fnames[0]);	return FALSE;    }    if (!set_defs(defptr, fnames)) {	free(fnames[0]);	return FALSE;    }    free(fnames[0]);    return TRUE;}	static charusage(int retval){    fprintf(stderr,	    "Usage: stinit [-h] [-v] [-f dbname] [-p] [drivename_or_number ...]\n");    exit(retval);}	intmain(int argc, char **argv){    FILE *dbf = NULL;    int argn;    int tapeno, parse_only = FALSE;    char *dbname = NULL;    devdef_tr defs;    defs.do_rewind = FALSE;    for (argn=1; argn < argc && *argv[argn] == '-'; argn++) {	if (*(argv[argn] + 1) == 'v')	    verbose++;	else if (*(argv[argn] + 1) == 'p')	    parse_only = TRUE;	else if (*(argv[argn] + 1) == 'h')	    usage(0);	else if (*(argv[argn] + 1) == 'r')	    defs.do_rewind = TRUE;	else if (*(argv[argn] + 1) == 'f') {	    argn += 1;	    if (argn >= argc)		usage(1);	    dbname = argv[argn];	}	else if (*(argv[argn] + 1) == '-' &&		 *(argv[argn] + 2) == 'v') {	    printf("stinit v. %s\n", VERSION);	    exit(0);	    break;	}	else	    usage(1);    }    if ((dbf = open_database(dbname)) == NULL)	return 1;      if (parse_only) {	if (argc > argn)	    fprintf(stderr, "Extra arguments on command line ignored.\n");	if (!find_pars(dbf, "xyz", "xyz", "xyz", &defs, TRUE))	    return 1;	return 0;    }    if (argc > argn) {  /* Initialize specific drives */	for ( ; argn < argc; argn++) {	    if (*argv[argn] == '-') {		usage(1);		return 1; /* Never executed but makes gcc happy */	    }	    else if (isdigit(*argv[argn]))		tapeno = strtol(argv[argn], NULL, 0);	    else if ((tapeno = tapenum(argv[argn])) < 0) {		fprintf(stderr, "Can't find tape number for name '%s'.\n",			argv[argn]);		continue;	    }	    if (!define_tape(tapeno, dbf, &defs, TRUE))		fprintf(stderr, "Definition for '%s' failed.\n", argv[argn]);	}    }    else {  /* Initialize all SCSI tapes */	for (tapeno=0; tapeno < MAX_TAPES; tapeno++)	    if (!define_tape(tapeno, dbf, &defs, FALSE)) {		fprintf(stderr, "Initialized %d tape device%s.\n",			tapeno, (tapeno != 1 ? "s" : ""));		return 0;  /* Process tapes until failure */	    }    }    return 0;}

⌨️ 快捷键说明

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