~ubuntu-branches/ubuntu/precise/ipe/precise

« back to all changes in this revision

Viewing changes to src/ipe/lfs.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Steve M. Robbins
  • Date: 2009-12-11 21:22:35 UTC
  • mfrom: (4.1.6 sid)
  • Revision ID: james.westby@ubuntu.com-20091211212235-5iio4nzpra64snab
Tags: 7.0.10-1
* New upstream.  Closes: #551192.
  - New build-depends: libcairo2-dev, liblua5.1-0-dev, gsfonts
  - patches/config.diff: Remove.  Upstream build system replaced.
  - Runtime lib package changed to libipe7.0.10 from libipe1c2a
  - Devel package renamed to libipe-dev (from libipe1-dev)
  - Package ipe depends on lua5.1 due to ipe-update-master.

* rules: Re-write to use dh.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
    This file is part of the extensible drawing editor Ipe.
 
4
    Copyright (C) 1993-2009  Otfried Cheong
 
5
 
 
6
    Ipe is free software; you can redistribute it and/or modify it
 
7
    under the terms of the GNU General Public License as published by
 
8
    the Free Software Foundation; either version 3 of the License, or
 
9
    (at your option) any later version.
 
10
 
 
11
    As a special exception, you have permission to link Ipe with the
 
12
    CGAL library and distribute executables, as long as you follow the
 
13
    requirements of the Gnu General Public License in regard to all of
 
14
    the software in the executable aside from CGAL.
 
15
 
 
16
    Ipe is distributed in the hope that it will be useful, but WITHOUT
 
17
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
18
    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
 
19
    License for more details.
 
20
 
 
21
    You should have received a copy of the GNU General Public License
 
22
    along with Ipe; if not, you can find it at
 
23
    "http://www.gnu.org/copyleft/gpl.html", or write to the Free
 
24
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
25
 
 
26
*/
 
27
/*
 
28
** LuaFileSystem
 
29
** Copyright Kepler Project 2003 (http://www.keplerproject.org/luafilesystem)
 
30
**
 
31
** File system manipulation library.
 
32
** This library offers these functions:
 
33
**   lfs.attributes (filepath [, attributename])
 
34
**   lfs.chdir (path)
 
35
**   lfs.currentdir ()
 
36
**   lfs.dir (path)
 
37
**   lfs.lock (fh, mode)
 
38
**   lfs.mkdir (path)
 
39
**   lfs.rmdir (path)
 
40
**   lfs.setmode (filepath, mode)
 
41
**   lfs.symlinkattributes (filepath [, attributename]) -- thanks to Sam Roberts
 
42
**   lfs.touch (filepath [, atime [, mtime]])
 
43
**   lfs.unlock (fh)
 
44
**
 
45
** $Id: lfs.c,v 1.53 2008/05/07 19:06:37 carregal Exp $
 
46
*/
 
47
 
 
48
#define _LARGEFILE64_SOURCE
 
49
 
 
50
#include <errno.h>
 
51
#include <stdio.h>
 
52
#include <string.h>
 
53
#include <stdlib.h>
 
54
#include <time.h>
 
55
#include <sys/stat.h>
 
56
 
 
57
#ifdef _WIN32
 
58
#include <direct.h>
 
59
#include <io.h>
 
60
#include <sys/locking.h>
 
61
#include <sys/utime.h>
 
62
#include <fcntl.h>
 
63
#else
 
64
#include <unistd.h>
 
65
#include <dirent.h>
 
66
#include <fcntl.h>
 
67
#include <sys/types.h>
 
68
#include <utime.h>
 
69
#endif
 
70
 
 
71
extern "C" {
 
72
#include "lua.h"
 
73
#include "lauxlib.h"
 
74
#include "lualib.h"
 
75
#include "lfs.h"
 
76
}
 
77
 
 
78
/* Define 'strerror' for systems that do not implement it */
 
79
#ifdef NO_STRERROR
 
80
#define strerror(_)     "System unable to describe the error"
 
81
#endif
 
82
 
 
83
/* Define 'getcwd' for systems that do not implement it */
 
84
#ifdef NO_GETCWD
 
85
#define getcwd(p,s)     NULL
 
86
#define getcwd_error    "Function 'getcwd' not provided by system"
 
