home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / FFFF3.ZIP / FFFF.C < prev    next >
C/C++ Source or Header  |  1990-04-29  |  13KB  |  506 lines

  1. /*──────────────────────────────────────────────────────────────────────────────
  2. Set tab spacing to 4
  3. Mettez les arrêts à tous 4 colonnes
  4. ────────────────────────────────────────────────────────────────────────────────
  5.  
  6.                                     FFFF.C
  7.                                     ══════
  8.  
  9.                         A "fast false floppy formatter"
  10.  
  11. ──────────────────────────────────────────────────────────────────────────────*/
  12.  
  13. #pragma pack(1)
  14.  
  15. #define INCL_BASE
  16. #define INCL_NOPM
  17. #define INCL_DOSDEVICES
  18. #include <stdio.h>
  19. #include <os2.h>
  20. #include <malloc.h>
  21. #include <string.h>
  22. #include <ctype.h>
  23. #include <stdlib.h>
  24.  
  25. #define DirectoryEntrySize    32
  26.  
  27. #ifndef TRUE
  28. #define TRUE    1
  29. #endif
  30. #ifndef FALSE
  31. #define    FALSE    0
  32. #endif
  33.  
  34. char    drive[] = "a:";
  35. typedef    UCHAR    FAT;
  36. typedef FAT        *pFAT;
  37.  
  38. FAT *allocFAT(PBIOSPARAMETERBLOCK);
  39. VOID readFAT (pFAT, PBIOSPARAMETERBLOCK, HFILE);
  40. VOID clearFAT(pFAT, PBIOSPARAMETERBLOCK);
  41. VOID writeFAT(pFAT, PBIOSPARAMETERBLOCK, HFILE);
  42. VOID readSector(HFILE, USHORT, pFAT, PBIOSPARAMETERBLOCK);
  43. VOID writeSector(HFILE, USHORT, pFAT, PBIOSPARAMETERBLOCK);
  44. VOID scrubDir(HFILE, PBIOSPARAMETERBLOCK);
  45. VOID Notify(char **, USHORT, USHORT);
  46. VOID Notify2(char **, USHORT, USHORT, USHORT);
  47. USHORT ErrorMap(USHORT);
  48. USHORT Language(VOID);
  49. TRACKLAYOUT *buildTrackLayout(PBIOSPARAMETERBLOCK);
  50.  
  51. FSINFO    FSInfo;
  52. USHORT    DiskHasVolumeLabel, OldLabel;
  53. USHORT    language;
  54. TRACKLAYOUT *tlo = NULL;
  55.  
  56. #define FFFMSG(x) (language+x)
  57. BYTE msgFile[] = "FFFF.MSG";
  58.  
  59. #define USA                  1
  60. #define FRENCH_CANADA      2
  61. #define LATIN_AMERICA      3
  62. #define NETHERLANDS         31
  63. #define BELGIUM             32
  64. #define FRANCE             33
  65. #define SPAIN             34
  66. #define ITALY             39
  67. #define SWITZERLAND         41
  68. #define UNITED_KINGDOM     44
  69. #define DENMARK             45
  70. #define SWEDEN             46
  71. #define NORWAY             47
  72. #define GERMANY             49
  73. #define AUSTRALIA         61
  74. #define PORTUGAL        351
  75. #define FINLAND            358
  76.  
  77. // Add new definitions as needed
  78. #define ENGLISH              0
  79. #define    FRENCH             40
  80. #define DUTCH             80
  81.  
  82. struct _language
  83. {
  84.     USHORT    country;
  85.     USHORT    language;
  86. } countryMap[] =
  87. {
  88.     {    USA,            ENGLISH    },
  89.     {    UNITED_KINGDOM,    ENGLISH },
  90.     {    AUSTRALIA,        ENGLISH    },
  91.     {    FRENCH_CANADA,    FRENCH    },
  92.     {    FRANCE,            FRENCH    },
  93.     {    SWITZERLAND,    FRENCH    },
  94.     {    NETHERLANDS,    DUTCH    },
  95.     {    0,                0        }
  96. };
  97.  
  98. /*──────────────────────────────────────────────────────────────────────────────
  99.  
  100.  
  101.     
  102. ──────────────────────────────────────────────────────────────────────────────*/
  103.  
  104. VOID main(int argc, char *argv[])
  105. {
  106.     BYTE
  107.         a = 0,
  108.         bCommand = 0;
  109.      HFILE
  110.         hDrive;
  111.     USHORT
  112.         usAction,
  113.         rv;
  114.     BIOSPARAMETERBLOCK
  115.             bpb;
  116.     FAT
  117.         *pFAT;
  118.     BYTE
  119.         errx[3][30],
  120.         *ppsMsg[3];
  121.         
  122.     ppsMsg[0] = errx[0];
  123.     ppsMsg[1] = errx[1];
  124.     ppsMsg[2] = errx[2];
  125.  
  126.     language = Language();
  127.     Notify(ppsMsg,0,FFFMSG(1));        // Announce program title
  128.     Notify(ppsMsg,0,FFFMSG(2));        // and version
  129.     putchar('\n');
  130.     if (argc > 1)
  131.     {
  132.         a = tolower(*argv[1]);
  133.         if (a < 'a' | a > 'b')
  134.             a = 0;
  135.        }
  136.     if (a == 0)
  137.     {
  138.         Notify(ppsMsg,0,FFFMSG(3));
  139.         exit(1);
  140.     }
  141.     drive[0] = a;
  142.  
  143.     rv = DosQFSInfo(a-'a'+1, 2, (PBYTE)&FSInfo, sizeof FSInfo);
  144.     if (rv & rv != ERROR_NO_VOLUME_LABEL)
  145.     {
  146.         Notify2(ppsMsg,0,FFFMSG(4),rv);
  147.         exit(1);
  148.     }
  149.     DiskHasVolumeLabel = !rv;
  150.     if (argc > 2)
  151.         if (argv[2][0] == '/' && tolower(argv[2][1]) == 'v')
  152.             if (argc > 3)
  153.             {
  154.                 DiskHasVolumeLabel = TRUE;
  155.                 OldLabel = FALSE;
  156.                 if (strlen(argv[3]) > 11)
  157.                     strncpy(FSInfo.vol.szVolLabel,argv[3],11);
  158.                 else
  159.                     strcpy(FSInfo.vol.szVolLabel,argv[3]);
  160.                 FSInfo.vol.cch = (BYTE)strlen(FSInfo.vol.szVolLabel);
  161.             }
  162.             else
  163.                 OldLabel = TRUE;
  164.         else
  165.             DiskHasVolumeLabel = FALSE;
  166.     else
  167.         DiskHasVolumeLabel = FALSE;
  168.  
  169.     if (rv=DosOpen(drive, &hDrive, &usAction, 0L, FILE_NORMAL, FILE_OPEN,
  170.             OPEN_ACCESS_READWRITE |
  171.             OPEN_SHARE_DENYREADWRITE |
  172.             OPEN_FLAGS_DASD, 0L))
  173.     {
  174.         errx[0][0] = toupper(argv[1][0]);
  175.         errx[0][1] = ':';
  176.         errx[0][2] = '\0';
  177.         Notify2(ppsMsg,1,FFFMSG(10),rv);
  178.         exit(1);
  179.     }
  180.  
  181.     DosDevIOCtl(0L, &bCommand, DSK_LOCKDRIVE, IOCTL_DISK, hDrive);
  182.     bCommand=1;
  183.     if (rv=DosDevIOCtl(&bpb, &bCommand,
  184.                         DSK_GETDEVICEPARAMS, IOCTL_DISK, hDrive))
  185.     {
  186.         errx[0][0] = toupper(argv[1][0]);
  187.         errx[0][1] = ':';
  188.         errx[0][2] = '\0';
  189.         Notify2(ppsMsg,1,FFFMSG(22),rv);
  190.         exit(1);
  191.     }
  192.  
  193.     pFAT = allocFAT(&bpb);
  194.  
  195.     Notify(ppsMsg,0,FFFMSG(23));
  196.     readFAT (pFAT, &bpb, hDrive);
  197.  
  198.     Notify(ppsMsg,0,FFFMSG(24));
  199.     clearFAT(pFAT, &bpb);
  200.  
  201.     Notify(ppsMsg,0,FFFMSG(25));
  202.     writeFAT(pFAT, &bpb, hDrive);
  203.  
  204.     Notify(ppsMsg,0,FFFMSG(26));
  205.     scrubDir(hDrive, &bpb);
  206.  
  207.     if (DiskHasVolumeLabel)
  208.     {
  209.         Notify(ppsMsg,0,OldLabel ? FFFMSG(28) : FFFMSG(27));
  210.         bCommand = 0;
  211.         DosDevIOCtl(0L, &bCommand, DSK_REDETERMINEMEDIA, IOCTL_DISK, hDrive);
  212.         DosDevIOCtl(0L, &bCommand, DSK_UNLOCKDRIVE, IOCTL_DISK, hDrive);
  213.         DosClose(hDrive);
  214.         DosSetFSInfo(a-'a'+1, 2, (PBYTE)(&FSInfo.vol), sizeof(FSInfo.vol));
  215.     }
  216.     else
  217.     {
  218.         DosDevIOCtl(0L, &bCommand, DSK_UNLOCKDRIVE, IOCTL_DISK, hDrive);
  219.         DosClose(hDrive);
  220.     }
  221. }
  222.  
  223. /*──────────────────────────────────────────────────────────────────────────────
  224.  
  225.     Allocate sufficient memory to hold a copy of the FAT
  226.     
  227. ──────────────────────────────────────────────────────────────────────────────*/
  228.  
  229. FAT *allocFAT(BIOSPARAMETERBLOCK *bpb)
  230. {
  231.     FAT        *f;
  232.  
  233.     f = (pFAT)malloc(bpb->usBytesPerSector * bpb->cFATs * bpb->usSectorsPerFAT);
  234.     if (f == NULL)
  235.     {
  236.         Notify(NULL,0,FFFMSG(29));
  237.         exit(1);
  238.     }
  239.     return f;
  240. }
  241.  
  242. /*──────────────────────────────────────────────────────────────────────────────
  243.  
  244.     Read the File Allocation Table into (allocated) memory
  245.     
  246. ──────────────────────────────────────────────────────────────────────────────*/
  247.  
  248. void readFAT(FAT *f, BIOSPARAMETERBLOCK *bpb, HFILE hDrive)
  249. {
  250.     USHORT    sector;
  251.  
  252.     for (sector=0; sector < bpb->usSectorsPerFAT; ++sector)
  253.         readSector(hDrive, sector+1, f+(sector * bpb->usBytesPerSector), bpb);
  254. }
  255.  
  256. /*──────────────────────────────────────────────────────────────────────────────
  257.  
  258.     Build a skeleton track layout table
  259.     
  260. ──────────────────────────────────────────────────────────────────────────────*/
  261.  
  262. TRACKLAYOUT *buildTrackLayout(BIOSPARAMETERBLOCK *bpb)
  263. {
  264.     TRACKLAYOUT
  265.         *t;
  266.     USHORT
  267.         x;
  268.  
  269.     t = (PTRACKLAYOUT)malloc(sizeof(TRACKLAYOUT)
  270.                                +(bpb->usSectorsPerTrack - 1)*4);
  271.  
  272.     t->bCommand = 0;
  273.  
  274.     for(x=0; x < bpb->usSectorsPerTrack; ++x)
  275.     {
  276.         t->TrackTable[x].usSectorNumber = x+1;
  277.         t->TrackTable[x].usSectorSize = bpb->usBytesPerSector;
  278.     }
  279.     return t;
  280. }
  281.  
  282. /*──────────────────────────────────────────────────────────────────────────────
  283.  
  284.     Read a single sector from a diskette
  285.     
  286. ──────────────────────────────────────────────────────────────────────────────*/
  287.  
  288. void readSector(HFILE hDrive, USHORT sector, FAT *f, BIOSPARAMETERBLOCK *bpb)
  289. {
  290.     USHORT rv;
  291.  
  292.     if (tlo == NULL)
  293.         tlo = buildTrackLayout(bpb);
  294.  
  295.     tlo->usHead = (sector % (bpb->usSectorsPerTrack * bpb->cHeads))
  296.                  / bpb->usSectorsPerTrack;
  297.     tlo->usCylinder = sector / (bpb->usSectorsPerTrack * bpb->cHeads);
  298.     tlo->usFirstSector = sector % bpb->usSectorsPerTrack;
  299.     tlo->cSectors = 1;
  300.  
  301.     if (rv=DosDevIOCtl(f, tlo, DSK_READTRACK, IOCTL_DISK, hDrive))
  302.     {
  303.         Notify2(NULL,0,FFFMSG(30),rv);
  304.         exit(1);
  305.     }
  306. }
  307.  
  308. /*──────────────────────────────────────────────────────────────────────────────
  309.  
  310.     Clear out all entries in the FAT which are not marked bad.
  311.     
  312. ──────────────────────────────────────────────────────────────────────────────*/
  313.  
  314. void clearFAT(FAT *f, BIOSPARAMETERBLOCK *bpb)
  315. {
  316.     USHORT    usEntriesInFAT,
  317.             usEntryNumber,
  318.             usEntry,
  319.             FATword,
  320.             *pEntry;
  321.  
  322.     usEntriesInFAT = bpb->usSectorsPerFAT * bpb->usBytesPerSector * 2 / 3;
  323.     for (usEntryNumber = 2; usEntryNumber < usEntriesInFAT; ++usEntryNumber)
  324.     {
  325.         pEntry = (PUSHORT)(f+(usEntryNumber*3/2));
  326.         FATword = usEntry = *pEntry;
  327.         if (usEntryNumber & 1)
  328.             usEntry >>= 4;
  329.         if ((usEntry &= 0x0FFF) != 0xFF7)
  330.             usEntry = 0;
  331.         if (usEntryNumber & 1)
  332.             FATword = (FATword & 0x000F) | (usEntry << 4);
  333.         else
  334.             FATword = (FATword & 0xF000) | usEntry;
  335.         *pEntry = FATword;
  336.     }
  337. }
  338.  
  339. /*──────────────────────────────────────────────────────────────────────────────
  340.  
  341.  
  342.     
  343. ──────────────────────────────────────────────────────────────────────────────*/
  344.  
  345. void writeFAT(FAT *f, BIOSPARAMETERBLOCK *bpb, HFILE hDrive)
  346. {
  347.     USHORT    sector, secBase;
  348.     BYTE    fat;
  349.     for (fat=0; fat < bpb->cFATs; ++fat)
  350.     {
  351.         secBase = fat * bpb->usSectorsPerFAT + 1;
  352.         for (sector=0; sector < bpb->usSectorsPerFAT; ++sector)
  353.             writeSector(hDrive, sector+secBase,
  354.                         f+(sector * bpb->usBytesPerSector), bpb);
  355.     }
  356. }
  357.  
  358. /*──────────────────────────────────────────────────────────────────────────────
  359.  
  360.  
  361.     
  362. ──────────────────────────────────────────────────────────────────────────────*/
  363.  
  364. void writeSector(HFILE hDrive, USHORT sector, FAT *f, BIOSPARAMETERBLOCK *bpb)
  365. {
  366.     USHORT rv;
  367.  
  368.     if (tlo == NULL)
  369.         tlo = buildTrackLayout(bpb);
  370.  
  371.     tlo->usHead = (sector % (bpb->usSectorsPerTrack * bpb->cHeads))
  372.                  / bpb->usSectorsPerTrack;
  373.     tlo->usCylinder = sector / (bpb->usSectorsPerTrack * bpb->cHeads);
  374.     tlo->usFirstSector = sector % bpb->usSectorsPerTrack;
  375.     tlo->cSectors = 1;
  376.  
  377.     if (rv=DosDevIOCtl(f, tlo, DSK_WRITETRACK, IOCTL_DISK, hDrive))
  378.     {
  379.         Notify2(NULL,0,FFFMSG(31),rv);
  380.         exit(1);
  381.     }
  382. }
  383.  
  384. /*──────────────────────────────────────────────────────────────────────────────
  385.  
  386.     Clear the root directory of a floppy disk
  387.     
  388. ──────────────────────────────────────────────────────────────────────────────*/
  389.  
  390. void scrubDir(HFILE hDrive, BIOSPARAMETERBLOCK *bpb)
  391. {
  392.     BYTE    *secBuf;
  393.     USHORT    sector, secBase;
  394.  
  395.     secBuf = calloc(1,bpb->usBytesPerSector);
  396.     
  397.     secBase = bpb->cFATs * bpb->usSectorsPerFAT + 1;
  398.     for (sector=0; sector < bpb->cRootEntries / DirectoryEntrySize; ++sector)
  399.         writeSector(hDrive, sector+secBase, secBuf, bpb);
  400. }
  401.  
  402. /*──────────────────────────────────────────────────────────────────────────────
  403.  
  404.     Notify() retrieves and displays a single message from the message
  405.     segment or file.
  406.     
  407. ──────────────────────────────────────────────────────────────────────────────*/
  408.  
  409. VOID Notify(char **ppsMsg, USHORT fields, USHORT MessageNumber)
  410. {
  411.     USHORT msgLen;
  412.     char *message;
  413.  
  414.     if ((message=malloc(200)) != NULL)
  415.     {
  416.         DosGetMessage(ppsMsg,fields,message,200,MessageNumber,msgFile,&msgLen);
  417.         DosPutMessage(fileno(stdout),msgLen,message);
  418.         free(message);
  419.     }
  420.     else
  421.         puts("Trouble getting memory for message display");
  422. }
  423.  
  424. /*──────────────────────────────────────────────────────────────────────────────
  425.  
  426.     Notify2() retrieves a primary and secondary message from the message
  427.     segment or file and displays both.
  428.     
  429. ──────────────────────────────────────────────────────────────────────────────*/
  430.  
  431. VOID Notify2(char **ppsMsg, USHORT fields,
  432.             USHORT MessageNumber, USHORT SecondaryMessageNumber)
  433. {
  434.     USHORT msgLen, msg2Len;
  435.     char *message;
  436.  
  437.     if ((message=malloc(400)) != NULL)
  438.     {
  439.         DosGetMessage(ppsMsg, fields, message,     200,
  440.                       MessageNumber,                    msgFile, &msgLen);
  441.         DosGetMessage(ppsMsg, 0,      message+200, 200,
  442.                       ErrorMap(SecondaryMessageNumber), msgFile, &msg2Len);
  443.         strncpy(message+msgLen, message+200, msg2Len); 
  444.         DosPutMessage(fileno(stdout), msgLen+msg2Len, message);
  445.         free(message);
  446.     }
  447.     else
  448.         puts("Trouble getting memory for message display");
  449. }
  450.  
  451. /*──────────────────────────────────────────────────────────────────────────────
  452.  
  453.  
  454.     
  455. ──────────────────────────────────────────────────────────────────────────────*/
  456.  
  457. USHORT ErrorMap(USHORT rv)
  458. {
  459.     switch (rv)
  460.     {
  461. case ERROR_BUFFER_OVERFLOW:            rv = FFFMSG(5);  break;
  462. case ERROR_INVALID_DRIVE:            rv = FFFMSG(6);  break;
  463. case ERROR_INVALID_LEVEL:            rv = FFFMSG(7);  break;
  464. case ERROR_NO_VOLUME_LABEL:            rv = FFFMSG(8);  break;
  465. case ERROR_ACCESS_DENIED:            rv = FFFMSG(11); break;
  466. case ERROR_DRIVE_LOCKED:            rv = FFFMSG(12); break;
  467. case ERROR_FILE_NOT_FOUND:            rv = FFFMSG(13); break;
  468. case ERROR_INVALID_ACCESS:            rv = FFFMSG(14); break;
  469. case ERROR_INVALID_PARAMETER:        rv = FFFMSG(15); break;
  470. case ERROR_NOT_DOS_DISK:            rv = FFFMSG(16); break;
  471. case ERROR_OPEN_FAILED:                rv = FFFMSG(17); break;
  472. case ERROR_PATH_NOT_FOUND:            rv = FFFMSG(18); break;
  473. case ERROR_SHARING_BUFFER_EXCEEDED:    rv = FFFMSG(19); break;
  474. case ERROR_SHARING_VIOLATION:        rv = FFFMSG(20); break;
  475. case ERROR_TOO_MANY_OPEN_FILES:        rv = FFFMSG(21); break;
  476. default:                             rv = FFFMSG(9);  break;
  477.     }
  478.     return rv;
  479. }
  480.  
  481. /*──────────────────────────────────────────────────────────────────────────────
  482.  
  483.  
  484.     
  485. ──────────────────────────────────────────────────────────────────────────────*/
  486.  
  487. USHORT Language(VOID)
  488. {
  489.     COUNTRYCODE cc;
  490.      COUNTRYINFO ci;
  491.     USHORT        cil, rv;
  492.  
  493.     cc.country = cc.codepage = 0;
  494.     if (rv=DosGetCtryInfo(sizeof ci, &cc, &ci, &cil))
  495.     {
  496.         printf("Error %u getting country code\n\n", rv);
  497.         return 0;
  498.     }
  499.  
  500. //    printf("Country=%u; codepage=%u\n\n", ci.country, ci.codepage);
  501.     for (rv = 0; countryMap[rv].country; ++rv)
  502.         if (ci.country == countryMap[rv].country)
  503.             return countryMap[rv].language;
  504.     return 0;
  505. }
  506.