FDVOL.C
上传用户:jnzhq888
上传日期:2007-01-18
资源大小:51694k
文件大小:8k
源码类别:

操作系统开发

开发平台:

WINDOWS

  1. /* fdvol.c - A stripped down version of the MINIX vol program.  It takes
  2.  * a file and breaks into into floppy-sized chunks, writing each one raw
  3.  * to a floppy.
  4.  *
  5.  *      Usage:          fdvol file drive KB [slow]
  6.  *
  7.  * Examples: fdvol 1440 a: foo.taz # 1.4 MB floppy a:
  8.  * fdvol 1200 b: foo.taz # 1.2 MB floppy b:
  9.  *                      fdvol slow 360 a: foo.taz # old machine
  10.  *                      fdvol 1440 a: foo bar # concatenate
  11.  *
  12.  * The optional 'slow' parameter forces the program to write in units of 3
  13.  * sectors. Folk tradition has it that this works around some buggy BIOSes.
  14.  *
  15.  * This code borrows heavily from Mark Becker's RaWrite program.
  16.  */
  17. #include <sys/types.h>
  18. #include <fcntl.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <ctype.h>
  23. #define TEST 0
  24. #if !TEST
  25. #include <alloc.h>
  26. #include <bios.h>
  27. #include <dir.h>
  28. #include <dos.h>
  29. #include <io.h>
  30. #endif
  31. #define FALSE 0
  32. #define TRUE (!FALSE)
  33. #define SECTORSIZE 512
  34. #define RESET 0
  35. #define LAST 1
  36. #define READ 2
  37. #define WRITE 3
  38. #define VERIFY 4
  39. #define FORMAT 5
  40. int done;
  41. char buffer[18*SECTORSIZE]; /* do I/O in units of up to 18 sectors */
  42. char testbuf[SECTORSIZE]; /* to do a test read of the first sector */
  43. int handler(void)
  44. {
  45. /* Catch CTRL-C and CTRL-Break. */
  46.   done = 1;
  47.   return(0);
  48. }
  49. void msg(char (*s))
  50. {
  51. /* Print an error message and quit. */
  52.   fprintf(stderr, "%sn", s);
  53.   _exit(1);
  54. }
  55. void Error(int status, int cyl, int head, int sector)
  56. {
  57. /* Identify the error code with a real error message. */
  58.   fprintf(stderr, "nError occured while writing cyl %d, head=%d, sector=%dn", cyl,head,sector+1);
  59.   switch (status) {
  60.     case 0x00: msg("Operation Successful"); break;
  61.     case 0x01: msg("Bad command"); break;
  62.     case 0x02: msg("Address mark not found"); break;
  63.     case 0x03: msg("Attempt to write on write-protected disk"); break;
  64.     case 0x04: msg("Sector not found"); break;
  65.     case 0x05: msg("Reset failed (hard disk)"); break;
  66.     case 0x06: msg("Disk changed since last operation"); break;
  67.     case 0x07: msg("Drive parameter activity failed"); break;
  68.     case 0x08: msg("DMA overrun"); break;
  69.     case 0x09: msg("Attempt to DMA across 64K boundary"); break;
  70.     case 0x0A: msg("Bad sector detected"); break;
  71.     case 0x0B: msg("Bad track detected"); break;
  72.     case 0x0C: msg("Unsupported track"); break;
  73.     case 0x10: msg("Bad CRC/ECC on disk read"); break;
  74.     case 0x11: msg("CRC/ECC corrected data error"); break;
  75.     case 0x20: msg("Controller has failed"); break;
  76.     case 0x40: msg("Seek operation failed"); break;
  77.     case 0x80: msg("Attachment failed to respond"); break;
  78.     case 0xAA: msg("Drive not ready (hard disk only"); break;
  79.     case 0xBB: msg("Undefined error occurred (hard disk only)"); break;
  80.     case 0xCC: msg("Write fault occurred"); break;
  81.     case 0xE0: msg("Status error"); break;
  82.     case 0xFF: msg("Sense operation failed"); break;
  83.   }
  84.   exit(1);
  85. }
  86. void main(int argc, char *argv[])
  87. {
  88.   int disknr = 1, fdin, count, drive, head, cyl, status, sector;
  89.   int max_cyl, chunk, nsectors, ct;
  90.   long offset, drive_size, r, cyl_size;
  91.   char *p, c;
  92.   int slow;
  93.   int kbsize;
  94.   char **files;
  95.   int nfiles, i;
  96. #if !TEST
  97.   /* Catch breaks. */
  98.   ctrlbrk(handler);
  99. #endif
  100. #if 0 /* Do we have to clear the screen? */
  101.   fprintf(stderr, "nnnnnnnnnnnnnnnnnnnnnnnnn");
  102. #endif
  103.   if (argc > 1 && strcmp(argv[1], "slow") == 0) { /* Lousy BIOS? */
  104. slow = 1;
  105. argc--;
  106. argv++;
  107.   } else {
  108. slow = 0;
  109.   }
  110.   /* Check the arguments for validity. */
  111.   if (argc < 4)
  112.         msg("Usage: fdvol [slow] #kilobytes drive-letter file1 [file2 ...]");
  113.   kbsize = atoi(argv[1]);
  114.   p = argv[2];
  115.   c = *p;
  116.   if (c == 'a' || c == 'A')
  117. drive = 0;
  118.   else if (c == 'b' || c == 'B')
  119.         drive = 1;
  120.   else
  121. msg("fdvol: Second parameter must be drive, either   a:   or   b:");
  122.   files = argv + 3;
  123.   nfiles = argc - 3;
  124.   switch(kbsize) {
  125.       case 360:
  126.         cyl_size = 9*2*SECTORSIZE;      /* bytes/cylinder */
  127.         max_cyl = 39;                   /* zero-based counting */
  128. drive_size = cyl_size * (max_cyl+1);
  129.         chunk = (!slow ? 9 * SECTORSIZE : 3 * SECTORSIZE);
  130.         nsectors = chunk/SECTORSIZE;
  131.         break;
  132.       case 720:
  133.         cyl_size = 9*2*SECTORSIZE;      /* bytes/cylinder */
  134.         max_cyl = 79;                   /* zero-based counting */
  135. drive_size = cyl_size * (max_cyl+1);
  136.         chunk = (!slow ? 9 * SECTORSIZE : 3 * SECTORSIZE);
  137.         nsectors = chunk/SECTORSIZE;
  138.         break;
  139.       case 1200:
  140.         cyl_size = 15*2*SECTORSIZE;          /* bytes/cylinder */
  141.         max_cyl = 79;                   /* zero-based counting */
  142. drive_size = cyl_size * (max_cyl+1);
  143.         chunk = (!slow ? 15 * SECTORSIZE : 3 * SECTORSIZE);
  144.         nsectors = chunk/SECTORSIZE;
  145.         break;
  146.       case 1440:
  147.         cyl_size = 18*2*SECTORSIZE;     /* bytes/cylinder */
  148.         max_cyl = 79;                   /* zero-based counting */
  149. drive_size = cyl_size * (max_cyl+1);
  150.         chunk = (!slow ? 18 * SECTORSIZE : 3 * SECTORSIZE);
  151.         nsectors = chunk/SECTORSIZE;
  152.         break;
  153.       default:
  154. msg("fdvol: First parameter must be one of: 360, 720, 1200, or 1440");
  155.   }
  156. #if !TEST
  157.   biosdisk(RESET, drive, 0, 0, 0, 0, testbuf);
  158. #endif
  159. /*
  160.  * Start writing data to diskette until there is no more data to write.
  161.  * Optionally read and write in units of 3 sectors.  Folk tradition says
  162.  * that this makes fewer buggy BIOSes unhappy than doing a whole track at a
  163.  * time.
  164.  */
  165.   offset = 0;
  166.   i = 0;
  167.   fdin = -1;
  168.   while(1) {
  169. if (done > 0) {
  170. if (done == 1) msg("User abort");
  171. #if !TEST
  172. biosdisk(READ, drive, 0, 0, 1, 1, testbuf); /* Retract head */
  173. #endif
  174.                 fprintf(stderr, "Done.                                                      n");
  175. exit(done == 1 ? 1 : 0);
  176. }
  177. /* Until a chunk is read. */
  178. count = 0;
  179. while (count < chunk) {
  180. if (fdin == -1) { /* open next file */
  181. #if !TEST
  182. _fmode = O_BINARY;
  183. #endif
  184. fdin = open(files[i], O_RDONLY);
  185. if (fdin < 0) {
  186. perror(files[i]);
  187. exit(1);
  188. }
  189. }
  190. /* read from file */
  191. ct = read(fdin, buffer + count, chunk - count);
  192. if (ct < 0) {
  193. perror(files[i]);
  194. exit(1);
  195. }
  196. if (ct == 0) { /* end of file */
  197. close(fdin);
  198. fdin = -1;
  199. /* choose next file */
  200. if (++i >= nfiles) break; /* no more files */
  201. }
  202. count += ct;
  203. }
  204. if (count == 0) { /* absolute EOF */
  205. done = 2;
  206. continue;
  207. }
  208. if (count < chunk) { /* pad last track */
  209. /* Pad out buffer with zeroes. */
  210. p = &buffer[count];
  211. while (p < &buffer[chunk]) *p++ = 0;
  212. done = 2;
  213. }
  214. r = offset % drive_size;
  215. if (r == 0) {
  216. /* An integral number of diskettes have been filled. Prompt. */
  217.                 fprintf(stderr, "Please insert formatted diskette #%d in drive %c, then hit Enter%cn", disknr, c, 7);
  218. disknr++;
  219. #if !TEST
  220. while(bioskey(1) == 0) ; /* wait for input */
  221. if ((bioskey(0) & 0x7F) == 3) exit(1); /* CTRL-C */
  222.                 biosdisk(READ,  drive, 0, 0, 1, 1, testbuf); /* get it going */
  223. #endif
  224. }
  225. /* Compute cyl, head, sector. */
  226. cyl = r/cyl_size;
  227. r -= cyl * cyl_size;
  228. head = (r < cyl_size/2 ? 0 : 1);
  229. r -= head * cyl_size/2;
  230. sector = r/SECTORSIZE;
  231.         fprintf(stderr, "Track: %2d  Head: %d  Sector: %2d    File offset: %ldr",
  232.                 cyl, head, sector+1,offset);
  233. #if !TEST
  234.         status = biosdisk(WRITE, drive, head, cyl, sector+1, nsectors, buffer);
  235.         if (status != 0) Error(status, cyl, head, sector);
  236. #else
  237. write(1, buffer, chunk);
  238. #endif
  239.         offset += chunk;
  240.    }
  241. }