home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / POSIXDIR.C < prev    next >
C/C++ Source or Header  |  1997-07-05  |  10KB  |  266 lines

  1. /* +++Date last modified: 05-Jul-1997 */
  2.  
  3. /*
  4. **  POSIXDIR.C - POSIX-style directory processing
  5. **
  6. **  Original Copyright 1988-1991 by Bob Stout as part of
  7. **  the MicroFirm Function Library (MFL)
  8. **
  9. **  The user is granted a free limited license to use this source file
  10. **  to create royalty-free programs, subject to the terms of the
  11. **  license restrictions specified in the LICENSE.MFL file.
  12. */
  13.  
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include <dos.h>
  17. #include <io.h>
  18. #include <errno.h>
  19. #include "sniptype.h"
  20. #include "dirent.h"
  21. #include "filnames.h"         /* For dos2unix() */
  22.  
  23. #define _NDIRS 20
  24.  
  25. int DFerr;
  26. DIR _DIRS[_NDIRS];            /* Initialize DIR array to zeros    */
  27.  
  28. /******************************************************************/
  29. /*                                                                */
  30. /*  opendir()                                                     */
  31. /*                                                                */
  32. /*  Function: Open a directory for reading.                       */
  33. /*                                                                */
  34. /*  Parameters: 1 - Directory name. May include path spec.        */
  35. /*                                                                */
  36. /*  Returns: Pointer to a DIR typedef'ed structure, similar       */
  37. /*           to fopen() returning a FILE pointer.                 */
  38. /*                                                                */
  39. /*           NULL if error, DFerr set as follows:                 */
  40. /*           Success_ - No error                                  */
  41. /*           ENOENT   - Could not locate directory or contents    */
  42. /*           ENOTDIR  - Not a directory                           */
  43. /*           ENOMEM   - Too many directories already open         */
  44. /*                                                                */
  45. /*  Side effects: The dd_size element of the DIR structure        */
  46. /*                will contain a number representing the total    */
  47. /*                number of entries in the directory. The         */
  48. /*                dd_loc element will be set to zero since        */
  49. /*                no elements have, as yet, been read.            */
  50. /*                                                                */
  51. /******************************************************************/
  52.  
  53. DIR *opendir(char *fname)
  54. {
  55.       int i;
  56.       unsigned n = 0;
  57.       char *p;
  58.       DOSFileData dstruct;
  59.  
  60.       for (i = 0; i < _NDIRS; ++i)
  61.       {
  62.             if (!_DIRS[i].dd_fd)
  63.                   break;
  64.       }
  65.       if (_NDIRS <= i)
  66.       {
  67.             DFerr = ENOMEM;
  68.             return NULL;
  69.       }
  70.  
  71.       dos2unix(fname);
  72.       if (':' == fname[1] && 1 < strlen(fname))
  73.             p = &fname[2];
  74.       else  p = fname;
  75.       while ('/' == LAST_CHAR(p) && 1 < strlen(p))
  76.             LAST_CHAR(p) = '\0';
  77.         
  78.       if (strcmp(p, "/") && strlen(p))
  79.       {
  80.             if (Success_ != (FIND_FIRST(fname, _A_ANY, &_DIRS[i].dd_buf)))
  81.             {
  82.                   DFerr = ENOENT;
  83.                   return NULL;
  84.             }
  85.             if (!(_A_SUBDIR & _DIRS[i].dd_buf.attrib))
  86.             {
  87.                   DFerr = ENOTDIR;
  88.                   return NULL;
  89.             }
  90.       }
  91.       strcpy(_DIRS[i].dd_dirname, fname);
  92.       if (!strlen(p))
  93.             strcat(_DIRS[i].dd_dirname, ".");
  94.       if ('/' != LAST_CHAR(_DIRS[i].dd_dirname))
  95.             strcat(_DIRS[i].dd_dirname, "/");
  96.       strcat(strupr(_DIRS[i].dd_dirname), "*.*");
  97.       if (Success_ != FIND_FIRST(_DIRS[i].dd_dirname,
  98.             _A_ANY, &_DIRS[i].dd_buf))
  99.       {
  100.             DFerr = ENOENT;
  101.             return NULL;
  102.       }
  103.       memcpy(&dstruct, &_DIRS[i].dd_buf, sizeof(DOSFileData));
  104.       do
  105.       {
  106.             ++n;
  107.       } while (Success_ == FIND_NEXT(&_DIRS[i].dd_buf));
  108.       memcpy(&_DIRS[i].dd_buf, &dstruct, sizeof(DOSFileData));
  109.       _DIRS[i].dd_size = n;
  110.       _DIRS[i].dd_loc  = 0;
  111.       _DIRS[i].dd_fd   = i + 1;
  112.       DFerr = Success_;
  113.       return &_DIRS[i];
  114. }
  115.  
  116. /******************************************************************/
  117. /*                                                                */
  118. /*  closedir()                                                    */
  119. /*                                                                */
  120. /*  Function: Close a previously opened directory.                */
  121. /*                                                                */
  122. /*  Parameters: 1 - DIR pointer of directory to close.            */
  123. /*                                                                */
  124. /*  Returns: Success_ or Error_.                                  */
  125. /*                                                                */
  126. /******************************************************************/
  127.  
  128. int closedir(DIR *dirp)
  129. {
  130.       if (0 == dirp->dd_fd || _NDIRS < dirp->dd_fd)
  131.       {
  132.             DFerr = EBADF;
  133.             return Error_;
  134.       }
  135.       FIND_END(dirp->dd_buf);
  136.       memset(dirp, 0, sizeof(DIR));
  137.       return Success_;
  138. }
  139.  
  140. /******************************************************************/
  141. /*                                                                */
  142. /*  rewinddir()                                                   */
  143. /*                                                                */
  144. /*  Function: Reset an open DIR to its first entry.               */
  145. /*                                                                */
  146. /*  Parameters: 1 - DIR pointer of directory to rewind.           */
  147. /*                                                                */
  148. /*  Returns: Success_ or Error_.                                  */
  149. /*                                                                */
  150. /******************************************************************/
  151.  
  152. int rewinddir(DIR *dirp)
  153. {
  154.       if (0 == dirp->dd_fd || _NDIRS < dirp->dd_fd)
  155.       {
  156.             DFerr = EBADF;
  157.             return Error_;
  158.       }
  159.       FIND_FIRST(dirp->dd_dirname, _A_ANY, &(dirp->dd_buf));
  160.       dirp->dd_loc = 0;
  161.       return Success_;
  162. }
  163.  
  164. /******************************************************************/
  165. /*                                                                */
  166. /*  seekdir()                                                     */
  167. /*                                                                */
  168. /*  Function: Point to a selected entry in a DIR.                 */
  169. /*                                                                */
  170. /*  Parameters: 1 - DIR pointer of directory to rewind.           */
  171. /*              2 - Offset of entry to seek                       */
  172. /*              3 - Origin of offset                              */
  173. /*                                                                */
  174. /*  Returns: A DOSFileData pointer, same as returned by DOS find  */
  175. /*           first/next calls.                                    */
  176. /*                                                                */
  177. /*           NULL if error, DFerr set as follows:                 */
  178. /*           Success_ - No error                                  */
  179. /*           EBADF    - Bad file (DIR) pointer                    */
  180. /*           EACCES   - Illegal origin specification              */
  181. /*           EOF      - Attempt to seek past end of directory     */
  182. /*                                                                */
  183. /******************************************************************/
  184.  
  185. DOSFileData *seekdir(DIR *dirp, int offset, int origin)
  186. {
  187.       int i, loc;
  188.  
  189.       if (0 == dirp->dd_fd || _NDIRS < dirp->dd_fd)
  190.       {
  191.             DFerr = EBADF;
  192.             return NULL;
  193.       }
  194.       switch (origin)
  195.       {
  196.       case SEEK_SET:
  197.             loc = offset + 1;
  198.             break;
  199.       case SEEK_CUR:
  200.             loc = dirp->dd_loc + offset;
  201.             break;
  202.       case SEEK_END:
  203.             loc = dirp->dd_size + offset;
  204.             break;
  205.       default:
  206.             DFerr = EACCES;
  207.             return NULL;
  208.       }
  209.  
  210.       if (loc > (int)dirp->dd_size || 0 >= loc)
  211.       {
  212.             DFerr = EOF;
  213.             return NULL;
  214.       }
  215.  
  216.       rewinddir(dirp);
  217.       for (i = 0; i < loc; ++i)
  218.             readdir(dirp);
  219.  
  220.       DFerr = Success_;
  221.       return (&(dirp->dd_buf));
  222. }
  223.  
  224. /******************************************************************/
  225. /*                                                                */
  226. /*  readdir()                                                     */
  227. /*                                                                */
  228. /*  Function: Reads entries from an open directory.               */
  229. /*                                                                */
  230. /*  Parameters: 1 - DIR pointer of directory to read.             */
  231. /*                                                                */
  232. /*  Returns: A DOSFileData pointer, same as returned by DOS find  */
  233. /*           first/next calls.                                    */
  234. /*                                                                */
  235. /*           NULL if error, DFerr set as follows:                 */
  236. /*           Success_ - No error                                  */
  237. /*           EBADF    - Bad file (DIR) pointer                    */
  238. /*           EOF      - Attempt to read past end of directory     */
  239. /*                                                                */
  240. /*  Side effects: The dd_loc element of the DIR structure         */
  241. /*                will contain a number representing which        */
  242. /*                element of the directory was returned. It may   */
  243. /*                range from 1 to dd_size.                        */
  244. /*                                                                */
  245. /******************************************************************/
  246.  
  247. DOSFileData *readdir(DIR *dirp)
  248. {
  249.       if (0 == dirp->dd_fd || _NDIRS < dirp->dd_fd)
  250.       {
  251.             DFerr = EBADF;
  252.             return NULL;
  253.       }
  254.       if (0 == dirp->dd_loc || Success_ == FIND_NEXT(&(dirp->dd_buf)))
  255.       {
  256.             dirp->dd_loc += 1;
  257.             DFerr = Success_;
  258.             return (&(dirp->dd_buf));
  259.       }
  260.       else
  261.       {
  262.             DFerr = EOF;
  263.             return NULL;
  264.       }
  265. }
  266.