home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / os2 / shfrg2.arj / DISK_API.C next >
Encoding:
C/C++ Source or Header  |  1992-04-14  |  16.1 KB  |  529 lines

  1. // ###################################################################
  2. //
  3. // Disk API calls for both DOS and OS2.
  4. //
  5. // NOTE:  Please define either __DOS__ or __OS2__ before/during compilation
  6. //
  7. // void       DosSetDrive(char drive_letter);
  8. // char      *translate_name(char *name);
  9. // short      DosDiskValid(char drive_letter);
  10. // USHORT     DosOpenDrive(char drive_letter);
  11. // void       DosCloseDrive(USHORT handle);
  12. // USHORT     DosBytesPerDiskSector(USHORT drive_handle);
  13. // short      DosReadSector(USHORT handle, void far* buffer, ULONG sector,
  14. //            USHORT count, USHORT bytes_per_sector);
  15. // void       DosDirInitialize(USHORT handle, USHORT huge *fat, ULONG fat_size,
  16. //            USHORT SectorsPerCluster, USHORT BytesPerSector,
  17. //            USHORT RootSector, USHORT FirstFileSector);
  18. // Directory *DosDirFindFirst(char* find, USHORT attributes,
  19. //            USHORT DirCluster);
  20. // Directory *DosDirFindNext(Directory *dir);
  21. // Directory *DosDirClose(Directory *dir);
  22. // char*      DosDiskVolume(char drive_letter, char* vol, short size);
  23. // ###################################################################
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <memory.h>
  28. #include <malloc.h>
  29. #include <string.h>
  30. #include <ctype.h>
  31.  
  32. #include "disk_api.h"
  33.  
  34. // ################################## Common #########################
  35. char *fname(char* filename, char *name, char *ext)
  36. {
  37.     int i;
  38.     char *p = filename;
  39.     char *e = p + 8;
  40.  
  41.     for (i = 0; i < 8; i++)                        // get name w/o trailing blanks
  42.     {
  43.         if ((*p++ = *name++) != ' ') e = p;
  44.     }
  45.  
  46.     if (*ext != ' ')                               // q. extension blank?
  47.     {
  48.         *e++ = '.';                                // a. no .. add the dot
  49.  
  50.         for (i = 0; (i < 3) && (*ext != ' '); i++) // add ext w/o blanks
  51.             *e++ = *ext++;
  52.     }
  53.  
  54.     *e = 0;                                        // terminate string w/null
  55.     return (filename);                             // return string to caller
  56. }
  57.  
  58.  
  59. short isroot(char* path)
  60. {
  61.     short slashes;
  62.  
  63.     for (slashes = 0; *path; path++)
  64.     {
  65.         if (*path == '\\' || *path == '/') slashes++;
  66.     }
  67.  
  68.     return (slashes <= 1) ? TRUE : FALSE;
  69. }
  70.  
  71.  
  72.  
  73.  
  74. // ################################## DOS ############################
  75. #ifdef __DOS__
  76.  
  77. void DosSetDrive(char drive_letter)       // set up the work drive
  78. {
  79.     int drives;
  80.     _dos_setdrive(toupper(drive_letter) - '@', &drives);
  81. }
  82.  
  83. char *translate_name(char *name)
  84. {
  85.     static  char translate_area[65];     // work/return area
  86.     union   REGS r;                      // work registers
  87.     struct  SREGS s;                     // ..and work segment regs
  88.     static  char far *sp;                // work pointer
  89.  
  90.     r.h.ah = 0x60;                       // ah = translate
  91.     sp     = (char far *)name;           // set up a pointer ..
  92.     r.x.si = FP_OFF(sp);                 // set pointer to input name
  93.     s.ds   = FP_SEG(sp);                 // .. and segment
  94.  
  95.     sp     = translate_area;             // set up a pointer ..
  96.     r.x.di = FP_OFF(sp);                 // set pointer to output area
  97.     s.es   = FP_SEG(sp);                 // .. and segment
  98.     int86x(0x21, &r, &r, &s);            // translate the name
  99.  
  100.     if (r.x.cflag)                       // if bad name ..
  101.         return (NULL);                   // .. return error
  102.     else
  103.         return (translate_area);         // return xlated name
  104. }
  105.  
  106. short DosDiskValid(char drive_letter)
  107. {
  108.     static char wdrv[] = " :\\";                // work area for drive name
  109.     union   REGS r;                         // work registers
  110.     struct  SREGS s;                        // ..and work segment regs
  111.  
  112.     r.x.ax = 0x4409;                        // ah = ioctl, local test
  113.     r.h.bl = (drive_letter - 'A') + 1;      // bl = drive to test
  114.     int86(0x21, &r, &r);                    // test drive
  115.  
  116.     if (r.x.cflag)                          // q. bad drive?
  117.         return (1);                         // a. yes .. error
  118.  
  119.     if (r.x.dx & 0x1000)                    // q. remote?
  120.         return (2);                         // a. yes .. error
  121.  
  122.     wdrv[0] = drive_letter;                 // set up name
  123.  
  124.     if (strcmp(wdrv, translate_name(wdrv))) // q. SUBST or ASSIGNED?
  125.         return (3);                         // a. yes .. return error
  126. }
  127.  
  128.  
  129.  
  130. USHORT DosOpenDrive(char drive_letter)
  131. {
  132.     return (toupper(drive_letter) - 'A');   // return A=0,B=1,C=2,...
  133. }
  134.  
  135. void DosCloseDrive(USHORT handle)
  136. {
  137. }
  138.  
  139.  
  140.  
  141. USHORT DosBytesPerDiskSector(USHORT drive_no)
  142. {
  143.     struct diskfree_t disk_free;
  144.  
  145.     if (_dos_getdiskfree(drive_no+1, &disk_free))
  146.       return 0;
  147.     else
  148.       return disk_free.bytes_per_sector;
  149. }
  150.  
  151. short DosReadSector(USHORT handle, void far* buffer, ULONG sector,
  152.   USHORT count, USHORT bytes_per_sector)
  153. {
  154.     union   REGS r;                          // work registers
  155.     struct  SREGS s;                         // ..and work segment regs
  156.     struct dos4_i25                          // dos 4.0 int 25 block
  157.     {
  158.         long  sector;                        // sector to read
  159.         short count;                         // number of sectors to read
  160.         char  far *read_addr;                // address of input area
  161.     } d4_i25, far *d4_i25p;                  // area and pointer
  162.  
  163.     if (_osmajor >= 4)
  164.     {
  165.         r.x.cx           = -1;               // cx = 0xffff
  166.         d4_i25.sector    = sector;           // read sector 0
  167.         d4_i25.count     = count;            // .. for 1 sector
  168.         d4_i25.read_addr = buffer;           // .. into boot record
  169.         d4_i25p          = &d4_i25;          // set up pointer
  170.         r.x.bx           = FP_OFF(d4_i25p);  // bx = offset  of parm block
  171.         s.ds             = FP_SEG(d4_i25p);  // ds = segment of parm block
  172.     }
  173.     else
  174.     {
  175.         r.x.cx = count;                      // cx = number of sectors
  176.         r.x.dx = sector;                     // dx = starting sector
  177.         r.x.bx = FP_OFF(buffer);             // bx = offset of buffer
  178.         s.ds   = FP_SEG(buffer);             // ds = segment of buffer
  179.     }
  180.  
  181.     r.h.al = handle;                         // al = drive number (A=0,..)
  182.     int86x(0x25, &r, &r, &s);                // read boot sector
  183.     return (r.x.cflag);
  184.  
  185. }
  186.  
  187.  
  188. void DosDirInitialize(USHORT handle, USHORT huge *fat, ULONG fat_size,
  189.   USHORT SectorsPerCluster, USHORT BytesPerSector, USHORT RootSector, USHORT FirstFileSector)
  190. {
  191. }
  192.  
  193. Directory * DosDirClose(Directory *dir)
  194. {
  195.     union   REGS r;                          // work registers
  196.     struct  SREGS s;                         // ..and work segment regs
  197.  
  198.     if (dir)
  199.     {
  200.         r.h.ah = 0x1a;                       // ah = set DTA
  201.         s.ds   = dir->oldds;                 // ds -> DTA segment
  202.         r.x.dx = dir->oldda;                 // ds:dx -> DTA
  203.         int86x(0x21, &r, &r, &s);            // setup new DTA
  204.         free(dir);
  205.     }
  206.     return NULL;
  207. }
  208.  
  209.  
  210. Directory *DosDirFindFirst(char* find, USHORT attributes, USHORT DirCluster)
  211. {
  212.     #define CLEAR(s,c) memset(s,c,sizeof(s)) // string clear
  213.  
  214.     union   REGS r;                          // work registers
  215.     struct  SREGS s;                         // ..and work segment regs
  216.     char far *cftmp;
  217.     Directory *dir;
  218.  
  219.     dir = calloc(sizeof(*dir), 1);
  220.     if (dir == NULL) return dir;
  221.  
  222.     r.h.ah = 0x2f;                           // ah = get dta
  223.     int86x(0x21, &r, &r, &s);                // .. ask DOS
  224.  
  225.     dir->oldds = s.es;                       // save old DTA segment
  226.     dir->oldda = r.x.bx;                     // .. and offset
  227.  
  228.     cftmp = (char far *)&dir->dta;           // get current dta address
  229.     r.h.ah = 0x1a;                           // ah = set DTA
  230.     s.ds   = FP_SEG(cftmp);                  // ds -> dir segment
  231.     r.x.dx = FP_OFF(cftmp);                  // ds:dx -> dir
  232.     int86x(0x21, &r, &r, &s);                // setup new DTA
  233.  
  234.     dir->fcb.hexff = 0xff;                   // extended fcb
  235.     CLEAR(dir->fcb.extra, 0);                // set extra area
  236.     CLEAR(dir->fcb.name, '?');               // .. and file name
  237.     CLEAR(dir->fcb.ext, '?');                // .. and extension
  238.     dir->fcb.attribute = FILES;              // set up attribute to find
  239.  
  240.     cftmp = (char far *)&dir->fcb;           // get current fcb address
  241.     r.h.ah = 0x11;                           // ah = find first
  242.     s.ds   = FP_SEG(cftmp);                  // ds -> segment of fcb
  243.     r.x.dx = FP_OFF(cftmp);                  // ds:dx -> offset
  244.     int86x(0x21, &r, &r, &s);                // .. find first
  245.  
  246.     if (r.h.al)                              // check return code
  247.         return DosDirClose(dir);
  248.  
  249.     // Update Public information section.
  250.  
  251.     dir->cluster = dir->dta.cluster;
  252.     dir->attrib  = (USHORT)dir->dta.attribute;
  253.     dir->size    = dir->dta.size;
  254.     fname(dir->name, dir->dta.name, dir->dta.ext);
  255.     return dir;
  256. }
  257.  
  258. Directory *DosDirFindNext(Directory *dir)
  259. {
  260.     union   REGS r;                          // work registers
  261.     struct  SREGS s;                         // ..and work segment regs
  262.     char far *cftmp = (char far *)&dir->fcb; // get current fcb address
  263.  
  264.     r.h.ah = 0x12;                           // ah = find next
  265.     s.ds   = FP_SEG(cftmp);                  // ds -> segment of fcb
  266.     r.x.dx = FP_OFF(cftmp);                  // ds:dx -> offset
  267.     int86x(0x21, &r, &r, &s);                // .. find next
  268.  
  269.     if (r.h.al)                              // check return code
  270.         return DosDirClose(dir);
  271.  
  272.     // Update Public information section.
  273.  
  274.     dir->cluster = dir->dta.cluster;
  275.     dir->attrib  = (USHORT)dir->dta.attribute;
  276.     dir->size    = dir->dta.size;
  277.     fname(dir->name, dir->dta.name, dir->dta.ext);
  278.     return dir;
  279. }
  280.  
  281.  
  282. char * DosDiskVolume(char drive_letter, char* vol, short vol_size)
  283. {
  284.     static char files[] = "?:\\*.*";
  285.     struct find_t dir;                       // structure for directory entry
  286.  
  287.     *files = drive_letter;
  288.  
  289.     if (_dos_findfirst(files, _A_VOLID, &dir) == 0)
  290.     {
  291.       memmove(dir.name+8, dir.name+9, 4);
  292.       return strncpy(vol, dir.name, vol_size);
  293.     }
  294.     else
  295.       return strncpy(vol, "?", vol_size);
  296. }
  297. #endif
  298.  
  299.  
  300. // ################################## OS2 ############################
  301. #ifdef __OS2__
  302.  
  303. static struct
  304. {
  305.     USHORT huge * FAT;                    // Current open disk FAT table
  306.     USHORT        handle;                 // Direct Disk Access Handle
  307.     USHORT        BytesPerSector;         // Disk Parmameters
  308.     USHORT        SectorsPerCluster;      //             ....
  309.     USHORT        RootSector;
  310.     USHORT        FirstFileSector;
  311. } os2_dir;
  312.  
  313.  
  314. void DosSetDrive(char drive_letter)       // set up the work drive
  315. {
  316.     DosSelectDisk((toupper(drive_letter) - 'A') + 1);
  317. }
  318.  
  319.  
  320. char *translate_name(char *name)
  321. {
  322.     return name;
  323. }
  324.  
  325.  
  326. short DosDiskValid(char drive_letter)
  327. {
  328.     // Possible try and lock drive ??
  329.  
  330.     return 0;
  331. }
  332.  
  333.  
  334. void DosCloseDrive(USHORT handle)
  335. {
  336.     DosClose(handle);
  337.     hfree(os2_dir.FAT);
  338.     memset(&os2_dir, 0, sizeof(os2_dir));     // Mark as unactive
  339. }
  340.  
  341.  
  342. USHORT DosOpenDrive(char drive_letter)
  343. {
  344.     char    drive_name[3];
  345.     USHORT  handle, action;
  346.  
  347.     drive_name[0] = drive_letter;
  348.     drive_name[1] = ':';
  349.     drive_name[2] = 0;
  350.  
  351.     if (DosOpen(drive_name, &handle, &action, 0L, 0, FILE_OPEN,
  352.      OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE | OPEN_FLAGS_DASD, 0L) == 0)
  353.         return handle;
  354.     else
  355.         return -1;
  356. }
  357.  
  358. USHORT DosBytesPerDiskSector(USHORT drive_handle)
  359. {
  360.     BIOSPARAMETERBLOCK bpb;
  361.     short              command = 1;   // current medium
  362.  
  363.     if (DosDevIOCtl(&bpb, &command, DSK_GETDEVICEPARAMS, IOCTL_DISK,
  364.       drive_handle) == 0)
  365.         return (bpb.usBytesPerSector);
  366.     else
  367.         return 0;
  368. }
  369.  
  370.  
  371. short DosReadSector(USHORT handle, void far* buffer, ULONG sector,
  372.   USHORT count, USHORT bytes_per_sector)
  373. {
  374.     long    distance = bytes_per_sector * sector;
  375.     ULONG   new_position;
  376.     USHORT  got_in;
  377.  
  378.     if (DosChgFilePtr(handle, distance, FILE_BEGIN, &new_position) ||
  379.       DosRead(handle, buffer, bytes_per_sector*count, &got_in) )
  380.         return -1;
  381.     else
  382.         return 0;
  383. }
  384.  
  385.  
  386. void huge *  _hmemmove(void huge * dst, void huge * src, ULONG len)
  387. {
  388.     // Huge memory mover
  389.  
  390.     #define PIECE  0x8000
  391.     char huge* dptr = dst;
  392.     char huge* sptr = src;
  393.  
  394.     if (len == 0L) return NULL;
  395.  
  396.     while (len)
  397.     {
  398.         if (len >= PIECE)
  399.         {
  400.             _fmemmove(dptr, sptr, PIECE);
  401.             dptr += PIECE;
  402.             sptr += PIECE;
  403.             len  -= PIECE;
  404.         }
  405.         else
  406.         {
  407.             _fmemmove(dptr, sptr, len);
  408.             len  = 0;
  409.         }
  410.     }
  411.     return dst;
  412. }
  413.  
  414.  
  415. void DosDirInitialize(USHORT handle, USHORT huge *fat, ULONG fat_size,
  416.   USHORT SectorsPerCluster, USHORT BytesPerSector, USHORT RootSector, USHORT FirstFileSector)
  417. {
  418.     // Make a copy of the current fat table for directory search.
  419.  
  420.     os2_dir.FAT = halloc(fat_size, 1);
  421.     if (os2_dir.FAT == NULL) return;
  422.  
  423.     _hmemmove(os2_dir.FAT, fat, fat_size);
  424.  
  425.     // Save disk parameters for use in physical directory search
  426.  
  427.     os2_dir.handle            = handle;
  428.     os2_dir.SectorsPerCluster = SectorsPerCluster;
  429.     os2_dir.BytesPerSector    = BytesPerSector;
  430.     os2_dir.RootSector        = RootSector;
  431.     os2_dir.FirstFileSector   = FirstFileSector;
  432. }
  433.  
  434.  
  435. Directory *DosDirClose(Directory *dir)
  436. {
  437.   if (dir != NULL) free(dir);
  438.   return NULL;
  439. }
  440.  
  441.  
  442. Directory * DosDirFindNext(Directory *dir)
  443. {
  444.     do
  445.     {
  446.         if (dir->entry >= os2_dir.BytesPerSector / sizeof(dir->entries[0]))
  447.         {
  448.             if (dir->next_fat_entry == 0)
  449.             {
  450.                 if (dir->fat_entry)
  451.                 {                                // q. End of directory!
  452.                     if (os2_dir.FAT[dir->fat_entry] >= 0xf000)
  453.                       return DosDirClose(dir);   // a. Yes, clean up
  454.  
  455.                     dir->fat_entry = os2_dir.FAT[dir->fat_entry];
  456.                     dir->sector    = (ULONG)(dir->fat_entry - 2) *
  457.                       os2_dir.SectorsPerCluster + os2_dir.FirstFileSector;
  458.                 }
  459.                 dir->next_fat_entry = os2_dir.SectorsPerCluster;
  460.             }
  461.             dir->entry = 0;
  462.         }
  463.  
  464.         if (dir->entry == 0)
  465.         {
  466.             if (DosReadSector(os2_dir.handle, &dir->entries, dir->sector, 1,
  467.               os2_dir.BytesPerSector))
  468.                 return DosDirClose(dir);
  469.  
  470.             dir->sector++;
  471.             dir->next_fat_entry--;
  472.         }
  473.  
  474.         // Update Public information section.
  475.  
  476.         dir->cluster = dir->entries[dir->entry].cluster;
  477.         dir->attrib  = (USHORT)dir->entries[dir->entry].attribute;
  478.         dir->size    = dir->entries[0].size;
  479.         fname(dir->name, dir->entries[dir->entry].name, dir->entries[dir->entry].ext);
  480.         dir->entry++;
  481.  
  482.         if (dir->name[0] == 0)                   // q. End of directory ?
  483.             return DosDirClose(dir);             // a. Yes, clean up
  484.     }
  485.     while (((dir->attrib & 0x37) && (dir->attrib & dir->search_attributes) == 0) ||
  486.       (dir->name[0] & 0x80) || dir->cluster == 0);
  487.  
  488.     return dir;
  489. }
  490.  
  491.  
  492. Directory * DosDirFindFirst(char* find, USHORT attributes, USHORT DirCluster)
  493. {
  494.     Directory * dir;
  495.  
  496.     // Allocate directory work structure
  497.  
  498.     dir = calloc(sizeof(*dir), 1);
  499.     if (dir == NULL) return NULL;
  500.  
  501.     // Initialize directory info.
  502.  
  503.     dir->fat_entry         = DirCluster;
  504.     dir->search_attributes = attributes;
  505.     dir->next_fat_entry    = os2_dir.SectorsPerCluster ;
  506.     dir->entry             = 0;
  507.  
  508.     if (DirCluster == 0)
  509.         dir->sector = os2_dir.RootSector;
  510.     else
  511.         dir->sector = (ULONG)(dir->fat_entry - 2) *
  512.           os2_dir.SectorsPerCluster + os2_dir.FirstFileSector;
  513.  
  514.     // Return first valid match if any?
  515.  
  516.     return DosDirFindNext(dir);
  517. }
  518.  
  519.  
  520. char * DosDiskVolume(char drive_letter, char* vol, short vol_size)
  521. {
  522.   FSINFO InfoBuf;
  523.  
  524.   DosQFSInfo(drive_letter-'@', 2, (void*)&InfoBuf, sizeof(InfoBuf));
  525.   return strncpy(vol, InfoBuf.vol.szVolLabel, vol_size);
  526. }
  527.  
  528. #endif
  529.