dirent.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:7k
源码类别:

多媒体

开发平台:

MultiPlatform

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