diff --git a/src/library.js b/src/library.js index d9e1942fa..d24f1f755 100644 --- a/src/library.js +++ b/src/library.js @@ -52,32 +52,33 @@ LibraryManager.library = { ___setErrNo(ERRNO_CODES.ENOTDIR); return 0; } - var err = _open(dirname, {{{ cDefine('O_RDONLY') }}}, allocate([0, 0, 0, 0], 'i32', ALLOC_STACK)); - // open returns 0 on failure, not -1 - return err === -1 ? 0 : err; + var fd = _open(dirname, {{{ cDefine('O_RDONLY') }}}, allocate([0, 0, 0, 0], 'i32', ALLOC_STACK)); + return fd === -1 ? 0 : FS.getPtrForStream(FS.getStream(fd)); }, - closedir__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'close'], + closedir__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'close', 'fileno'], closedir: function(dirp) { // int closedir(DIR *dirp); // http://pubs.opengroup.org/onlinepubs/007908799/xsh/closedir.html - return _close(dirp); + var fd = _fileno(dirp); + return _close(fd); }, telldir__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'], telldir: function(dirp) { // long int telldir(DIR *dirp); // http://pubs.opengroup.org/onlinepubs/007908799/xsh/telldir.html - var stream = FS.getStream(dirp); + var stream = FS.getStreamFromPtr(dirp); if (!stream || !FS.isDir(stream.node.mode)) { ___setErrNo(ERRNO_CODES.EBADF); return -1; } return stream.position; }, - seekdir__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'lseek'], + seekdir__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'lseek', 'fileno'], seekdir: function(dirp, loc) { // void seekdir(DIR *dirp, long int loc); // http://pubs.opengroup.org/onlinepubs/007908799/xsh/seekdir.html - _lseek(dirp, loc, {{{ cDefine('SEEK_SET') }}}); + var fd = _fileno(dirp); + _lseek(fd, loc, {{{ cDefine('SEEK_SET') }}}); }, rewinddir__deps: ['seekdir'], rewinddir: function(dirp) { @@ -89,7 +90,7 @@ LibraryManager.library = { readdir_r: function(dirp, entry, result) { // int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); // http://pubs.opengroup.org/onlinepubs/007908799/xsh/readdir_r.html - var stream = FS.getStream(dirp); + var stream = FS.getStreamFromPtr(dirp); if (!stream) { return ___setErrNo(ERRNO_CODES.EBADF); } @@ -134,7 +135,7 @@ LibraryManager.library = { readdir: function(dirp) { // struct dirent *readdir(DIR *dirp); // http://pubs.opengroup.org/onlinepubs/007908799/xsh/readdir_r.html - var stream = FS.getStream(dirp); + var stream = FS.getStreamFromPtr(dirp); if (!stream) { ___setErrNo(ERRNO_CODES.EBADF); return 0; @@ -2290,19 +2291,20 @@ LibraryManager.library = { clearerr: function(stream) { // void clearerr(FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/clearerr.html - stream = FS.getStream(stream); + stream = FS.getStreamFromPtr(stream); if (!stream) { return; } stream.eof = false; stream.error = false; }, - fclose__deps: ['close', 'fsync'], + fclose__deps: ['close', 'fsync', 'fileno'], fclose: function(stream) { // int fclose(FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/fclose.html - _fsync(stream); - return _close(stream); + var fd = _fileno(stream); + _fsync(fd); + return _close(fd); }, fdopen__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'], fdopen: function(fildes, mode) { @@ -2323,21 +2325,21 @@ LibraryManager.library = { } else { stream.error = false; stream.eof = false; - return fildes; + return FS.getPtrForStream(stream); } }, feof__deps: ['$FS'], feof: function(stream) { // int feof(FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/feof.html - stream = FS.getStream(stream); + stream = FS.getStreamFromPtr(stream); return Number(stream && stream.eof); }, ferror__deps: ['$FS'], ferror: function(stream) { // int ferror(FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/ferror.html - stream = FS.getStream(stream); + stream = FS.getStreamFromPtr(stream); return Number(stream && stream.error); }, fflush__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'], @@ -2351,7 +2353,7 @@ LibraryManager.library = { fgetc: function(stream) { // int fgetc(FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/fgetc.html - var streamObj = FS.getStream(stream); + var streamObj = FS.getStreamFromPtr(stream); if (!streamObj) return -1; if (streamObj.eof || streamObj.error) return -1; var ret = _fread(_fgetc.ret, 1, 1, stream); @@ -2376,7 +2378,7 @@ LibraryManager.library = { fgetpos: function(stream, pos) { // int fgetpos(FILE *restrict stream, fpos_t *restrict pos); // http://pubs.opengroup.org/onlinepubs/000095399/functions/fgetpos.html - stream = FS.getStream(stream); + stream = FS.getStreamFromPtr(stream); if (!stream) { ___setErrNo(ERRNO_CODES.EBADF); return -1; @@ -2394,7 +2396,7 @@ LibraryManager.library = { fgets: function(s, n, stream) { // char *fgets(char *restrict s, int n, FILE *restrict stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/fgets.html - var streamObj = FS.getStream(stream); + var streamObj = FS.getStreamFromPtr(stream); if (!streamObj) return 0; if (streamObj.error || streamObj.eof) return 0; var byte_; @@ -2418,8 +2420,7 @@ LibraryManager.library = { fileno: function(stream) { // int fileno(FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/fileno.html - // We use file descriptor numbers and FILE* streams interchangeably. - return stream; + return FS.getStreamFromPtr(stream).fd; }, ftrylockfile: function() { // int ftrylockfile(FILE *file); @@ -2461,19 +2462,20 @@ LibraryManager.library = { ___setErrNo(ERRNO_CODES.EINVAL); return 0; } - var ret = _open(filename, flags, allocate([0x1FF, 0, 0, 0], 'i32', ALLOC_STACK)); // All creation permissions. - return (ret == -1) ? 0 : ret; + var fd = _open(filename, flags, allocate([0x1FF, 0, 0, 0], 'i32', ALLOC_STACK)); // All creation permissions. + return fd === -1 ? 0 : FS.getPtrForStream(FS.getStream(fd)); }, - fputc__deps: ['$FS', 'write'], + fputc__deps: ['$FS', 'write', 'fileno'], fputc__postset: '_fputc.ret = allocate([0], "i8", ALLOC_STATIC);', fputc: function(c, stream) { // int fputc(int c, FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/fputc.html var chr = unSign(c & 0xFF); {{{ makeSetValue('_fputc.ret', '0', 'chr', 'i8') }}}; - var ret = _write(stream, _fputc.ret, 1); + var fd = _fileno(stream); + var ret = _write(fd, _fputc.ret, 1); if (ret == -1) { - var streamObj = FS.getStream(stream); + var streamObj = FS.getStreamFromPtr(stream); if (streamObj) streamObj.error = true; return -1; } else { @@ -2489,11 +2491,12 @@ LibraryManager.library = { return _fputc(c, {{{ makeGetValue(makeGlobalUse('_stdout'), '0', 'void*') }}}); }, putchar_unlocked: 'putchar', - fputs__deps: ['write', 'strlen'], + fputs__deps: ['write', 'strlen', 'fileno'], fputs: function(s, stream) { // int fputs(const char *restrict s, FILE *restrict stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/fputs.html - return _write(stream, s, _strlen(s)); + var fd = _fileno(stream); + return _write(fd, s, _strlen(s)); }, puts__deps: ['fputs', 'fputc', 'stdout'], puts: function(s) { @@ -2518,7 +2521,7 @@ LibraryManager.library = { return 0; } var bytesRead = 0; - var streamObj = FS.getStream(stream); + var streamObj = FS.getStreamFromPtr(stream); if (!streamObj) { ___setErrNo(ERRNO_CODES.EBADF); return 0; @@ -2528,7 +2531,7 @@ LibraryManager.library = { bytesToRead--; bytesRead++; } - var err = _read(stream, ptr, bytesToRead); + var err = _read(streamObj.fd, ptr, bytesToRead); if (err == -1) { if (streamObj) streamObj.error = true; return 0; @@ -2542,7 +2545,7 @@ LibraryManager.library = { // FILE *freopen(const char *restrict filename, const char *restrict mode, FILE *restrict stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/freopen.html if (!filename) { - var streamObj = FS.getStream(stream); + var streamObj = FS.getStreamFromPtr(stream); if (!streamObj) { ___setErrNo(ERRNO_CODES.EBADF); return 0; @@ -2554,15 +2557,16 @@ LibraryManager.library = { _fclose(stream); return _fopen(filename, mode); }, - fseek__deps: ['$FS', 'lseek'], + fseek__deps: ['$FS', 'lseek', 'fileno'], fseek: function(stream, offset, whence) { // int fseek(FILE *stream, long offset, int whence); // http://pubs.opengroup.org/onlinepubs/000095399/functions/fseek.html - var ret = _lseek(stream, offset, whence); + var fd = _fileno(stream); + var ret = _lseek(fd, offset, whence); if (ret == -1) { return -1; } - stream = FS.getStream(stream); + stream = FS.getStreamFromPtr(stream); stream.eof = false; return 0; }, @@ -2571,7 +2575,7 @@ LibraryManager.library = { fsetpos: function(stream, pos) { // int fsetpos(FILE *stream, const fpos_t *pos); // http://pubs.opengroup.org/onlinepubs/000095399/functions/fsetpos.html - stream = FS.getStream(stream); + stream = FS.getStreamFromPtr(stream); if (!stream) { ___setErrNo(ERRNO_CODES.EBADF); return -1; @@ -2590,7 +2594,7 @@ LibraryManager.library = { ftell: function(stream) { // long ftell(FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/ftell.html - stream = FS.getStream(stream); + stream = FS.getStreamFromPtr(stream); if (!stream) { ___setErrNo(ERRNO_CODES.EBADF); return -1; @@ -2603,15 +2607,16 @@ LibraryManager.library = { } }, ftello: 'ftell', - fwrite__deps: ['$FS', 'write'], + fwrite__deps: ['$FS', 'write', 'fileno'], fwrite: function(ptr, size, nitems, stream) { // size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/fwrite.html var bytesToWrite = nitems * size; if (bytesToWrite == 0) return 0; - var bytesWritten = _write(stream, ptr, bytesToWrite); + var fd = _fileno(stream); + var bytesWritten = _write(fd, ptr, bytesToWrite); if (bytesWritten == -1) { - var streamObj = FS.getStream(stream); + var streamObj = FS.getStreamFromPtr(stream); if (streamObj) streamObj.error = true; return 0; } else { @@ -2674,7 +2679,7 @@ LibraryManager.library = { // void rewind(FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/rewind.html _fseek(stream, 0, 0); // SEEK_SET. - var streamObj = FS.getStream(stream); + var streamObj = FS.getStreamFromPtr(stream); if (streamObj) streamObj.error = false; }, setvbuf: function(stream, buf, type, size) { @@ -2731,7 +2736,7 @@ LibraryManager.library = { ungetc: function(c, stream) { // int ungetc(int c, FILE *stream); // http://pubs.opengroup.org/onlinepubs/000095399/functions/ungetc.html - stream = FS.getStream(stream); + stream = FS.getStreamFromPtr(stream); if (!stream) { return -1; } @@ -2756,7 +2761,7 @@ LibraryManager.library = { fscanf: function(stream, format, varargs) { // int fscanf(FILE *restrict stream, const char *restrict format, ... ); // http://pubs.opengroup.org/onlinepubs/000095399/functions/scanf.html - var streamObj = FS.getStream(stream); + var streamObj = FS.getStreamFromPtr(stream); if (!streamObj) { return -1; } @@ -2899,7 +2904,7 @@ LibraryManager.library = { // ========================================================================== mmap__deps: ['$FS'], - mmap: function(start, num, prot, flags, stream, offset) { + mmap: function(start, num, prot, flags, fd, offset) { /* FIXME: Since mmap is normally implemented at the kernel level, * this implementation simply uses malloc underneath the call to * mmap. @@ -2910,13 +2915,13 @@ LibraryManager.library = { if (!_mmap.mappings) _mmap.mappings = {}; - if (stream == -1) { + if (fd == -1) { ptr = _malloc(num); if (!ptr) return -1; _memset(ptr, 0, num); allocated = true; } else { - var info = FS.getStream(stream); + var info = FS.getStream(fd); if (!info) return -1; try { var res = FS.mmap(info, HEAPU8, start, num, offset, prot, flags); diff --git a/src/library_fs.js b/src/library_fs.js index 8d83048e3..e97ba588d 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -413,6 +413,22 @@ mergeInto(LibraryManager.library, { FS.streams[fd] = null; }, + // + // file pointers + // + // instead of maintaining a separate mapping from FILE* to file descriptors, + // we employ a simple trick: the pointer to a stream is its fd plus 1. This + // means that all valid streams have a valid non-zero pointer while allowing + // the fs for stdin to be the standard value of zero. + // + // + getStreamFromPtr: function(ptr) { + return FS.streams[ptr - 1]; + }, + getPtrForStream: function(stream) { + return stream ? stream.fd + 1 : 0; + }, + // // devices // @@ -1166,15 +1182,15 @@ mergeInto(LibraryManager.library, { // open default streams for the stdin, stdout and stderr devices var stdin = FS.open('/dev/stdin', 'r'); - {{{ makeSetValue(makeGlobalUse('_stdin'), 0, 'stdin.fd', 'void*') }}}; + {{{ makeSetValue(makeGlobalUse('_stdin'), 0, 'FS.getPtrForStream(stdin)', 'void*') }}}; assert(stdin.fd === 0, 'invalid handle for stdin (' + stdin.fd + ')'); var stdout = FS.open('/dev/stdout', 'w'); - {{{ makeSetValue(makeGlobalUse('_stdout'), 0, 'stdout.fd', 'void*') }}}; + {{{ makeSetValue(makeGlobalUse('_stdout'), 0, 'FS.getPtrForStream(stdout)', 'void*') }}}; assert(stdout.fd === 1, 'invalid handle for stdout (' + stdout.fd + ')'); var stderr = FS.open('/dev/stderr', 'w'); - {{{ makeSetValue(makeGlobalUse('_stderr'), 0, 'stderr.fd', 'void*') }}}; + {{{ makeSetValue(makeGlobalUse('_stderr'), 0, 'FS.getPtrForStream(stderr)', 'void*') }}}; assert(stderr.fd === 2, 'invalid handle for stderr (' + stderr.fd + ')'); }, ensureErrnoError: function() {