1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/osfile/modules/osfile_unix_back.jsm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,737 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +{ 1.9 + if (typeof Components != "undefined") { 1.10 + // We do not wish osfile_unix_back.jsm to be used directly as a main thread 1.11 + // module yet. When time comes, it will be loaded by a combination of 1.12 + // a main thread front-end/worker thread implementation that makes sure 1.13 + // that we are not executing synchronous IO code in the main thread. 1.14 + 1.15 + throw new Error("osfile_unix_back.jsm cannot be used from the main thread yet"); 1.16 + } 1.17 + (function(exports) { 1.18 + "use strict"; 1.19 + if (exports.OS && exports.OS.Unix && exports.OS.Unix.File) { 1.20 + return; // Avoid double initialization 1.21 + } 1.22 + 1.23 + let SharedAll = 1.24 + require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm"); 1.25 + let SysAll = 1.26 + require("resource://gre/modules/osfile/osfile_unix_allthreads.jsm"); 1.27 + let LOG = SharedAll.LOG.bind(SharedAll, "Unix", "back"); 1.28 + let libc = SysAll.libc; 1.29 + let Const = SharedAll.Constants.libc; 1.30 + 1.31 + /** 1.32 + * Initialize the Unix module. 1.33 + * 1.34 + * @param {function=} declareFFI 1.35 + */ 1.36 + // FIXME: Both |init| and |aDeclareFFI| are deprecated, we should remove them 1.37 + let init = function init(aDeclareFFI) { 1.38 + let declareFFI; 1.39 + if (aDeclareFFI) { 1.40 + declareFFI = aDeclareFFI.bind(null, libc); 1.41 + } else { 1.42 + declareFFI = SysAll.declareFFI; 1.43 + } 1.44 + let declareLazyFFI = SharedAll.declareLazyFFI; 1.45 + 1.46 + // Initialize types that require additional OS-specific 1.47 + // support - either finalization or matching against 1.48 + // OS-specific constants. 1.49 + let Type = Object.create(SysAll.Type); 1.50 + let SysFile = exports.OS.Unix.File = { Type: Type }; 1.51 + 1.52 + /** 1.53 + * A file descriptor. 1.54 + */ 1.55 + Type.fd = Type.int.withName("fd"); 1.56 + Type.fd.importFromC = function importFromC(fd_int) { 1.57 + return ctypes.CDataFinalizer(fd_int, SysFile._close); 1.58 + }; 1.59 + 1.60 + 1.61 + /** 1.62 + * A C integer holding -1 in case of error or a file descriptor 1.63 + * in case of success. 1.64 + */ 1.65 + Type.negativeone_or_fd = Type.fd.withName("negativeone_or_fd"); 1.66 + Type.negativeone_or_fd.importFromC = 1.67 + function importFromC(fd_int) { 1.68 + if (fd_int == -1) { 1.69 + return -1; 1.70 + } 1.71 + return ctypes.CDataFinalizer(fd_int, SysFile._close); 1.72 + }; 1.73 + 1.74 + /** 1.75 + * A C integer holding -1 in case of error or a meaningless value 1.76 + * in case of success. 1.77 + */ 1.78 + Type.negativeone_or_nothing = 1.79 + Type.int.withName("negativeone_or_nothing"); 1.80 + 1.81 + /** 1.82 + * A C integer holding -1 in case of error or a positive integer 1.83 + * in case of success. 1.84 + */ 1.85 + Type.negativeone_or_ssize_t = 1.86 + Type.ssize_t.withName("negativeone_or_ssize_t"); 1.87 + 1.88 + /** 1.89 + * Various libc integer types 1.90 + */ 1.91 + Type.mode_t = 1.92 + Type.intn_t(Const.OSFILE_SIZEOF_MODE_T).withName("mode_t"); 1.93 + Type.uid_t = 1.94 + Type.intn_t(Const.OSFILE_SIZEOF_UID_T).withName("uid_t"); 1.95 + Type.gid_t = 1.96 + Type.intn_t(Const.OSFILE_SIZEOF_GID_T).withName("gid_t"); 1.97 + 1.98 + /** 1.99 + * Type |time_t| 1.100 + */ 1.101 + Type.time_t = 1.102 + Type.intn_t(Const.OSFILE_SIZEOF_TIME_T).withName("time_t"); 1.103 + 1.104 + // Structure |dirent| 1.105 + // Building this type is rather complicated, as its layout varies between 1.106 + // variants of Unix. For this reason, we rely on a number of constants 1.107 + // (computed in C from the C data structures) that give us the layout. 1.108 + // The structure we compute looks like 1.109 + // { int8_t[...] before_d_type; // ignored content 1.110 + // int8_t d_type ; 1.111 + // int8_t[...] before_d_name; // ignored content 1.112 + // char[...] d_name; 1.113 + // }; 1.114 + { 1.115 + let d_name_extra_size = 0; 1.116 + if (Const.OSFILE_SIZEOF_DIRENT_D_NAME < 8) { 1.117 + // d_name is defined like "char d_name[1];" on some platforms 1.118 + // (e.g. Solaris), we need to give it more size for our structure. 1.119 + d_name_extra_size = 256; 1.120 + } 1.121 + 1.122 + let dirent = new SharedAll.HollowStructure("dirent", 1.123 + Const.OSFILE_SIZEOF_DIRENT + d_name_extra_size); 1.124 + if (Const.OSFILE_OFFSETOF_DIRENT_D_TYPE != undefined) { 1.125 + // |dirent| doesn't have d_type on some platforms (e.g. Solaris). 1.126 + dirent.add_field_at(Const.OSFILE_OFFSETOF_DIRENT_D_TYPE, 1.127 + "d_type", ctypes.uint8_t); 1.128 + } 1.129 + dirent.add_field_at(Const.OSFILE_OFFSETOF_DIRENT_D_NAME, 1.130 + "d_name", ctypes.ArrayType(ctypes.char, 1.131 + Const.OSFILE_SIZEOF_DIRENT_D_NAME + d_name_extra_size)); 1.132 + 1.133 + // We now have built |dirent|. 1.134 + Type.dirent = dirent.getType(); 1.135 + } 1.136 + Type.null_or_dirent_ptr = 1.137 + new SharedAll.Type("null_of_dirent", 1.138 + Type.dirent.out_ptr.implementation); 1.139 + 1.140 + // Structure |stat| 1.141 + // Same technique 1.142 + { 1.143 + let stat = new SharedAll.HollowStructure("stat", 1.144 + Const.OSFILE_SIZEOF_STAT); 1.145 + stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_MODE, 1.146 + "st_mode", Type.mode_t.implementation); 1.147 + stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_UID, 1.148 + "st_uid", Type.uid_t.implementation); 1.149 + stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_GID, 1.150 + "st_gid", Type.gid_t.implementation); 1.151 + 1.152 + // Here, things get complicated with different data structures. 1.153 + // Some platforms have |time_t st_atime| and some platforms have 1.154 + // |timespec st_atimespec|. However, since |timespec| starts with 1.155 + // a |time_t|, followed by nanoseconds, we just cheat and pretend 1.156 + // that everybody has |time_t st_atime|, possibly followed by padding 1.157 + stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_ATIME, 1.158 + "st_atime", Type.time_t.implementation); 1.159 + stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_MTIME, 1.160 + "st_mtime", Type.time_t.implementation); 1.161 + stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_CTIME, 1.162 + "st_ctime", Type.time_t.implementation); 1.163 + 1.164 + // To complicate further, MacOS and some BSDs have a field |birthtime| 1.165 + if ("OSFILE_OFFSETOF_STAT_ST_BIRTHTIME" in Const) { 1.166 + stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_BIRTHTIME, 1.167 + "st_birthtime", Type.time_t.implementation); 1.168 + } 1.169 + 1.170 + stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_SIZE, 1.171 + "st_size", Type.off_t.implementation); 1.172 + Type.stat = stat.getType(); 1.173 + } 1.174 + 1.175 + // Structure |DIR| 1.176 + if ("OSFILE_SIZEOF_DIR" in Const) { 1.177 + // On platforms for which we need to access the fields of DIR 1.178 + // directly (e.g. because certain functions are implemented 1.179 + // as macros), we need to define DIR as a hollow structure. 1.180 + let DIR = new SharedAll.HollowStructure( 1.181 + "DIR", 1.182 + Const.OSFILE_SIZEOF_DIR); 1.183 + 1.184 + DIR.add_field_at( 1.185 + Const.OSFILE_OFFSETOF_DIR_DD_FD, 1.186 + "dd_fd", 1.187 + Type.fd.implementation); 1.188 + 1.189 + Type.DIR = DIR.getType(); 1.190 + } else { 1.191 + // On other platforms, we keep DIR as a blackbox 1.192 + Type.DIR = 1.193 + new SharedAll.Type("DIR", 1.194 + ctypes.StructType("DIR")); 1.195 + } 1.196 + 1.197 + Type.null_or_DIR_ptr = 1.198 + Type.DIR.out_ptr.withName("null_or_DIR*"); 1.199 + Type.null_or_DIR_ptr.importFromC = function importFromC(dir) { 1.200 + if (dir == null || dir.isNull()) { 1.201 + return null; 1.202 + } 1.203 + return ctypes.CDataFinalizer(dir, SysFile._close_dir); 1.204 + }; 1.205 + 1.206 + // Structure |timeval| 1.207 + { 1.208 + let timeval = new SharedAll.HollowStructure( 1.209 + "timeval", 1.210 + Const.OSFILE_SIZEOF_TIMEVAL); 1.211 + timeval.add_field_at( 1.212 + Const.OSFILE_OFFSETOF_TIMEVAL_TV_SEC, 1.213 + "tv_sec", 1.214 + Type.long.implementation); 1.215 + timeval.add_field_at( 1.216 + Const.OSFILE_OFFSETOF_TIMEVAL_TV_USEC, 1.217 + "tv_usec", 1.218 + Type.long.implementation); 1.219 + Type.timeval = timeval.getType(); 1.220 + Type.timevals = new SharedAll.Type("two timevals", 1.221 + ctypes.ArrayType(Type.timeval.implementation, 2)); 1.222 + } 1.223 + 1.224 + // Types fsblkcnt_t and fsfilcnt_t, used by structure |statvfs| 1.225 + Type.fsblkcnt_t = 1.226 + Type.uintn_t(Const.OSFILE_SIZEOF_FSBLKCNT_T).withName("fsblkcnt_t"); 1.227 + 1.228 + // Structure |statvfs| 1.229 + // Use an hollow structure 1.230 + { 1.231 + let statvfs = new SharedAll.HollowStructure("statvfs", 1.232 + Const.OSFILE_SIZEOF_STATVFS); 1.233 + 1.234 + statvfs.add_field_at(Const.OSFILE_OFFSETOF_STATVFS_F_BSIZE, 1.235 + "f_bsize", Type.unsigned_long.implementation); 1.236 + statvfs.add_field_at(Const.OSFILE_OFFSETOF_STATVFS_F_BAVAIL, 1.237 + "f_bavail", Type.fsblkcnt_t.implementation); 1.238 + 1.239 + Type.statvfs = statvfs.getType(); 1.240 + } 1.241 + 1.242 + // Declare libc functions as functions of |OS.Unix.File| 1.243 + 1.244 + // Finalizer-related functions 1.245 + libc.declareLazy(SysFile, "_close", 1.246 + "close", ctypes.default_abi, 1.247 + /*return */ctypes.int, 1.248 + /*fd*/ ctypes.int); 1.249 + 1.250 + SysFile.close = function close(fd) { 1.251 + // Detach the finalizer and call |_close|. 1.252 + return fd.dispose(); 1.253 + }; 1.254 + 1.255 + libc.declareLazy(SysFile, "_close_dir", 1.256 + "closedir", ctypes.default_abi, 1.257 + /*return */ctypes.int, 1.258 + /*dirp*/ Type.DIR.in_ptr.implementation); 1.259 + 1.260 + SysFile.closedir = function closedir(fd) { 1.261 + // Detach the finalizer and call |_close_dir|. 1.262 + return fd.dispose(); 1.263 + }; 1.264 + 1.265 + { 1.266 + // Symbol free() is special. 1.267 + // We override the definition of free() on several platforms. 1.268 + let default_lib = new SharedAll.Library("default_lib", 1.269 + "a.out"); 1.270 + try { 1.271 + // On platforms for which we override free(), nspr defines 1.272 + // a special library name "a.out" that will resolve to the 1.273 + // correct implementation free(). 1.274 + 1.275 + default_lib.declareLazy(SysFile, "free", 1.276 + "free", ctypes.default_abi, 1.277 + /*return*/ ctypes.void_t, 1.278 + /*ptr*/ ctypes.voidptr_t); 1.279 + 1.280 + } catch (ex) { 1.281 + // We don't have an a.out library or a.out doesn't contain free. 1.282 + // Either way, use the ordinary libc free. 1.283 + 1.284 + libc.declareLazy(SysFile, "free", 1.285 + "free", ctypes.default_abi, 1.286 + /*return*/ ctypes.void_t, 1.287 + /*ptr*/ ctypes.voidptr_t); 1.288 + } 1.289 + } 1.290 + 1.291 + 1.292 + // Other functions 1.293 + libc.declareLazyFFI(SysFile, "access", 1.294 + "access", ctypes.default_abi, 1.295 + /*return*/ Type.negativeone_or_nothing, 1.296 + /*path*/ Type.path, 1.297 + /*mode*/ Type.int); 1.298 + 1.299 + libc.declareLazyFFI(SysFile, "chdir", 1.300 + "chdir", ctypes.default_abi, 1.301 + /*return*/ Type.negativeone_or_nothing, 1.302 + /*path*/ Type.path); 1.303 + 1.304 + libc.declareLazyFFI(SysFile, "chmod", 1.305 + "chmod", ctypes.default_abi, 1.306 + /*return*/ Type.negativeone_or_nothing, 1.307 + /*path*/ Type.path, 1.308 + /*mode*/ Type.mode_t); 1.309 + 1.310 + libc.declareLazyFFI(SysFile, "chown", 1.311 + "chown", ctypes.default_abi, 1.312 + /*return*/ Type.negativeone_or_nothing, 1.313 + /*path*/ Type.path, 1.314 + /*uid*/ Type.uid_t, 1.315 + /*gid*/ Type.gid_t); 1.316 + 1.317 + libc.declareLazyFFI(SysFile, "copyfile", 1.318 + "copyfile", ctypes.default_abi, 1.319 + /*return*/ Type.negativeone_or_nothing, 1.320 + /*source*/ Type.path, 1.321 + /*dest*/ Type.path, 1.322 + /*state*/ Type.void_t.in_ptr, // Ignored atm 1.323 + /*flags*/ Type.uint32_t); 1.324 + 1.325 + libc.declareLazyFFI(SysFile, "dup", 1.326 + "dup", ctypes.default_abi, 1.327 + /*return*/ Type.negativeone_or_fd, 1.328 + /*fd*/ Type.fd); 1.329 + 1.330 + if ("OSFILE_SIZEOF_DIR" in Const) { 1.331 + // On platforms for which |dirfd| is a macro 1.332 + SysFile.dirfd = 1.333 + function dirfd(DIRp) { 1.334 + return Type.DIR.in_ptr.implementation(DIRp).contents.dd_fd; 1.335 + }; 1.336 + } else { 1.337 + // On platforms for which |dirfd| is a function 1.338 + libc.declareLazyFFI(SysFile, "dirfd", 1.339 + "dirfd", ctypes.default_abi, 1.340 + /*return*/ Type.negativeone_or_fd, 1.341 + /*dir*/ Type.DIR.in_ptr); 1.342 + } 1.343 + 1.344 + libc.declareLazyFFI(SysFile, "chdir", 1.345 + "chdir", ctypes.default_abi, 1.346 + /*return*/ Type.negativeone_or_nothing, 1.347 + /*path*/ Type.path); 1.348 + 1.349 + libc.declareLazyFFI(SysFile, "fchdir", 1.350 + "fchdir", ctypes.default_abi, 1.351 + /*return*/ Type.negativeone_or_nothing, 1.352 + /*fd*/ Type.fd); 1.353 + 1.354 + libc.declareLazyFFI(SysFile, "fchmod", 1.355 + "fchmod", ctypes.default_abi, 1.356 + /*return*/ Type.negativeone_or_nothing, 1.357 + /*fd*/ Type.fd, 1.358 + /*mode*/ Type.mode_t); 1.359 + 1.360 + libc.declareLazyFFI(SysFile, "fchown", 1.361 + "fchown", ctypes.default_abi, 1.362 + /*return*/ Type.negativeone_or_nothing, 1.363 + /*fd*/ Type.fd, 1.364 + /*uid_t*/ Type.uid_t, 1.365 + /*gid_t*/ Type.gid_t); 1.366 + 1.367 + libc.declareLazyFFI(SysFile, "fsync", 1.368 + "fsync", ctypes.default_abi, 1.369 + /*return*/ Type.negativeone_or_nothing, 1.370 + /*fd*/ Type.fd); 1.371 + 1.372 + libc.declareLazyFFI(SysFile, "getcwd", 1.373 + "getcwd", ctypes.default_abi, 1.374 + /*return*/ Type.out_path, 1.375 + /*buf*/ Type.out_path, 1.376 + /*size*/ Type.size_t); 1.377 + 1.378 + libc.declareLazyFFI(SysFile, "getwd", 1.379 + "getwd", ctypes.default_abi, 1.380 + /*return*/ Type.out_path, 1.381 + /*buf*/ Type.out_path); 1.382 + 1.383 + // Two variants of |getwd| which allocate the memory 1.384 + // dynamically. 1.385 + 1.386 + // Linux/Android version 1.387 + libc.declareLazyFFI(SysFile, "get_current_dir_name", 1.388 + "get_current_dir_name", ctypes.default_abi, 1.389 + /*return*/ Type.out_path.releaseWithLazy(() => 1.390 + SysFile.free 1.391 + )); 1.392 + 1.393 + // MacOS/BSD version (will return NULL on Linux/Android) 1.394 + libc.declareLazyFFI(SysFile, "getwd_auto", 1.395 + "getwd", ctypes.default_abi, 1.396 + /*return*/ Type.out_path.releaseWithLazy(() => 1.397 + SysFile.free 1.398 + ), 1.399 + /*buf*/ Type.void_t.out_ptr); 1.400 + 1.401 + libc.declareLazyFFI(SysFile, "fdatasync", 1.402 + "fdatasync", ctypes.default_abi, 1.403 + /*return*/ Type.negativeone_or_nothing, 1.404 + /*fd*/ Type.fd); // Note: MacOS/BSD-specific 1.405 + 1.406 + libc.declareLazyFFI(SysFile, "ftruncate", 1.407 + "ftruncate", ctypes.default_abi, 1.408 + /*return*/ Type.negativeone_or_nothing, 1.409 + /*fd*/ Type.fd, 1.410 + /*length*/ Type.off_t); 1.411 + 1.412 + 1.413 + libc.declareLazyFFI(SysFile, "lchown", 1.414 + "lchown", ctypes.default_abi, 1.415 + /*return*/ Type.negativeone_or_nothing, 1.416 + /*path*/ Type.path, 1.417 + /*uid_t*/ Type.uid_t, 1.418 + /*gid_t*/ Type.gid_t); 1.419 + 1.420 + libc.declareLazyFFI(SysFile, "link", 1.421 + "link", ctypes.default_abi, 1.422 + /*return*/ Type.negativeone_or_nothing, 1.423 + /*source*/ Type.path, 1.424 + /*dest*/ Type.path); 1.425 + 1.426 + libc.declareLazyFFI(SysFile, "lseek", 1.427 + "lseek", ctypes.default_abi, 1.428 + /*return*/ Type.off_t, 1.429 + /*fd*/ Type.fd, 1.430 + /*offset*/ Type.off_t, 1.431 + /*whence*/ Type.int); 1.432 + 1.433 + libc.declareLazyFFI(SysFile, "mkdir", 1.434 + "mkdir", ctypes.default_abi, 1.435 + /*return*/ Type.int, 1.436 + /*path*/ Type.path, 1.437 + /*mode*/ Type.int); 1.438 + 1.439 + libc.declareLazyFFI(SysFile, "mkstemp", 1.440 + "mkstemp", ctypes.default_abi, 1.441 + /*return*/ Type.fd, 1.442 + /*template*/ Type.out_path); 1.443 + 1.444 + libc.declareLazyFFI(SysFile, "open", 1.445 + "open", ctypes.default_abi, 1.446 + /*return*/ Type.negativeone_or_fd, 1.447 + /*path*/ Type.path, 1.448 + /*oflags*/ Type.int, 1.449 + /*mode*/ Type.int); 1.450 + 1.451 + if (OS.Constants.Sys.Name == "NetBSD") { 1.452 + libc.declareLazyFFI(SysFile, "opendir", 1.453 + "__opendir30", ctypes.default_abi, 1.454 + /*return*/ Type.null_or_DIR_ptr, 1.455 + /*path*/ Type.path); 1.456 + } else { 1.457 + libc.declareLazyFFI(SysFile, "opendir", 1.458 + "opendir", ctypes.default_abi, 1.459 + /*return*/ Type.null_or_DIR_ptr, 1.460 + /*path*/ Type.path); 1.461 + } 1.462 + 1.463 + libc.declareLazyFFI(SysFile, "pread", 1.464 + "pread", ctypes.default_abi, 1.465 + /*return*/ Type.negativeone_or_ssize_t, 1.466 + /*fd*/ Type.fd, 1.467 + /*buf*/ Type.void_t.out_ptr, 1.468 + /*nbytes*/ Type.size_t, 1.469 + /*offset*/ Type.off_t); 1.470 + 1.471 + libc.declareLazyFFI(SysFile, "pwrite", 1.472 + "pwrite", ctypes.default_abi, 1.473 + /*return*/ Type.negativeone_or_ssize_t, 1.474 + /*fd*/ Type.fd, 1.475 + /*buf*/ Type.void_t.in_ptr, 1.476 + /*nbytes*/ Type.size_t, 1.477 + /*offset*/ Type.off_t); 1.478 + 1.479 + libc.declareLazyFFI(SysFile, "read", 1.480 + "read", ctypes.default_abi, 1.481 + /*return*/Type.negativeone_or_ssize_t, 1.482 + /*fd*/ Type.fd, 1.483 + /*buf*/ Type.void_t.out_ptr, 1.484 + /*nbytes*/Type.size_t); 1.485 + 1.486 + libc.declareLazyFFI(SysFile, "posix_fadvise", 1.487 + "posix_fadvise", ctypes.default_abi, 1.488 + /*return*/ Type.int, 1.489 + /*fd*/ Type.fd, 1.490 + /*offset*/ Type.off_t, 1.491 + /*len*/ Type.off_t, 1.492 + /*advise*/ Type.int); 1.493 + 1.494 + if (Const._DARWIN_FEATURE_64_BIT_INODE) { 1.495 + // Special case for MacOS X 10.5+ 1.496 + // Symbol name "readdir" still exists but is used for a 1.497 + // deprecated function that does not match the 1.498 + // constants of |Const|. 1.499 + libc.declareLazyFFI(SysFile, "readdir", 1.500 + "readdir$INODE64", ctypes.default_abi, 1.501 + /*return*/ Type.null_or_dirent_ptr, 1.502 + /*dir*/ Type.DIR.in_ptr); // For MacOS X 1.503 + } else if (OS.Constants.Sys.Name == "NetBSD") { 1.504 + libc.declareLazyFFI(SysFile, "readdir", 1.505 + "__readdir30", ctypes.default_abi, 1.506 + /*return*/Type.null_or_dirent_ptr, 1.507 + /*dir*/ Type.DIR.in_ptr); // Other Unices 1.508 + } else { 1.509 + libc.declareLazyFFI(SysFile, "readdir", 1.510 + "readdir", ctypes.default_abi, 1.511 + /*return*/Type.null_or_dirent_ptr, 1.512 + /*dir*/ Type.DIR.in_ptr); // Other Unices 1.513 + } 1.514 + 1.515 + libc.declareLazyFFI(SysFile, "rename", 1.516 + "rename", ctypes.default_abi, 1.517 + /*return*/ Type.negativeone_or_nothing, 1.518 + /*old*/ Type.path, 1.519 + /*new*/ Type.path); 1.520 + 1.521 + libc.declareLazyFFI(SysFile, "rmdir", 1.522 + "rmdir", ctypes.default_abi, 1.523 + /*return*/ Type.int, 1.524 + /*path*/ Type.path); 1.525 + 1.526 + libc.declareLazyFFI(SysFile, "splice", 1.527 + "splice", ctypes.default_abi, 1.528 + /*return*/ Type.long, 1.529 + /*fd_in*/ Type.fd, 1.530 + /*off_in*/ Type.off_t.in_ptr, 1.531 + /*fd_out*/ Type.fd, 1.532 + /*off_out*/Type.off_t.in_ptr, 1.533 + /*len*/ Type.size_t, 1.534 + /*flags*/ Type.unsigned_int); // Linux/Android-specific 1.535 + 1.536 + libc.declareLazyFFI(SysFile, "statvfs", 1.537 + "statvfs", ctypes.default_abi, 1.538 + /*return*/ Type.negativeone_or_nothing, 1.539 + /*path*/ Type.path, 1.540 + /*buf*/ Type.statvfs.out_ptr); 1.541 + 1.542 + libc.declareLazyFFI(SysFile, "symlink", 1.543 + "symlink", ctypes.default_abi, 1.544 + /*return*/ Type.negativeone_or_nothing, 1.545 + /*source*/ Type.path, 1.546 + /*dest*/ Type.path); 1.547 + 1.548 + libc.declareLazyFFI(SysFile, "truncate", 1.549 + "truncate", ctypes.default_abi, 1.550 + /*return*/Type.negativeone_or_nothing, 1.551 + /*path*/ Type.path, 1.552 + /*length*/ Type.off_t); 1.553 + 1.554 + libc.declareLazyFFI(SysFile, "unlink", 1.555 + "unlink", ctypes.default_abi, 1.556 + /*return*/ Type.negativeone_or_nothing, 1.557 + /*path*/ Type.path); 1.558 + 1.559 + libc.declareLazyFFI(SysFile, "write", 1.560 + "write", ctypes.default_abi, 1.561 + /*return*/ Type.negativeone_or_ssize_t, 1.562 + /*fd*/ Type.fd, 1.563 + /*buf*/ Type.void_t.in_ptr, 1.564 + /*nbytes*/ Type.size_t); 1.565 + 1.566 + // Weird cases that require special treatment 1.567 + 1.568 + // OSes use a variety of hacks to differentiate between 1.569 + // 32-bits and 64-bits versions of |stat|, |lstat|, |fstat|. 1.570 + if (Const._DARWIN_FEATURE_64_BIT_INODE) { 1.571 + // MacOS X 64-bits 1.572 + libc.declareLazyFFI(SysFile, "stat", 1.573 + "stat$INODE64", ctypes.default_abi, 1.574 + /*return*/ Type.negativeone_or_nothing, 1.575 + /*path*/ Type.path, 1.576 + /*buf*/ Type.stat.out_ptr 1.577 + ); 1.578 + libc.declareLazyFFI(SysFile, "lstat", 1.579 + "lstat$INODE64", ctypes.default_abi, 1.580 + /*return*/ Type.negativeone_or_nothing, 1.581 + /*path*/ Type.path, 1.582 + /*buf*/ Type.stat.out_ptr 1.583 + ); 1.584 + libc.declareLazyFFI(SysFile, "fstat", 1.585 + "fstat$INODE64", ctypes.default_abi, 1.586 + /*return*/ Type.negativeone_or_nothing, 1.587 + /*path*/ Type.fd, 1.588 + /*buf*/ Type.stat.out_ptr 1.589 + ); 1.590 + } else if (Const._STAT_VER != undefined) { 1.591 + const ver = Const._STAT_VER; 1.592 + let xstat_name, lxstat_name, fxstat_name; 1.593 + if (OS.Constants.Sys.Name == "SunOS") { 1.594 + // Solaris 1.595 + xstat_name = "_xstat"; 1.596 + lxstat_name = "_lxstat"; 1.597 + fxstat_name = "_fxstat"; 1.598 + } else { 1.599 + // Linux, all widths 1.600 + xstat_name = "__xstat"; 1.601 + lxstat_name = "__lxstat"; 1.602 + fxstat_name = "__fxstat"; 1.603 + } 1.604 + 1.605 + let Stat = {}; 1.606 + libc.declareLazyFFI(Stat, "xstat", 1.607 + xstat_name, ctypes.default_abi, 1.608 + /*return*/ Type.negativeone_or_nothing, 1.609 + /*_stat_ver*/ Type.int, 1.610 + /*path*/ Type.path, 1.611 + /*buf*/ Type.stat.out_ptr); 1.612 + libc.declareLazyFFI(Stat, "lxstat", 1.613 + lxstat_name, ctypes.default_abi, 1.614 + /*return*/ Type.negativeone_or_nothing, 1.615 + /*_stat_ver*/ Type.int, 1.616 + /*path*/ Type.path, 1.617 + /*buf*/ Type.stat.out_ptr); 1.618 + libc.declareLazyFFI(Stat, "fxstat", 1.619 + fxstat_name, ctypes.default_abi, 1.620 + /*return*/ Type.negativeone_or_nothing, 1.621 + /*_stat_ver*/ Type.int, 1.622 + /*fd*/ Type.fd, 1.623 + /*buf*/ Type.stat.out_ptr); 1.624 + 1.625 + 1.626 + SysFile.stat = function stat(path, buf) { 1.627 + return Stat.xstat(ver, path, buf); 1.628 + }; 1.629 + 1.630 + SysFile.lstat = function lstat(path, buf) { 1.631 + return Stat.lxstat(ver, path, buf); 1.632 + }; 1.633 + 1.634 + SysFile.fstat = function fstat(fd, buf) { 1.635 + return Stat.fxstat(ver, fd, buf); 1.636 + }; 1.637 + } else if (OS.Constants.Sys.Name == "NetBSD") { 1.638 + // NetBSD 5.0 and newer 1.639 + libc.declareLazyFFI(SysFile, "stat", 1.640 + "__stat50", ctypes.default_abi, 1.641 + /*return*/ Type.negativeone_or_nothing, 1.642 + /*path*/ Type.path, 1.643 + /*buf*/ Type.stat.out_ptr 1.644 + ); 1.645 + libc.declareLazyFFI(SysFile, "lstat", 1.646 + "__lstat50", ctypes.default_abi, 1.647 + /*return*/ Type.negativeone_or_nothing, 1.648 + /*path*/ Type.path, 1.649 + /*buf*/ Type.stat.out_ptr 1.650 + ); 1.651 + libc.declareLazyFFI(SysFile, "fstat", 1.652 + "__fstat50", ctypes.default_abi, 1.653 + /*return*/ Type.negativeone_or_nothing, 1.654 + /*fd*/ Type.fd, 1.655 + /*buf*/ Type.stat.out_ptr 1.656 + ); 1.657 + } else { 1.658 + // Mac OS X 32-bits, other Unix 1.659 + libc.declareLazyFFI(SysFile, "stat", 1.660 + "stat", ctypes.default_abi, 1.661 + /*return*/ Type.negativeone_or_nothing, 1.662 + /*path*/ Type.path, 1.663 + /*buf*/ Type.stat.out_ptr 1.664 + ); 1.665 + libc.declareLazyFFI(SysFile, "lstat", 1.666 + "lstat", ctypes.default_abi, 1.667 + /*return*/ Type.negativeone_or_nothing, 1.668 + /*path*/ Type.path, 1.669 + /*buf*/ Type.stat.out_ptr 1.670 + ); 1.671 + libc.declareLazyFFI(SysFile, "fstat", 1.672 + "fstat", ctypes.default_abi, 1.673 + /*return*/ Type.negativeone_or_nothing, 1.674 + /*fd*/ Type.fd, 1.675 + /*buf*/ Type.stat.out_ptr 1.676 + ); 1.677 + } 1.678 + 1.679 + // We cannot make a C array of CDataFinalizer, so 1.680 + // pipe cannot be directly defined as a C function. 1.681 + 1.682 + let Pipe = {}; 1.683 + libc.declareLazyFFI(Pipe, "_pipe", 1.684 + "pipe", ctypes.default_abi, 1.685 + /*return*/ Type.negativeone_or_nothing, 1.686 + /*fds*/ new SharedAll.Type("two file descriptors", 1.687 + ctypes.ArrayType(ctypes.int, 2))); 1.688 + 1.689 + // A shared per-thread buffer used to communicate with |pipe| 1.690 + let _pipebuf = new (ctypes.ArrayType(ctypes.int, 2))(); 1.691 + 1.692 + SysFile.pipe = function pipe(array) { 1.693 + let result = Pipe._pipe(_pipebuf); 1.694 + if (result == -1) { 1.695 + return result; 1.696 + } 1.697 + array[0] = ctypes.CDataFinalizer(_pipebuf[0], SysFile._close); 1.698 + array[1] = ctypes.CDataFinalizer(_pipebuf[1], SysFile._close); 1.699 + return result; 1.700 + }; 1.701 + 1.702 + if (OS.Constants.Sys.Name == "NetBSD") { 1.703 + libc.declareLazyFFI(SysFile, "utimes", 1.704 + "__utimes50", ctypes.default_abi, 1.705 + /*return*/ Type.negativeone_or_nothing, 1.706 + /*path*/ Type.path, 1.707 + /*timeval[2]*/ Type.timevals.out_ptr 1.708 + ); 1.709 + } else { 1.710 + libc.declareLazyFFI(SysFile, "utimes", 1.711 + "utimes", ctypes.default_abi, 1.712 + /*return*/ Type.negativeone_or_nothing, 1.713 + /*path*/ Type.path, 1.714 + /*timeval[2]*/ Type.timevals.out_ptr 1.715 + ); 1.716 + } 1.717 + if (OS.Constants.Sys.Name == "NetBSD") { 1.718 + libc.declareLazyFFI(SysFile, "futimes", 1.719 + "__futimes50", ctypes.default_abi, 1.720 + /*return*/ Type.negativeone_or_nothing, 1.721 + /*fd*/ Type.fd, 1.722 + /*timeval[2]*/ Type.timevals.out_ptr 1.723 + ); 1.724 + } else { 1.725 + libc.declareLazyFFI(SysFile, "futimes", 1.726 + "futimes", ctypes.default_abi, 1.727 + /*return*/ Type.negativeone_or_nothing, 1.728 + /*fd*/ Type.fd, 1.729 + /*timeval[2]*/ Type.timevals.out_ptr 1.730 + ); 1.731 + } 1.732 + }; 1.733 + 1.734 + exports.OS.Unix = { 1.735 + File: { 1.736 + _init: init 1.737 + } 1.738 + }; 1.739 + })(this); 1.740 +}