87
#else
 
88
#define getcwd_error    strerror(errno)
 
89
#endif
 
90
 
 
91
#define DIR_METATABLE "directory metatable"
 
92
#define MAX_DIR_LENGTH 1023
 
93
typedef struct dir_data {
 
94
        int  closed;
 
95
#ifdef _WIN32
 
96
        long hFile;
 
97
        char pattern[MAX_DIR_LENGTH+1];
 
98
#else
 
99
        DIR *dir;
 
100
#endif
 
101
} dir_data;
 
102
 
 
103
 
 
104
#ifdef _WIN32
 
105
#define lfs_setmode(L,file,m)   ((void)L, _setmode(_fileno(file), m))
 
106
#define STAT_STRUCT struct _stati64
 
107
#define STAT_FUNC _stati64
 
108
#else
 
109
#define _O_TEXT               0
 
110
#define _O_BINARY             0
 
111
#define lfs_setmode(L,file,m)   ((void)((void)file,m),  \
 
112
                 luaL_error(L, LUA_QL("setmode") " not supported on this platform"), -1)
 
113
#ifdef HAVE_STAT64
 
114
#define STAT_STRUCT struct stat64
 
115
#define STAT_FUNC stat64
 
116
#define LSTAT_FUNC lstat64
 
117
#else
 
118
#define STAT_STRUCT struct stat
 
119
#define STAT_FUNC stat
 
120
#define LSTAT_FUNC lstat
 
121
#endif
 
122
#endif
 
123
 
 
124
/*
 
125
** This function changes the working (current) directory
 
126
*/
 
127
static int change_dir (lua_State *L) {
 
128
        const char *path = luaL_checkstring(L, 1);
 
129
        if (chdir(path)) {
 
130
                lua_pushnil (L);
 
131
                lua_pushfstring (L,"Unable to change working directory to '%s'\n%s\n",
 
132
                                path, chdir_error);
 
133
                return 2;
 
134
        } else {
 
135
                lua_pushboolean (L, 1);
 
136
                return 1;
 
137
        }
 
138
}
 
139
 
 
140
/*
 
141
** This function returns the current directory
 
142
** If unable to get the current directory, it returns nil
 
143
**  and a string describing the error
 
144
*/
 
145
static int get_dir (lua_State *L) {
 
146
  char *path;
 
147
  if ((path = getcwd(NULL, 0)) == NULL) {
 
148
    lua_pushnil(L);
 
149
    lua_pushstring(L, getcwd_error);
 
150
    return 2;
 
151
  }
 
152
  else {
 
153
    lua_pushstring(L, path);
 
154
    free(path);
 
155
    return 1;
 
156
  }
 
157
}
 
158
 
 
159
/*
 
160
** Check if the given element on the stack is a file and returns it.
 
161
*/
 
162
static FILE *check_file (lua_State *L, int idx, const char *funcname) {
 
163
        FILE **fh = (FILE **)luaL_checkudata (L, idx, "FILE*");
 
164
        if (fh == NULL) {
 
165
                luaL_error (L, "%s: not a file", funcname);
 
166
                return 0;
 
167
        } else if (*fh == NULL) {
 
168
                luaL_error (L, "%s: closed file", funcname);
 
169
                return 0;
 
170
        } else
 
171
                return *fh;
 
172
}
 
173
 
 
174
 
 
175
/*
 
176
**
 
177
*/
 
