SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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
26 static DataStructures::List< _findinfo_t* > fileInfo;
27
28 #include "slikenet/memoryoverride.h"
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);
168 SLNet::OP_DELETE(fi, _FILE_AND_LINE_);
169 return 0;
170 }
171 #endif