home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_C / SNIP9404.ZIP / POSIXDIR.C < prev    next >
C/C++ Source or Header  |  1994-04-03  |  10KB  |  277 lines

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