178
static int _file_lock (lua_State *L, FILE *fh, const char *mode, const long start, long len, const char *funcname) {
 
179
        int code;
 
180
#ifdef _WIN32
 
181
        /* lkmode valid values are:
 
182
           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.
 
183
           LK_NBLCK   Locks the specified bytes. If the bytes cannot be locked, the constant returns an error.
 
184
           LK_NBRLCK  Same as _LK_NBLCK.
 
185
           LK_RLCK    Same as _LK_LOCK.
 
186
           LK_UNLCK   Unlocks the specified bytes, which must have been previously locked.
 
187
 
 
188
           Regions should be locked only briefly and should be unlocked before closing a file or exiting the program.
 
189
 
 
190
           http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__locking.asp
 
191
        */
 
192
        int lkmode;
 
193
        switch (*mode) {
 
194
                case 'r': lkmode = LK_NBLCK; break;
 
195
                case 'w': lkmode = LK_NBLCK; break;
 
196
                case 'u': lkmode = LK_UNLCK; break;
 
197
                default : return luaL_error (L, "%s: invalid mode", funcname);
 
198
        }
 
199
        if (!len) {
 
200
                fseek (fh, 0L, SEEK_END);
 
201
                len = ftell (fh);
 
202
        }
 
203
        fseek (fh, start, SEEK_SET);
 
204
        code = _locking (fileno(fh), lkmode, len);
 
205
#else
 
206
        struct flock f;
 
207
        switch (*mode) {
 
208
                case 'w': f.l_type = F_WRLCK; break;
 
209
                case 'r': f.l_type = F_RDLCK; break;
 
210
                case 'u': f.l_type = F_UNLCK; break;
 
211
                default : return luaL_error (L, "%s: invalid mode", funcname);
 
212
        }
 
213
        f.l_whence = SEEK_SET;
 
214
        f.l_start = (off_t)start;
 
215
        f.l_len = (off_t)len;
 
216
        code = fcntl (fileno(fh), F_SETLK, &f);
 
217
#endif
 
218
        return (code != -1);
 
219
}
 
220
 
 
221
#ifdef _WIN32
 
222
static int lfs_g_setmode (lua_State *L, FILE *f, int arg) {
 
223
  static const int mode[] = {_O_TEXT, _O_BINARY};
 
224
  static const char *const modenames[] = {"text", "binary", NULL};
 
225
  int op = luaL_checkoption(L, arg, NULL, modenames);
 
226
  int res = lfs_setmode(L, f, mode[op]);
 
227
  if (res != -1) {
 
228
    int i;
 
229
    lua_pushboolean(L, 1);
 
230
    for (i = 0; modenames[i] != NULL; i++) {
 
231
      if (mode[i] == res) {
 
232
        lua_pushstring(L, modenames[i]);
 
233
        goto exit;
 
234
      }
 
235
    }
 
236
    lua_pushnil(L);
 
237
  exit:
 
238
    return 2;
 
239
  } else {
 
240
    int en = errno;
 
241
    lua_pushnil(L);
 
242
    lua_pushfstring(L, "%s", strerror(en));
 
243
    lua_pushinteger(L, en);
 
244
    return 3;
 
245
  }
 
246
}
 
247
#else
 
248
static int lfs_g_setmode (lua_State *L, FILE *f, int arg) {
 
249
  lua_pushboolean(L, 0);
 
250
  lua_pushliteral(L, "setmode not supported on this platform");
 
251
  return 2;
 
252
}
 
253
#endif
 
254
 
 
255
static int lfs_f_setmode(lua_State *L) {
 
256
  return lfs_g_setmode(L, check_file(L, 1, "setmode"), 2);
 
257
}
 
258
 
 
259
/*
 
260
** Locks a file.
 
261
** @param #1 File handle.
 
262
** @param #2 String with lock mode ('w'rite, 'r'ead).
 
263
** @param #3 Number with start position (optional).
 
264
** @param #4 Number with length (optional).
 
265
*/
 
266
static int file_lock (lua_State *L) {
 
267
        FILE *fh = check_file (L, 1, "lock");
 
268
        const char *mode = luaL_checkstring (L, 2);
 
269
        const long start = luaL_optlong (L, 3, 0);
 
270
        long len = luaL_optlong (L, 4, 0);
 
271
        if (_file_lock (L, fh, mode, start, len, "lock")) {
 
272
                lua_pushboolean (L, 1);
 
273
                return 1;
 
274
        } else {
 
275
                lua_pushnil (L);
 
276
                lua_pushfstring (L, "%s", strerror(errno));
 
277
                return 2;
 
278
        }
 
279
}
 
280
 
 
281
 
 
282
/*
 
283
** Unlocks a file.
 
284
** @param #1 File handle.
 
285
** @param #2 Number with start position (optional).
 
286
** @param #3 Number with length (optional).
 
287
*/
 
