mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-05 00:25:27 +00:00
583 lines
22 KiB
JavaScript
583 lines
22 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
{
|
|
if (typeof Components != "undefined") {
|
|
// We do not wish osfile_unix_back.jsm to be used directly as a main thread
|
|
// module yet. When time comes, it will be loaded by a combination of
|
|
// a main thread front-end/worker thread implementation that makes sure
|
|
// that we are not executing synchronous IO code in the main thread.
|
|
|
|
throw new Error("osfile_unix_back.jsm cannot be used from the main thread yet");
|
|
}
|
|
(function(exports) {
|
|
"use strict";
|
|
if (!exports.OS) {
|
|
exports.OS = {};
|
|
}
|
|
if (!exports.OS.Unix) {
|
|
exports.OS.Unix = {};
|
|
}
|
|
if (exports.OS.Unix.File) {
|
|
return; // Avoid double-initialization
|
|
}
|
|
exports.OS.Unix.File = {};
|
|
|
|
let LOG = exports.OS.Shared.LOG.bind(OS.Shared, "Unix", "back");
|
|
let libc = exports.OS.Shared.Unix.libc;
|
|
|
|
/**
|
|
* Initialize the Unix module.
|
|
*
|
|
* @param {function=} declareFFI
|
|
*/
|
|
// FIXME: Both |init| and |aDeclareFFI| are deprecated, we should remove them
|
|
let init = function init(aDeclareFFI) {
|
|
let declareFFI;
|
|
if (aDeclareFFI) {
|
|
declareFFI = aDeclareFFI.bind(null, libc);
|
|
} else {
|
|
declareFFI = exports.OS.Shared.Unix.declareFFI;
|
|
}
|
|
|
|
// Shorthands
|
|
let OSUnix = exports.OS.Unix;
|
|
let UnixFile = exports.OS.Unix.File;
|
|
if (!exports.OS.Types) {
|
|
exports.OS.Types = {};
|
|
}
|
|
let Type = exports.OS.Shared.Type;
|
|
let Types = Type;
|
|
|
|
// Initialize types that require additional OS-specific
|
|
// support - either finalization or matching against
|
|
// OS-specific constants.
|
|
|
|
/**
|
|
* A file descriptor.
|
|
*/
|
|
Types.fd = Type.int.withName("fd");
|
|
Types.fd.importFromC = function importFromC(fd_int) {
|
|
return ctypes.CDataFinalizer(fd_int, _close);
|
|
};
|
|
|
|
|
|
/**
|
|
* A C integer holding -1 in case of error or a file descriptor
|
|
* in case of success.
|
|
*/
|
|
Types.negativeone_or_fd = Types.fd.withName("negativeone_or_fd");
|
|
Types.negativeone_or_fd.importFromC =
|
|
function importFromC(fd_int) {
|
|
if (fd_int == -1) {
|
|
return -1;
|
|
}
|
|
return ctypes.CDataFinalizer(fd_int, _close);
|
|
};
|
|
|
|
/**
|
|
* A C integer holding -1 in case of error or a meaningless value
|
|
* in case of success.
|
|
*/
|
|
Types.negativeone_or_nothing =
|
|
Types.int.withName("negativeone_or_nothing");
|
|
|
|
/**
|
|
* A C integer holding -1 in case of error or a positive integer
|
|
* in case of success.
|
|
*/
|
|
Types.negativeone_or_ssize_t =
|
|
Types.ssize_t.withName("negativeone_or_ssize_t");
|
|
|
|
/**
|
|
* Various libc integer types
|
|
*/
|
|
Types.mode_t =
|
|
Types.intn_t(OS.Constants.libc.OSFILE_SIZEOF_MODE_T).withName("mode_t");
|
|
Types.uid_t =
|
|
Types.intn_t(OS.Constants.libc.OSFILE_SIZEOF_UID_T).withName("uid_t");
|
|
Types.gid_t =
|
|
Types.intn_t(OS.Constants.libc.OSFILE_SIZEOF_GID_T).withName("gid_t");
|
|
|
|
/**
|
|
* Type |time_t|
|
|
*/
|
|
Types.time_t =
|
|
Types.intn_t(OS.Constants.libc.OSFILE_SIZEOF_TIME_T).withName("time_t");
|
|
|
|
// Structure |dirent|
|
|
// Building this type is rather complicated, as its layout varies between
|
|
// variants of Unix. For this reason, we rely on a number of constants
|
|
// (computed in C from the C data structures) that give us the layout.
|
|
// The structure we compute looks like
|
|
// { int8_t[...] before_d_type; // ignored content
|
|
// int8_t d_type ;
|
|
// int8_t[...] before_d_name; // ignored content
|
|
// char[...] d_name;
|
|
// };
|
|
{
|
|
let dirent = new OS.Shared.HollowStructure("dirent",
|
|
OS.Constants.libc.OSFILE_SIZEOF_DIRENT);
|
|
dirent.add_field_at(OS.Constants.libc.OSFILE_OFFSETOF_DIRENT_D_TYPE,
|
|
"d_type", ctypes.uint8_t);
|
|
dirent.add_field_at(OS.Constants.libc.OSFILE_OFFSETOF_DIRENT_D_NAME,
|
|
"d_name", ctypes.ArrayType(ctypes.char, OS.Constants.libc.OSFILE_SIZEOF_DIRENT_D_NAME));
|
|
|
|
// We now have built |dirent|.
|
|
Types.dirent = dirent.getType();
|
|
}
|
|
Types.null_or_dirent_ptr =
|
|
new Type("null_of_dirent",
|
|
Types.dirent.out_ptr.implementation);
|
|
|
|
// Structure |stat|
|
|
// Same technique
|
|
{
|
|
let stat = new OS.Shared.HollowStructure("stat",
|
|
OS.Constants.libc.OSFILE_SIZEOF_STAT);
|
|
stat.add_field_at(OS.Constants.libc.OSFILE_OFFSETOF_STAT_ST_MODE,
|
|
"st_mode", Types.mode_t.implementation);
|
|
stat.add_field_at(OS.Constants.libc.OSFILE_OFFSETOF_STAT_ST_UID,
|
|
"st_uid", Types.uid_t.implementation);
|
|
stat.add_field_at(OS.Constants.libc.OSFILE_OFFSETOF_STAT_ST_GID,
|
|
"st_gid", Types.gid_t.implementation);
|
|
|
|
// Here, things get complicated with different data structures.
|
|
// Some platforms have |time_t st_atime| and some platforms have
|
|
// |timespec st_atimespec|. However, since |timespec| starts with
|
|
// a |time_t|, followed by nanoseconds, we just cheat and pretend
|
|
// that everybody has |time_t st_atime|, possibly followed by padding
|
|
stat.add_field_at(OS.Constants.libc.OSFILE_OFFSETOF_STAT_ST_ATIME,
|
|
"st_atime", Types.time_t.implementation);
|
|
stat.add_field_at(OS.Constants.libc.OSFILE_OFFSETOF_STAT_ST_MTIME,
|
|
"st_mtime", Types.time_t.implementation);
|
|
stat.add_field_at(OS.Constants.libc.OSFILE_OFFSETOF_STAT_ST_CTIME,
|
|
"st_ctime", Types.time_t.implementation);
|
|
|
|
// To complicate further, MacOS and some BSDs have a field |birthtime|
|
|
if ("OSFILE_OFFSETOF_STAT_ST_BIRTHTIME" in OS.Constants.libc) {
|
|
stat.add_field_at(OS.Constants.libc.OSFILE_OFFSETOF_STAT_ST_BIRTHTIME,
|
|
"st_birthtime", Types.time_t.implementation);
|
|
}
|
|
|
|
stat.add_field_at(OS.Constants.libc.OSFILE_OFFSETOF_STAT_ST_SIZE,
|
|
"st_size", Types.size_t.implementation);
|
|
Types.stat = stat.getType();
|
|
}
|
|
|
|
// Structure |DIR|
|
|
if ("OSFILE_SIZEOF_DIR" in OS.Constants.libc) {
|
|
// On platforms for which we need to access the fields of DIR
|
|
// directly (e.g. because certain functions are implemented
|
|
// as macros), we need to define DIR as a hollow structure.
|
|
let DIR = new OS.Shared.HollowStructure(
|
|
"DIR",
|
|
OS.Constants.libc.OSFILE_SIZEOF_DIR);
|
|
|
|
DIR.add_field_at(
|
|
OS.Constants.libc.OSFILE_OFFSETOF_DIR_DD_FD,
|
|
"dd_fd",
|
|
Types.fd.implementation);
|
|
|
|
Types.DIR = DIR.getType();
|
|
} else {
|
|
// On other platforms, we keep DIR as a blackbox
|
|
Types.DIR =
|
|
new Type("DIR",
|
|
ctypes.StructType("DIR"));
|
|
}
|
|
|
|
Types.null_or_DIR_ptr =
|
|
Types.DIR.out_ptr.withName("null_or_DIR*");
|
|
Types.null_or_DIR_ptr.importFromC = function importFromC(dir) {
|
|
if (dir == null || dir.isNull()) {
|
|
return null;
|
|
}
|
|
return ctypes.CDataFinalizer(dir, _close_dir);
|
|
};
|
|
|
|
// Declare libc functions as functions of |OS.Unix.File|
|
|
|
|
// Finalizer-related functions
|
|
let _close = UnixFile._close =
|
|
libc.declare("close", ctypes.default_abi,
|
|
/*return */ctypes.int,
|
|
/*fd*/ ctypes.int);
|
|
|
|
UnixFile.close = function close(fd) {
|
|
// Detach the finalizer and call |_close|.
|
|
return fd.dispose();
|
|
};
|
|
|
|
let _close_dir =
|
|
libc.declare("closedir", ctypes.default_abi,
|
|
/*return */ctypes.int,
|
|
/*dirp*/ Types.DIR.in_ptr.implementation);
|
|
|
|
UnixFile.closedir = function closedir(fd) {
|
|
// Detach the finalizer and call |_close_dir|.
|
|
return fd.dispose();
|
|
};
|
|
|
|
UnixFile.free =
|
|
libc.declare("free", ctypes.default_abi,
|
|
/*return*/ ctypes.void_t,
|
|
/*ptr*/ ctypes.voidptr_t);
|
|
|
|
// Other functions
|
|
UnixFile.access =
|
|
declareFFI("access", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*path*/ Types.path,
|
|
/*mode*/ Types.int);
|
|
|
|
UnixFile.chdir =
|
|
declareFFI("chdir", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*path*/ Types.path);
|
|
|
|
UnixFile.chmod =
|
|
declareFFI("chmod", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*path*/ Types.path,
|
|
/*mode*/ Types.mode_t);
|
|
|
|
UnixFile.chown =
|
|
declareFFI("chown", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*path*/ Types.path,
|
|
/*uid*/ Types.uid_t,
|
|
/*gid*/ Types.gid_t);
|
|
|
|
UnixFile.copyfile =
|
|
declareFFI("copyfile", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*source*/ Types.path,
|
|
/*dest*/ Types.path,
|
|
/*state*/ Types.void_t.in_ptr, // Ignored atm
|
|
/*flags*/ Types.uint32_t);
|
|
|
|
UnixFile.dup =
|
|
declareFFI("dup", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_fd,
|
|
/*fd*/ Types.fd);
|
|
|
|
if ("OSFILE_SIZEOF_DIR" in OS.Constants.libc) {
|
|
// On platforms for which |dirfd| is a macro
|
|
UnixFile.dirfd =
|
|
function dirfd(DIRp) {
|
|
return Types.DIR.in_ptr.implementation(DIRp).contents.dd_fd;
|
|
};
|
|
} else {
|
|
// On platforms for which |dirfd| is a function
|
|
UnixFile.dirfd =
|
|
declareFFI("dirfd", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_fd,
|
|
/*dir*/ Types.DIR.in_ptr);
|
|
}
|
|
|
|
UnixFile.chdir =
|
|
declareFFI("chdir", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*path*/ Types.path);
|
|
|
|
UnixFile.fchdir =
|
|
declareFFI("fchdir", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*fd*/ Types.fd);
|
|
|
|
UnixFile.fchown =
|
|
declareFFI("fchown", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*fd*/ Types.fd,
|
|
/*uid_t*/ Types.uid_t,
|
|
/*gid_t*/ Types.gid_t);
|
|
|
|
UnixFile.fsync =
|
|
declareFFI("fsync", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*fd*/ Types.fd);
|
|
|
|
UnixFile.getcwd =
|
|
declareFFI("getcwd", ctypes.default_abi,
|
|
/*return*/ Types.out_path,
|
|
/*buf*/ Types.out_path,
|
|
/*size*/ Types.size_t);
|
|
|
|
UnixFile.getwd =
|
|
declareFFI("getwd", ctypes.default_abi,
|
|
/*return*/ Types.out_path,
|
|
/*buf*/ Types.out_path);
|
|
|
|
// Two variants of |getwd| which allocate the memory
|
|
// dynamically.
|
|
|
|
// Linux/Android version
|
|
UnixFile.get_current_dir_name =
|
|
declareFFI("get_current_dir_name", ctypes.default_abi,
|
|
/*return*/ Types.out_path.releaseWith(UnixFile.free));
|
|
|
|
// MacOS/BSD version (will return NULL on Linux/Android)
|
|
UnixFile.getwd_auto =
|
|
declareFFI("getwd", ctypes.default_abi,
|
|
/*return*/ Types.out_path.releaseWith(UnixFile.free),
|
|
/*buf*/ Types.void_t.out_ptr);
|
|
|
|
UnixFile.fdatasync =
|
|
declareFFI("fdatasync", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*fd*/ Types.fd); // Note: MacOS/BSD-specific
|
|
|
|
UnixFile.ftruncate =
|
|
declareFFI("ftruncate", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*fd*/ Types.fd,
|
|
/*length*/ Types.off_t);
|
|
|
|
if (OS.Constants.libc._DARWIN_FEATURE_64_BIT_INODE) {
|
|
UnixFile.fstat =
|
|
declareFFI("fstat$INODE64", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*path*/ Types.fd,
|
|
/*buf*/ Types.stat.out_ptr
|
|
);
|
|
} else {
|
|
UnixFile.fstat =
|
|
declareFFI("fstat", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*path*/ Types.fd,
|
|
/*buf*/ Types.stat.out_ptr
|
|
);
|
|
}
|
|
|
|
UnixFile.lchown =
|
|
declareFFI("lchown", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*path*/ Types.path,
|
|
/*uid_t*/ Types.uid_t,
|
|
/*gid_t*/ Types.gid_t);
|
|
|
|
UnixFile.link =
|
|
declareFFI("link", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*source*/ Types.path,
|
|
/*dest*/ Types.path);
|
|
|
|
UnixFile.lseek =
|
|
declareFFI("lseek", ctypes.default_abi,
|
|
/*return*/ Types.off_t,
|
|
/*fd*/ Types.fd,
|
|
/*offset*/ Types.off_t,
|
|
/*whence*/ Types.int);
|
|
|
|
UnixFile.mkdir =
|
|
declareFFI("mkdir", ctypes.default_abi,
|
|
/*return*/ Types.int,
|
|
/*path*/ Types.path,
|
|
/*mode*/ Types.int);
|
|
|
|
UnixFile.mkstemp =
|
|
declareFFI("mkstemp", ctypes.default_abi,
|
|
/*return*/ Types.fd,
|
|
/*template*/Types.out_path);
|
|
|
|
UnixFile.open =
|
|
declareFFI("open", ctypes.default_abi,
|
|
/*return*/Types.negativeone_or_fd,
|
|
/*path*/ Types.path,
|
|
/*oflags*/Types.int,
|
|
/*mode*/ Types.int);
|
|
|
|
UnixFile.opendir =
|
|
declareFFI("opendir", ctypes.default_abi,
|
|
/*return*/ Types.null_or_DIR_ptr,
|
|
/*path*/ Types.path);
|
|
|
|
UnixFile.pread =
|
|
declareFFI("pread", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_ssize_t,
|
|
/*fd*/ Types.fd,
|
|
/*buf*/ Types.void_t.out_ptr,
|
|
/*nbytes*/ Types.size_t,
|
|
/*offset*/ Types.off_t);
|
|
|
|
UnixFile.pwrite =
|
|
declareFFI("pwrite", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_ssize_t,
|
|
/*fd*/ Types.fd,
|
|
/*buf*/ Types.void_t.in_ptr,
|
|
/*nbytes*/ Types.size_t,
|
|
/*offset*/ Types.off_t);
|
|
|
|
UnixFile.read =
|
|
declareFFI("read", ctypes.default_abi,
|
|
/*return*/Types.negativeone_or_ssize_t,
|
|
/*fd*/ Types.fd,
|
|
/*buf*/ Types.void_t.out_ptr,
|
|
/*nbytes*/Types.size_t);
|
|
|
|
if (OS.Constants.libc._DARWIN_FEATURE_64_BIT_INODE) {
|
|
// Special case for MacOS X 10.5+
|
|
// Symbol name "readdir" still exists but is used for a
|
|
// deprecated function that does not match the
|
|
// constants of |OS.Constants.libc|.
|
|
UnixFile.readdir =
|
|
declareFFI("readdir$INODE64", ctypes.default_abi,
|
|
/*return*/Types.null_or_dirent_ptr,
|
|
/*dir*/ Types.DIR.in_ptr); // For MacOS X
|
|
} else {
|
|
UnixFile.readdir =
|
|
declareFFI("readdir", ctypes.default_abi,
|
|
/*return*/Types.null_or_dirent_ptr,
|
|
/*dir*/ Types.DIR.in_ptr); // Other Unices
|
|
}
|
|
|
|
UnixFile.rename =
|
|
declareFFI("rename", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*old*/ Types.path,
|
|
/*new*/ Types.path);
|
|
|
|
UnixFile.rmdir =
|
|
declareFFI("rmdir", ctypes.default_abi,
|
|
/*return*/ Types.int,
|
|
/*path*/ Types.path);
|
|
|
|
UnixFile.splice =
|
|
declareFFI("splice", ctypes.default_abi,
|
|
/*return*/ Types.long,
|
|
/*fd_in*/ Types.fd,
|
|
/*off_in*/ Types.off_t.in_ptr,
|
|
/*fd_out*/ Types.fd,
|
|
/*off_out*/Types.off_t.in_ptr,
|
|
/*len*/ Types.size_t,
|
|
/*flags*/ Types.unsigned_int); // Linux/Android-specific
|
|
|
|
UnixFile.symlink =
|
|
declareFFI("symlink", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*source*/ Types.path,
|
|
/*dest*/ Types.path);
|
|
|
|
UnixFile.truncate =
|
|
declareFFI("truncate", ctypes.default_abi,
|
|
/*return*/Types.negativeone_or_nothing,
|
|
/*path*/ Types.path,
|
|
/*length*/ Types.off_t);
|
|
|
|
UnixFile.unlink =
|
|
declareFFI("unlink", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*path*/ Types.path);
|
|
|
|
UnixFile.write =
|
|
declareFFI("write", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_ssize_t,
|
|
/*fd*/ Types.fd,
|
|
/*buf*/ Types.void_t.in_ptr,
|
|
/*nbytes*/ Types.size_t);
|
|
|
|
// Weird cases that require special treatment
|
|
|
|
// OSes use a variety of hacks to differentiate between
|
|
// 32-bits and 64-bits versions of |stat|, |lstat|, |fstat|.
|
|
if (OS.Constants.libc._DARWIN_FEATURE_64_BIT_INODE) {
|
|
// MacOS X 64-bits
|
|
UnixFile.stat =
|
|
declareFFI("stat$INODE64", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*path*/ Types.path,
|
|
/*buf*/ Types.stat.out_ptr
|
|
);
|
|
UnixFile.lstat =
|
|
declareFFI("lstat$INODE64", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*path*/ Types.path,
|
|
/*buf*/ Types.stat.out_ptr
|
|
);
|
|
UnixFile.fstat =
|
|
declareFFI("fstat$INODE64", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*path*/ Types.fd,
|
|
/*buf*/ Types.stat.out_ptr
|
|
);
|
|
} else if (OS.Constants.libc._STAT_VER != undefined) {
|
|
const ver = OS.Constants.libc._STAT_VER;
|
|
// Linux, all widths
|
|
let xstat =
|
|
declareFFI("__xstat", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*_stat_ver*/ Types.int,
|
|
/*path*/ Types.path,
|
|
/*buf*/ Types.stat.out_ptr);
|
|
let lxstat =
|
|
declareFFI("__lxstat", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*_stat_ver*/ Types.int,
|
|
/*path*/ Types.path,
|
|
/*buf*/ Types.stat.out_ptr);
|
|
let fxstat =
|
|
declareFFI("__fxstat", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*_stat_ver*/ Types.int,
|
|
/*fd*/ Types.fd,
|
|
/*buf*/ Types.stat.out_ptr);
|
|
|
|
UnixFile.stat = function stat(path, buf) {
|
|
return xstat(ver, path, buf);
|
|
};
|
|
UnixFile.lstat = function stat(path, buf) {
|
|
return lxstat(ver, path, buf);
|
|
};
|
|
UnixFile.fstat = function stat(fd, buf) {
|
|
return fxstat(ver, fd, buf);
|
|
};
|
|
} else {
|
|
// Mac OS X 32-bits, other Unix
|
|
UnixFile.stat =
|
|
declareFFI("stat", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*path*/ Types.path,
|
|
/*buf*/ Types.stat.out_ptr
|
|
);
|
|
UnixFile.lstat =
|
|
declareFFI("lstat", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*path*/ Types.path,
|
|
/*buf*/ Types.stat.out_ptr
|
|
);
|
|
UnixFile.fstat =
|
|
declareFFI("fstat", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*fd*/ Types.fd,
|
|
/*buf*/ Types.stat.out_ptr
|
|
);
|
|
}
|
|
|
|
// We cannot make a C array of CDataFinalizer, so
|
|
// pipe cannot be directly defined as a C function.
|
|
|
|
let _pipe =
|
|
declareFFI("pipe", ctypes.default_abi,
|
|
/*return*/ Types.negativeone_or_nothing,
|
|
/*fds*/ new Type("two file descriptors",
|
|
ctypes.ArrayType(ctypes.int, 2)));
|
|
|
|
// A shared per-thread buffer used to communicate with |pipe|
|
|
let _pipebuf = new (ctypes.ArrayType(ctypes.int, 2))();
|
|
|
|
UnixFile.pipe = function pipe(array) {
|
|
let result = _pipe(_pipebuf);
|
|
if (result == -1) {
|
|
return result;
|
|
}
|
|
array[0] = ctypes.CDataFinalizer(_pipebuf[0], _close);
|
|
array[1] = ctypes.CDataFinalizer(_pipebuf[1], _close);
|
|
return result;
|
|
};
|
|
};
|
|
exports.OS.Unix.File._init = init;
|
|
})(this);
|
|
}
|