📄 dasdfmt.c
字号:
/* * * dasdfmt.c * * S390 version * Copyright (C) 1999,2000 IBM Corporation * Author(s): Utz Bacher, <utz.bacher@de.ibm.com> * * Device-in-use-checks by Fritz Elfert, <felfert@to.com> * * Still to do: * detect non-switch parameters ("dasdfmt -n 170 XY") and complain about them */#include <unistd.h>#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ioctl.h>#include <errno.h>#include <getopt.h>#include <limits.h>#include <stdlib.h>#include <string.h>#include <dirent.h>#include <mntent.h>#include "../../../drivers/s390/block/dasd.h" /* uses DASD_PARTN_BITS */#define __KERNEL__ /* we want to use kdev_t and not have to define it */#include <linux/kdev_t.h>#undef __KERNEL__#define EXIT_MISUSE 1#define EXIT_BUSY 2#define TEMPFILENAME "/tmp/ddfXXXXXX"#define TEMPFILENAMECHARS 8 /* 8 characters are fixed in all temp filenames */#define IOCTL_COMMAND 'D' << 8#define SLASHDEV "/dev/"#define PROC_DASD_DEVICES "/proc/dasd/devices"#define DASD_DRIVER_NAME "dasd"#define PROC_LINE_LENGTH 80#define ERR_LENGTH 80#define MAX_FILELEN NAME_MAX+PATH_MAX#define GIVEN_DEVNO 1#define GIVEN_MAJOR 2#define GIVEN_MINOR 4#define CHECK_START 1#define CHECK_END 2#define CHECK_BLKSIZE 4#define CHECK_ALL ~0#define ERRMSG(x...) {fflush(stdout);fprintf(stderr,x);}#define ERRMSG_EXIT(ec,x...) {fflush(stdout);fprintf(stderr,x);exit(ec);}#define CHECK_SPEC_MAX_ONCE(i,str) \ {if (i>1) \ ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \ "can only be specified once\n",prog_name);}#define PARSE_PARAM_INTO(x,param,base,str) \ {x=(int)strtol(param,&endptr,base); \ if (*endptr) \ ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \ "is in invalid format\n",prog_name);}typedef struct { int start_unit; int stop_unit; int blksize;} format_data_t;char prog_name[]="dasd_format";char tempfilename[]=TEMPFILENAME;voidexit_usage(int exitcode){ printf("Usage: %s [-htvyV] [-b blocksize] <range> <diskspec>\n\n", prog_name); printf(" where <range> is either\n"); printf(" -s start_track -e end_track\n"); printf(" or\n"); printf(" -r start_track-end_track\n"); printf(" and <diskspec> is either\n"); printf(" -f /dev/dasdX\n"); printf(" or\n"); printf(" -n <s390-devnr>\n"); exit(exitcode);}voidget_xno_from_xno(int *devno,kdev_t *major_no,kdev_t *minor_no,int mode){ FILE *file; int d,rc; kdev_t mi,ma; int mi_i,ma_i; /* for scanf :-( */ char line[PROC_LINE_LENGTH]; file=fopen(PROC_DASD_DEVICES,"r"); if (file==NULL) ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to open " \ PROC_DASD_DEVICES ": %s (do you have the /proc " \ "filesystem enabled?)\n",prog_name,strerror(errno)); fgets(line,sizeof(line),file); /* omit first line */ while (fgets(line,sizeof(line),file)!=NULL) { rc=sscanf(line,"%X%d%d",&d,&ma_i,&mi_i); ma=ma_i; mi=mi_i; if ( (rc==3) && !((d!=*devno)&&(mode&GIVEN_DEVNO)) && !((ma!=*major_no)&&(mode&GIVEN_MAJOR)) && !((mi!=*minor_no)&&(mode&GIVEN_MINOR)) ) { *devno=d; *major_no=ma; *minor_no=mi; /* yes, this is a quick exit, but the easiest way */ fclose(file); return; } } fclose(file); ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to find device in the /proc " \ "filesystem (are you sure to have the right param line?)\n", prog_name);}char *get_devname_from_devno(int devno,int verbosity){ kdev_t major_no,minor_no; kdev_t file_major,file_minor; struct stat stat_buf; int rc; int found; char *devname; char tmpname[MAX_FILELEN]; DIR *dp; struct dirent *direntp; /**** get minor number ****/ get_xno_from_xno(&devno,&major_no,&minor_no,GIVEN_DEVNO); /**** get device file ****/ if ((dp=opendir(SLASHDEV)) == NULL) ERRMSG_EXIT(EXIT_FAILURE,"%s: unable to read " SLASHDEV \ "\n",prog_name); found=0; while ((direntp=readdir(dp)) != NULL) { strcpy(tmpname,SLASHDEV); strcat(tmpname,direntp->d_name); rc=stat(tmpname,&stat_buf); if (!rc) { file_major=MAJOR(stat_buf.st_rdev); file_minor=MINOR(stat_buf.st_rdev); if ((file_major==major_no) && (file_minor==minor_no)) { found=1; break; } } } if (found) { devname=malloc(strlen(direntp->d_name)); strcpy(devname,tmpname); } rc=closedir(dp); if (rc<0) ERRMSG("%s: unable to close directory " SLASHDEV \ "; continuing\n",prog_name); if (found) return devname; if (verbosity>=1) printf("I didn't find device node in " SLASHDEV \ "; trying to create a temporary node\n"); /**** get temp file and create device node *****/ rc=mkstemp(tempfilename); if (rc==-1) ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to get temporary " \ "filename: %s\n",prog_name,strerror(errno)); close(rc); rc=unlink(tempfilename); rc=mknod(tempfilename,S_IFBLK|0600,MKDEV(major_no,minor_no)); if (rc) ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to create temporary " \ "device node %s: %s\n",prog_name,tempfilename, strerror(errno)); return tempfilename;}char *check_param(int mode,format_data_t data){ char *s; if (NULL==(s=malloc(ERR_LENGTH))) ERRMSG_EXIT(EXIT_FAILURE,"%s: not enough memory.\n",prog_name); if ((mode&CHECK_START)&&(data.start_unit<0)) { strcpy(s,"start track must be greater than zero"); goto exit; } if ((mode&CHECK_END)&&(data.stop_unit<-1)) { strcpy(s,"end track must be -1 or greater than zero"); goto exit; } if ((mode&CHECK_END)&&(data.start_unit>data.stop_unit)&& (data.stop_unit!=-1)) { strcpy(s,"end track must be higher than start track"); goto exit; } if ((mode&CHECK_BLKSIZE)&&(data.blksize<1)) { strcpy(s,"blocksize must be a positive integer"); goto exit; } if (mode&CHECK_BLKSIZE) while (data.blksize>0) { if ((data.blksize%2)&&(data.blksize!=1)) { strcpy(s,"blocksize must be a power of 2"); goto exit; } data.blksize/=2; } free(s); return NULL;exit: return s;}#define ASK_PRINTOUT printf("Please enter %s",output)#define ASK_GETBUFFER fgets(buffer,sizeof(buffer),stdin)#define ASK_SCANFORNUMBER(var) rc=sscanf(buffer,"%d%c",&var,&c)#define ASK_COMPLAIN_FORMAT if ((rc==2)&&(c=='\n')) rc=1; \ if (rc==-1) rc=1; /* this happens, if enter is pressed */ \ if (rc!=1) printf(" -- wrong input, try again.\n")#define ASK_CHECK_PARAM(mode) str=check_param(mode,params); \ if (str!=NULL) { printf(" -- %s\n",str); rc=0; free(str); }format_data_task_user_for_data(format_data_t params){ char buffer[20]; /* should be enough for inputing track numbers */ char c; int i,rc; char *str; char output[60],o2[12]; i=params.start_unit; do { params.start_unit=i; sprintf(output,"the start track of the range to format " \ "[%d]: ",i); ASK_PRINTOUT; ASK_GETBUFFER; ASK_SCANFORNUMBER(params.start_unit); ASK_COMPLAIN_FORMAT; ASK_CHECK_PARAM(CHECK_START); } while (rc!=1); i=params.stop_unit; do { params.stop_unit=i; sprintf(output,"the end track of the range to format ["); if (i==-1) sprintf(o2,"END]: "); else sprintf(o2,"%d]: ",i); strcat(output,o2); ASK_PRINTOUT; ASK_GETBUFFER; if ( (!strcasecmp(buffer,"end")) || (!strcasecmp(buffer,"end\n")) ) { rc=1; params.stop_unit=-1; } else { ASK_SCANFORNUMBER(params.stop_unit); ASK_COMPLAIN_FORMAT; ASK_CHECK_PARAM(CHECK_END); } } while (rc!=1); i=params.blksize; do { params.blksize=i; sprintf(output,"the blocksize of the formatting [%d]: ",i); ASK_PRINTOUT; ASK_GETBUFFER; ASK_SCANFORNUMBER(params.blksize); ASK_COMPLAIN_FORMAT; ASK_CHECK_PARAM(CHECK_BLKSIZE); } while (rc!=1); return params;}/* Check if the device we are going to format is mounted. * If true, complain and exit. */voidcheck_mounted(int major, int minor){ FILE *f; int ishift = 0; struct mntent *ment; struct stat stbuf; char line[128]; /* If whole disk to be formatted ... */ if ((minor % (1U << DASD_PARTN_BITS)) == 0) { /* ... ignore partition-selector */ minor >>= DASD_PARTN_BITS; ishift = DASD_PARTN_BITS; } /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -