Differentiate between file pointers and file descriptors.

This commit is contained in:
Ryan Kelly 2014-01-29 22:03:09 +11:00
Родитель dd5c0f51c7
Коммит 0dbab8bac7
2 изменённых файлов: 70 добавлений и 49 удалений

Просмотреть файл

@ -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);

Просмотреть файл

@ -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() {