PFDISK.C
上传用户:yeshiping1
上传日期:2007-01-06
资源大小:29k
文件大小:16k
源码类别:

磁盘编程

开发平台:

Others

  1. /*
  2.  * pfdisk - Partition a Fixed DISK
  3.  * by Gordon W. Ross, Jan. 1990
  4.  *
  5.  * See the file "pfdisk.doc" for user instructions.
  6.  *
  7.  * This program uses a simple, line-oriented interpreter,
  8.  * designed for both interactive and non-interactive use.
  9.  * To facilitate non-interactive use, the output from the
  10.  * 'L' (list partitions) command is carefully arranged so it
  11.  * can be used directly as command input.  Neat trick, eh?
  12.  */
  13. char *versionString =
  14.   "# pfdisk version 1.2 by Gordon W. Ross  Aug. 1990n";
  15. /* These don't really matter.  The user is asked to set them. */
  16. #define DEFAULT_CYLS 306
  17. #define DEFAULT_HEADS 4
  18. #define DEFAULT_SECTORS 17
  19. #define PROMPT_STRING "pfdisk> "
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <ctype.h>
  23. #include "sysdep.h"
  24. #include "syscodes.h"
  25. typedef unsigned char uchar;
  26. typedef unsigned int uint;
  27. typedef unsigned long ulong;
  28. struct part { /* An entry in the partition table */
  29.   uchar active; /* active flag (0x80 or 0) */
  30.   uchar b_head; /* begin head */
  31.   uchar b_sec; /*   sector */
  32.   uchar b_cyl; /*  cylinder */
  33.   uchar sysid; /* system id (see sysid.c) */
  34.   uchar e_head; /* end  head */
  35.   uchar e_sec; /* end sector */
  36.   uchar e_cyl; /* end cylinder */
  37.   /* These two are just longs, but this way is machine independent. */
  38.   uchar lsBeg[4]; /* logical sectors, beginning */
  39.   uchar lsLen[4]; /* logical sectors, length */
  40. };
  41. #define LOC_PT 0x1BE
  42. #define LOC_NT 0x180
  43. #define LOC_GWR 0x1A0
  44. #define MAGIC_LOC 0x1FE
  45. #define MAGIC_0 0x55
  46. #define MAGIC_1 0xAA
  47. #define MAX_LINE 80
  48. char buffer[SECSIZE]; /* The boot block buffer */
  49. int bufmod=0; /* buffer modified... */
  50. /* (zero means buffer is unmodified) */
  51. int useNTable; /* boot sector uses name table */
  52. /* device parameters (force someone to set them!) */
  53. unsigned cyls = DEFAULT_CYLS;
  54. unsigned heads = DEFAULT_HEADS;
  55. unsigned sectors = DEFAULT_SECTORS;
  56. char *devname; /* device name */
  57. char cmdline[MAX_LINE];
  58. char filename[80]; /* used by r/w commands */
  59. char *prompt; /* null if no tty input */
  60. /* Some of these strings are used in more than one place.
  61.  * For consistency, I put a newline on all of them.
  62.  */
  63. char h_h[] = "? <enter>             : Help summaryn";
  64. char h_l[] = "L                     : List partition tablen";
  65. char h_1[] = "1 id first last name  : set partition 1n";
  66. char h_2[] = "2,3,4 ... (like 1)    : set respective partitionn";
  67. char h_a[] = "A n                   : Activate partition nn";
  68. char h_g[] = "G cyls heads sectors  : set disk Geometryn";
  69. char h_i[] = "I                     : list known ID numbersn";
  70. char h_r[] = "R [optional-file]     : Read  device (or specified file)n";
  71. char h_w[] = "W [optional-file]     : Write device (or specified file)n";
  72. char h_q[] = "Q[!]                  : Quit (! means force)n";
  73. char * helpTable[] = {
  74. h_h, h_l, h_1, h_2, h_a, h_g, h_i, h_r, h_w, h_q,
  75. "# (All command letters have lower-case equivalents.)n",
  76. (char *) 0 }; /* This MUST have a zero as the last element */
  77. char *BadArg="Error: bad argument: %sn";
  78. char *WarnNotSaved =
  79. "Warning, modified partition table not saved.n";
  80. help()
  81. {
  82.   char ** p;
  83.   for (p = helpTable; *p; p++)
  84.     printf(*p);
  85. }
  86. /* forward declarations */
  87. void checkValidity();
  88. char * setPartition();
  89. char * makeActive();
  90. char * setGeometry();
  91. ulong chs2long();
  92. char * nameID();
  93. int printIDs();
  94. main(argc,argv)
  95. int argc;
  96. char *argv[];
  97. {
  98.   char *cmdp; /* points to command word */
  99.   char *argp; /* points to command args */
  100.   /* check command line args (device name) */
  101.   if (argc != 2) {
  102.     usage(argv[0]); /* See s-sysname.c */
  103.     exit(1);
  104.   }
  105.   devname = argv[1];
  106.   /* Should we prompt? */
  107.   prompt = (isatty(fileno(stdin))) ? PROMPT_STRING : (char *) 0;
  108.   /* Print version name. */
  109.   fputs(versionString, stderr);
  110.   /* get disk parameters */
  111.   getGeometry(devname,&cyls,&heads,&sectors);
  112.   /* Get the boot block. */
  113.   if (getBBlk(devname, buffer) < 0)
  114.     fprintf(stderr,"%s: read failedn", devname);
  115.   checkValidity();
  116.   if (prompt) fprintf(stderr,"For help, enter: '?'n");
  117.   /* Read and process commands a line at a time. */
  118.   while (1) {
  119.     if (prompt) fputs(prompt,stdout);
  120.     if (! fgets(cmdline, MAX_LINE, stdin)) break;
  121.     /* Find beginning of command word */
  122.     cmdp = cmdline;
  123.     while (isspace(*cmdp)) cmdp++;
  124.     /* find beginning of args */
  125.     argp = cmdp;
  126.     while (*argp && !isspace(*argp)) argp++;
  127.     while (isspace(*argp) || *argp=='=') argp++;
  128.     switch (*cmdp) {
  129.     case '': /* blank line */
  130.     case '#': /* line comment */
  131.       break;
  132.     case '?': case 'h': case 'H':
  133.       help();
  134.       break;
  135.     case '1': /* set partition entry */
  136.     case '2': case '3': case '4':
  137.       argp = setPartition(cmdp, argp);
  138.       if (argp) { /* arg list error */
  139. fprintf(stderr,BadArg,argp);
  140. fprintf(stderr,h_1);
  141. fprintf(stderr,h_2);
  142. break;
  143.       }
  144.       bufmod = 1;
  145.       break;
  146.     case 'a': case 'A': /* activate partition */
  147.       argp = makeActive(argp);
  148.       if (argp) {
  149. fprintf(stderr,BadArg,argp);
  150. fprintf(stderr,h_a);
  151. break;
  152.       }
  153.       bufmod = 1;
  154.       break;
  155.     case 'g': case 'G': /* set disk parameters (Geometry) */
  156.       argp = setGeometry(argp);
  157.       if (argp) { /* arg list error */
  158. fprintf(stderr,BadArg,argp);
  159. fprintf(stderr,h_g);
  160.       }
  161.       break;
  162.     case 'i': case 'I': /* List known ID numbers */
  163.       printIDs();
  164.       break;
  165.     case 'l': case 'L': /* List the partition table */
  166.       listPTable();
  167.       break;
  168.     case 'q': case 'Q': /* Quit */
  169.       if (bufmod && (cmdp[1]  != '!')) {
  170. fprintf(stderr,"07%s%sn", WarnNotSaved,
  171. "Use 'wq' or 'q!' (enter ? for help).");
  172. break;
  173.       }
  174.       exit(0);
  175.       /*NOTREACHED*/
  176.     case 'r': case 'R': /* read from device or file */
  177.       if (sscanf(argp,"%80s",filename) == 1) {
  178. /* Arg specified, read from filename */
  179. if (getFile(filename, buffer, SECSIZE) < 0)
  180.   fprintf(stderr,"%s: read failedn", filename);
  181. bufmod = 1;
  182.       } else {
  183. /* No arg, use device. */
  184. if (getBBlk(devname, buffer) < 0)
  185.   fprintf(stderr,"%s: read failedn", devname);
  186. bufmod = 0;
  187.       }
  188.       checkValidity();
  189.       break;
  190.     case 'w': case 'W': /* Write to file or device */
  191.       if (sscanf(argp,"%80s",filename) == 1) {
  192. /* Arg specified, write to filename */
  193. if (putFile(filename, buffer, SECSIZE) < 0)
  194.   fprintf(stderr, "%s: write failedn", filename);
  195.       } else {  /* No arg, use device. */
  196. if (putBBlk(devname, buffer) < 0)
  197.   fprintf(stderr, "%s: write failedn", devname);
  198. bufmod = 0;
  199.       }
  200.       if (cmdp[1] == 'q' || cmdp[1] == 'Q') exit(0);
  201.       break;
  202.     default:
  203.       fprintf(stderr,"'%c': unrecognized.  Enter '?' for help.n", *cmdp);
  204.       break;
  205.     } /* switch */
  206.   } /* while */
  207.   if (bufmod) fprintf(stderr, WarnNotSaved);
  208.   exit(0);
  209. } /* main */
  210. /* Check for valid boot block (magic number in last two bytes).
  211.  * Also, check for presence of partition name table.
  212.  */
  213. void checkValidity()
  214. {
  215.   /* Check the magic number. */
  216.   if ((buffer[MAGIC_LOC] & 0xFF) != MAGIC_0 ||
  217.       (buffer[MAGIC_LOC+1] & 0xFF) != MAGIC_1 ) {
  218.     /* The boot sector is not valid -- Fix it. */
  219.     buffer[MAGIC_LOC] = MAGIC_0;
  220.     buffer[MAGIC_LOC+1] = MAGIC_1;
  221.     bufmod = 1;
  222.     fprintf(stderr,
  223. "ntWarning:  The boot sector has an invalid magic number.n
  224. tThe magic number has been fixed, but the other contentsn
  225. tare probably garbage.  Initialize using the command:n
  226. ttR boot-program-file (i.e. bootmenu.bin)n
  227. tthen set each partition entry if necessary.n");
  228.   }
  229.   /* Does it use a name table (for a boot menu)?
  230.    * My boot program does, and can be identified by
  231.    * finding my name in a particular (unused) area.
  232.    */
  233.   useNTable = !strcmp(&buffer[LOC_GWR], "Gordon W. Ross");
  234. }
  235. char * setPartition(cmdp,argp) /* return string on error */
  236. char *cmdp,*argp;
  237. {
  238.   struct part *pp; /* partition entry */
  239.   char * np; /* name table pointer */
  240.   char * newname; /* name field */
  241.   int index; /* partition index (0..3) */
  242.   uint id; /* ID code (see syscodes.c) */
  243.   uint first,last; /* user supplied cylinders */
  244.   uint c,h,s; /* working cyl,head,sect, */
  245.   uint len; /* chars seen by sscanf */
  246.   ulong lsbeg, lslen; /* logical begin, length */
  247.   /* Value check the index */
  248.   index = *cmdp - '1';
  249.   if (index < 0 || index > 3)
  250.     return("index");
  251.   pp = (struct part *) &buffer[LOC_PT + index * 16];
  252.   np = &buffer[LOC_NT + index * 8];
  253.   /* Read System ID */
  254.   if (sscanf(argp,"%i%n", &id, &len) < 1)
  255.     return("id");
  256.   argp += len;
  257.   /* If ID==0, just clear out the entry and return. */
  258.   if (id == 0) {
  259.     strncpy( (char *) pp, "", 16);
  260.     if (useNTable) strncpy( np, "", 8);
  261.     return((char *)0);
  262.   }
  263.   /* Read first and last cylinder */
  264.   if (sscanf(argp,"%i%i%n",&first, &last, &len) < 2)
  265.     return("first last (missing)");
  266.   argp += len;
  267.   /* Reasonable start,end cylinder numbers? */
  268.   if (first > last) return("first > last");
  269.   if (first > 1023) return("first > 1023");
  270.   if (last >= cyls) return("last >= cyls");
  271.   /* Get (optional) system name. */
  272.   if (*argp == 'n') { /* no name given, use default */
  273.     newname = nameID(id);
  274.   } else { /* use the given name */
  275.     /* skip leading space */
  276.     while (*argp == ' ') argp++;
  277.     newname = argp;
  278.     /* Remove newline from end */
  279.     while (isgraph(*argp)||*argp==' ') argp++;
  280.     *argp = '';
  281.     useNTable = 1;
  282.   }
  283.   /* Set the ID and name. */
  284.   pp->sysid = id;
  285.   if (useNTable) {
  286.     strncpy(np, newname, 8);
  287.     strcpy(&buffer[LOC_GWR], "Gordon W. Ross");
  288.   }
  289.   /* set beginning c,h,s */
  290.   c = first;
  291.   /* if c == 0, head == 1 (reserve track 0) */
  292.   h = (first) ? 0 : 1;
  293.   s = 1;
  294.   pp->b_cyl = c & 0xFF;
  295.   pp->b_head = h;
  296.   pp->b_sec = s | ((c >> 2) & 0xC0);
  297.   /* Set the logical sector begin field */
  298.   lsbeg = lslen = chs2long(c,h,s); /* using lslen as temp. */
  299.   pp->lsBeg[0] = lslen & 0xff; lslen >>= 8;
  300.   pp->lsBeg[1] = lslen & 0xff; lslen >>= 8;
  301.   pp->lsBeg[2] = lslen & 0xff; lslen >>= 8;
  302.   pp->lsBeg[3] = lslen & 0xff; lslen >>= 8;
  303.   /* set ending c,h,s (last may be larger than 1023) */
  304.   c = (last>1023) ? 1023 : last; /* limit c to 1023 */
  305.   h = heads - 1; s = sectors;
  306.   pp->e_cyl = c & 0xFF;
  307.   pp->e_head = h;
  308.   pp->e_sec = s | ((c >> 2) & 0xC0);
  309.   /* Set the logical sector length field (using REAL end cylinder) */
  310.   lslen = chs2long(last,h,s) + 1 - lsbeg;
  311.   pp->lsLen[0] = lslen & 0xff; lslen >>= 8;
  312.   pp->lsLen[1] = lslen & 0xff; lslen >>= 8;
  313.   pp->lsLen[2] = lslen & 0xff; lslen >>= 8;
  314.   pp->lsLen[3] = lslen & 0xff; lslen >>= 8;
  315.   return((char *)0); /* success */
  316. } /* setPartition() */
  317. char * makeActive(argp) /* return error string or zero */
  318. char *argp;
  319. {
  320.   struct part *pp; /* partition entry */
  321.   int i,act; /* which one becomes active */
  322.   if (sscanf(argp,"%d", &act) < 1)
  323.     return("missing index");
  324.   act--; /* make it zero-origin */
  325.   i=0; pp = (struct part *) &buffer[LOC_PT];
  326.   while (i<4) {
  327.     pp->active = 0;
  328.     if (i == act) {
  329.       if (pp->sysid == 0) return("partition empty");
  330.       pp->active = 0x80;
  331.     }
  332.     i++; pp++;
  333.   }
  334.   return((char *)0);
  335. }
  336. char * setGeometry(argp) /* return string on error */
  337. char *argp;
  338. {
  339.   int c,h,s;
  340.   if (sscanf(argp,"%i%i%i", &c, &h, &s) < 3)
  341.     return("(missing)");
  342.   if (c<1) return("cyls");
  343.   if (h<1) return("heads");
  344.   if (s<1) return("sectors");
  345.   cyls=c; heads=h; sectors=s;
  346.   return((char *)0);
  347. }
  348. listPTable() /* print out partition table */
  349. {
  350.   struct part * pp; /* partition table entry */
  351.   char *name;
  352.   int i; /* partition number */
  353.   int numActive=0; /* active partition [1-4], 0==none */
  354.   uint pbc,pbh,pbs; /* physical beginning  c,h,s */
  355.   uint pec,peh,pes; /* physical ending     c,h,s */
  356.   uint lbc,lbh,lbs; /* logical beginning   c,h,s */
  357.   uint lec,leh,les; /* logical ending      c,h,s */
  358.   ulong lsbeg,lslen; /* logical sectors: begin, length */
  359.   printf("# Partition table on device: %sn", devname);
  360.   printf("geometry %d %d %d (cyls heads sectors)n",
  361.  cyls, heads, sectors);
  362.   printf("#  ID  First(cyl)  Last(cyl)  Name     ");
  363.   printf("# start, length (sectors)n");
  364.   for (i=0; i<4; i++) {
  365.     pp = (struct part *) &buffer[LOC_PT + i * 16];
  366.     if (pp->active) {
  367.       if(numActive)
  368. fprintf(stderr,"Error: multiple active partitions.n");
  369.       else numActive = i+1;
  370.     }
  371.     /* physical beginning c,h,s */
  372.     pbc = pp->b_cyl & 0xff | (pp->b_sec << 2) & 0x300;
  373.     pbh = pp->b_head;
  374.     pbs = pp->b_sec & 0x3F;
  375.     /* physical ending c,h,s */
  376.     pec = pp->e_cyl & 0xff | (pp->e_sec << 2) & 0x300;
  377.     peh = pp->e_head;
  378.     pes = pp->e_sec & 0x3F;
  379.     /* compute logical beginning (c,h,s) */
  380.     lsbeg = ((((((pp->lsBeg[3] ) << 8 )
  381. | pp->lsBeg[2] ) << 8 )
  382. | pp->lsBeg[1] ) << 8 )
  383. | pp->lsBeg[0] ;
  384.     long2chs(lsbeg, &lbc, &lbh, &lbs);
  385.     /* compute logical ending (c,h,s) */
  386.     lslen = ((((((pp->lsLen[3]) << 8 )
  387. | pp->lsLen[2]) << 8 )
  388. | pp->lsLen[1]) << 8 )
  389. | pp->lsLen[0] ;
  390.     /* keep beginning <= end ... */
  391.     if (lslen > 0) long2chs(lsbeg+lslen-1, &lec, &leh, &les);
  392.     else    long2chs(lsbeg,    &lec, &leh, &les);
  393.     if (useNTable)
  394.       name = &buffer[LOC_NT + i * 8];
  395.     else
  396.       name = nameID((uint) pp->sysid);
  397.     /* show physical begin, logical end (works for cyl>1023) */
  398.     /*      #  ID  First(cyl)  Last(cyl)  Name... # ... */
  399.     printf("%d %3d   %4d       %4d       %-8.8s # %ld, %ldn",
  400.    i+1, pp->sysid, pbc, lec, name, lsbeg, lslen );
  401.     /* That's all, for an empty partition. */
  402.     if (pp->sysid == 0) continue;
  403.     /*
  404.      * Now do some consistency checks...
  405.      */
  406.     /* Same physical / logical beginning? */
  407.     if (pbc != lbc || pbh != lbh || pbs != lbs ) {
  408.       printf("# note: first(%d): ", i+1);
  409.       printf("phys=(%d,%d,%d) ",    pbc, pbh, pbs);
  410.       printf("logical=(%d,%d,%d)n",lbc, lbh, lbs);
  411.     }
  412.     /* Same physical / logical ending? */
  413.     if (pec != lec || peh != leh || pes != les ) {
  414.       printf("# note:  last(%d): ", i+1);
  415.       printf("phys=(%d,%d,%d) ",    pec, peh, pes);
  416.       printf("logical=(%d,%d,%d)n",lec, leh, les);
  417.     }
  418.     /* Beginning on cylinder boundary? */
  419.     if (pbc == 0) { /* exception: start on head 1 */
  420.       if (pbh != 1 || pbs != 1) {
  421. printf("# note: first(%i): ", i+1);
  422. printf("phys=(%d,%d,%d) ", pbc, pbh, pbs);
  423. printf("should be (%d,1,1)n", pbc);
  424.       }
  425.     } else { /* not on cyl 0 */
  426.       if (pbh != 0 || pbs != 1) {
  427. printf("# note: first(%i): ", i+1);
  428. printf("phys=(%d,%d,%d) ", pbc, pbh, pbs);
  429. printf("should be (%d,0,1)n", pbc);
  430.       }
  431.     }
  432.     /* Ending on cylinder boundary? */
  433.     if (peh != (heads-1) || pes != sectors) {
  434.       printf("# note: last(%i): ", i+1);
  435.       printf("phys=(%d,%d,%d) ", pec, peh, pes);
  436.       printf("should be (%d,%d,%d)n",
  437.      pec, heads-1, sectors);
  438.     }
  439.   } /* for */
  440.   printf("active: %d  %sn", numActive,
  441.  (numActive) ? "" : "(none)");
  442. } /* listPTable() */
  443. ulong chs2long(c,h,s)
  444. uint c,h,s;
  445. {
  446.   ulong l;
  447.   if (s<1) s=1;
  448.   l  = c; l *= heads;
  449.   l += h; l *= sectors;
  450.   l += (s - 1);
  451.   return(l);
  452. }
  453. long2chs(ls, c, h, s) /* convert logical sec-num to c,h,s */
  454. ulong ls; /* Logical Sector number */
  455. uint *c,*h,*s; /* cyl, head, sector */
  456. {
  457.   int spc = heads * sectors;
  458.   *c = ls / spc;
  459.   ls = ls % spc;
  460.   *h = ls / sectors;
  461.   *s = ls % sectors + 1; /* sectors count from 1 */
  462. }
  463. char * nameID(n)
  464. unsigned int n;
  465. {
  466.   struct intString *is;
  467.   is = sysCodes;
  468.   while (is->i) {
  469.     if (is->i == n) return(is->s);
  470.     is++;
  471.   }
  472.   if (!n) return(is->s);
  473.   return("unknown");
  474. }
  475. int printIDs() /* print the known system IDs */
  476. {
  477.   struct intString * is = sysCodes;
  478.   /* This might need to do more processing eventually, i.e.
  479.    * if (prompt) { ... do more processing ... }
  480.    */
  481.   printf("_ID_t__Name__ ____Description____n");
  482.   while (is->i) {
  483.     printf("%3dt%sn", is->i, is->s);
  484.     is++;
  485.   }
  486. }