toolkit/components/osfile/modules/osfile_unix_back.jsm

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 {
michael@0 6 if (typeof Components != "undefined") {
michael@0 7 // We do not wish osfile_unix_back.jsm to be used directly as a main thread
michael@0 8 // module yet. When time comes, it will be loaded by a combination of
michael@0 9 // a main thread front-end/worker thread implementation that makes sure
michael@0 10 // that we are not executing synchronous IO code in the main thread.
michael@0 11
michael@0 12 throw new Error("osfile_unix_back.jsm cannot be used from the main thread yet");
michael@0 13 }
michael@0 14 (function(exports) {
michael@0 15 "use strict";
michael@0 16 if (exports.OS && exports.OS.Unix && exports.OS.Unix.File) {
michael@0 17 return; // Avoid double initialization
michael@0 18 }
michael@0 19
michael@0 20 let SharedAll =
michael@0 21 require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");
michael@0 22 let SysAll =
michael@0 23 require("resource://gre/modules/osfile/osfile_unix_allthreads.jsm");
michael@0 24 let LOG = SharedAll.LOG.bind(SharedAll, "Unix", "back");
michael@0 25 let libc = SysAll.libc;
michael@0 26 let Const = SharedAll.Constants.libc;
michael@0 27
michael@0 28 /**
michael@0 29 * Initialize the Unix module.
michael@0 30 *
michael@0 31 * @param {function=} declareFFI
michael@0 32 */
michael@0 33 // FIXME: Both |init| and |aDeclareFFI| are deprecated, we should remove them
michael@0 34 let init = function init(aDeclareFFI) {
michael@0 35 let declareFFI;
michael@0 36 if (aDeclareFFI) {
michael@0 37 declareFFI = aDeclareFFI.bind(null, libc);
michael@0 38 } else {
michael@0 39 declareFFI = SysAll.declareFFI;
michael@0 40 }
michael@0 41 let declareLazyFFI = SharedAll.declareLazyFFI;
michael@0 42
michael@0 43 // Initialize types that require additional OS-specific
michael@0 44 // support - either finalization or matching against
michael@0 45 // OS-specific constants.
michael@0 46 let Type = Object.create(SysAll.Type);
michael@0 47 let SysFile = exports.OS.Unix.File = { Type: Type };
michael@0 48
michael@0 49 /**
michael@0 50 * A file descriptor.
michael@0 51 */
michael@0 52 Type.fd = Type.int.withName("fd");
michael@0 53 Type.fd.importFromC = function importFromC(fd_int) {
michael@0 54 return ctypes.CDataFinalizer(fd_int, SysFile._close);
michael@0 55 };
michael@0 56
michael@0 57
michael@0 58 /**
michael@0 59 * A C integer holding -1 in case of error or a file descriptor
michael@0 60 * in case of success.
michael@0 61 */
michael@0 62 Type.negativeone_or_fd = Type.fd.withName("negativeone_or_fd");
michael@0 63 Type.negativeone_or_fd.importFromC =
michael@0 64 function importFromC(fd_int) {
michael@0 65 if (fd_int == -1) {
michael@0 66 return -1;
michael@0 67 }
michael@0 68 return ctypes.CDataFinalizer(fd_int, SysFile._close);
michael@0 69 };
michael@0 70
michael@0 71 /**
michael@0 72 * A C integer holding -1 in case of error or a meaningless value
michael@0 73 * in case of success.
michael@0 74 */
michael@0 75 Type.negativeone_or_nothing =
michael@0 76 Type.int.withName("negativeone_or_nothing");
michael@0 77
michael@0 78 /**
michael@0 79 * A C integer holding -1 in case of error or a positive integer
michael@0 80 * in case of success.
michael@0 81 */
michael@0 82 Type.negativeone_or_ssize_t =
michael@0 83 Type.ssize_t.withName("negativeone_or_ssize_t");
michael@0 84
michael@0 85 /**
michael@0 86 * Various libc integer types
michael@0 87 */
michael@0 88 Type.mode_t =
michael@0 89 Type.intn_t(Const.OSFILE_SIZEOF_MODE_T).withName("mode_t");
michael@0 90 Type.uid_t =
michael@0 91 Type.intn_t(Const.OSFILE_SIZEOF_UID_T).withName("uid_t");
michael@0 92 Type.gid_t =
michael@0 93 Type.intn_t(Const.OSFILE_SIZEOF_GID_T).withName("gid_t");
michael@0 94
michael@0 95 /**
michael@0 96 * Type |time_t|
michael@0 97 */
michael@0 98 Type.time_t =
michael@0 99 Type.intn_t(Const.OSFILE_SIZEOF_TIME_T).withName("time_t");
michael@0 100
michael@0 101 // Structure |dirent|
michael@0 102 // Building this type is rather complicated, as its layout varies between
michael@0 103 // variants of Unix. For this reason, we rely on a number of constants
michael@0 104 // (computed in C from the C data structures) that give us the layout.
michael@0 105 // The structure we compute looks like
michael@0 106 // { int8_t[...] before_d_type; // ignored content
michael@0 107 // int8_t d_type ;
michael@0 108 // int8_t[...] before_d_name; // ignored content
michael@0 109 // char[...] d_name;
michael@0 110 // };
michael@0 111 {
michael@0 112 let d_name_extra_size = 0;
michael@0 113 if (Const.OSFILE_SIZEOF_DIRENT_D_NAME < 8) {
michael@0 114 // d_name is defined like "char d_name[1];" on some platforms
michael@0 115 // (e.g. Solaris), we need to give it more size for our structure.
michael@0 116 d_name_extra_size = 256;
michael@0 117 }
michael@0 118
michael@0 119 let dirent = new SharedAll.HollowStructure("dirent",
michael@0 120 Const.OSFILE_SIZEOF_DIRENT + d_name_extra_size);
michael@0 121 if (Const.OSFILE_OFFSETOF_DIRENT_D_TYPE != undefined) {
michael@0 122 // |dirent| doesn't have d_type on some platforms (e.g. Solaris).
michael@0 123 dirent.add_field_at(Const.OSFILE_OFFSETOF_DIRENT_D_TYPE,
michael@0 124 "d_type", ctypes.uint8_t);
michael@0 125 }
michael@0 126 dirent.add_field_at(Const.OSFILE_OFFSETOF_DIRENT_D_NAME,
michael@0 127 "d_name", ctypes.ArrayType(ctypes.char,
michael@0 128 Const.OSFILE_SIZEOF_DIRENT_D_NAME + d_name_extra_size));
michael@0 129
michael@0 130 // We now have built |dirent|.
michael@0 131 Type.dirent = dirent.getType();
michael@0 132 }
michael@0 133 Type.null_or_dirent_ptr =
michael@0 134 new SharedAll.Type("null_of_dirent",
michael@0 135 Type.dirent.out_ptr.implementation);
michael@0 136
michael@0 137 // Structure |stat|
michael@0 138 // Same technique
michael@0 139 {
michael@0 140 let stat = new SharedAll.HollowStructure("stat",
michael@0 141 Const.OSFILE_SIZEOF_STAT);
michael@0 142 stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_MODE,
michael@0 143 "st_mode", Type.mode_t.implementation);
michael@0 144 stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_UID,
michael@0 145 "st_uid", Type.uid_t.implementation);
michael@0 146 stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_GID,
michael@0 147 "st_gid", Type.gid_t.implementation);
michael@0 148
michael@0 149 // Here, things get complicated with different data structures.
michael@0 150 // Some platforms have |time_t st_atime| and some platforms have
michael@0 151 // |timespec st_atimespec|. However, since |timespec| starts with
michael@0 152 // a |time_t|, followed by nanoseconds, we just cheat and pretend
michael@0 153 // that everybody has |time_t st_atime|, possibly followed by padding
michael@0 154 stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_ATIME,
michael@0 155 "st_atime", Type.time_t.implementation);
michael@0 156 stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_MTIME,
michael@0 157 "st_mtime", Type.time_t.implementation);
michael@0 158 stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_CTIME,
michael@0 159 "st_ctime", Type.time_t.implementation);
michael@0 160
michael@0 161 // To complicate further, MacOS and some BSDs have a field |birthtime|
michael@0 162 if ("OSFILE_OFFSETOF_STAT_ST_BIRTHTIME" in Const) {
michael@0 163 stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_BIRTHTIME,
michael@0 164 "st_birthtime", Type.time_t.implementation);
michael@0 165 }
michael@0 166
michael@0 167 stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_SIZE,
michael@0 168 "st_size", Type.off_t.implementation);
michael@0 169 Type.stat = stat.getType();
michael@0 170 }
michael@0 171
michael@0 172 // Structure |DIR|
michael@0 173 if ("OSFILE_SIZEOF_DIR" in Const) {
michael@0 174 // On platforms for which we need to access the fields of DIR
michael@0 175 // directly (e.g. because certain functions are implemented
michael@0 176 // as macros), we need to define DIR as a hollow structure.
michael@0 177 let DIR = new SharedAll.HollowStructure(
michael@0 178 "DIR",
michael@0 179 Const.OSFILE_SIZEOF_DIR);
michael@0 180
michael@0 181 DIR.add_field_at(
michael@0 182 Const.OSFILE_OFFSETOF_DIR_DD_FD,
michael@0 183 "dd_fd",
michael@0 184 Type.fd.implementation);
michael@0 185
michael@0 186 Type.DIR = DIR.getType();
michael@0 187 } else {
michael@0 188 // On other platforms, we keep DIR as a blackbox
michael@0 189 Type.DIR =
michael@0 190 new SharedAll.Type("DIR",
michael@0 191 ctypes.StructType("DIR"));
michael@0 192 }
michael@0 193
michael@0 194 Type.null_or_DIR_ptr =
michael@0 195 Type.DIR.out_ptr.withName("null_or_DIR*");
michael@0 196 Type.null_or_DIR_ptr.importFromC = function importFromC(dir) {
michael@0 197 if (dir == null || dir.isNull()) {
michael@0 198 return null;
michael@0 199 }
michael@0 200 return ctypes.CDataFinalizer(dir, SysFile._close_dir);
michael@0 201 };
michael@0 202
michael@0 203 // Structure |timeval|
michael@0 204 {
michael@0 205 let timeval = new SharedAll.HollowStructure(
michael@0 206 "timeval",
michael@0 207 Const.OSFILE_SIZEOF_TIMEVAL);
michael@0 208 timeval.add_field_at(
michael@0 209 Const.OSFILE_OFFSETOF_TIMEVAL_TV_SEC,
michael@0 210 "tv_sec",
michael@0 211 Type.long.implementation);
michael@0 212 timeval.add_field_at(
michael@0 213 Const.OSFILE_OFFSETOF_TIMEVAL_TV_USEC,
michael@0 214 "tv_usec",
michael@0 215 Type.long.implementation);
michael@0 216 Type.timeval = timeval.getType();
michael@0 217 Type.timevals = new SharedAll.Type("two timevals",
michael@0 218 ctypes.ArrayType(Type.timeval.implementation, 2));
michael@0 219 }
michael@0 220
michael@0 221 // Types fsblkcnt_t and fsfilcnt_t, used by structure |statvfs|
michael@0 222 Type.fsblkcnt_t =
michael@0 223 Type.uintn_t(Const.OSFILE_SIZEOF_FSBLKCNT_T).withName("fsblkcnt_t");
michael@0 224
michael@0 225 // Structure |statvfs|
michael@0 226 // Use an hollow structure
michael@0 227 {
michael@0 228 let statvfs = new SharedAll.HollowStructure("statvfs",
michael@0 229 Const.OSFILE_SIZEOF_STATVFS);
michael@0 230
michael@0 231 statvfs.add_field_at(Const.OSFILE_OFFSETOF_STATVFS_F_BSIZE,
michael@0 232 "f_bsize", Type.unsigned_long.implementation);
michael@0 233 statvfs.add_field_at(Const.OSFILE_OFFSETOF_STATVFS_F_BAVAIL,
michael@0 234 "f_bavail", Type.fsblkcnt_t.implementation);
michael@0 235
michael@0 236 Type.statvfs = statvfs.getType();
michael@0 237 }
michael@0 238
michael@0 239 // Declare libc functions as functions of |OS.Unix.File|
michael@0 240
michael@0 241 // Finalizer-related functions
michael@0 242 libc.declareLazy(SysFile, "_close",
michael@0 243 "close", ctypes.default_abi,
michael@0 244 /*return */ctypes.int,
michael@0 245 /*fd*/ ctypes.int);
michael@0 246
michael@0 247 SysFile.close = function close(fd) {
michael@0 248 // Detach the finalizer and call |_close|.
michael@0 249 return fd.dispose();
michael@0 250 };
michael@0 251
michael@0 252 libc.declareLazy(SysFile, "_close_dir",
michael@0 253 "closedir", ctypes.default_abi,
michael@0 254 /*return */ctypes.int,
michael@0 255 /*dirp*/ Type.DIR.in_ptr.implementation);
michael@0 256
michael@0 257 SysFile.closedir = function closedir(fd) {
michael@0 258 // Detach the finalizer and call |_close_dir|.
michael@0 259 return fd.dispose();
michael@0 260 };
michael@0 261
michael@0 262 {
michael@0 263 // Symbol free() is special.
michael@0 264 // We override the definition of free() on several platforms.
michael@0 265 let default_lib = new SharedAll.Library("default_lib",
michael@0 266 "a.out");
michael@0 267 try {
michael@0 268 // On platforms for which we override free(), nspr defines
michael@0 269 // a special library name "a.out" that will resolve to the
michael@0 270 // correct implementation free().
michael@0 271
michael@0 272 default_lib.declareLazy(SysFile, "free",
michael@0 273 "free", ctypes.default_abi,
michael@0 274 /*return*/ ctypes.void_t,
michael@0 275 /*ptr*/ ctypes.voidptr_t);
michael@0 276
michael@0 277 } catch (ex) {
michael@0 278 // We don't have an a.out library or a.out doesn't contain free.
michael@0 279 // Either way, use the ordinary libc free.
michael@0 280
michael@0 281 libc.declareLazy(SysFile, "free",
michael@0 282 "free", ctypes.default_abi,
michael@0 283 /*return*/ ctypes.void_t,
michael@0 284 /*ptr*/ ctypes.voidptr_t);
michael@0 285 }
michael@0 286 }
michael@0 287
michael@0 288
michael@0 289 // Other functions
michael@0 290 libc.declareLazyFFI(SysFile, "access",
michael@0 291 "access", ctypes.default_abi,
michael@0 292 /*return*/ Type.negativeone_or_nothing,
michael@0 293 /*path*/ Type.path,
michael@0 294 /*mode*/ Type.int);
michael@0 295
michael@0 296 libc.declareLazyFFI(SysFile, "chdir",
michael@0 297 "chdir", ctypes.default_abi,
michael@0 298 /*return*/ Type.negativeone_or_nothing,
michael@0 299 /*path*/ Type.path);
michael@0 300
michael@0 301 libc.declareLazyFFI(SysFile, "chmod",
michael@0 302 "chmod", ctypes.default_abi,
michael@0 303 /*return*/ Type.negativeone_or_nothing,
michael@0 304 /*path*/ Type.path,
michael@0 305 /*mode*/ Type.mode_t);
michael@0 306
michael@0 307 libc.declareLazyFFI(SysFile, "chown",
michael@0 308 "chown", ctypes.default_abi,
michael@0 309 /*return*/ Type.negativeone_or_nothing,
michael@0 310 /*path*/ Type.path,
michael@0 311 /*uid*/ Type.uid_t,
michael@0 312 /*gid*/ Type.gid_t);
michael@0 313
michael@0 314 libc.declareLazyFFI(SysFile, "copyfile",
michael@0 315 "copyfile", ctypes.default_abi,
michael@0 316 /*return*/ Type.negativeone_or_nothing,
michael@0 317 /*source*/ Type.path,
michael@0 318 /*dest*/ Type.path,
michael@0 319 /*state*/ Type.void_t.in_ptr, // Ignored atm
michael@0 320 /*flags*/ Type.uint32_t);
michael@0 321
michael@0 322 libc.declareLazyFFI(SysFile, "dup",
michael@0 323 "dup", ctypes.default_abi,
michael@0 324 /*return*/ Type.negativeone_or_fd,
michael@0 325 /*fd*/ Type.fd);
michael@0 326
michael@0 327 if ("OSFILE_SIZEOF_DIR" in Const) {
michael@0 328 // On platforms for which |dirfd| is a macro
michael@0 329 SysFile.dirfd =
michael@0 330 function dirfd(DIRp) {
michael@0 331 return Type.DIR.in_ptr.implementation(DIRp).contents.dd_fd;
michael@0 332 };
michael@0 333 } else {
michael@0 334 // On platforms for which |dirfd| is a function
michael@0 335 libc.declareLazyFFI(SysFile, "dirfd",
michael@0 336 "dirfd", ctypes.default_abi,
michael@0 337 /*return*/ Type.negativeone_or_fd,
michael@0 338 /*dir*/ Type.DIR.in_ptr);
michael@0 339 }
michael@0 340
michael@0 341 libc.declareLazyFFI(SysFile, "chdir",
michael@0 342 "chdir", ctypes.default_abi,
michael@0 343 /*return*/ Type.negativeone_or_nothing,
michael@0 344 /*path*/ Type.path);
michael@0 345
michael@0 346 libc.declareLazyFFI(SysFile, "fchdir",
michael@0 347 "fchdir", ctypes.default_abi,
michael@0 348 /*return*/ Type.negativeone_or_nothing,
michael@0 349 /*fd*/ Type.fd);
michael@0 350
michael@0 351 libc.declareLazyFFI(SysFile, "fchmod",
michael@0 352 "fchmod", ctypes.default_abi,
michael@0 353 /*return*/ Type.negativeone_or_nothing,
michael@0 354 /*fd*/ Type.fd,
michael@0 355 /*mode*/ Type.mode_t);
michael@0 356
michael@0 357 libc.declareLazyFFI(SysFile, "fchown",
michael@0 358 "fchown", ctypes.default_abi,
michael@0 359 /*return*/ Type.negativeone_or_nothing,
michael@0 360 /*fd*/ Type.fd,
michael@0 361 /*uid_t*/ Type.uid_t,
michael@0 362 /*gid_t*/ Type.gid_t);
michael@0 363
michael@0 364 libc.declareLazyFFI(SysFile, "fsync",
michael@0 365 "fsync", ctypes.default_abi,
michael@0 366 /*return*/ Type.negativeone_or_nothing,
michael@0 367 /*fd*/ Type.fd);
michael@0 368
michael@0 369 libc.declareLazyFFI(SysFile, "getcwd",
michael@0 370 "getcwd", ctypes.default_abi,
michael@0 371 /*return*/ Type.out_path,
michael@0 372 /*buf*/ Type.out_path,
michael@0 373 /*size*/ Type.size_t);
michael@0 374
michael@0 375 libc.declareLazyFFI(SysFile, "getwd",
michael@0 376 "getwd", ctypes.default_abi,
michael@0 377 /*return*/ Type.out_path,
michael@0 378 /*buf*/ Type.out_path);
michael@0 379
michael@0 380 // Two variants of |getwd| which allocate the memory
michael@0 381 // dynamically.
michael@0 382
michael@0 383 // Linux/Android version
michael@0 384 libc.declareLazyFFI(SysFile, "get_current_dir_name",
michael@0 385 "get_current_dir_name", ctypes.default_abi,
michael@0 386 /*return*/ Type.out_path.releaseWithLazy(() =>
michael@0 387 SysFile.free
michael@0 388 ));
michael@0 389
michael@0 390 // MacOS/BSD version (will return NULL on Linux/Android)
michael@0 391 libc.declareLazyFFI(SysFile, "getwd_auto",
michael@0 392 "getwd", ctypes.default_abi,
michael@0 393 /*return*/ Type.out_path.releaseWithLazy(() =>
michael@0 394 SysFile.free
michael@0 395 ),
michael@0 396 /*buf*/ Type.void_t.out_ptr);
michael@0 397
michael@0 398 libc.declareLazyFFI(SysFile, "fdatasync",
michael@0 399 "fdatasync", ctypes.default_abi,
michael@0 400 /*return*/ Type.negativeone_or_nothing,
michael@0 401 /*fd*/ Type.fd); // Note: MacOS/BSD-specific
michael@0 402
michael@0 403 libc.declareLazyFFI(SysFile, "ftruncate",
michael@0 404 "ftruncate", ctypes.default_abi,
michael@0 405 /*return*/ Type.negativeone_or_nothing,
michael@0 406 /*fd*/ Type.fd,
michael@0 407 /*length*/ Type.off_t);
michael@0 408
michael@0 409
michael@0 410 libc.declareLazyFFI(SysFile, "lchown",
michael@0 411 "lchown", ctypes.default_abi,
michael@0 412 /*return*/ Type.negativeone_or_nothing,
michael@0 413 /*path*/ Type.path,
michael@0 414 /*uid_t*/ Type.uid_t,
michael@0 415 /*gid_t*/ Type.gid_t);
michael@0 416
michael@0 417 libc.declareLazyFFI(SysFile, "link",
michael@0 418 "link", ctypes.default_abi,
michael@0 419 /*return*/ Type.negativeone_or_nothing,
michael@0 420 /*source*/ Type.path,
michael@0 421 /*dest*/ Type.path);
michael@0 422
michael@0 423 libc.declareLazyFFI(SysFile, "lseek",
michael@0 424 "lseek", ctypes.default_abi,
michael@0 425 /*return*/ Type.off_t,
michael@0 426 /*fd*/ Type.fd,
michael@0 427 /*offset*/ Type.off_t,
michael@0 428 /*whence*/ Type.int);
michael@0 429
michael@0 430 libc.declareLazyFFI(SysFile, "mkdir",
michael@0 431 "mkdir", ctypes.default_abi,
michael@0 432 /*return*/ Type.int,
michael@0 433 /*path*/ Type.path,
michael@0 434 /*mode*/ Type.int);
michael@0 435
michael@0 436 libc.declareLazyFFI(SysFile, "mkstemp",
michael@0 437 "mkstemp", ctypes.default_abi,
michael@0 438 /*return*/ Type.fd,
michael@0 439 /*template*/ Type.out_path);
michael@0 440
michael@0 441 libc.declareLazyFFI(SysFile, "open",
michael@0 442 "open", ctypes.default_abi,
michael@0 443 /*return*/ Type.negativeone_or_fd,
michael@0 444 /*path*/ Type.path,
michael@0 445 /*oflags*/ Type.int,
michael@0 446 /*mode*/ Type.int);
michael@0 447
michael@0 448 if (OS.Constants.Sys.Name == "NetBSD") {
michael@0 449 libc.declareLazyFFI(SysFile, "opendir",
michael@0 450 "__opendir30", ctypes.default_abi,
michael@0 451 /*return*/ Type.null_or_DIR_ptr,
michael@0 452 /*path*/ Type.path);
michael@0 453 } else {
michael@0 454 libc.declareLazyFFI(SysFile, "opendir",
michael@0 455 "opendir", ctypes.default_abi,
michael@0 456 /*return*/ Type.null_or_DIR_ptr,
michael@0 457 /*path*/ Type.path);
michael@0 458 }
michael@0 459
michael@0 460 libc.declareLazyFFI(SysFile, "pread",
michael@0 461 "pread", ctypes.default_abi,
michael@0 462 /*return*/ Type.negativeone_or_ssize_t,
michael@0 463 /*fd*/ Type.fd,
michael@0 464 /*buf*/ Type.void_t.out_ptr,
michael@0 465 /*nbytes*/ Type.size_t,
michael@0 466 /*offset*/ Type.off_t);
michael@0 467
michael@0 468 libc.declareLazyFFI(SysFile, "pwrite",
michael@0 469 "pwrite", ctypes.default_abi,
michael@0 470 /*return*/ Type.negativeone_or_ssize_t,
michael@0 471 /*fd*/ Type.fd,
michael@0 472 /*buf*/ Type.void_t.in_ptr,
michael@0 473 /*nbytes*/ Type.size_t,
michael@0 474 /*offset*/ Type.off_t);
michael@0 475
michael@0 476 libc.declareLazyFFI(SysFile, "read",
michael@0 477 "read", ctypes.default_abi,
michael@0 478 /*return*/Type.negativeone_or_ssize_t,
michael@0 479 /*fd*/ Type.fd,
michael@0 480 /*buf*/ Type.void_t.out_ptr,
michael@0 481 /*nbytes*/Type.size_t);
michael@0 482
michael@0 483 libc.declareLazyFFI(SysFile, "posix_fadvise",
michael@0 484 "posix_fadvise", ctypes.default_abi,
michael@0 485 /*return*/ Type.int,
michael@0 486 /*fd*/ Type.fd,
michael@0 487 /*offset*/ Type.off_t,
michael@0 488 /*len*/ Type.off_t,
michael@0 489 /*advise*/ Type.int);
michael@0 490
michael@0 491 if (Const._DARWIN_FEATURE_64_BIT_INODE) {
michael@0 492 // Special case for MacOS X 10.5+
michael@0 493 // Symbol name "readdir" still exists but is used for a
michael@0 494 // deprecated function that does not match the
michael@0 495 // constants of |Const|.
michael@0 496 libc.declareLazyFFI(SysFile, "readdir",
michael@0 497 "readdir$INODE64", ctypes.default_abi,
michael@0 498 /*return*/ Type.null_or_dirent_ptr,
michael@0 499 /*dir*/ Type.DIR.in_ptr); // For MacOS X
michael@0 500 } else if (OS.Constants.Sys.Name == "NetBSD") {
michael@0 501 libc.declareLazyFFI(SysFile, "readdir",
michael@0 502 "__readdir30", ctypes.default_abi,
michael@0 503 /*return*/Type.null_or_dirent_ptr,
michael@0 504 /*dir*/ Type.DIR.in_ptr); // Other Unices
michael@0 505 } else {
michael@0 506 libc.declareLazyFFI(SysFile, "readdir",
michael@0 507 "readdir", ctypes.default_abi,
michael@0 508 /*return*/Type.null_or_dirent_ptr,
michael@0 509 /*dir*/ Type.DIR.in_ptr); // Other Unices
michael@0 510 }
michael@0 511
michael@0 512 libc.declareLazyFFI(SysFile, "rename",
michael@0 513 "rename", ctypes.default_abi,
michael@0 514 /*return*/ Type.negativeone_or_nothing,
michael@0 515 /*old*/ Type.path,
michael@0 516 /*new*/ Type.path);
michael@0 517
michael@0 518 libc.declareLazyFFI(SysFile, "rmdir",
michael@0 519 "rmdir", ctypes.default_abi,
michael@0 520 /*return*/ Type.int,
michael@0 521 /*path*/ Type.path);
michael@0 522
michael@0 523 libc.declareLazyFFI(SysFile, "splice",
michael@0 524 "splice", ctypes.default_abi,
michael@0 525 /*return*/ Type.long,
michael@0 526 /*fd_in*/ Type.fd,
michael@0 527 /*off_in*/ Type.off_t.in_ptr,
michael@0 528 /*fd_out*/ Type.fd,
michael@0 529 /*off_out*/Type.off_t.in_ptr,
michael@0 530 /*len*/ Type.size_t,
michael@0 531 /*flags*/ Type.unsigned_int); // Linux/Android-specific
michael@0 532
michael@0 533 libc.declareLazyFFI(SysFile, "statvfs",
michael@0 534 "statvfs", ctypes.default_abi,
michael@0 535 /*return*/ Type.negativeone_or_nothing,
michael@0 536 /*path*/ Type.path,
michael@0 537 /*buf*/ Type.statvfs.out_ptr);
michael@0 538
michael@0 539 libc.declareLazyFFI(SysFile, "symlink",
michael@0 540 "symlink", ctypes.default_abi,
michael@0 541 /*return*/ Type.negativeone_or_nothing,
michael@0 542 /*source*/ Type.path,
michael@0 543 /*dest*/ Type.path);
michael@0 544
michael@0 545 libc.declareLazyFFI(SysFile, "truncate",
michael@0 546 "truncate", ctypes.default_abi,
michael@0 547 /*return*/Type.negativeone_or_nothing,
michael@0 548 /*path*/ Type.path,
michael@0 549 /*length*/ Type.off_t);
michael@0 550
michael@0 551 libc.declareLazyFFI(SysFile, "unlink",
michael@0 552 "unlink", ctypes.default_abi,
michael@0 553 /*return*/ Type.negativeone_or_nothing,
michael@0 554 /*path*/ Type.path);
michael@0 555
michael@0 556 libc.declareLazyFFI(SysFile, "write",
michael@0 557 "write", ctypes.default_abi,
michael@0 558 /*return*/ Type.negativeone_or_ssize_t,
michael@0 559 /*fd*/ Type.fd,
michael@0 560 /*buf*/ Type.void_t.in_ptr,
michael@0 561 /*nbytes*/ Type.size_t);
michael@0 562
michael@0 563 // Weird cases that require special treatment
michael@0 564
michael@0 565 // OSes use a variety of hacks to differentiate between
michael@0 566 // 32-bits and 64-bits versions of |stat|, |lstat|, |fstat|.
michael@0 567 if (Const._DARWIN_FEATURE_64_BIT_INODE) {
michael@0 568 // MacOS X 64-bits
michael@0 569 libc.declareLazyFFI(SysFile, "stat",
michael@0 570 "stat$INODE64", ctypes.default_abi,
michael@0 571 /*return*/ Type.negativeone_or_nothing,
michael@0 572 /*path*/ Type.path,
michael@0 573 /*buf*/ Type.stat.out_ptr
michael@0 574 );
michael@0 575 libc.declareLazyFFI(SysFile, "lstat",
michael@0 576 "lstat$INODE64", ctypes.default_abi,
michael@0 577 /*return*/ Type.negativeone_or_nothing,
michael@0 578 /*path*/ Type.path,
michael@0 579 /*buf*/ Type.stat.out_ptr
michael@0 580 );
michael@0 581 libc.declareLazyFFI(SysFile, "fstat",
michael@0 582 "fstat$INODE64", ctypes.default_abi,
michael@0 583 /*return*/ Type.negativeone_or_nothing,
michael@0 584 /*path*/ Type.fd,
michael@0 585 /*buf*/ Type.stat.out_ptr
michael@0 586 );
michael@0 587 } else if (Const._STAT_VER != undefined) {
michael@0 588 const ver = Const._STAT_VER;
michael@0 589 let xstat_name, lxstat_name, fxstat_name;
michael@0 590 if (OS.Constants.Sys.Name == "SunOS") {
michael@0 591 // Solaris
michael@0 592 xstat_name = "_xstat";
michael@0 593 lxstat_name = "_lxstat";
michael@0 594 fxstat_name = "_fxstat";
michael@0 595 } else {
michael@0 596 // Linux, all widths
michael@0 597 xstat_name = "__xstat";
michael@0 598 lxstat_name = "__lxstat";
michael@0 599 fxstat_name = "__fxstat";
michael@0 600 }
michael@0 601
michael@0 602 let Stat = {};
michael@0 603 libc.declareLazyFFI(Stat, "xstat",
michael@0 604 xstat_name, ctypes.default_abi,
michael@0 605 /*return*/ Type.negativeone_or_nothing,
michael@0 606 /*_stat_ver*/ Type.int,
michael@0 607 /*path*/ Type.path,
michael@0 608 /*buf*/ Type.stat.out_ptr);
michael@0 609 libc.declareLazyFFI(Stat, "lxstat",
michael@0 610 lxstat_name, ctypes.default_abi,
michael@0 611 /*return*/ Type.negativeone_or_nothing,
michael@0 612 /*_stat_ver*/ Type.int,
michael@0 613 /*path*/ Type.path,
michael@0 614 /*buf*/ Type.stat.out_ptr);
michael@0 615 libc.declareLazyFFI(Stat, "fxstat",
michael@0 616 fxstat_name, ctypes.default_abi,
michael@0 617 /*return*/ Type.negativeone_or_nothing,
michael@0 618 /*_stat_ver*/ Type.int,
michael@0 619 /*fd*/ Type.fd,
michael@0 620 /*buf*/ Type.stat.out_ptr);
michael@0 621
michael@0 622
michael@0 623 SysFile.stat = function stat(path, buf) {
michael@0 624 return Stat.xstat(ver, path, buf);
michael@0 625 };
michael@0 626
michael@0 627 SysFile.lstat = function lstat(path, buf) {
michael@0 628 return Stat.lxstat(ver, path, buf);
michael@0 629 };
michael@0 630
michael@0 631 SysFile.fstat = function fstat(fd, buf) {
michael@0 632 return Stat.fxstat(ver, fd, buf);
michael@0 633 };
michael@0 634 } else if (OS.Constants.Sys.Name == "NetBSD") {
michael@0 635 // NetBSD 5.0 and newer
michael@0 636 libc.declareLazyFFI(SysFile, "stat",
michael@0 637 "__stat50", ctypes.default_abi,
michael@0 638 /*return*/ Type.negativeone_or_nothing,
michael@0 639 /*path*/ Type.path,
michael@0 640 /*buf*/ Type.stat.out_ptr
michael@0 641 );
michael@0 642 libc.declareLazyFFI(SysFile, "lstat",
michael@0 643 "__lstat50", ctypes.default_abi,
michael@0 644 /*return*/ Type.negativeone_or_nothing,
michael@0 645 /*path*/ Type.path,
michael@0 646 /*buf*/ Type.stat.out_ptr
michael@0 647 );
michael@0 648 libc.declareLazyFFI(SysFile, "fstat",
michael@0 649 "__fstat50", ctypes.default_abi,
michael@0 650 /*return*/ Type.negativeone_or_nothing,
michael@0 651 /*fd*/ Type.fd,
michael@0 652 /*buf*/ Type.stat.out_ptr
michael@0 653 );
michael@0 654 } else {
michael@0 655 // Mac OS X 32-bits, other Unix
michael@0 656 libc.declareLazyFFI(SysFile, "stat",
michael@0 657 "stat", ctypes.default_abi,
michael@0 658 /*return*/ Type.negativeone_or_nothing,
michael@0 659 /*path*/ Type.path,
michael@0 660 /*buf*/ Type.stat.out_ptr
michael@0 661 );
michael@0 662 libc.declareLazyFFI(SysFile, "lstat",
michael@0 663 "lstat", ctypes.default_abi,
michael@0 664 /*return*/ Type.negativeone_or_nothing,
michael@0 665 /*path*/ Type.path,
michael@0 666 /*buf*/ Type.stat.out_ptr
michael@0 667 );
michael@0 668 libc.declareLazyFFI(SysFile, "fstat",
michael@0 669 "fstat", ctypes.default_abi,
michael@0 670 /*return*/ Type.negativeone_or_nothing,
michael@0 671 /*fd*/ Type.fd,
michael@0 672 /*buf*/ Type.stat.out_ptr
michael@0 673 );
michael@0 674 }
michael@0 675
michael@0 676 // We cannot make a C array of CDataFinalizer, so
michael@0 677 // pipe cannot be directly defined as a C function.
michael@0 678
michael@0 679 let Pipe = {};
michael@0 680 libc.declareLazyFFI(Pipe, "_pipe",
michael@0 681 "pipe", ctypes.default_abi,
michael@0 682 /*return*/ Type.negativeone_or_nothing,
michael@0 683 /*fds*/ new SharedAll.Type("two file descriptors",
michael@0 684 ctypes.ArrayType(ctypes.int, 2)));
michael@0 685
michael@0 686 // A shared per-thread buffer used to communicate with |pipe|
michael@0 687 let _pipebuf = new (ctypes.ArrayType(ctypes.int, 2))();
michael@0 688
michael@0 689 SysFile.pipe = function pipe(array) {
michael@0 690 let result = Pipe._pipe(_pipebuf);
michael@0 691 if (result == -1) {
michael@0 692 return result;
michael@0 693 }
michael@0 694 array[0] = ctypes.CDataFinalizer(_pipebuf[0], SysFile._close);
michael@0 695 array[1] = ctypes.CDataFinalizer(_pipebuf[1], SysFile._close);
michael@0 696 return result;
michael@0 697 };
michael@0 698
michael@0 699 if (OS.Constants.Sys.Name == "NetBSD") {
michael@0 700 libc.declareLazyFFI(SysFile, "utimes",
michael@0 701 "__utimes50", ctypes.default_abi,
michael@0 702 /*return*/ Type.negativeone_or_nothing,
michael@0 703 /*path*/ Type.path,
michael@0 704 /*timeval[2]*/ Type.timevals.out_ptr
michael@0 705 );
michael@0 706 } else {
michael@0 707 libc.declareLazyFFI(SysFile, "utimes",
michael@0 708 "utimes", ctypes.default_abi,
michael@0 709 /*return*/ Type.negativeone_or_nothing,
michael@0 710 /*path*/ Type.path,
michael@0 711 /*timeval[2]*/ Type.timevals.out_ptr
michael@0 712 );
michael@0 713 }
michael@0 714 if (OS.Constants.Sys.Name == "NetBSD") {
michael@0 715 libc.declareLazyFFI(SysFile, "futimes",
michael@0 716 "__futimes50", ctypes.default_abi,
michael@0 717 /*return*/ Type.negativeone_or_nothing,
michael@0 718 /*fd*/ Type.fd,
michael@0 719 /*timeval[2]*/ Type.timevals.out_ptr
michael@0 720 );
michael@0 721 } else {
michael@0 722 libc.declareLazyFFI(SysFile, "futimes",
michael@0 723 "futimes", ctypes.default_abi,
michael@0 724 /*return*/ Type.negativeone_or_nothing,
michael@0 725 /*fd*/ Type.fd,
michael@0 726 /*timeval[2]*/ Type.timevals.out_ptr
michael@0 727 );
michael@0 728 }
michael@0 729 };
michael@0 730
michael@0 731 exports.OS.Unix = {
michael@0 732 File: {
michael@0 733 _init: init
michael@0 734 }
michael@0 735 };
michael@0 736 })(this);
michael@0 737 }

mercurial