123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143 |
- /* -*- C -*- */
- #include "paths.h"
- /* ------------------------------------------------------ */
- /* Utils to manipulate strings */
- #define SBINCREMENT 256
- typedef struct {
- char *buffer;
- int maxlen;
- int len;
- } SB;
- static void
- sbinit(SB *sb)
- {
- sb->buffer = (char*)malloc(SBINCREMENT);
- sb->maxlen = SBINCREMENT;
- sb->len = 0;
- }
- static char *
- sbfree(SB *sb)
- {
- if (sb->buffer)
- free(sb->buffer);
- sb->buffer = 0;
- return 0;
- }
- static void
- sbgrow(SB *sb, int n)
- {
- if (sb->buffer && sb->len + n > sb->maxlen)
- {
- int nlen = sb->maxlen;
- while (sb->len + n > nlen)
- nlen += SBINCREMENT;
- sb->buffer = (char*)realloc(sb->buffer, nlen);
- sb->maxlen = nlen;
- }
- }
- static void
- sbadd1(SB *sb, char c)
- {
- sbgrow(sb, 1);
- if (sb->buffer)
- sb->buffer[sb->len++] = c;
- }
- static void
- sbaddn(SB *sb, const char *s, int n)
- {
- sbgrow(sb, n);
- if (sb->buffer && s && n)
- memcpy(sb->buffer + sb->len, s, n);
- else if (sb->buffer && n)
- sbfree(sb);
- sb->len += n;
- }
- static void
- sbaddsf(SB *sb, char *s)
- {
- if (s)
- sbaddn(sb, s, strlen(s));
- else
- sbfree(sb);
- if (s)
- free((void*)s);
- }
- static void
- sbslash(SB *sb)
- {
- int i;
- if (sb->buffer && sb->len)
- for(i=0; i<sb->len; i++)
- if (sb->buffer[i]=='\\')
- sb->buffer[i]='/';
- }
- static int
- sbpush(lua_State *L, SB *sb)
- {
- sbslash(sb);
- lua_pushlstring(L, sb->buffer, sb->len);
- sbfree(sb);
- return 1;
- }
- static int
- sbsetpush(lua_State *L, SB *sb, const char *s)
- {
- sbfree(sb);
- lua_pushstring(L, s);
- return 1;
- }
- /* ------------------------------------------------------ */
- /* filep, dirp, basename, dirname */
- static int
- filep(lua_State *L, int i)
- {
- const char *s = luaL_checkstring(L, i);
- #ifdef _WIN32
- struct _stat buf;
- if (_stat(s,&buf) < 0)
- return 0;
- if (buf.st_mode & S_IFDIR)
- return 0;
- #else
- struct stat buf;
- if (stat(s,&buf) < 0)
- return 0;
- if (buf.st_mode & S_IFDIR)
- return 0;
- #endif
- return 1;
- }
- static int
- dirp(lua_State *L, int i)
- {
- const char *s = luaL_checkstring(L, i);
- #ifdef _WIN32
- char buffer[8];
- struct _stat buf;
- const char *last;
- if ((s[0]=='/' || s[0]=='\\') &&
- (s[1]=='/' || s[1]=='\\') && !s[2])
- return 1;
- if (s[0] && isalpha((unsigned char)(s[0])) && s[1] == ':' && s[2] == 0)
- { buffer[0]=s[0]; buffer[1]=':'; buffer[2]='.'; buffer[3]=0; s = buffer; }
- if (_stat(s, &buf) >= 0)
- if (buf.st_mode & S_IFDIR)
- return 1;
- #else
- struct stat buf;
- if (stat(s,&buf)==0)
- if (buf.st_mode & S_IFDIR)
- return 1;
- #endif
- return 0;
- }
- static int
- lua_filep(lua_State *L)
- {
- lua_pushboolean(L, filep(L, 1));
- return 1;
- }
- static int
- lua_dirp(lua_State *L)
- {
- lua_pushboolean(L, dirp(L, 1));
- return 1;
- }
- static int
- lua_basename(lua_State *L)
- {
- const char *fname = luaL_checkstring(L, 1);
- const char *suffix = luaL_optstring(L, 2, 0);
- #ifdef _WIN32
- int sl;
- const char *p, *s;
- SB sb;
- sbinit(&sb);
- /* Special cases */
- if (fname[0] && fname[1]==':') {
- sbaddn(&sb, fname, 2);
- fname += 2;
- if (fname[0]=='/' || fname[0]=='\\')
- sbadd1(&sb, '/');
- while (fname[0]=='/' || fname[0]=='\\')
- fname += 1;
- if (fname[0]==0)
- return sbpush(L, &sb);
- sb.len = 0;
- }
- /* Position p after last nontrivial slash */
- s = p = fname;
- while (*s) {
- if ((s[0]=='\\' || s[0]=='/') &&
- (s[1] && s[1]!='/' && s[1]!='\\' ) )
- p = s + 1;
- s++;
- }
- /* Copy into buffer */
- while (*p && *p!='/' && *p!='\\')
- sbadd1(&sb, *p++);
- /* Process suffix */
- if (suffix==0 || suffix[0]==0)
- return sbpush(L, &sb);
- if (suffix[0]=='.')
- suffix += 1;
- if (suffix[0]==0)
- return sbpush(L, &sb);
- sl = strlen(suffix);
- if (sb.len > sl) {
- s = sb.buffer + sb.len - (sl + 1);
- if (s[0]=='.' && _strnicmp(s+1,suffix, sl)==0)
- sb.len = s - sb.buffer;
- }
- return sbpush(L, &sb);
-
- #else
- int sl;
- const char *s, *p;
- SB sb;
- sbinit(&sb);
- /* Position p after last nontrivial slash */
- s = p = fname;
- while (*s) {
- if (s[0]=='/' && s[1] && s[1]!='/')
- p = s + 1;
- s++;
- }
- /* Copy into buffer */
- while (*p && *p!='/')
- sbadd1(&sb, *p++);
- /* Process suffix */
- if (suffix==0 || suffix[0]==0)
- return sbpush(L, &sb);
- if (suffix[0]=='.')
- suffix += 1;
- if (suffix[0]==0)
- return sbpush(L, &sb);
- sl = strlen(suffix);
- if (sb.len > sl) {
- s = sb.buffer + sb.len - (sl + 1);
- if (s[0]=='.' && strncmp(s+1,suffix, sl)==0)
- sb.len = s - sb.buffer;
- }
- return sbpush(L, &sb);
- #endif
- }
- static int
- lua_dirname(lua_State *L)
- {
- const char *fname = luaL_checkstring(L, 1);
- #ifdef _WIN32
- const char *s;
- const char *p;
- SB sb;
- sbinit(&sb);
- /* Handle leading drive specifier */
- if (isalpha((unsigned char)fname[0]) && fname[1]==':') {
- sbadd1(&sb, *fname++);
- sbadd1(&sb, *fname++);
- }
- /* Search last non terminal / or \ */
- p = 0;
- s = fname;
- while (*s) {
- if ((s[0]=='\\' || s[0]=='/') &&
- (s[1] && s[1]!='/' && s[1]!='\\') )
- p = s;
- s++;
- }
- /* Cannot find non terminal / or \ */
- if (p == 0) {
- if (sb.len > 0) {
- if (fname[0]==0 || fname[0]=='/' || fname[0]=='\\')
- sbadd1(&sb, '/');
- return sbpush(L, &sb);
- } else {
- if (fname[0]=='/' || fname[0]=='\\')
- return sbsetpush(L, &sb, "//");
- else
- return sbsetpush(L, &sb, ".");
- }
- }
- /* Single leading slash */
- if (p == fname) {
- sbadd1(&sb, '/');
- return sbpush(L, &sb);
- }
- /* Backtrack all slashes */
- while (p>fname && (p[-1]=='/' || p[-1]=='\\'))
- p--;
- /* Multiple leading slashes */
- if (p == fname)
- return sbsetpush(L, &sb, "//");
- /* Regular case */
- s = fname;
- do {
- sbadd1(&sb, *s++);
- } while (s<p);
- return sbpush(L, &sb);
- #else
- const char *s = fname;
- const char *p = 0;
- SB sb;
- sbinit(&sb);
- while (*s) {
- if (s[0]=='/' && s[1] && s[1]!='/')
- p = s;
- s++;
- }
- if (!p) {
- if (fname[0]=='/')
- return sbsetpush(L, &sb, fname);
- else
- return sbsetpush(L, &sb, ".");
- }
- s = fname;
- do {
- sbadd1(&sb, *s++);
- } while (s<p);
- return sbpush(L, &sb);
- #endif
- }
- static int
- lua_extname(lua_State *L)
- {
- const char *fname = luaL_checkstring(L, 1);
- const char *p;
- p = fname + strlen(fname) - 1;
- while (p >= fname) {
- if (*p == '.') {
- lua_pushstring(L, p + 1);
- return 1;
- }
- p--;
- }
- return 0;
- }
- /* ------------------------------------------------------ */
- /* cwd and concat */
- static int
- lua_cwd(lua_State *L)
- {
- #ifdef _WIN32
- char drv[2];
- int l;
- SB sb;
- sbinit(&sb);
- drv[0] = '.'; drv[1] = 0;
- l = GetFullPathNameA(drv, sb.maxlen, sb.buffer, 0);
- if (l > sb.maxlen) {
- sbgrow(&sb, l+1);
- l = GetFullPathNameA(drv, sb.maxlen, sb.buffer, 0);
- }
- if (l <= 0)
- return sbsetpush(L, &sb, ".");
- sb.len += l;
- return sbpush(L, &sb);
- #elif HAVE_GETCWD
-
- const char *s;
- SB sb;
- sbinit(&sb);
- s = getcwd(sb.buffer, sb.maxlen);
- while (!s && errno==ERANGE)
- {
- sbgrow(&sb, sb.maxlen + SBINCREMENT);
- s = getcwd(sb.buffer, sb.maxlen);
- }
- if (! s)
- return sbsetpush(L, &sb, ".");
- sb.len += strlen(s);
- return sbpush(L, &sb);
- #else
-
- const char *s;
- SB sb;
- sbinit(&sb);
- sbgrow(&sb, PATH_MAX);
- s = getwd(sb.buffer);
- if (! s)
- return sbsetpush(L, &sb, ".");
- sb.len += strlen(s);
- return sbpush(L, &sb);
- #endif
- }
- static int
- concat_fname(lua_State *L, const char *fname)
- {
- const char *from = lua_tostring(L, -1);
- #ifdef _WIN32
- const char *s;
- SB sb;
- sbinit(&sb);
- sbaddn(&sb, from, strlen(from));
- if (fname==0)
- return sbpush(L, &sb);
- /* Handle absolute part of fname */
- if (fname[0]=='/' || fname[0]=='\\') {
- if (fname[1]=='/' || fname[1]=='\\') {
- sb.len = 0; /* Case //abcd */
- sbaddn(&sb, "//", 2);
- } else {
- char drive;
- if (sb.len >= 2 && sb.buffer[1]==':' /* Case "/abcd" */
- && isalpha((unsigned char)(sb.buffer[0])) )
- drive = sb.buffer[0];
- else
- drive = _getdrive() + 'A' - 1;
- sb.len = 0;
- sbadd1(&sb, drive);
- sbaddn(&sb, ":/", 2);
- }
- } else if (fname[0] && /* Case "x:abcd" */
- isalpha((unsigned char)(fname[0])) && fname[1]==':') {
- if (fname[2]!='/' && fname[2]!='\\') {
- if (sb.len < 2 || sb.buffer[1]!=':'
- || !isalpha((unsigned char)(sb.buffer[0]))
- || (toupper((unsigned char)sb.buffer[0]) !=
- toupper((unsigned char)fname[0]) ) )
- {
- int l;
- char drv[4];
- sb.len = 0;
- drv[0]=fname[0]; drv[1]=':'; drv[2]='.'; drv[3]=0;
- l = GetFullPathNameA(drv, sb.maxlen, sb.buffer, 0);
- if (l > sb.maxlen) {
- sbgrow(&sb, l+1);
- l = GetFullPathNameA(drv, sb.maxlen, sb.buffer, 0);
- }
- if (l <= 0)
- sbaddn(&sb, drv, 3);
- else
- sb.len += l;
- }
- fname += 2;
- } else {
- sb.len = 0; /* Case "x:/abcd" */
- sbadd1(&sb, toupper((unsigned char)fname[0]));
- sbaddn(&sb, ":/", 2);
- fname += 2;
- while (*fname == '/' || *fname == '\\')
- fname += 1;
- }
- }
- /* Process path components */
- for (;;)
- {
- while (*fname=='/' || *fname=='\\')
- fname ++;
- if (*fname == 0)
- return sbpush(L, &sb);
- if (fname[0]=='.') {
- if (fname[1]=='/' || fname[1]=='\\' || fname[1]==0) {
- fname += 1;
- continue;
- }
- if (fname[1]=='.')
- if (fname[2]=='/' || fname[2]=='\\' || fname[2]==0) {
- size_t l;
- fname += 2;
- lua_pushcfunction(L, lua_dirname);
- sbpush(L, &sb);
- lua_call(L, 1, 1);
- s = lua_tolstring(L, -1, &l);
- sbinit(&sb);
- sbaddn(&sb, s, l);
- lua_pop(L, 1);
- continue;
- }
- }
- if (sb.len==0 ||
- (sb.buffer[sb.len-1]!='/' && sb.buffer[sb.len-1]!='\\') )
- sbadd1(&sb, '/');
- while (*fname && *fname!='/' && *fname!='\\')
- sbadd1(&sb, *fname++);
- }
-
- #else
- SB sb;
- sbinit(&sb);
- if (fname && fname[0]=='/')
- sbadd1(&sb, '/');
- else
- sbaddn(&sb, from, strlen(from));
- for (;;) {
- while (fname && fname[0]=='/')
- fname++;
- if (!fname || !fname[0]) {
- sbadd1(&sb, '/');
- while (sb.len > 1 && sb.buffer[sb.len-1]=='/')
- sb.len --;
- return sbpush(L, &sb);
- }
- if (fname[0]=='.') {
- if (fname[1]=='/' || fname[1]==0) {
- fname +=1;
- continue;
- }
- if (fname[1]=='.')
- if (fname[2]=='/' || fname[2]==0) {
- fname +=2;
- while (sb.len > 0 && sb.buffer[sb.len-1]=='/')
- sb.len --;
- while (sb.len > 0 && sb.buffer[sb.len-1]!='/')
- sb.len --;
- continue;
- }
- }
- if (sb.len == 0 || sb.buffer[sb.len-1] != '/')
- sbadd1(&sb, '/');
- while (*fname!=0 && *fname!='/')
- sbadd1(&sb, *fname++);
- }
-
-
- #endif
- }
- static int
- lua_concatfname(lua_State *L)
- {
- int i;
- int narg = lua_gettop(L);
- lua_cwd(L);
- for (i=1; i<=narg; i++)
- {
- concat_fname(L, luaL_checkstring(L, i));
- lua_remove(L, -2);
- }
- return 1;
- }
- /* ------------------------------------------------------ */
- /* execdir */
- static int
- lua_execdir(lua_State *L)
- {
- const char *s = 0;
- #if HAVE_LUA_EXECUTABLE_DIR
- s = lua_executable_dir(0);
- #endif
- if (s && s[0])
- lua_pushstring(L, s);
- else
- lua_pushnil(L);
- return 1;
- }
- /* ------------------------------------------------------ */
- /* file lists */
- static int
- lua_dir(lua_State *L)
- {
- int k = 0;
- const char *s = luaL_checkstring(L, 1);
- #ifdef _WIN32
- SB sb;
- struct _finddata_t info;
- intptr_t hfind;
- /* special cases */
- lua_createtable(L, 0, 0);
- if ((s[0]=='/' || s[0]=='\\') &&
- (s[1]=='/' || s[1]=='\\') && !s[2])
- {
- int drive;
- hfind = GetLogicalDrives();
- for (drive='A'; drive<='Z'; drive++)
- if (hfind & ((intptr_t)1<<(drive-'A'))) {
- lua_pushfstring(L, "%c:/", drive);
- lua_rawseti(L, -2, ++k);
- }
- }
- else if (dirp(L, 1)) {
- lua_pushliteral(L, "..");
- lua_rawseti(L, -2, ++k);
- } else {
- lua_pushnil(L);
- return 1;
- }
- /* files */
- sbinit(&sb);
- sbaddn(&sb, s, strlen(s));
- if (sb.len>0 && sb.buffer[sb.len-1]!='/' && sb.buffer[sb.len-1]!='\\')
- sbadd1(&sb, '/');
- sbaddn(&sb, "*.*", 3);
- sbadd1(&sb, 0);
- hfind = _findfirst(sb.buffer, &info);
- if (hfind != -1) {
- do {
- if (strcmp(".",info.name) && strcmp("..",info.name)) {
- lua_pushstring(L, info.name);
- lua_rawseti(L, -2, ++k);
- }
- } while ( _findnext(hfind, &info) != -1 );
- _findclose(hfind);
- }
- sbfree(&sb);
- #else
- DIR *dirp;
- struct dirent *d;
- dirp = opendir(s);
- if (dirp) {
- lua_createtable(L, 0, 0);
- while ((d = readdir(dirp))) {
- int n = NAMLEN(d);
- lua_pushlstring(L, d->d_name, n);
- lua_rawseti(L, -2, ++k);
- }
- closedir(dirp);
- } else
- lua_pushnil(L);
- #endif
-
- return 1;
- }
- /* ------------------------------------------------------ */
- /* tmpname */
- static const char *tmpnames_key = "tmpname_sentinel";
- struct tmpname_s {
- struct tmpname_s *next;
- char tmp[4];
- };
- static int
- gc_tmpname(lua_State *L)
- {
- if (lua_isuserdata(L, -1))
- {
- struct tmpname_s **pp = (struct tmpname_s **)lua_touserdata(L, -1);
- while (pp && *pp)
- {
- struct tmpname_s *p = *pp;
- *pp = p->next;
- remove(p->tmp);
- free(p);
- }
- }
- return 0;
- }
- static void
- add_tmpname(lua_State *L, const char *tmp)
- {
- struct tmpname_s **pp = 0;
- lua_pushlightuserdata(L, (void*)tmpnames_key);
- lua_rawget(L, LUA_REGISTRYINDEX);
- if (lua_isuserdata(L, -1))
- {
- pp = (struct tmpname_s **)lua_touserdata(L, -1);
- lua_pop(L, 1);
- }
- else
- {
- lua_pop(L, 1);
- /* create sentinel */
- lua_pushlightuserdata(L, (void*)tmpnames_key);
- pp = (struct tmpname_s **)lua_newuserdata(L, sizeof(void*));
- pp[0] = 0;
- lua_createtable(L, 0, 1);
- lua_pushcfunction(L, gc_tmpname);
- lua_setfield(L,-2,"__gc");
- lua_setmetatable(L, -2);
- lua_rawset(L, LUA_REGISTRYINDEX);
- }
- while (pp && *pp)
- {
- struct tmpname_s *p = *pp;
- if (!strcmp(p->tmp, tmp)) return;
- pp = &(p->next);
- }
- if (pp)
- {
- int len = strlen(tmp);
- struct tmpname_s *t = (struct tmpname_s*)malloc(len + sizeof(struct tmpname_s));
- if (t)
- {
- t->next = 0;
- memcpy(t->tmp, tmp, len);
- t->tmp[len] = 0;
- *pp = t;
- }
- }
- }
- static int
- lua_tmpname(lua_State *L)
- {
- #ifdef _WIN32
- char *tmp = _tempnam("c:/temp", "luatmp");
- #else
- char *tmp = tempnam(NULL, "luatmp");
- #endif
- if (tmp)
- {
- lua_pushstring(L, tmp);
- add_tmpname(L, tmp);
- free(tmp);
- return 1;
- }
- else
- {
- lua_pushnil(L);
- return 1;
- }
- }
- /* ------------------------------------------------------ */
- /* mkdir, rmdir */
- static int
- pushresult (lua_State *L, int i, const char *filename) {
- int en = errno;
- if (i) {
- lua_pushboolean(L, 1);
- return 1;
- }
- else {
- lua_pushnil(L);
- lua_pushfstring(L, "%s: %s", filename, strerror(en));
- lua_pushinteger(L, en);
- return 3;
- }
- }
- static int
- lua_mkdir(lua_State *L)
- {
- int status = 0;
- const char *s = luaL_checkstring(L, 1);
- lua_pushcfunction(L, lua_mkdir);
- lua_pushcfunction(L, lua_dirname);
- lua_pushvalue(L, 1);
- lua_call(L, 1, 1);
- if (! dirp(L, -1))
- lua_call(L, 1, 3);
- #ifdef _WIN32
- status = _mkdir(s);
- #else
- status = mkdir(s, 0777);
- #endif
- return pushresult(L, status == 0, s);
- }
- static int
- lua_rmdir(lua_State *L)
- {
- const char *s = luaL_checkstring(L, 1);
- #ifdef _WIN32
- int status = _rmdir(s);
- #else
- int status = rmdir(s);
- #endif
- return pushresult(L, status == 0, s);
- }
- /* ------------------------------------------------------ */
- /* uname */
- static int
- lua_uname(lua_State *L)
- {
- #if defined(_WIN32)
- const char *name;
- SYSTEM_INFO info;
- lua_pushliteral(L, "Windows");
- name = getenv("COMPUTERNAME");
- lua_pushstring(L, name ? name : "");
- memset(&info, 0, sizeof(info));
- GetSystemInfo(&info);
- if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
- lua_pushliteral(L, "AMD64");
- else if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
- lua_pushliteral(L, "X86");
- else if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM)
- lua_pushliteral(L, "ARM");
- else if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
- lua_pushliteral(L, "IA64");
- else if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
- lua_pushstring(L, "");
- return 3;
- #else
- # if defined(HAVE_SYS_UTSNAME_H)
- struct utsname info;
- if (uname(&info) >= 0)
- {
- lua_pushstring(L, info.sysname);
- lua_pushstring(L, info.nodename);
- lua_pushstring(L, info.machine);
- return 3;
- }
- # endif
- lua_pushstring(L, "Unknown");
- return 1;
- #endif
- }
- static int
- lua_getregistryvalue(lua_State *L)
- {
- #ifdef _WIN32
- static char *keynames[] = {
- "HKEY_CLASSES_ROOT",
- "HKEY_CURRENT_CONFIG",
- "HKEY_CURRENT_USER",
- "HKEY_LOCAL_MACHINE",
- "HKEY_USERS",
- NULL };
- static HKEY keys[] = {
- HKEY_CLASSES_ROOT,
- HKEY_CURRENT_CONFIG,
- HKEY_CURRENT_USER,
- HKEY_LOCAL_MACHINE,
- HKEY_USERS
- };
- HKEY rkey = keys[ luaL_checkoption(L, 1, NULL, keynames) ];
- const char *subkey = luaL_checkstring(L, 2);
- const char *value = luaL_checkstring(L, 3);
- HKEY skey;
- DWORD type;
- DWORD len = 0;
- char *data = NULL;
- LONG res;
- res = RegOpenKeyExA(rkey, subkey, 0, KEY_READ, &skey);
- if (res != ERROR_SUCCESS)
- {
- lua_pushnil(L);
- lua_pushinteger(L, res);
- if (res == ERROR_FILE_NOT_FOUND)
- lua_pushstring(L, "subkey not found");
- if (res == ERROR_ACCESS_DENIED)
- lua_pushstring(L, "subkey access denied");
- else
- return 2;
- return 3;
- }
- res = RegQueryValueExA(skey, value, NULL, &type, (LPBYTE)data, &len);
- if (len > 0)
- {
- len += 8;
- data = (char*)malloc(len);
- if (! data)
- luaL_error(L, "out of memory");
- res = RegQueryValueExA(skey, value, NULL, &type, (LPBYTE)data, &len);
- }
- RegCloseKey(skey);
- if (res != ERROR_SUCCESS)
- {
- if (data)
- free(data);
- lua_pushnil(L);
- lua_pushinteger(L, res);
- if (res == ERROR_FILE_NOT_FOUND)
- lua_pushstring(L, "value not found");
- if (res == ERROR_ACCESS_DENIED)
- lua_pushstring(L, "value access denied");
- else
- return 2;
- return 3;
- }
- switch(type)
- {
- case REG_DWORD:
- lua_pushinteger(L, (lua_Integer)*(const DWORD*)data);
- if (data)
- free(data);
- return 1;
- case REG_EXPAND_SZ:
- if (data && len > 0)
- {
- if ((len = ExpandEnvironmentStrings(data, NULL, 0)) > 0)
- {
- char *buf = (char*)malloc(len + 8);
- if (!buf)
- luaL_error(L, "out of memory");
- len = ExpandEnvironmentStrings(data, buf, len+8);
- free(data);
- data = buf;
- }
- }
- /* fall thru */
- case REG_SZ:
- if (data && len > 0)
- if (((const char*)data)[len-1] == 0)
- len -= 1;
- /* fall thru */
- case REG_BINARY:
- if (data && len > 0)
- lua_pushlstring(L, (const char*)data, (int)len);
- else
- lua_pushliteral(L, "");
- if (data)
- free(data);
- return 1;
- /* unimplemented */
- case REG_QWORD:
- case REG_MULTI_SZ:
- default:
- lua_pushnil(L);
- lua_pushinteger(L, res);
- lua_pushfstring(L, "getting registry type %d not implemented", type);
- return 3;
- }
- #else
- luaL_error(L, "This function exists only on windows");
- return 0;
- #endif
- }
- /* ------------------------------------------------------ */
- /* require (with global flag) */
- #ifdef HAVE_DLOPEN
- # define NEED_PATH_REQUIRE 1
- # include <dlfcn.h>
- # ifndef RTLD_LAZY
- # define RTLD_LAZY 1
- # endif
- # ifndef RTLD_GLOBAL
- # define RTLD_GLOBAL 0
- # endif
- # define LL_LOAD(h,fname) h=dlopen(fname,RTLD_LAZY|RTLD_GLOBAL)
- # define LL_SYM(h,sym) dlsym(h, sym)
- #endif
- #ifdef _WIN32
- # define NEED_PATH_REQUIRE 1
- # include <windows.h>
- # define LL_LOAD(h,fname) h=(void*)LoadLibraryA(fname)
- # define LL_SYM(h,sym) GetProcAddress((HINSTANCE)h,sym)
- #endif
- #if NEED_PATH_REQUIRE
- /* {{{ functions copied or derived from loadlib.c */
- static int readable (const char *filename)
- {
- FILE *f = fopen(filename, "r"); /* try to open file */
- if (f == NULL) return 0; /* open failed */
- fclose(f);
- return 1;
- }
- #if LUA_VERSION_NUM >= 502 /* LUA52 compatibility defs */
- #define LUA_PATHSEP ";"
- #define PATHS_LUA_CLEANUP_DEFS 1
- #endif
- static const char *pushnexttemplate (lua_State *L, const char *path)
- {
- const char *l;
- while (*path == *LUA_PATHSEP) path++; /* skip separators */
- if (*path == '\0') return NULL; /* no more templates */
- l = strchr(path, *LUA_PATHSEP); /* find next separator */
- if (l == NULL) l = path + strlen(path);
- lua_pushlstring(L, path, l - path); /* template */
- return l;
- }
- #ifdef PATHS_LUA_CLEANUP_DEFS /* cleanup after yourself */
- #undef LUA_PATHSEP
- #endif
- static const char *pushfilename (lua_State *L, const char *name)
- {
- const char *path;
- const char *filename;
- lua_getglobal(L, "package");
- lua_getfield(L, -1, "cpath");
- lua_remove(L, -2);
- if (! (path = lua_tostring(L, -1)))
- luaL_error(L, LUA_QL("package.cpath") " must be a string");
- lua_pushliteral(L, "");
- while ((path = pushnexttemplate(L, path))) {
- filename = luaL_gsub(L, lua_tostring(L, -1), "?", name);
- lua_remove(L, -2);
- if (readable(filename))
- { /* stack: cpath errmsg filename */
- lua_remove(L, -3);
- lua_remove(L, -2);
- return lua_tostring(L, -1);
- }
- lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
- lua_remove(L, -2); /* remove file name */
- lua_concat(L, 2); /* add entry to possible error message */
- }
- lua_pushfstring(L, "module " LUA_QS " not found", name);
- lua_replace(L, -3);
- lua_concat(L, 2);
- lua_error(L);
- return 0;
- }
- /* functions copied or derived from loadlib.c }}} */
- static int
- path_require(lua_State *L)
- {
- const char *filename;
- lua_CFunction func;
- void *handle;
- const char *name = luaL_checkstring(L, 1);
- lua_settop(L, 1);
- lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); /* index 2 */
- lua_getfield(L, 2, name);
- if (lua_toboolean(L, -1))
- return 1;
- filename = pushfilename(L, name); /* index 3 */
- LL_LOAD(handle, filename);
- if (! handle)
- luaL_error(L, "cannot load " LUA_QS, filename);
- lua_pushfstring(L, "luaopen_%s", name); /* index 4 */
- func = (lua_CFunction)LL_SYM(handle, lua_tostring(L, -1));
- if (! func)
- luaL_error(L, "no symbol " LUA_QS " in module " LUA_QS,
- lua_tostring(L, -1), filename);
- lua_pushboolean(L, 1);
- lua_setfield(L, 2, name);
- lua_pushcfunction(L, func);
- lua_pushstring(L, name);
- lua_call(L, 1, 1);
- if (! lua_isnil(L, -1))
- lua_setfield(L, 2, name);
- lua_getfield(L, 2, name);
- return 1;
- }
- #else
- /* fallback to calling require */
- static int
- path_require(lua_State *L)
- {
- int narg = lua_gettop(L);
- lua_getglobal(L, "require");
- lua_insert(L, 1);
- lua_call(L, narg, 1);
- return 1;
- }
- #endif
- /* ------------------------------------------------------ */
- /* register */
- static const struct luaL_Reg paths__ [] = {
- {"filep", lua_filep},
- {"dirp", lua_dirp},
- {"basename", lua_basename},
- {"dirname", lua_dirname},
- {"extname", lua_extname},
- {"cwd", lua_cwd},
- {"concat", lua_concatfname},
- {"execdir", lua_execdir},
- {"dir", lua_dir},
- {"tmpname", lua_tmpname},
- {"mkdir", lua_mkdir},
- {"rmdir", lua_rmdir},
- {"uname", lua_uname},
- {"getregistryvalue", lua_getregistryvalue},
- {"require", path_require},
- {NULL, NULL}
- };
- PATHS_API int
- luaopen_libpaths(lua_State *L)
- {
- lua_newtable(L);
- lua_pushvalue(L, -1);
- lua_setglobal(L, "paths");
- #if LUA_VERSION_NUM >= 502
- luaL_setfuncs(L, paths__, 0);
- #else
- luaL_register(L, NULL, paths__);
- #endif
- return 1;
- }
|