288
static int file_unlock (lua_State *L) {
 
289
        FILE *fh = check_file (L, 1, "unlock");
 
290
        const long start = luaL_optlong (L, 2, 0);
 
291
        long len = luaL_optlong (L, 3, 0);
 
292
        if (_file_lock (L, fh, "u", start, len, "unlock")) {
 
293
                lua_pushboolean (L, 1);
 
294
                return 1;
 
295
        } else {
 
296
                lua_pushnil (L);
 
297
                lua_pushfstring (L, "%s", strerror(errno));
 
298
                return 2;
 
299
        }
 
300
}
 
301
 
 
302
 
 
303
static int make_dir (lua_State *L) {
 
304
        const char *path = luaL_checkstring (L, 1);
 
305
        int fail;
 
306
#ifdef _WIN32
 
307
        int oldmask = umask (0);
 
308
        fail = _mkdir (path);
 
309
#else
 
310
        mode_t oldmask = umask( (mode_t)0 );
 
311
        fail =  mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |
 
312
                             S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH );
 
313
#endif
 
314
        if (fail) {
 
315
                lua_pushnil (L);
 
316
        lua_pushfstring (L, "%s", strerror(errno));
 
317
                return 2;
 
318
        }
 
319
        umask (oldmask);
 
320
        lua_pushboolean (L, 1);
 
321
        return 1;
 
322
}
 
323
 
 
324
/*
 
325
** Removes a directory.
 
326
** @param #1 Directory path.
 
327
*/
 
328
static int remove_dir (lua_State *L) {
 
329
        const char *path = luaL_checkstring (L, 1);
 
330
        int fail;
 
331
 
 
332
        fail = rmdir (path);
 
333
 
 
334
        if (fail) {
 
335
                lua_pushnil (L);
 
336
                lua_pushfstring (L, "%s", strerror(errno));
 
337
                return 2;
 
338
        }
 
339
        lua_pushboolean (L, 1);
 
340
        return 1;
 
341
}
 
342
 
 
343
/*
 
344
** Directory iterator
 
345
*/
 
346
static int dir_iter (lua_State *L) {
 
347
#ifdef _WIN32
 
348
        struct _finddata_t c_file;
 
349
#else
 
350
        struct dirent *entry;
 
351
#endif
 
352
        dir_data *d = (dir_data *)lua_touserdata (L, lua_upvalueindex (1));
 
353
        luaL_argcheck (L, !d->closed, 1, "closed directory");
 
354
#ifdef _WIN32
 
355
        if (d->hFile == 0L) { /* first entry */
 
356
                if ((d->hFile = _findfirst (d->pattern, &c_file)) == -1L) {
 
357
                        lua_pushnil (L);
 
358
                        lua_pushstring (L, strerror (errno));
 
359
                        return 2;
 
360
                } else {
 
361
                        lua_pushstring (L, c_file.name);
 
362
                        return 1;
 
363
                }
 
364
        } else { /* next entry */
 
365
                if (_findnext (d->hFile, &c_file) == -1L) {
 
366
                        /* no more entries => close directory */
 
367
                        _findclose (d->hFile);
 
368
                        d->closed = 1;
 
369
                        return 0;
 
370
                } else {
 
371
                        lua_pushstring (L, c_file.name);
 
372
                        return 1;
 
373
                }
 
374
        }
 
375
#else
 
376
        if ((entry = readdir (d->dir)) != NULL) {
 
377
                lua_pushstring (L, entry->d_name);
 
378
                return 1;
 
379
        } else {
 
380
                /* no more entries => close directory */
 
381
                closedir (d->dir);
 
382
                d->closed = 1;
 
383
                return 0;
 
384
        }
 
385
#endif
 
386
}
 
387
 
 
388
 
 
389
/*
 
390
** Closes directory iterators
 
391
*/
 
392
static int dir_close (lua_State *L) {
 
393
        dir_data *d = (dir_data *)lua_touserdata (L, 1);
 
394
#ifdef _WIN32
 
395
        if (!d->closed && d->hFile) {
 
396
                _findclose (d->hFile);
 
397
                d->closed = 1;
 
398
        }
 
399
#else
 
400
        if (!d->closed && d->dir) {
 
401
                closedir (d->dir);
 
402
                d->closed = 1;
 
403
        }
 
404
#endif
 
405
        return 0;
 
406
}
 
407
 
 
408
 
 
409
/*
 
410
** Factory of directory iterators
 
411
*/
 
