home *** CD-ROM | disk | FTP | other *** search
/ Programming Win32 Under the API / ProgrammingWin32UnderTheApiPatVillani.iso / src / mingw-runtime-19991107 / mingw / dirent.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-11-07  |  6.0 KB  |  314 lines

  1. /*
  2.  * dirent.c
  3.  *
  4.  * Derived from DIRLIB.C by Matt J. Weinstein 
  5.  * This note appears in the DIRLIB.H
  6.  * DIRLIB.H by M. J. Weinstein   Released to public domain 1-Jan-89
  7.  *
  8.  * Updated by Jeremy Bettis <jeremy@hksys.com>
  9.  * Significantly revised and rewinddir, seekdir and telldir added by Colin
  10.  * Peters <colin@fu.is.saga-u.ac.jp>
  11.  *
  12.  * $Revision: 1.2 $
  13.  * $Author: khan $
  14.  * $Date: 1999/01/04 23:21:11 $
  15.  *
  16.  */
  17.  
  18. #include <stdlib.h>
  19. #include <errno.h>
  20. #include <string.h>
  21. #include <io.h>
  22. #include <direct.h>
  23. #include <sys/stat.h>
  24.  
  25. #include <dirent.h>
  26.  
  27. #define SUFFIX    "*"
  28. #define    SLASH    "\\"
  29.  
  30. /*
  31.  * opendir
  32.  *
  33.  * Returns a pointer to a DIR structure appropriately filled in to begin
  34.  * searching a directory.
  35.  */
  36. DIR *
  37. opendir (const char *szPath)
  38. {
  39.   DIR *nd;
  40.   struct _stat statDir;
  41.  
  42.   errno = 0;
  43.  
  44.   if (!szPath)
  45.     {
  46.       errno = EFAULT;
  47.       return (DIR *) 0;
  48.     }
  49.  
  50.   if (szPath[0] == '\0')
  51.     {
  52.       errno = ENOTDIR;
  53.       return (DIR *) 0;
  54.     }
  55.  
  56.   /* Attempt to determine if the given path really is a directory. */
  57.   if (_stat (szPath, &statDir))
  58.     {
  59.       /* Error, stat should have set an error value. */
  60.       return (DIR *) 0;
  61.     }
  62.  
  63.   if (!S_ISDIR (statDir.st_mode))
  64.     {
  65.       /* Error, stat reports not a directory. */
  66.       errno = ENOTDIR;
  67.       return (DIR *) 0;
  68.     }
  69.  
  70.   /* Allocate enough space to store DIR structure and the complete
  71.    * directory path given. */
  72.   nd = (DIR *) malloc (sizeof (DIR) + strlen (szPath) + strlen (SLASH) +
  73.                strlen (SUFFIX));
  74.  
  75.   if (!nd)
  76.     {
  77.       /* Error, out of memory. */
  78.       errno = ENOMEM;
  79.       return (DIR *) 0;
  80.     }
  81.  
  82.   /* Create the search expression. */
  83.   strcpy (nd->dd_name, szPath);
  84.  
  85.   /* Add on a slash if the path does not end with one. */
  86.   if (nd->dd_name[0] != '\0' &&
  87.       nd->dd_name[strlen (nd->dd_name) - 1] != '/' &&
  88.       nd->dd_name[strlen (nd->dd_name) - 1] != '\\')
  89.     {
  90.       strcat (nd->dd_name, SLASH);
  91.     }
  92.  
  93.   /* Add on the search pattern */
  94.   strcat (nd->dd_name, SUFFIX);
  95.  
  96.   /* Initialize handle to -1 so that a premature closedir doesn't try
  97.    * to call _findclose on it. */
  98.   nd->dd_handle = -1;
  99.  
  100.   /* Initialize the status. */
  101.   nd->dd_stat = 0;
  102.  
  103.   /* Initialize the dirent structure. ino and reclen are invalid under
  104.    * Win32, and name simply points at the appropriate part of the
  105.    * findfirst_t structure. */
  106.   nd->dd_dir.d_ino = 0;
  107.   nd->dd_dir.d_reclen = 0;
  108.   nd->dd_dir.d_namlen = 0;
  109.   nd->dd_dir.d_name = nd->dd_dta.name;
  110.  
  111.   return nd;
  112. }
  113.  
  114.  
  115. /*
  116.  * readdir
  117.  *
  118.  * Return a pointer to a dirent structure filled with the information on the
  119.  * next entry in the directory.
  120.  */
  121. struct dirent *
  122. readdir (DIR * dirp)
  123. {
  124.   errno = 0;
  125.  
  126.   /* Check for valid DIR struct. */
  127.   if (!dirp)
  128.     {
  129.       errno = EFAULT;
  130.       return (struct dirent *) 0;
  131.     }
  132.  
  133.   if (dirp->dd_dir.d_name != dirp->dd_dta.name)
  134.     {
  135.       /* The structure does not seem to be set up correctly. */
  136.       errno = EINVAL;
  137.       return (struct dirent *) 0;
  138.     }
  139.  
  140.   if (dirp->dd_stat < 0)
  141.     {
  142.       /* We have already returned all files in the directory
  143.        * (or the structure has an invalid dd_stat). */
  144.       return (struct dirent *) 0;
  145.     }
  146.   else if (dirp->dd_stat == 0)
  147.     {
  148.       /* We haven't started the search yet. */
  149.       /* Start the search */
  150.       dirp->dd_handle = _findfirst (dirp->dd_name, &(dirp->dd_dta));
  151.  
  152.       if (dirp->dd_handle == -1)
  153.     {
  154.       /* Whoops! Seems there are no files in that
  155.        * directory. */
  156.       dirp->dd_stat = -1;
  157.     }
  158.       else
  159.     {
  160.       dirp->dd_stat = 1;
  161.     }
  162.     }
  163.   else
  164.     {
  165.       /* Get the next search entry. */
  166.       if (_findnext (dirp->dd_handle, &(dirp->dd_dta)))
  167.     {
  168.       /* We are off the end or otherwise error. */
  169.       _findclose (dirp->dd_handle);
  170.       dirp->dd_handle = -1;
  171.       dirp->dd_stat = -1;
  172.     }
  173.       else
  174.     {
  175.       /* Update the status to indicate the correct
  176.        * number. */
  177.       dirp->dd_stat++;
  178.     }
  179.     }
  180.  
  181.   if (dirp->dd_stat > 0)
  182.     {
  183.       /* Successfully got an entry. Everything about the file is
  184.        * already appropriately filled in except the length of the
  185.        * file name. */
  186.       dirp->dd_dir.d_namlen = strlen (dirp->dd_dir.d_name);
  187.       return &dirp->dd_dir;
  188.     }
  189.  
  190.   return (struct dirent *) 0;
  191. }
  192.  
  193.  
  194. /*
  195.  * closedir
  196.  *
  197.  * Frees up resources allocated by opendir.
  198.  */
  199. int
  200. closedir (DIR * dirp)
  201. {
  202.   int rc;
  203.  
  204.   errno = 0;
  205.   rc = 0;
  206.  
  207.   if (!dirp)
  208.     {
  209.       errno = EFAULT;
  210.       return -1;
  211.     }
  212.  
  213.   if (dirp->dd_handle != -1)
  214.     {
  215.       rc = _findclose (dirp->dd_handle);
  216.     }
  217.  
  218.   /* Delete the dir structure. */
  219.   free (dirp);
  220.  
  221.   return rc;
  222. }
  223.  
  224. /*
  225.  * rewinddir
  226.  *
  227.  * Return to the beginning of the directory "stream". We simply call findclose
  228.  * and then reset things like an opendir.
  229.  */
  230. void
  231. rewinddir (DIR * dirp)
  232. {
  233.   errno = 0;
  234.  
  235.   if (!dirp)
  236.     {
  237.       errno = EFAULT;
  238.       return;
  239.     }
  240.  
  241.   if (dirp->dd_handle != -1)
  242.     {
  243.       _findclose (dirp->dd_handle);
  244.     }
  245.  
  246.   dirp->dd_handle = -1;
  247.   dirp->dd_stat = 0;
  248. }
  249.  
  250. /*
  251.  * telldir
  252.  *
  253.  * Returns the "position" in the "directory stream" which can be used with
  254.  * seekdir to go back to an old entry. We simply return the value in stat.
  255.  */
  256. long
  257. telldir (DIR * dirp)
  258. {
  259.   errno = 0;
  260.  
  261.   if (!dirp)
  262.     {
  263.       errno = EFAULT;
  264.       return -1;
  265.     }
  266.   return dirp->dd_stat;
  267. }
  268.  
  269. /*
  270.  * seekdir
  271.  *
  272.  * Seek to an entry previously returned by telldir. We rewind the directory
  273.  * and call readdir repeatedly until either dd_stat is the position number
  274.  * or -1 (off the end). This is not perfect, in that the directory may
  275.  * have changed while we weren't looking. But that is probably the case with
  276.  * any such system.
  277.  */
  278. void
  279. seekdir (DIR * dirp, long lPos)
  280. {
  281.   errno = 0;
  282.  
  283.   if (!dirp)
  284.     {
  285.       errno = EFAULT;
  286.       return;
  287.     }
  288.  
  289.   if (lPos < -1)
  290.     {
  291.       /* Seeking to an invalid position. */
  292.       errno = EINVAL;
  293.       return;
  294.     }
  295.   else if (lPos == -1)
  296.     {
  297.       /* Seek past end. */
  298.       if (dirp->dd_handle != -1)
  299.     {
  300.       _findclose (dirp->dd_handle);
  301.     }
  302.       dirp->dd_handle = -1;
  303.       dirp->dd_stat = -1;
  304.     }
  305.   else
  306.     {
  307.       /* Rewind and read forward to the appropriate index. */
  308.       rewinddir (dirp);
  309.  
  310.       while ((dirp->dd_stat < lPos) && readdir (dirp))
  311.     ;
  312.     }
  313. }
  314.