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.

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

mercurial