DSL
Directory.cpp
1 //@AUTOHEADER@BEGIN@
2 /***********************************************************************\
3 | Drift Standard Libraries v1.01 |
4 | Copyright 2010-2023 Drift Solutions / Indy Sams |
5 | Docs and more information available at https://www.driftsolutions.dev |
6 | This file released under the 3-clause BSD license, |
7 | see included DSL.LICENSE.TXT file for details. |
8 \***********************************************************************/
9 //@AUTOHEADER@END@
10 
11 #include <drift/dslcore.h>
12 #include <drift/Directory.h>
13 #include <drift/GenLib.h>
14 
15 Directory::Directory() {
16  hFind = NULL;
17  mDir = NULL;
18 #if defined(__DSL_USE_READDIR_R__)
19  last_res = NULL;
20 #endif
21 }
22 
23 Directory::Directory(const char * dir) {
24  hFind = NULL;
25  mDir = NULL;
26 #if defined(__DSL_USE_READDIR_R__)
27  last_res = NULL;
28 #endif
29  Open(dir);
30 }
31 
32 Directory::Directory(const wchar_t * dir) {
33  hFind = NULL;
34  mDir = NULL;
35 #if defined(__DSL_USE_READDIR_R__)
36  last_res = NULL;
37 #endif
38  Open(dir);
39 }
40 
41 Directory::~Directory() {
42  Close();
43 }
44 
45 bool Directory::Open(const char * dir) {
46  this->Close();
47  if (dir == NULL || dir[0] == 0) { return false; }
48  this->mDir = new char[strlen(dir)+16];
49  strcpy(mDir, dir);
50 #if defined(WIN32)
51  int bufSize = int(strlen(dir)) + 16;
52  wchar_t * wbuf = new wchar_t[bufSize];
53  int n = MultiByteToWideChar(CP_UTF8, 0, dir, -1, wbuf, bufSize);
54  if (n == 0) {
55  n = MultiByteToWideChar(CP_THREAD_ACP, 0, dir, -1, wbuf, bufSize);
56  }
57  if (n == 0) {
58  return false;
59  }
60  bool ret = Open(wbuf);
61  delete [] wbuf;
62  return ret;
63 #else
64  if (mDir[strlen(mDir)-1] == PATH_SEP) { mDir[strlen(mDir)-1]=0; }
65 #if defined(__DSL_USE_READDIR_R__)
66  last_res = NULL;
67 #endif
68  hFind = opendir(mDir);
69  strcat(mDir, PATH_SEPS);
70  if (!this->hFind) {
71  return false;
72  }
73  return true;
74 #endif
75 }
76 
77 bool Directory::Open(const wchar_t * dir) {
78  this->Close();
79  if (dir == NULL || wcslen(dir) == 0) { return false; }
80  this->wDir = new wchar_t[wcslen(dir)+16];
81  wcscpy(wDir, dir);
82 #if defined(WIN32)
83  if (wDir[wcslen(wDir)-1] != PATH_SEP) { wcscat(wDir, WPATH_SEPS); }
84  wcscat(wDir, L"*");
85 #else
86  //we do not yet support Unicode on Linux (don't know which APIs to use)
87  char dir2[MAX_PATH];
88  wcstombs(dir2, dir, sizeof(dir2));
89  return Open(dir2);
90 #endif
91  return true;
92 }
93 
94 bool Directory::Read(char * buf, unsigned long bufSize, bool * is_dir, int64 * size) {
95  memset(buf, 0, bufSize);
96 #if defined(WIN32)
97  wchar_t * wbuf = new wchar_t[bufSize+1];
98  bool ret = Read(wbuf, bufSize, is_dir, size);
99  WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, bufSize, NULL, NULL);
100  delete [] wbuf;
101  return ret;
102  /*
103  if (!this->hFind) {
104  this->hFind = FindFirstFileA(mDir, &wfdA);
105  strrchr(mDir, PATH_SEP)[1]=0;
106  if (hFind != INVALID_HANDLE_VALUE) {
107  if (is_dir) {
108  *is_dir = (wfdA.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true:false;
109  }
110  if (size) {
111  LARGE_INTEGER li;
112  li.LowPart = wfdA.nFileSizeLow;
113  li.HighPart = wfdA.nFileSizeHigh;
114  *size = li.QuadPart;
115  }
116  strlcpy(buf, wfdA.cFileName, bufSize);
117  return true;
118  } else {
119  hFind = NULL;
120  }
121  } else {
122  if (FindNextFileA(this->hFind, &wfdA)) {
123  if (is_dir) {
124  *is_dir = (wfdA.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true:false;
125  }
126  if (size) {
127  LARGE_INTEGER li;
128  li.LowPart = wfdA.nFileSizeLow;
129  li.HighPart = wfdA.nFileSizeHigh;
130  *size = li.QuadPart;
131  }
132  strlcpy(buf, wfdA.cFileName, bufSize);
133  return true;
134  }
135  }
136  */
137 #else
138  if (!this->hFind) {
139  return false;
140  }
141 
142 #if !defined(__DSL_USE_READDIR_R__)
143  dirent * de = readdir(hFind);
144  if (de != NULL) {
145 #else
146  dirent rde;
147  dirent * de = &rde;
148  if (readdir_r(hFind, &de, &last_res) == 0 && last_res != NULL) {
149 #endif
150  /* If the d_type is DT_LNK then we'll have to stat it to know if it's a directory or not */
151  if (is_dir != NULL && size == NULL && (de->d_type == DT_DIR || de->d_type == DT_REG)) {
152  *is_dir = (de->d_type == DT_DIR) ? true:false;
153  } else if (is_dir != NULL || size != NULL) {
154  snprintf(buf, bufSize,"%s%s", mDir, de->d_name);
155  struct stat st;
156  if (stat(buf, &st) == 0) {
157  if (is_dir) {
158  *is_dir = S_ISDIR(st.st_mode) ? true:false;
159  }
160  if (size) {
161  *size = st.st_size;
162  }
163  }
164  }
165  strlcpy(buf, de->d_name, bufSize);
166  return true;
167  }
168 
169 #endif
170  return false;
171 }
172 
173 bool Directory::Read(wchar_t * buf, unsigned long bufSize, bool * is_dir, int64 * size) {
174  memset(buf, 0, bufSize);
175 #if defined(WIN32)
176  if (hFind == NULL) {
177  hFind = FindFirstFileW(wDir, &wfdW);
178  wcsrchr(wDir, PATH_SEP)[1] = 0;
179  if (hFind != INVALID_HANDLE_VALUE) {
180  if (is_dir) {
181  *is_dir = (wfdW.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false;
182  }
183  if (size) {
184  LARGE_INTEGER li;
185  li.LowPart = wfdW.nFileSizeLow;
186  li.HighPart = wfdW.nFileSizeHigh;
187  *size = li.QuadPart;
188  }
189  wcsncpy(buf, wfdW.cFileName, bufSize);
190  return true;
191  } else {
192  hFind = NULL;
193  }
194  } else {
195  if (FindNextFileW(this->hFind, &wfdW)) {
196  if (is_dir) {
197  *is_dir = (wfdW.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false;
198  }
199  if (size) {
200  LARGE_INTEGER li;
201  li.LowPart = wfdW.nFileSizeLow;
202  li.HighPart = wfdW.nFileSizeHigh;
203  *size = li.QuadPart;
204  }
205  wcsncpy(buf, wfdW.cFileName, bufSize);
206  return true;
207  }
208  }
209 #else
210  char * tmp = (char *)dsl_malloc(bufSize+1);
211  tmp[bufSize] = 0;
212  bool ret = Read(tmp, bufSize, is_dir, size);
213  if (ret) {
214  mbstowcs(buf, tmp, bufSize);
215  }
216  dsl_free(tmp);
217  return ret;
218 #endif
219  return false;
220 }
221 
223  if (hFind) {
224 #if defined(WIN32)
225  FindClose(hFind);
226 #else
227  closedir(hFind);
228 #endif
229  hFind = NULL;
230  }
231  if (this->mDir) {
232  delete [] mDir;
233  mDir = NULL;
234  }
235 }
bool Read(char *buf, unsigned long bufSize, bool *is_dir=NULL, int64 *size=NULL)
Definition: Directory.cpp:94
bool Open(const char *dir)
Open directory (ANSI/UTF-8)
Definition: Directory.cpp:45
void Close()
Close the directory. Will be called automatically during deconstruction.
Definition: Directory.cpp:222
DSL_API void DSL_CC dsl_free(void *ptr)
Definition: dsl.cpp:345
DSL_API size_t DSL_CC strlcpy(char *dst, const char *src, size_t siz)
Definition: GenLib.cpp:905