diff options
author | tomas <tomas> | 2004-07-29 14:26:33 +0000 |
---|---|---|
committer | tomas <tomas> | 2004-07-29 14:26:33 +0000 |
commit | 70052678b19e026a8db3ecb58824d6aa770ea589 (patch) | |
tree | b68dfb62ee1eaf1b788ade7ba91a551118f5834c /src | |
parent | 8addf14a396466982f62503a6dfa5793a53b1b8e (diff) | |
download | luafilesystem-70052678b19e026a8db3ecb58824d6aa770ea589.tar.gz luafilesystem-70052678b19e026a8db3ecb58824d6aa770ea589.tar.bz2 luafilesystem-70052678b19e026a8db3ecb58824d6aa770ea589.zip |
Substituicao nos nomes dos arquivos.
Diffstat (limited to 'src')
-rw-r--r-- | src/lfs.c | 351 | ||||
-rw-r--r-- | src/lfs.h | 10 |
2 files changed, 361 insertions, 0 deletions
diff --git a/src/lfs.c b/src/lfs.c new file mode 100644 index 0000000..d494dd3 --- /dev/null +++ b/src/lfs.c | |||
@@ -0,0 +1,351 @@ | |||
1 | /* | ||
2 | ** File system manipulation library. | ||
3 | ** This library offers these functions: | ||
4 | ** lfs.attributes (filepath [, attributename]) | ||
5 | ** lfs.chdir (path) | ||
6 | ** lfs.currentdir () | ||
7 | ** lfs.dir (path) | ||
8 | ** lfs.mkdir (path) | ||
9 | ** lfs.lock (fh, mode) | ||
10 | ** lfs.unlock (fh) | ||
11 | ** | ||
12 | ** $Id: lfs.c,v 1.1 2004/07/29 14:26:33 tomas Exp $ | ||
13 | */ | ||
14 | |||
15 | #include <errno.h> | ||
16 | #include <stdio.h> | ||
17 | #include <string.h> | ||
18 | #include <time.h> | ||
19 | |||
20 | #ifdef WIN32 | ||
21 | #include <direct.h> | ||
22 | #include <io.h> | ||
23 | #include <sys/locking.h> | ||
24 | #else | ||
25 | #include <unistd.h> | ||
26 | #include <dirent.h> | ||
27 | #include <fcntl.h> | ||
28 | #include <sys/types.h> | ||
29 | #include <sys/stat.h> | ||
30 | #endif | ||
31 | |||
32 | #include <lua.h> | ||
33 | #include <lauxlib.h> | ||
34 | #include <lualib.h> | ||
35 | |||
36 | #include "lfs.h" | ||
37 | |||
38 | /* Define 'strerror' for systems that do not implement it */ | ||
39 | #ifdef NO_STRERROR | ||
40 | #define strerror(_) "System unable to describe the error" | ||
41 | #endif | ||
42 | |||
43 | /* Define 'getcwd' for systems that do not implement it */ | ||
44 | #ifdef NO_GETCWD | ||
45 | #define getcwd(p,s) NULL | ||
46 | #define getcwd_error "Function 'getcwd' not provided by system" | ||
47 | #else | ||
48 | #define getcwd_error strerror(errno) | ||
49 | #endif | ||
50 | |||
51 | #define DIR_METATABLE "directory metatable" | ||
52 | #define MAX_DIR_LENGTH 1023 | ||
53 | #ifdef _WIN32 | ||
54 | typedef struct dir_data { | ||
55 | long hFile; | ||
56 | char pattern[MAX_DIR_LENGTH+1]; | ||
57 | } dir_data; | ||
58 | #endif | ||
59 | |||
60 | |||
61 | /* | ||
62 | ** This function changes the working (current) directory | ||
63 | */ | ||
64 | static int change_dir (lua_State *L) { | ||
65 | const char *path = luaL_checkstring(L, 1); | ||
66 | if (chdir(path)) | ||
67 | luaL_error(L,"Unable to change working directory to '%s'\n%s\n", | ||
68 | path, chdir_error); | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | /* | ||
73 | ** This function returns the current directory | ||
74 | ** If unable to get the current directory, it returns nil | ||
75 | ** and a string describing the error | ||
76 | */ | ||
77 | static int get_dir (lua_State *L) { | ||
78 | char path[255+2]; | ||
79 | if (getcwd(path, 255) == NULL) { | ||
80 | lua_pushnil(L); | ||
81 | lua_pushstring(L, getcwd_error); | ||
82 | return 2; | ||
83 | } | ||
84 | else { | ||
85 | lua_pushstring(L, path); | ||
86 | return 1; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | /* | ||
91 | ** Check if the given element on the stack is a file and returns it. | ||
92 | */ | ||
93 | static FILE *check_file (lua_State *L, int idx, const char *funcname) { | ||
94 | FILE **fh = (FILE **)luaL_checkudata (L, idx, "FILE*"); | ||
95 | if (fh == NULL) { | ||
96 | luaL_error (L, "%s: not a file", funcname); | ||
97 | return 0; | ||
98 | } else if (*fh == NULL) { | ||
99 | luaL_error (L, "%s: closed file", funcname); | ||
100 | return 0; | ||
101 | } else | ||
102 | return *fh; | ||
103 | } | ||
104 | |||
105 | |||
106 | /* | ||
107 | ** | ||
108 | */ | ||
109 | static int _file_lock (lua_State *L, FILE *fh, const char *mode, const long start, long len, const char *funcname) { | ||
110 | int code; | ||
111 | #ifdef WIN32 | ||
112 | /* lkmode valid values are: | ||
113 | _LK_LOCK Locks the specified bytes. If the bytes cannot be locked, the program immediately tries again after 1 second. If, after 10 attempts, the bytes cannot be locked, the constant returns an error. | ||
114 | _LK_NBLCK Locks the specified bytes. If the bytes cannot be locked, the constant returns an error. | ||
115 | _LK_NBRLCK Same as _LK_NBLCK. | ||
116 | _LK_RLCK Same as _LK_LOCK. | ||
117 | _LK_UNLCK Unlocks the specified bytes, which must have been previously locked. | ||
118 | |||
119 | Regions should be locked only briefly and should be unlocked before closing a file or exiting the program. | ||
120 | |||
121 | http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__locking.asp | ||
122 | */ | ||
123 | int lkmode; | ||
124 | switch (*mode) { | ||
125 | case 'r': lkmode = _LK_NBLCK; break; | ||
126 | case 'w': lkmode = _LK_NBLCK; break; | ||
127 | case 'u': lkmode = _LK_UNLCK; break; | ||
128 | default : luaL_error (L, "%s: invalid mode", funcname); | ||
129 | } | ||
130 | if (!len) { | ||
131 | fseek (fh, 0L, SEEK_END); | ||
132 | len = ftell (fh); | ||
133 | } | ||
134 | fseek (fh, start, SEEK_SET); | ||
135 | code = _locking (fileno(fh), lkmode, len); | ||
136 | #else | ||
137 | struct flock f; | ||
138 | switch (*mode) { | ||
139 | case 'w': f.l_type = F_WRLCK; break; | ||
140 | case 'r': f.l_type = F_RDLCK; break; | ||
141 | case 'u': f.l_type = F_UNLCK; break; | ||
142 | default : luaL_error (L, "%s: invalid mode", funcname); | ||
143 | } | ||
144 | f.l_whence = SEEK_SET; | ||
145 | f.l_start = (off_t)start; | ||
146 | f.l_len = (off_t)len; | ||
147 | code = fcntl (fileno(fh), F_SETLK, &f); | ||
148 | #endif | ||
149 | return (code != -1); | ||
150 | } | ||
151 | |||
152 | |||
153 | /* | ||
154 | ** Locks a file. | ||
155 | ** @param #1 File handle. | ||
156 | ** @param #2 String with lock mode ('w'rite, 'r'ead). | ||
157 | ** @param #3 Number with start position (optional). | ||
158 | ** @param #4 Number with length (optional). | ||
159 | */ | ||
160 | static int file_lock (lua_State *L) { | ||
161 | FILE *fh = check_file (L, 1, "lock"); | ||
162 | const char *mode = luaL_checkstring (L, 2); | ||
163 | const long start = luaL_optlong (L, 3, 0); | ||
164 | long len = luaL_optlong (L, 4, 0); | ||
165 | if (_file_lock (L, fh, mode, start, len, "lock")) { | ||
166 | lua_pushboolean (L, 1); | ||
167 | return 1; | ||
168 | } else { | ||
169 | lua_pushboolean (L, 0); | ||
170 | lua_pushfstring (L, "%s", strerror(errno)); | ||
171 | return 2; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | |||
176 | /* | ||
177 | ** Unlocks a file. | ||
178 | ** @param #1 File handle. | ||
179 | ** @param #2 Number with start position (optional). | ||
180 | ** @param #3 Number with length (optional). | ||
181 | */ | ||
182 | static int file_unlock (lua_State *L) { | ||
183 | FILE *fh = check_file (L, 1, "unlock"); | ||
184 | const long start = luaL_optlong (L, 2, 0); | ||
185 | long len = luaL_optlong (L, 3, 0); | ||
186 | if (_file_lock (L, fh, "u", start, len, "unlock")) { | ||
187 | lua_pushboolean (L, 1); | ||
188 | return 1; | ||
189 | } else { | ||
190 | lua_pushboolean (L, 0); | ||
191 | lua_pushfstring (L, "%s", strerror(errno)); | ||
192 | return 2; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | |||
197 | /* | ||
198 | static void cgilua_sleep( lua_State *L ) | ||
199 | { | ||
200 | unsigned int usec = (unsigned int)luaL_check_number( L, 1 ); | ||
201 | |||
202 | #ifndef WIN32 | ||
203 | sleep( (unsigned int)ceil( usec/1000.0 )); | ||
204 | #else | ||
205 | Sleep( (DWORD)usec ); | ||
206 | #endif | ||
207 | } | ||
208 | |||
209 | static void cgilua_filesize( lua_State *L ) | ||
210 | { | ||
211 | struct stat info; | ||
212 | char *file = luaL_check_string( L, 1 ); | ||
213 | |||
214 | if (stat(file, &info)) | ||
215 | { | ||
216 | lua_pushnil( L ); | ||
217 | lua_pushstring( L, "Cannot retrieve stat info from file" ); | ||
218 | return; | ||
219 | } | ||
220 | lua_pushnumber(L, info.st_size); | ||
221 | } | ||
222 | */ | ||
223 | |||
224 | static int make_dir (lua_State *L) { | ||
225 | const char *path = luaL_checkstring (L, 1); | ||
226 | int fail; | ||
227 | #ifdef WIN32 | ||
228 | int oldmask = umask (0); | ||
229 | fail = _mkdir (path); | ||
230 | #else | ||
231 | mode_t oldmask = umask( (mode_t)0 ); | ||
232 | fail = mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | | ||
233 | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH ); | ||
234 | #endif | ||
235 | lua_pushboolean (L, fail); | ||
236 | umask (oldmask); | ||
237 | return 1; | ||
238 | } | ||
239 | |||
240 | |||
241 | /* | ||
242 | ** Directory iterator | ||
243 | */ | ||
244 | static int dir_iter (lua_State *L) { | ||
245 | #ifdef _WIN32 | ||
246 | dir_data *d = (dir_data *)lua_touserdata (L, lua_upvalueindex (1)); | ||
247 | struct _finddata_t c_file; | ||
248 | if (d->hFile == 0L) { /* first entry */ | ||
249 | if ((d->hFile = _findfirst (d->pattern, &c_file)) == -1L) { | ||
250 | lua_pushnil (L); | ||
251 | lua_pushstring (L, strerror (errno)); | ||
252 | return 2; | ||
253 | } else { | ||
254 | lua_pushstring (L, c_file.name); | ||
255 | return 1; | ||
256 | } | ||
257 | } else { /* next entry */ | ||
258 | if (_findnext (d->hFile, &c_file) == -1L) | ||
259 | return 0; | ||
260 | else { | ||
261 | lua_pushstring (L, c_file.name); | ||
262 | return 1; | ||
263 | } | ||
264 | } | ||
265 | #else | ||
266 | DIR *d = *(DIR **) lua_touserdata (L, lua_upvalueindex (1)); | ||
267 | struct dirent *entry; | ||
268 | if ((entry = readdir (d)) != NULL) { | ||
269 | lua_pushstring (L, entry->d_name); | ||
270 | return 1; | ||
271 | } | ||
272 | else | ||
273 | return 0; | ||
274 | #endif | ||
275 | } | ||
276 | |||
277 | |||
278 | /* | ||
279 | ** Closes directory iterators | ||
280 | */ | ||
281 | static int dir_close (lua_State *L) { | ||
282 | #ifdef _WIN32 | ||
283 | dir_data *d = (dir_data *)lua_touserdata (L, 1); | ||
284 | if (d->hFile) { | ||
285 | _findclose (d->hFile); | ||
286 | } | ||
287 | #else | ||
288 | DIR *d = *(DIR **)lua_touserdata (L, 1); | ||
289 | if (d) | ||
290 | closedir (d); | ||
291 | #endif | ||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | |||
296 | /* | ||
297 | ** Factory of directory iterators | ||
298 | */ | ||
299 | static int dir_iter_factory (lua_State *L) { | ||
300 | const char *path = luaL_checkstring (L, 1); | ||
301 | #ifdef _WIN32 | ||
302 | dir_data *dir = (dir_data *) lua_newuserdata (L, sizeof(dir_data)); | ||
303 | dir->hFile = 0L; | ||
304 | if (strlen(path) > MAX_DIR_LENGTH) | ||
305 | luaL_error (L, "path too long: %s", path); | ||
306 | else | ||
307 | sprintf (dir->pattern, "%s/*", path); | ||
308 | luaL_getmetatable (L, DIR_METATABLE); | ||
309 | lua_setmetatable (L, -2); | ||
310 | #else | ||
311 | DIR **d = (DIR **) lua_newuserdata (L, sizeof(DIR *)); | ||
312 | luaL_getmetatable (L, DIR_METATABLE); | ||
313 | lua_setmetatable (L, -2); | ||
314 | *d = opendir (path); | ||
315 | if (*d == NULL) | ||
316 | luaL_error (L, "cannot open %s: %s", path, strerror (errno)); | ||
317 | #endif | ||
318 | lua_pushcclosure (L, dir_iter, 1); | ||
319 | return 1; | ||
320 | } | ||
321 | |||
322 | |||
323 | /* | ||
324 | ** Creates directory metatable. | ||
325 | */ | ||
326 | static int dir_create_meta (lua_State *L) { | ||
327 | luaL_newmetatable (L, DIR_METATABLE); | ||
328 | /* set its __gc field */ | ||
329 | lua_pushstring (L, "__gc"); | ||
330 | lua_pushcfunction (L, dir_close); | ||
331 | lua_settable (L, -3); | ||
332 | |||
333 | return 1; | ||
334 | } | ||
335 | |||
336 | |||
337 | static const struct luaL_reg fslib[] = { | ||
338 | {"chdir", change_dir}, | ||
339 | {"currentdir", get_dir}, | ||
340 | {"dir", dir_iter_factory}, | ||
341 | {"lock", file_lock}, | ||
342 | {"mkdir", make_dir}, | ||
343 | {"unlock", file_unlock}, | ||
344 | {NULL, NULL}, | ||
345 | }; | ||
346 | |||
347 | int luaopen_lfs (lua_State *L) { | ||
348 | dir_create_meta (L); | ||
349 | luaL_openlib (L, "lfs", fslib, 0); | ||
350 | return 1; | ||
351 | } | ||
diff --git a/src/lfs.h b/src/lfs.h new file mode 100644 index 0000000..67871f2 --- /dev/null +++ b/src/lfs.h | |||
@@ -0,0 +1,10 @@ | |||
1 | /* Define 'chdir' for systems that do not implement it */ | ||
2 | /* $Id: lfs.h,v 1.1 2004/07/29 14:26:33 tomas Exp $ */ | ||
3 | #ifdef NO_CHDIR | ||
4 | #define chdir(p) (-1) | ||
5 | #define chdir_error "Function 'chdir' not provided by system" | ||
6 | #else | ||
7 | #define chdir_error strerror(errno) | ||
8 | #endif | ||
9 | |||
10 | int luaopen_lfs (lua_State *L); | ||