1 /* @(#)dirent.c 1.4 17/02/02 Copyright 2011-2017 J. Schilling */ 2 #include <schily/mconfig.h> 3 #ifndef lint 4 static UConst char sccsid[] = 5 "@(#)dirent.c 1.4 17/02/02 Copyright 2011-2017 J. Schilling"; 6 #endif 7 /* 8 * Copyright (c) 2011-2017 J. Schilling 9 */ 10 /* 11 * The contents of this file are subject to the terms of the 12 * Common Development and Distribution License, Version 1.0 only 13 * (the "License"). You may not use this file except in compliance 14 * with the License. 15 * 16 * See the file CDDL.Schily.txt in this distribution for details. 17 * A copy of the CDDL is also available via the Internet at 18 * http://www.opensource.org/licenses/cddl1.txt 19 * 20 * When distributing Covered Code, include this CDDL HEADER in each 21 * file and include the License file CDDL.Schily.txt from this distribution. 22 */ 23 24 #include <schily/dirent.h> 25 #include <schily/maxpath.h> 26 #include <schily/string.h> 27 #include <schily/errno.h> 28 29 #ifdef NEED_READDIR 30 31 #if defined(__MINGW32__) || defined(_MSC_VER) 32 33 #include <schily/windows.h> 34 #include <schily/utypes.h> 35 #include <schily/schily.h> 36 37 EXPORT DIR *opendir __PR((const char *)); 38 EXPORT int closedir __PR((DIR *)); 39 EXPORT struct dirent *readdir __PR((DIR *)); 40 41 EXPORT DIR * 42 opendir(dname) 43 const char *dname; 44 { 45 char path[PATH_MAX]; 46 size_t len; 47 uint32_t attr; 48 DIR *dp; 49 50 if (dname == NULL) { 51 seterrno(EFAULT); 52 return ((DIR *)0); 53 } 54 len = strlen(dname); 55 if (len > PATH_MAX) { 56 seterrno(ENAMETOOLONG); 57 return ((DIR *)0); 58 } 59 if (len == 0) { 60 seterrno(ENOENT); 61 return ((DIR *)0); 62 } 63 64 attr = GetFileAttributes(dname); 65 if (attr == INVALID_FILE_ATTRIBUTES || 66 (attr & FILE_ATTRIBUTE_DIRECTORY) == 0) { 67 seterrno(ENOTDIR); 68 return ((DIR *)0); 69 } 70 path[0] = '\0'; 71 _fullpath(path, dname, PATH_MAX); 72 len = strlen(path); 73 if (len == 0) { 74 seterrno(ENOENT); 75 return ((DIR *)0); 76 } 77 78 dp = malloc(sizeof (*dp) + len + 2); /* Add 2 for "/ *" */ 79 if (dp == NULL) { 80 seterrno(ENOMEM); 81 return ((DIR *)0); 82 } 83 strcpy(dp->dd_dirname, path); 84 if (dp->dd_dirname[len-1] != '/' && 85 dp->dd_dirname[len-1] != '\\') { 86 dp->dd_dirname[len] = '\\'; 87 len++; 88 } 89 dp->dd_dirname[len++] = '*'; 90 dp->dd_dirname[len] = '\0'; 91 dp->dd_handle = -1; 92 dp->dd_state = 0; 93 94 dp->dd_dir.d_ino = 0; 95 dp->dd_dir.d_reclen = 0; 96 dp->dd_dir.d_namlen = 0; 97 zerobytes(dp->dd_dir.d_name, sizeof (dp->dd_dir.d_name)); 98 99 return (dp); 100 } 101 102 EXPORT int 103 closedir(dp) 104 DIR *dp; 105 { 106 int ret = 0; 107 108 if (dp == NULL) { 109 seterrno(EFAULT); 110 return (-1); 111 } 112 if (dp->dd_handle != -1) { 113 ret = _findclose(dp->dd_handle); 114 } 115 free(dp); 116 117 return (ret); 118 } 119 120 EXPORT struct dirent * 121 readdir(dp) 122 DIR *dp; 123 { 124 if (dp == NULL) { 125 seterrno(EFAULT); 126 return ((struct dirent *)0); 127 } 128 if (dp->dd_state == (char)-1) { 129 return ((struct dirent *)0); 130 } else if (dp->dd_state == (char)0) { 131 dp->dd_handle = _findfirst(dp->dd_dirname, &(dp->dd_data)); 132 if (dp->dd_handle != -1) 133 dp->dd_state = 1; 134 else 135 dp->dd_state = -1; 136 } else { 137 if (_findnext(dp->dd_handle, &(dp->dd_data))) { 138 uint32_t werrno = GetLastError(); 139 140 if (werrno == ERROR_NO_MORE_FILES) 141 seterrno(0); 142 _findclose(dp->dd_handle); 143 dp->dd_handle = -1; 144 dp->dd_state = -1; 145 } else { 146 dp->dd_state = 1; /* state++ to support seekdir */ 147 } 148 } 149 if (dp->dd_state > 0) { 150 strlcpy(dp->dd_dir.d_name, dp->dd_data.name, 151 sizeof (dp->dd_dir.d_name)); 152 153 return (&dp->dd_dir); 154 } 155 return ((struct dirent *)0); 156 } 157 158 #endif /* defined(__MINGW32__) || defined(_MSC_VER) */ 159 160 #endif /* NEED_READDIR */ 161