412
static int dir_iter_factory (lua_State *L) {
 
413
        const char *path = luaL_checkstring (L, 1);
 
414
        dir_data *d = (dir_data *) lua_newuserdata (L, sizeof(dir_data));
 
415
        d->closed = 0;
 
416
#ifdef _WIN32
 
417
        d->hFile = 0L;
 
418
        luaL_getmetatable (L, DIR_METATABLE);
 
419
        lua_setmetatable (L, -2);
 
420
        if (strlen(path) > MAX_DIR_LENGTH)
 
421
                luaL_error (L, "path too long: %s", path);
 
422
        else
 
423
                sprintf (d->pattern, "%s/*", path);
 
424
#else
 
425
        luaL_getmetatable (L, DIR_METATABLE);
 
426
        lua_setmetatable (L, -2);
 
427
        d->dir = opendir (path);
 
428
        if (d->dir == NULL)
 
429
                luaL_error (L, "cannot open %s: %s", path, strerror (errno));
 
430
#endif
 
431
        lua_pushcclosure (L, dir_iter, 1);
 
432
        return 1;
 
433
}
 
434
 
 
435
 
 
436
/*
 
437
** Creates directory metatable.
 
438
*/
 
439
static int dir_create_meta (lua_State *L) {
 
440
        luaL_newmetatable (L, DIR_METATABLE);
 
441
        /* set its __gc field */
 
442
        lua_pushstring (L, "__gc");
 
443
        lua_pushcfunction (L, dir_close);
 
444
        lua_settable (L, -3);
 
445
 
 
446
        return 1;
 
447
}
 
448
 
 
449
 
 
450
#ifdef _WIN32
 
451
 #ifndef S_ISDIR
 
452
   #define S_ISDIR(mode)  (mode&_S_IFDIR)
 
453
 #endif
 
454
 #ifndef S_ISREG
 
455
   #define S_ISREG(mode)  (mode&_S_IFREG)
 
456
 #endif
 
457
 #ifndef S_ISLNK
 
458
   #define S_ISLNK(mode)  (0)
 
459
 #endif
 
460
 #ifndef S_ISSOCK
 
461
   #define S_ISSOCK(mode)  (0)
 
462
 #endif
 
463
 #ifndef S_ISFIFO
 
464
   #define S_ISFIFO(mode)  (0)
 
465
 #endif
 
466
 #ifndef S_ISCHR
 
467
   #define S_ISCHR(mode)  (mode&_S_IFCHR)
 
468
 #endif
 
469
 #ifndef S_ISBLK
 
470
   #define S_ISBLK(mode)  (0)
 
471
 #endif
 
472
#endif
 
473
/*
 
474
** Convert the inode protection mode to a string.
 
475
*/
 
476
#ifdef _WIN32
 
