home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 6 File / 06-File.zip / SHFRAG.ZIP / DISK_API.C next >
C/C++ Source or Header  |  1992-02-06  |  16KB  |  528 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);
  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, USHORT count)
  152. {
  153.     union   REGS r;                          // work registers
  154.     struct  SREGS s;                         // ..and work segment regs
  155.     struct dos4_i25                          // dos 4.0 int 25 block
  156.     {
  157.         long  sector;                        // sector to read
  158.         short count;                         // number of sectors to read
  159.         char  far *read_addr;                // address of input area
  160.     } d4_i25, far *d4_i25p;                  // area and pointer
  161.  
  162.     if (_osmajor >= 4)
  163.     {
  164.         r.x.cx           = -1;               // cx = 0xffff
  165.         d4_i25.sector    = sector;           // read sector 0
  166.         d4_i25.count     = count;            // .. for 1 sector
  167.         d4_i25.read_addr = buffer;           // .. into boot record
  168.         d4_i25p          = &d4_i25;          // set up pointer
  169.         r.x.bx           = FP_OFF(d4_i25p);  // bx = offset  of parm block
  170.         s.ds             = FP_SEG(d4_i25p);  // ds = segment of parm block
  171.     }
  172.     else
  173.     {
  174.         r.x.cx = count;                      // cx = number of sectors
  175.         r.x.dx = sector;                     // dx = starting sector
  176.         r.x.bx = FP_OFF(buffer);             // bx = offset of buffer
  177.         s.ds   = FP_SEG(buffer);             // ds = segment of buffer
  178.     }
  179.  
  180.     r.h.al = handle;                         // al = drive number (A=0,..)
  181.     int86x(0x25, &r, &r, &s);                // read boot sector
  182.     return (r.x.cflag);
  183.  
  184. }
  185.  
  186.  
  187. void DosDirInitialize(USHORT handle, USHORT huge *fat, ULONG fat_size,
  188.   USHORT SectorsPerCluster, USHORT BytesPerSector, USHORT RootSector, USHORT FirstFileSector)
  189. {
  190. }
  191.  
  192. Directory * DosDirClose(Directory *dir)
  193. {
  194.     union   REGS r;                          // work registers
  195.     struct  SREGS s;                         // ..and work segment regs
  196.  
  197.     if (dir)
  198.     {
  199.         r.h.ah = 0x1a;                       // ah = set DTA
  200.         s.ds   = dir->oldds;                 // ds -> DTA segment
  201.         r.x.dx = dir->oldda;                 // ds:dx -> DTA
  202.         int86x(0x21, &r, &r, &s);            // setup new DTA
  203.         free(dir);
  204.     }
  205.     return NULL;
  206. }
  207.  
  208.  
  209. Directory *DosDirFindFirst(char* find, USHORT attributes, USHORT DirCluster)
  210. {
  211.     #define CLEAR(s,c) memset(s,c,sizeof(s)) // string clear
  212.  
  213.     union   REGS r;                          // work registers
  214.     struct  SREGS s;                         // ..and work segment regs
  215.     char far *cftmp;
  216.     Directory *dir;
  217.  
  218.     dir = calloc(sizeof(*dir), 1);
  219.     if (dir == NULL) return dir;
  220.  
  221.     r.h.ah = 0x2f;                           // ah = get dta
  222.     int86x(0x21, &r, &r, &s);                // .. ask DOS
  223.  
  224.     dir->oldds = s.es;                       // save old DTA segment
  225.     dir->oldda = r.x.bx;                     // .. and offset
  226.  
  227.     cftmp = (char far *)&dir->dta;           // get current dta address
  228.     r.h.ah = 0x1a;                           // ah = set DTA
  229.     s.ds   = FP_SEG(cftmp);                  // ds -> dir segment
  230.     r.x.dx = FP_OFF(cftmp);                  // ds:dx -> dir
  231.     int86x(0x21, &r, &r, &s);                // setup new DTA
  232.  
  233.     dir->fcb.hexff = 0xff;                   // extended fcb
  234.     CLEAR(dir->fcb.extra, 0);                // set extra area
  235.     CLEAR(dir->fcb.name, '?');               // .. and file name
  236.     CLEAR(dir->fcb.ext, '?');                // .. and extension
  237.     dir->fcb.attribute = FILES;              // set up attribute to find
  238.  
  239.     cftmp = (char far *)&dir->fcb;           // get current fcb address
  240.     r.h.ah = 0x11;                           // ah = find first
  241.     s.ds   = FP_SEG(cftmp);                  // ds -> segment of fcb
  242.     r.x.dx = FP_OFF(cftmp);                  // ds:dx -> offset
  243.     int86x(0x21, &r, &r, &s);                // .. find first
  244.  
  245.     if (r.h.al)                              // check return code
  246.         return DosDirClose(dir);
  247.  
  248.     // Update Public information section.
  249.  
  250.     dir->cluster = dir->dta.cluster;
  251.     dir->attrib  = (USHORT)dir->dta.attribute;
  252.     dir->size    = dir->dta.size;
  253.     fname(dir->name, dir->dta.name, dir->dta.ext);
  254.     return dir;
  255. }
  256.  
  257. Directory *DosDirFindNext(Directory *dir)
  258. {
  259.     union   REGS r;                          // work registers
  260.     struct  SREGS s;                         // ..and work segment regs
  261.     char far *cftmp = (char far *)&dir->fcb; // get current fcb address
  262.  
  263.     r.h.ah = 0x12;                           // ah = find next
  264.     s.ds   = FP_SEG(cftmp);                  // ds -> segment of fcb
  265.     r.x.dx = FP_OFF(cftmp);                  // ds:dx -> offset
  266.     int86x(0x21, &r, &r, &s);                // .. find next
  267.  
  268.     if (r.h.al)                              // check return code
  269.         return DosDirClose(dir);
  270.  
  271.     // Update Public information section.
  272.  
  273.     dir->cluster = dir->dta.cluster;
  274.     dir->attrib  = (USHORT)dir->dta.attribute;
  275.     dir->size    = dir->dta.size;
  276.     fname(dir->name, dir->dta.name, dir->dta.ext);
  277.     return dir;
  278. }
  279.  
  280.  
  281. char * DosDiskVolume(char drive_letter, char* vol, short vol_size)
  282. {
  283.     static char files[] = "?:\\*";
  284.     struct find_t dir;                       // structure for directory entry
  285.  
  286.     *files = drive_letter;
  287.  
  288.     if (_dos_findfirst(files, _A_VOLID, &dir) == 0)
  289.     {
  290.       memmove(dir.name+8, dir.name+9, 4);
  291.       return strncpy(vol, dir.name, vol_size);
  292.     }
  293.     else
  294.       return strncpy(vol, "?", vol_size);
  295. }
  296. #endif
  297.  
  298.  
  299. // ################################## OS2 ############################
  300. #ifdef __OS2__
  301.  
  302. #define SECTOR_SIZE 512                   // This is NOT SAFE  !!!!
  303.  
  304. static struct
  305. {
  306.     USHORT huge * FAT;                    // Current open disk FAT table
  307.     USHORT        handle;                 // Direct Disk Access Handle
  308.     USHORT        BytesPerSector;         // Disk Parmameters
  309.     USHORT        SectorsPerCluster;      //             ....
  310.     USHORT        RootSector;
  311.     USHORT        FirstFileSector;
  312. } os2_dir;
  313.  
  314.  
  315. void DosSetDrive(char drive_letter)       // set up the work drive
  316. {
  317.     DosSelectDisk((toupper(drive_letter) - 'A') + 1);
  318. }
  319.  
  320.  
  321. char *translate_name(char *name)
  322. {
  323.     return name;
  324. }
  325.  
  326.  
  327. short DosDiskValid(char drive_letter)
  328. {
  329.     // Possible try and lock drive ??
  330.  
  331.     return 0;
  332. }
  333.  
  334.  
  335. void DosCloseDrive(USHORT handle)
  336. {
  337.     DosClose(handle);
  338.     hfree(os2_dir.FAT);
  339.     memset(&os2_dir, 0, sizeof(os2_dir));     // Mark as unactive
  340. }
  341.  
  342.  
  343. USHORT DosOpenDrive(char drive_letter)
  344. {
  345.     char    drive_name[3];
  346.     USHORT  handle, action;
  347.  
  348.     drive_name[0] = drive_letter;
  349.     drive_name[1] = ':';
  350.     drive_name[2] = 0;
  351.  
  352.     if (DosOpen(drive_name, &handle, &action, 0L, 0, FILE_OPEN,
  353.      OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE | OPEN_FLAGS_DASD, 0L) == 0)
  354.         return handle;
  355.     else
  356.         return -1;
  357. }
  358.  
  359. USHORT DosBytesPerDiskSector(USHORT drive_handle)
  360. {
  361.     BIOSPARAMETERBLOCK bpb;
  362.     short              command = 1;   // current medium
  363.  
  364.     if (DosDevIOCtl(&bpb, &command, DSK_GETDEVICEPARAMS, IOCTL_DISK,
  365.       drive_handle) == 0)
  366.         return (bpb.usBytesPerSector);
  367.     else
  368.         return 0;
  369. }
  370.  
  371.  
  372. short DosReadSector(USHORT handle, void far* buffer, ULONG sector, USHORT count)
  373. {
  374.     long    distance = SECTOR_SIZE * sector;
  375.     ULONG   new_position;
  376.     USHORT  got_in;
  377.  
  378.     if (DosChgFilePtr(handle, distance, FILE_BEGIN, &new_position) ||
  379.       DosRead(handle, buffer, SECTOR_SIZE*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 >= 16)
  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.                 return DosDirClose(dir);
  468.  
  469.             dir->sector++;
  470.             dir->next_fat_entry--;
  471.         }
  472.  
  473.         // Update Public information section.
  474.  
  475.         dir->cluster = dir->entries[dir->entry].cluster;
  476.         dir->attrib  = (USHORT)dir->entries[dir->entry].attribute;
  477.         dir->size    = dir->entries[0].size;
  478.         fname(dir->name, dir->entries[dir->entry].name, dir->entries[dir->entry].ext);
  479.         dir->entry++;
  480.  
  481.         if (dir->name[0] == 0)                   // q. End of directory ?
  482.             return DosDirClose(dir);             // a. Yes, clean up
  483.     }
  484.     while (((dir->attrib & 0x17) && (dir->attrib & dir->search_attributes) == 0) ||
  485.       (dir->name[0] & 0x80) || dir->cluster == 0);
  486.  
  487.     return dir;
  488. }
  489.  
  490.  
  491. Directory * DosDirFindFirst(char* find, USHORT attributes, USHORT DirCluster)
  492. {
  493.     Directory * dir;
  494.  
  495.     // Allocate directory work structure
  496.  
  497.     dir = calloc(sizeof(*dir), 1);
  498.     if (dir == NULL) return NULL;
  499.  
  500.     // Initialize directory info.
  501.  
  502.     dir->fat_entry         = DirCluster;
  503.     dir->search_attributes = attributes;
  504.     dir->next_fat_entry    = os2_dir.SectorsPerCluster ;
  505.     dir->entry             = 0;
  506.  
  507.     if (DirCluster == 0)
  508.         dir->sector = os2_dir.RootSector;
  509.     else
  510.         dir->sector = (ULONG)(dir->fat_entry - 2) *
  511.           os2_dir.SectorsPerCluster + os2_dir.FirstFileSector;
  512.  
  513.     // Return first valid match if any?
  514.  
  515.     return DosDirFindNext(dir);
  516. }
  517.  
  518.  
  519. char * DosDiskVolume(char drive_letter, char* vol, short vol_size)
  520. {
  521.   FSINFO InfoBuf;
  522.  
  523.   DosQFSInfo(drive_letter-'@', 2, (void*)&InfoBuf, sizeof(InfoBuf));
  524.   return strncpy(vol, InfoBuf.vol.szVolLabel, vol_size);
  525. }
  526.  
  527. #endif
  528.