X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fnasal%2Fiolib.c;h=b91190177bb2a758afff2f217f42c3cf993680ee;hb=1ca9c7dbf6f42be1a43a5e5621563af8f6c0ecb2;hp=9d65fa1e3cab6e080738d21ea28edcdfdd3a2516;hpb=a770d2a97254826efc32802ec59646565116294a;p=simgear.git diff --git a/simgear/nasal/iolib.c b/simgear/nasal/iolib.c index 9d65fa1e..b9119017 100644 --- a/simgear/nasal/iolib.c +++ b/simgear/nasal/iolib.c @@ -7,11 +7,11 @@ #include "iolib.h" static void ghostDestroy(void* g); -naGhostType naIOGhostType = { ghostDestroy }; +naGhostType naIOGhostType = { ghostDestroy, "iofile" }; static struct naIOGhost* ioghost(naRef r) { - if(naGhost_type(r) == &naIOGhostType) + if(naGhost_type(r) == &naIOGhostType && IOGHOST(r)->handle) return naGhost_ptr(r); return 0; } @@ -32,9 +32,9 @@ static naRef f_read(naContext c, naRef me, int argc, naRef* args) naRef len = argc > 2 ? naNumValue(args[2]) : naNil(); if(!g || !MUTABLE(str) || !IS_NUM(len)) naRuntimeError(c, "bad argument to read()"); - if(str.ref.ptr.str->len < (int)len.num) + if(naStr_len(str) < (int)len.num) naRuntimeError(c, "string not big enough for read"); - return naNum(g->type->read(c, g->handle, (char*)str.ref.ptr.str->data, + return naNum(g->type->read(c, g->handle, naStr_data(str), (int)len.num)); } @@ -44,8 +44,8 @@ static naRef f_write(naContext c, naRef me, int argc, naRef* args) naRef str = argc > 1 ? args[1] : naNil(); if(!g || !IS_STR(str)) naRuntimeError(c, "bad argument to write()"); - return naNum(g->type->write(c, g->handle, (char*)str.ref.ptr.str->data, - str.ref.ptr.str->len)); + return naNum(g->type->write(c, g->handle, naStr_data(str), + naStr_len(str))); } static naRef f_seek(naContext c, naRef me, int argc, naRef* args) @@ -67,6 +67,15 @@ static naRef f_tell(naContext c, naRef me, int argc, naRef* args) return naNum(g->type->tell(c, g->handle)); } +static naRef f_flush(naContext c, naRef me, int argc, naRef* args) +{ + struct naIOGhost* g = argc==1 ? ioghost(args[0]) : 0; + if(!g) + naRuntimeError(c, "bad argument to flush()"); + g->type->flush(c, g->handle); + return naNil(); +} + static void ghostDestroy(void* g) { struct naIOGhost* io = (struct naIOGhost*)g; @@ -79,7 +88,8 @@ static void ghostDestroy(void* g) static void ioclose(naContext c, void* f) { - if(fclose(f) != 0 && c) naRuntimeError(c, strerror(errno)); + if(f) + if(fclose(f) != 0 && c) naRuntimeError(c, strerror(errno)); } static int ioread(naContext c, void* f, char* buf, unsigned int len) @@ -110,13 +120,19 @@ static int iotell(naContext c, void* f) return n; } +static void ioflush(naContext c, void* f) +{ + if(fflush(f)) naRuntimeError(c, strerror(errno)); +} + static void iodestroy(void* f) { - ioclose(0, f); + if(f != stdin && f != stdout && f != stderr) + ioclose(0, f); } struct naIOType naStdIOType = { ioclose, ioread, iowrite, ioseek, - iotell, iodestroy }; + iotell, ioflush, iodestroy }; naRef naIOGhost(naContext c, FILE* f) { @@ -126,22 +142,25 @@ naRef naIOGhost(naContext c, FILE* f) return naNewGhost(c, &naIOGhostType, ghost); } +#if SG_NASAL_UNRESTRICTED_OPEN +// Allows unrestricted file access, which would be a security hole +// Replaced by the one in flightgear src/Scripting/NasalSys.cxx static naRef f_open(naContext c, naRef me, int argc, naRef* args) { FILE* f; naRef file = argc > 0 ? naStringValue(c, args[0]) : naNil(); naRef mode = argc > 1 ? naStringValue(c, args[1]) : naNil(); if(!IS_STR(file)) naRuntimeError(c, "bad argument to open()"); - f = fopen((char*)file.ref.ptr.str->data, - IS_STR(mode) ? (const char*)mode.ref.ptr.str->data : "r"); + f = fopen(naStr_data(file), IS_STR(mode) ? naStr_data(mode) : "rb"); if(!f) naRuntimeError(c, strerror(errno)); return naIOGhost(c, f); } +#endif // frees buffer before tossing an error static int getcguard(naContext ctx, FILE* f, void* buf) { - char c; + int c; naModUnlock(); c = fgetc(f); naModLock(); if(ferror(f)) { naFree(buf); @@ -157,76 +176,94 @@ static naRef f_readln(naContext ctx, naRef me, int argc, naRef* args) { naRef result; struct naIOGhost* g = argc==1 ? ioghost(args[0]) : 0; - int i=0, sz = 128; - char* buf; + int i=0, c, sz = 128; + char *buf; if(!g || g->type != &naStdIOType) naRuntimeError(ctx, "bad argument to readln()"); buf = naAlloc(sz); while(1) { - char c = getcguard(ctx, g->handle, buf); + c = getcguard(ctx, g->handle, buf); if(c == EOF || c == '\n') break; if(c == '\r') { - char c2 = getcguard(ctx, g->handle, buf); + int c2 = getcguard(ctx, g->handle, buf); if(c2 != EOF && c2 != '\n') - ungetc(c2, g->handle); + if(EOF == ungetc(c2, g->handle)) + break; break; } buf[i++] = c; if(i >= sz) buf = naRealloc(buf, sz *= 2); } - result = naStr_fromdata(naNewString(ctx), buf, i); + result = c == EOF ? naNil() : naStr_fromdata(naNewString(ctx), buf, i); naFree(buf); return result; } +#ifdef _WIN32 +#define S_ISLNK(m) 0 +#define S_ISSOCK(m) 0 +#endif +#ifdef _MSC_VER +#define S_ISREG(m) (((m)&_S_IFMT)==_S_IFREG) +#define S_ISDIR(m) (((m)&_S_IFMT)==_S_IFDIR) +#define S_ISCHR(m) (((m)&_S_IFMT)==_S_IFCHR) +#define S_ISFIFO(m) (((m)&_S_IFMT)==_S_IFIFO) +#define S_ISBLK(m) 0 +typedef unsigned short mode_t; +#endif +static naRef ftype(naContext ctx, mode_t m) +{ + const char* t = "unk"; + if(S_ISREG(m)) t = "reg"; + else if(S_ISDIR(m)) t = "dir"; else if(S_ISCHR(m)) t = "chr"; + else if(S_ISBLK(m)) t = "blk"; else if(S_ISFIFO(m)) t = "fifo"; + else if(S_ISLNK(m)) t = "lnk"; else if(S_ISSOCK(m)) t = "sock"; + return naStr_fromdata(naNewString(ctx), t, strlen(t)); +} + static naRef f_stat(naContext ctx, naRef me, int argc, naRef* args) { int n=0; struct stat s; naRef result, path = argc > 0 ? naStringValue(ctx, args[0]) : naNil(); if(!IS_STR(path)) naRuntimeError(ctx, "bad argument to stat()"); - if(stat((char*)path.ref.ptr.str->data, &s) < 0) { + if(stat(naStr_data(path), &s) < 0) { if(errno == ENOENT) return naNil(); naRuntimeError(ctx, strerror(errno)); } result = naNewVector(ctx); - naVec_setsize(result, 11); + naVec_setsize(ctx, result, 12); #define FLD(x) naVec_set(result, n++, naNum(s.st_##x)); FLD(dev); FLD(ino); FLD(mode); FLD(nlink); FLD(uid); FLD(gid); FLD(rdev); FLD(size); FLD(atime); FLD(mtime); FLD(ctime); #undef FLD + naVec_set(result, n++, ftype(ctx, s.st_mode)); return result; } -static struct func { char* name; naCFunction func; } funcs[] = { +static naCFuncItem funcs[] = { { "close", f_close }, { "read", f_read }, { "write", f_write }, { "seek", f_seek }, { "tell", f_tell }, + { "flush", f_flush }, +#if SG_NASAL_UNRESTRICTED_OPEN { "open", f_open }, +#endif { "readln", f_readln }, { "stat", f_stat }, + { 0 } }; -static void setsym(naContext c, naRef hash, char* sym, naRef val) -{ - naRef name = naStr_fromdata(naNewString(c), sym, strlen(sym)); - naHash_set(hash, naInternSymbol(name), val); -} - -naRef naIOLib(naContext c) +naRef naInit_io(naContext c) { - naRef ns = naNewHash(c); - int i, n = sizeof(funcs)/sizeof(struct func); - for(i=0; i