diff options
Diffstat (limited to 'MSVC/readline/dirent.c')
-rw-r--r-- | MSVC/readline/dirent.c | 357 |
1 files changed, 357 insertions, 0 deletions
diff --git a/MSVC/readline/dirent.c b/MSVC/readline/dirent.c new file mode 100644 index 0000000..435b597 --- /dev/null +++ b/MSVC/readline/dirent.c @@ -0,0 +1,357 @@ +/* + * dirent.c + * + * Derived from DIRLIB.C by Matt J. Weinstein + * This note appears in the DIRLIB.H + * DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89 + * + * Updated by Jeremy Bettis <jeremy@hksys.com> + * Significantly revised and rewinddir, seekdir and telldir added by Colin + * Peters <colin@fu.is.saga-u.ac.jp> + * + * $Revision: 1.1 $ + * $Author: pixel $ + * $Date: 2004-04-28 14:23:36 $ + * + */ + +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <io.h> +#include <direct.h> +#include <sys/stat.h> + +#include "dirent.h" + +#define SUFFIX "*" +#define SLASH "\\" + +char * __stdcall CharPrevA(const char *, const char *); + +static int +isUNCRoot(const char *path) +{ + if (path[0] == '\\' && path[1] == '\\') { + const char *p; + if (p = strchr(path + 3, '\\')) { + if (!p[1]) + return 0; + if (p = strchr(p + 1, '\\')) { + if (!p[1]) + return 1; + } else + return 1; + } + } + return 0; +} + +#ifndef S_ISDIR +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif +/* + * opendir + * + * Returns a pointer to a DIR structure appropriately filled in to begin + * searching a directory. + */ +DIR * +opendir (const char *szPath) +{ + DIR *nd; + struct _stat statDir; + char buf1[_MAX_PATH]; + char buf2[_MAX_PATH]; + const char *p; + char *q; + int len; + + errno = 0; + + if (!szPath) + { + errno = EFAULT; + return (DIR *) 0; + } + + if (szPath[0] == '\0') + { + errno = ENOTDIR; + return (DIR *) 0; + } + + for (p = szPath, q = buf1; *p; p++, q++) + { + if (*p == '/') + *q = '\\'; + else + *q = *p; + } + *q = '\0'; + + _fullpath(buf2, buf1, sizeof buf2); + len = strlen(buf2); + p = CharPrevA(buf2, buf2 + len); + if (isUNCRoot(buf2)) { + if (*p != '\\') + strcat(buf2, "\\"); + } else if (*p == '\\' || *p == ':') + strcat(buf2, "."); + + /* Attempt to determine if the given path really is a directory. */ + if (_stat (buf2, &statDir)) + { + /* Error, stat should have set an error value. */ + return (DIR *) 0; + } + + if (!S_ISDIR (statDir.st_mode)) + { + /* Error, stat reports not a directory. */ + errno = ENOTDIR; + return (DIR *) 0; + } + + if (*p == '\\') + buf2[len - 1] = '\0'; + + /* Allocate enough space to store DIR structure and the complete + * directory path given. */ + nd = (DIR *) malloc (sizeof (DIR) + strlen (buf2) + strlen (SLASH) + + strlen (SUFFIX)); + + if (!nd) + { + /* Error, out of memory. */ + errno = ENOMEM; + return (DIR *) 0; + } + + /* Create the search expression. */ + strcpy (nd->dd_name, buf2); + + /* Add on a slash. */ + strcat (nd->dd_name, SLASH); + + /* Add on the search pattern */ + strcat (nd->dd_name, SUFFIX); + + /* Initialize handle to -1 so that a premature closedir doesn't try + * to call _findclose on it. */ + nd->dd_handle = -1; + + /* Initialize the status. */ + nd->dd_stat = 0; + + /* Initialize the dirent structure. ino and reclen are invalid under + * Win32, and name simply points at the appropriate part of the + * findfirst_t structure. */ + nd->dd_dir.d_ino = 0; + nd->dd_dir.d_reclen = 0; + nd->dd_dir.d_namlen = 0; + nd->dd_dir.d_name = nd->dd_dta.name; + + return nd; +} + + +/* + * readdir + * + * Return a pointer to a dirent structure filled with the information on the + * next entry in the directory. + */ +struct dirent * +readdir (DIR * dirp) +{ + errno = 0; + + /* Check for valid DIR struct. */ + if (!dirp) + { + errno = EFAULT; + return (struct dirent *) 0; + } + + if (dirp->dd_dir.d_name != dirp->dd_dta.name) + { + /* The structure does not seem to be set up correctly. */ + errno = EINVAL; + return (struct dirent *) 0; + } + + if (dirp->dd_stat < 0) + { + /* We have already returned all files in the directory + * (or the structure has an invalid dd_stat). */ + return (struct dirent *) 0; + } + else if (dirp->dd_stat == 0) + { + /* We haven't started the search yet. */ + /* Start the search */ + dirp->dd_handle = _findfirst (dirp->dd_name, &(dirp->dd_dta)); + + if (dirp->dd_handle == -1) + { + /* Whoops! Seems there are no files in that + * directory. */ + dirp->dd_stat = -1; + } + else + { + dirp->dd_stat = 1; + } + } + else + { + /* Get the next search entry. */ + if (_findnext (dirp->dd_handle, &(dirp->dd_dta))) + { + /* We are off the end or otherwise error. */ + _findclose (dirp->dd_handle); + dirp->dd_handle = -1; + dirp->dd_stat = -1; + } + else + { + /* Update the status to indicate the correct + * number. */ + dirp->dd_stat++; + } + } + + if (dirp->dd_stat > 0) + { + /* Successfully got an entry. Everything about the file is + * already appropriately filled in except the length of the + * file name. */ + dirp->dd_dir.d_namlen = strlen (dirp->dd_dir.d_name); + return &dirp->dd_dir; + } + + return (struct dirent *) 0; +} + + +/* + * closedir + * + * Frees up resources allocated by opendir. + */ +int +closedir (DIR * dirp) +{ + int rc; + + errno = 0; + rc = 0; + + if (!dirp) + { + errno = EFAULT; + return -1; + } + + if (dirp->dd_handle != -1) + { + rc = _findclose (dirp->dd_handle); + } + + /* Delete the dir structure. */ + free (dirp); + + return rc; +} + +/* + * rewinddir + * + * Return to the beginning of the directory "stream". We simply call findclose + * and then reset things like an opendir. + */ +void +rewinddir (DIR * dirp) +{ + errno = 0; + + if (!dirp) + { + errno = EFAULT; + return; + } + + if (dirp->dd_handle != -1) + { + _findclose (dirp->dd_handle); + } + + dirp->dd_handle = -1; + dirp->dd_stat = 0; +} + +/* + * telldir + * + * Returns the "position" in the "directory stream" which can be used with + * seekdir to go back to an old entry. We simply return the value in stat. + */ +long +telldir (DIR * dirp) +{ + errno = 0; + + if (!dirp) + { + errno = EFAULT; + return -1; + } + return dirp->dd_stat; +} + +/* + * seekdir + * + * Seek to an entry previously returned by telldir. We rewind the directory + * and call readdir repeatedly until either dd_stat is the position number + * or -1 (off the end). This is not perfect, in that the directory may + * have changed while we weren't looking. But that is probably the case with + * any such system. + */ +void +seekdir (DIR * dirp, long lPos) +{ + errno = 0; + + if (!dirp) + { + errno = EFAULT; + return; + } + + if (lPos < -1) + { + /* Seeking to an invalid position. */ + errno = EINVAL; + return; + } + else if (lPos == -1) + { + /* Seek past end. */ + if (dirp->dd_handle != -1) + { + _findclose (dirp->dd_handle); + } + dirp->dd_handle = -1; + dirp->dd_stat = -1; + } + else + { + /* Rewind and read forward to the appropriate index. */ + rewinddir (dirp); + + while ((dirp->dd_stat < lPos) && readdir (dirp)) + ; + } +} |