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 void sbadd1(SB *sb, char c) { sbgrow(sb, 1); if (sb->buffer) sb->buffer[sb->len++] = c; }
static const char * executable_dir(const char *progname) { SB sb; struct stat sbuf; if (! progname) return 0; sbinit(&sb); if (progname[0]=='/') sbaddn(&sb, progname, strlen(progname)); else if (strchr(progname,'/')) sbaddsf(&sb,catpath(NULL,progname)); else { char *p = getenv("PATH"); for (;;) { sb.len = 0; if (! (p && *p)) return sbfree(&sb); while (*p && *p!=':') sbadd1(&sb, *p++); if (*p ==':') p++; sbadd1(&sb, 0); sb.len = 0; sbaddsf(&sb, catpath(sb.buffer, progname)); sbadd1(&sb, 0); if (sb.buffer && stat(sb.buffer,&sbuf)>=0 && S_ISREG(sbuf.st_mode)) if (access(sb.buffer, X_OK) >= 0) break; } } #ifdef S_ISLNK sbadd1(&sb, 0); while(sb.buffer && lstat(sb.buffer,&sbuf)>=0 && S_ISLNK(sbuf.st_mode)) { int h,l; sbaddn(&sb,"../",3); h = sb.len; while ((l=readlink(sb.buffer,sb.buffer+h,sb.maxlen-h))>=sb.maxlen-h) sbgrow(&sb, sb.maxlen - h + SBINCREMENT); if (l < 0) return sbfree(&sb); sb.len = h + l; sbadd1(&sb,0); sb.len = 0; sbaddsf(&sb, catpath(sb.buffer,sb.buffer+h-3)); sbadd1(&sb,0); } #endif while (sb.buffer && sb.len>0 && sb.buffer[sb.len-1]=='/') sb.len -= 1; while (sb.buffer && sb.len>0 && sb.buffer[sb.len-1]!='/') sb.len -= 1; while (sb.buffer && sb.len>0 && sb.buffer[sb.len-1]=='/') sb.len -= 1; sbadd1(&sb, 0); return sb.buffer; }
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 char * catpath(const char *from, const char *fname) { SB sb; sbinit(&sb); if (fname && fname[0]=='/') sbadd1(&sb, '/'); else if (from) sbaddsf(&sb, catpath(NULL,from)); else { char *cwd = 0; while (sb.buffer && !cwd) { cwd = getcwd(sb.buffer + sb.len, sb.maxlen - sb.len); if (cwd || errno != ERANGE) break; sbgrow(&sb, sb.maxlen - sb.len + SBINCREMENT); } if (cwd) sb.len += strlen(cwd); else sbfree(&sb); } for (;;) { while (fname && fname[0]=='/') fname++; if (!fname || !fname[0]) { while (&sb.buffer && sb.len>0 && sb.buffer[sb.len-1]=='/') sb.len -= 1; sbadd1(&sb, 0); return sb.buffer; } 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.buffer && sb.len>0 && sb.buffer[sb.len-1]=='/') sb.len -= 1; while (sb.buffer && sb.len>0 && sb.buffer[sb.len-1]!='/') sb.len -= 1; continue; } } if (sb.len==0 || (sb.buffer && sb.buffer[sb.len-1]!='/')) sbadd1(&sb, '/'); while (*fname!=0 && *fname!='/') sbadd1(&sb, *fname++); } sbadd1(&sb, 0); return sb.buffer; }
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 }