aboutsummaryrefslogtreecommitdiff
path: root/src/library.js
diff options
context:
space:
mode:
authormax99x <max99x@gmail.com>2011-07-20 10:20:09 +0300
committermax99x <max99x@gmail.com>2011-07-21 02:48:24 +0300
commit10ca04685b6e0ec0e8089fbe859e0085d8020622 (patch)
treee256b40bfbf8324e73c977b82c36cc4a227f7be5 /src/library.js
parent278416d5426493959216d46279d3c40f91f33f81 (diff)
Implemented <fcntl.h>.
Diffstat (limited to 'src/library.js')
-rw-r--r--src/library.js191
1 files changed, 178 insertions, 13 deletions
diff --git a/src/library.js b/src/library.js
index 46c396cb..793454de 100644
--- a/src/library.js
+++ b/src/library.js
@@ -679,6 +679,184 @@ LibraryManager.library = {
},
// ==========================================================================
+ // fcntl.h
+ // ==========================================================================
+
+ __flock_struct_layout: Types.structDefinitions.flock,
+ open__deps: ['$FS', '__setErrNo', '$ERRNO_CODES',
+ 'strlen', 'strcpy', 'dirname', 'basename'],
+ open: function(path, oflag, mode) {
+ // int open(const char *path, int oflag, ...);
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html
+ // NOTE: This implementation tries to mimic glibc rather that strictly
+ // following the POSIX standard.
+
+ // Simplify flags.
+ var accessMode = oflag & 0x3; // O_ACCMODE.
+ var isWrite = accessMode != 0x0; // O_RDONLY.
+ var isRead = accessMode != 0x1; // O_WRONLY.
+ var isCreate = Boolean(oflag & 0x40); // O_CREAT.
+ var isExistCheck = Boolean(oflag & 0x80); // O_EXCL.
+ var isTruncate = Boolean(oflag & 0x200); // O_TRUNC.
+ var isAppend = Boolean(oflag & 0x400); // O_APPEND.
+
+ // Verify path.
+ var pathStr = Pointer_stringify(path);
+ if (!pathStr) {
+ ___setErrNo(ERRNO_CODES.ENOENT);
+ return -1;
+ }
+ var absolutePath = FS.absolutePath(pathStr);
+ if (absolutePath === null) {
+ ___setErrNo(ERRNO_CODES.ENOENT);
+ return -1;
+ }
+ var buffer = _malloc(_strlen(path) + 1);
+ var parentPath = Pointer_stringify(_dirname(_strcpy(buffer, path)));
+ var name = Pointer_stringify(_basename(_strcpy(buffer, path)));
+ _free(buffer);
+ var parent = FS.findObject(parentPath);
+ if (parent === null) return -1;
+ if (!parent.isFolder || !parent.read) {
+ ___setErrNo(ERRNO_CODES.EACCES);
+ return -1;
+ }
+ var target = parent.contents[name] || null;
+
+ // Verify the file exists, create if needed and allowed.
+ if (target) {
+ if (isCreate && isExistCheck) {
+ ___setErrNo(ERRNO_CODES.EEXIST);
+ return -1;
+ }
+ if ((isWrite || isCreate || isTruncate) && target.isFolder) {
+ ___setErrNo(ERRNO_CODES.EISDIR);
+ return -1;
+ }
+ if (isRead && !target.read || isWrite && !target.write) {
+ ___setErrNo(ERRNO_CODES.EACCES);
+ return -1;
+ }
+ if (isTruncate && !target.isDevice) {
+ target.contents = [];
+ } else {
+ if (!FS.forceLoadFile(target)) {
+ ___setErrNo(ERRNO_CODES.EIO);
+ return -1;
+ }
+ }
+ } else {
+ if (!isCreate) {
+ ___setErrNo(ERRNO_CODES.ENOENT);
+ return -1;
+ }
+ if (!parent.write) {
+ ___setErrNo(ERRNO_CODES.EACCES);
+ return -1;
+ }
+ target = FS.createDataFile(parent, name, [], mode & 0x100, mode & 0x80); // S_IRUSR, S_IWUSR.
+ }
+
+ // Actually create an open stream.
+ var id = FS.streams.length;
+ FS.streams[id] = {
+ isFolder: false,
+ path: absolutePath,
+ object: target,
+ position: 0,
+ isRead: isRead,
+ isWrite: isWrite,
+ isAppend: isAppend
+ };
+ return id;
+ },
+ creat__deps: ['open'],
+ creat: function(path, mode) {
+ // int creat(const char *path, mode_t mode);
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/creat.html
+ return _open(path, 0x241, mode); // O_WRONLY | O_CREAT | O_TRUNC.
+ },
+ fcntl__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', '__flock_struct_layout'],
+ fcntl: function(fildes, cmd, arg) {
+ // int fcntl(int fildes, int cmd, ...);
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/fcntl.html
+ if (!(fildes in FS.streams)) {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return -1;
+ }
+ var stream = FS.streams[fildes];
+ switch (cmd) {
+ case 0: // F_DUPFD.
+ if (arg < 0) {
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return -1;
+ }
+ var newStream = {};
+ for (var member in stream) {
+ newStream[member] = stream[member];
+ }
+ if (arg in FS.streams) arg = FS.streams.length;
+ FS.streams[arg] = newStream;
+ return arg;
+ case 1: // F_GETFD.
+ case 2: // F_SETFD.
+ return 0; // FD_CLOEXEC makes no sense for a single process.
+ case 3: // F_GETFL.
+ var flags = 0;
+ if (stream.isRead && stream.isWrite) flags = 0x2; // O_RDWR.
+ else if (!stream.isRead && stream.isWrite) flags = 0x1; // O_WRONLY.
+ else if (stream.isRead && !stream.isWrite) flags = 0x0; // O_RDONLY.
+ if (stream.isAppend) flags |= 0x400; // O_APPEND.
+ // Synchronization and blocking flags are irrelevant to us.
+ return flags;
+ case 4: // F_SETFL.
+ stream.isAppend = Boolean(arg | 0x400); // O_APPEND.
+ // Synchronization and blocking flags are irrelevant to us.
+ return 0;
+ case 5: // F_GETLK.
+ var offset = ___flock_struct_layout.members.l_type.offset;
+ // We're always unlocked.
+ {{{ makeSetValue('arg', 'offset', '2', 'i16') }}} // F_UNLCK.
+ return 0;
+ case 6: // F_SETLK.
+ case 7: // F_SETLKW.
+ // Pretend that the locking is successful.
+ return 0;
+ case 8: // F_SETOWN.
+ case 9: // F_GETOWN.
+ // These are for sockets. We don't have them implemented (yet?).
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return -1;
+ default:
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return -1;
+ }
+ // Should never be reached. Only to silence strict warnings.
+ return -1;
+ },
+ posix_fadvise: function(fd, offset, len, advice) {
+ // int posix_fadvise(int fd, off_t offset, off_t len, int advice);
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/posix_fadvise.html
+ // Advise as much as you wish. We don't care.
+ return 0;
+ },
+ posix_madvise: 'posix_fadvise',
+ posix_fallocate__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'],
+ posix_fallocate: function(fd, offset, len) {
+ // int posix_fallocate(int fd, off_t offset, off_t len);
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/posix_fallocate.html
+ if (!(fd in FS.streams) || FS.streams[fd].link ||
+ FS.streams[fd].isFolder || FS.streams[fd].isDevice) {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return -1;
+ }
+ var contents = FS.streams[fd].object.contents;
+ var limit = offset + len;
+ while (limit > contents.length) contents.push(0);
+ return 0;
+ },
+
+ // ==========================================================================
_scanString: function() {
// Supports %x, %4x, %d.%d, %s
@@ -1446,17 +1624,6 @@ LibraryManager.library = {
// unix file IO, see http://rabbit.eng.miami.edu/info/functions/unixio.html
- open: function(filename, flags, mode) {
- filename = Pointer_stringify(filename);
- if (flags === 0) { // RDONLY
- return STDIO.open(filename);
- } else if (flags === 1) { // WRONLY
- return STDIO.prepare(filename);
- } else {
- return assert(false, 'open with odd params: ' + [flags, mode]);
- }
- },
-
__01open64___deps: ['open'],
__01open64_: function(filename, mode, flags) {
// open(), but with flags and mode switched.
@@ -1472,8 +1639,6 @@ LibraryManager.library = {
return STDIO.read(stream, ptr, numbytes);
},
- fcntl: function() { }, // TODO...
-
mmap: function(start, num, prot, flags, stream, offset) {
// Leaky and non-shared... FIXME
var info = STDIO.streams[stream];