SLikeNet  0.1.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
_FindFirst.cpp
Go to the documentation of this file.
1 /*
2  * This file was taken from RakNet 4.082.
3  * Please see licenses/RakNet license.txt for the underlying license and related copyright.
4  *
5  * Modified work: Copyright (c) 2016-2017, SLikeSoft UG (haftungsbeschränkt)
6  *
7  * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
8  * license found in the license.txt file in the root directory of this source tree.
9  */
10 
15 #if (defined(__GNUC__) || defined(__GCCXML__)) && !defined(_WIN32)
16 #include "slikenet/_FindFirst.h"
17 #include "slikenet/DS_List.h"
18 
19 #include <sys/stat.h>
20 
21 #include <fnmatch.h>
22 #include "slikenet/linux_adapter.h"
23 #include "slikenet/osx_adapter.h"
24 
25 
27 
29 #include "slikenet/assert.h"
30 
34 long _findfirst(const char *name, _finddata_t *f)
35 {
36  SLNet::RakString nameCopy = name;
37  SLNet::RakString filter;
38 
39  // This is linux only, so don't bother with '\'
40  const char* lastSep = strrchr(name,'/');
41  if(!lastSep)
42  {
43  // filter pattern only is given, search current directory.
44  filter = nameCopy;
45  nameCopy = ".";
46  } else
47  {
48  // strip filter pattern from directory name, leave
49  // trailing '/' intact.
50  filter = lastSep+1;
51  unsigned sepIndex = lastSep - name;
52  nameCopy.Erase(sepIndex+1, nameCopy.GetLength() - sepIndex-1);
53  }
54 
55  DIR* dir = opendir(nameCopy);
56 
57  if(!dir) return -1;
58 
59  _findinfo_t* fi = SLNet::OP_NEW<_findinfo_t>( _FILE_AND_LINE_ );
60  fi->filter = filter;
61  fi->dirName = nameCopy; // we need to remember this for stat()
62  fi->openedDir = dir;
63  fileInfo.Insert(fi, _FILE_AND_LINE_);
64 
65  long ret = fileInfo.Size()-1;
66 
67  // Retrieve the first file. We cannot rely on the first item
68  // being '.'
69  if (_findnext(ret, f) == -1) return -1;
70  else return ret;
71 }
72 
73 
74 
75 
76 
77 
78 
79 
80 
81 
82 
83 
84 
85 
86 
87 
88 
89 
90 
91 
92 
93 
94 
95 
96 
97 
98 
99 
100 
101 
102 
103 int _findnext(long h, _finddata_t *f)
104 {
105  RakAssert(h >= 0 && h < (long)fileInfo.Size());
106  if (h < 0 || h >= (long)fileInfo.Size()) return -1;
107 
108  _findinfo_t* fi = fileInfo[h];
109 
110  while(true)
111  {
112  dirent* entry = readdir(fi->openedDir);
113  if(entry == 0) return -1;
114 
115  // Only report stuff matching our filter
116  if (fnmatch(fi->filter, entry->d_name, FNM_PATHNAME) != 0) continue;
117 
118  // To reliably determine the entry's type, we must do
119  // a stat... don't rely on entry->d_type, as this
120  // might be unavailable!
121  struct stat filestat;
122  SLNet::RakString fullPath = fi->dirName + entry->d_name;
123  if (stat(fullPath, &filestat) != 0)
124  {
125  RAKNET_DEBUG_PRINTF("Cannot stat %s\n", fullPath.C_String());
126  continue;
127  }
128 
129  if (S_ISREG(filestat.st_mode))
130  {
131  f->attrib = _A_NORMAL;
132  } else if (S_ISDIR(filestat.st_mode))
133  {
134  f->attrib = _A_SUBDIR;
135  } else continue; // We are interested in files and
136  // directories only. Links currently
137  // are not supported.
138 
139  f->size = filestat.st_size;
140  strncpy_s(f->name, entry->d_name, STRING_BUFFER_SIZE);
141 
142  return 0;
143  }
144 
145  return -1;
146 }
147 
148 
149 
150 
151 
155 int _findclose(long h)
156 {
157  if (h==-1) return 0;
158 
159  if (h < 0 || h >= (long)fileInfo.Size())
160  {
161  RakAssert(false);
162  return -1;
163  }
164 
165  _findinfo_t* fi = fileInfo[h];
166  closedir(fi->openedDir);
167  fileInfo.RemoveAtIndex(h);
169  return 0;
170 }
171 #endif