477
static const char *mode2string (unsigned short mode) {
 
478
#else
 
479
static const char *mode2string (mode_t mode) {
 
480
#endif
 
481
  if ( S_ISREG(mode) )
 
482
    return "file";
 
483
  else if ( S_ISDIR(mode) )
 
484
    return "directory";
 
485
  else if ( S_ISLNK(mode) )
 
486
        return "link";
 
487
  else if ( S_ISSOCK(mode) )
 
488
    return "socket";
 
489
  else if ( S_ISFIFO(mode) )
 
490
        return "named pipe";
 
491
  else if ( S_ISCHR(mode) )
 
492
        return "char device";
 
493
  else if ( S_ISBLK(mode) )
 
494
        return "block device";
 
495
  else
 
496
        return "other";
 
497
}
 
498
 
 
499
 
 
500
/*
 
501
** Set access time and modification values for file
 
502
*/
 
503
static int file_utime (lua_State *L) {
 
504
        const char *file = luaL_checkstring (L, 1);
 
505
        struct utimbuf utb, *buf;
 
506
 
 
507
        if (lua_gettop (L) == 1) /* set to current date/time */
 
508
                buf = NULL;
 
509
        else {
 
510
                utb.actime = (time_t)luaL_optnumber (L, 2, 0);
 
511
                utb.modtime = (time_t)luaL_optnumber (L, 3, utb.actime);
 
512
                buf = &utb;
 
513
        }
 
514
        if (utime (file, buf)) {
 
515
                lua_pushnil (L);
 
516
                lua_pushfstring (L, "%s", strerror (errno));
 
517
                return 2;
 
518
        }
 
519
        lua_pushboolean (L, 1);
 
520
        return 1;
 
521
}
 
522
 
 
523
 
 
524
/* inode protection mode */
 
525
static void push_st_mode (lua_State *L, STAT_STRUCT *info) {
 
526
        lua_pushstring (L, mode2string (info->st_mode));
 
527
}
 
528
/* device inode resides on */
 
529
static void push_st_dev (lua_State *L, STAT_STRUCT *info) {
 
530
        lua_pushnumber (L, (lua_Number)info->st_dev);
 
531
}
 
532
/* inode's number */
 
533
static void push_st_ino (lua_State *L, STAT_STRUCT *info) {
 
534
        lua_pushnumber (L, (lua_Number)info->st_ino);
 
535
}
 
536
/* number of hard links to the file */
 
537
static void push_st_nlink (lua_State *L, STAT_STRUCT *info) {
 
538
        lua_pushnumber (L, (lua_Number)info->st_nlink);
 
539
}
 
540
/* user-id of owner */
 
541
static void push_st_uid (lua_State *L, STAT_STRUCT *info) {
 
542
        lua_pushnumber (L, (lua_Number)info->st_uid);
 
543
}
 
544
/* group-id of owner */
 
545
static void push_st_gid (lua_State *L, STAT_STRUCT *info) {
 
546
        lua_pushnumber (L, (lua_Number)info->st_gid);
 
547
}
 
548
/* device type, for special file inode */
 
549
static void push_st_rdev (lua_State *L, STAT_STRUCT *info) {
 
550
        lua_pushnumber (L, (lua_Number)info->st_rdev);
 
551
}
 
552
/* time of last access */
 
553
static void push_st_atime (lua_State *L, STAT_STRUCT *info) {
 
554
        lua_pushnumber (L, info->st_atime);
 
555
}
 
556
/* time of last data modification */
 
557
static void push_st_mtime (lua_State *L, STAT_STRUCT *info) {
 
558
        lua_pushnumber (L, info->st_mtime);
 
559
}
 
560
/* time of last file status change */
 
561
static void push_st_ctime (lua_State *L, STAT_STRUCT *info) {
 
562
        lua_pushnumber (L, info->st_ctime);
 
563
}
 
564
/* file size, in bytes */
 
565
static void push_st_size (lua_State *L, STAT_STRUCT *info) {
 
566
        lua_pushnumber (L, (lua_Number)info->st_size);
 
567
}
 
568
#ifndef _WIN32
 
569
/* blocks allocated for file */
 
570
static void push_st_blocks (lua_State *L, STAT_STRUCT *info) {
 
571
        lua_pushnumber (L, (lua_Number)info->st_blocks);
 
572
}
 
573
/* optimal file system I/O blocksize */
 
574
static void push_st_blksize (lua_State *L, STAT_STRUCT *info) {
 
575
        lua_pushnumber (L, (lua_Number)info->st_blksize);
 
576
}
 
577
#endif
 
578
static void push_invalid (lua_State *L, STAT_STRUCT *info) {
 
579
  luaL_error(L, "invalid attribute name");
 
580
#ifndef _WIN32
 
581
  info->st_blksize = 0; /* never reached */
 
582
#endif
 
583
}
 
584
 
 
585
typedef void (*_push_function) (lua_State *L, STAT_STRUCT *info);
 
586
 
 
587
struct _stat_members {
 
588
        const char *name;
 
589
        _push_function push;
 
590
};
 
591
 
 
592
struct _stat_members members[] = {
 
593
        { "mode",         push_st_mode },
 
594
        { "dev",          push_st_dev },
 
595
        { "ino",          push_st_ino },
 
596
        { "nlink",        push_st_nlink },
 
597
        { "uid",          push_st_uid },
 
598
        { "gid",          push_st_gid },
 
599
        { "rdev",         push_st_rdev },
 
600
        { "access",       push_st_atime },
 
601
        { "modification", push_st_mtime },
 
602
        { "change",       push_st_ctime },
 
603
        { "size",         push_st_size },
 
604
#ifndef _WIN32
 
605
        { "blocks",       push_st_blocks },
 
606
        { "blksize",      push_st_blksize },
 
607
#endif
 
608
        { NULL, push_invalid }
 
609
};
 
610
 
 
611
/*
 
612
** Get file or symbolic link information
 
613
*/
 
614
static int _file_info_ (lua_State *L, int (*st)(const char*, STAT_STRUCT*)) {
 
615
        int i;
 
616
        STAT_STRUCT info;
 
617
        const char *file = luaL_checkstring (L, 1);
 
618
 
 
619
        if (st(file, &info)) {
 
620
                lua_pushnil (L);
 
621
                lua_pushfstring (L, "cannot obtain information from file `%s'", file);
 
622
                return 2;
 
623
        }
 
624
        if (lua_isstring (L, 2)) {
 
625
                int v;
 
626
                const char *member = lua_tostring (L, 2);
 
627
                if (strcmp (member, "mode") == 0) v = 0;
 
628
#ifndef _WIN32
 
629
                else if (strcmp (member, "blocks")  == 0) v = 11;
 
630
                else if (strcmp (member, "blksize") == 0) v = 12;
 
631
#endif
 
632
                else /* look for member */
 
633
                        for (v = 1; members[v].name; v++)
 
634
                                if (*members[v].name == *member)
 
635
                                        break;
 
636
                /* push member value and return */
 
637
                members[v].push (L, &info);
 
638
                return 1;
 
639
        } else if (!lua_istable (L, 2))
 
640
                /* creates a table if none is given */
 
641
                lua_newtable (L);
 
642
        /* stores all members in table on top of the stack */
 
643
        for (i = 0; members[i].name; i++) {
 
644
                lua_pushstring (L, members[i].name);
 
645
                members[i].push (L, &info);
 
646
                lua_rawset (L, -3);
 
647
        }
 
648
        return 1;
 
649
}
 
650
 
 
651
 
 
652
/*
 
653
** Get file information using stat.
 
654
*/
 
655
static int file_info (lua_State *L) {
 
656
        return _file_info_ (L, STAT_FUNC);
 
657
}
 
658
 
 
659
 
 
660
/*
 
661
** Get symbolic link information using lstat.
 
662
*/
 
663
#ifndef _WIN32
 
664
static int link_info (lua_State *L) {
 
665
        return _file_info_ (L, LSTAT_FUNC);
 
666
}
 
667
#else
 
668
static int link_info (lua_State *L) {
 
669
  lua_pushboolean(L, 0);
 
670
  lua_pushliteral(L, "symlinkattributes not supported on this platform");
 
671
  return 2;
 
672
}
 
673
#endif
 
674
 
 
675
 
 
676
/*
 
677
** Assumes the table is on top of the stack.
 
678
*/
 
679
static void set_info (lua_State *L) {
 
680
        lua_pushliteral (L, "_COPYRIGHT");
 
681
        lua_pushliteral (L, "Copyright (C) 2003 Kepler Project");
 
682
        lua_settable (L, -3);
 
683
        lua_pushliteral (L, "_DESCRIPTION");
 
684
        lua_pushliteral (L, "LuaFileSystem is a Lua library developed to complement the set of functions related to file systems offered by the standard Lua distribution");
 
685
        lua_settable (L, -3);
 
686
        lua_pushliteral (L, "_VERSION");
 
687
        lua_pushliteral (L, "LuaFileSystem 1.4.1");
 
688
        lua_settable (L, -3);
 
689
}
 
690
 
 
691
 
 
692
static const struct luaL_reg fslib[] = {
 
693
        {"attributes", file_info},
 
694
        {"chdir", change_dir},
 
695
        {"currentdir", get_dir},
 
696
        {"dir", dir_iter_factory},
 
697
        {"lock", file_lock},
 
698
        {"mkdir", make_dir},
 
699
        {"rmdir", remove_dir},
 
700
        {"symlinkattributes", link_info},
 
701
        {"setmode", lfs_f_setmode},
 
702
        {"touch", file_utime},
 
703
        {"unlock", file_unlock},
 
704
        {NULL, NULL},
 
705
};
 
706
 
 
707
extern "C" int luaopen_lfs (lua_State *L) {
 
708
        dir_create_meta (L);
 
709
        luaL_register (L, "lfs", fslib);
 
710
        set_info (L);
 
711
        return 1;
 
712
}