"Fossies" - the Fresh Open Source Software Archive

Member "UXP-2019.06.08/toolkit/components/osfile/modules/osfile_unix_back.jsm" (8 Jun 2019, 29912 Bytes) of package /linux/www/UXP-2019.06.08.tar.gz:


As a special service "Fossies" has tried to format the requested text file into HTML format (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "osfile_unix_back.jsm": 2019.03.27_vs_2019.06.08.

    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/. */
    4 
    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.
   11 
   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      }
   19 
   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;
   27 
   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;
   42 
   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 };
   48 
   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        };
   56 
   57 
   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          };
   70 
   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");
   77 
   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");
   84 
   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");
   94 
   95        /**
   96         * Type |time_t|
   97         */
   98        Type.time_t =
   99          Type.intn_t(Const.OSFILE_SIZEOF_TIME_T).withName("time_t");
  100 
  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          }
  118 
  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));
  129 
  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);
  136 
  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);
  148 
  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);
  160 
  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          }
  166 
  167          stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_SIZE,
  168                         "st_size", Type.off_t.implementation);
  169          Type.stat = stat.getType();
  170        }
  171 
  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);
  180 
  181          DIR.add_field_at(
  182            Const.OSFILE_OFFSETOF_DIR_DD_FD,
  183            "dd_fd",
  184            Type.fd.implementation);
  185 
  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        }
  193 
  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        };
  202 
  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        }
  220 
  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");
  224 
  225        // Structure |statvfs|
  226        // Use an hollow structure
  227        {
  228          let statvfs = new SharedAll.HollowStructure("statvfs",
  229            Const.OSFILE_SIZEOF_STATVFS);
  230 
  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);
  235 
  236          Type.statvfs = statvfs.getType();
  237        }
  238 
  239        // Declare libc functions as functions of |OS.Unix.File|
  240 
  241        // Finalizer-related functions
  242        libc.declareLazy(SysFile, "_close",
  243                         "close", ctypes.default_abi,
  244                         /*return */ctypes.int,
  245                         /*fd*/     ctypes.int);
  246 
  247        SysFile.close = function close(fd) {
  248          // Detach the finalizer and call |_close|.
  249          return fd.dispose();
  250        };
  251 
  252        libc.declareLazy(SysFile, "_close_dir",
  253                         "closedir", ctypes.default_abi,
  254                         /*return */ctypes.int,
  255                         /*dirp*/   Type.DIR.in_ptr.implementation);
  256 
  257        SysFile.closedir = function closedir(fd) {
  258          // Detach the finalizer and call |_close_dir|.
  259          return fd.dispose();
  260        };
  261 
  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 
  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().
  271          // If it turns out we don't have an a.out library or a.out
  272          // doesn't contain free, use the ordinary libc free.
  273 
  274          default_lib.declareLazyWithFallback(libc, SysFile, "free",
  275            "free", ctypes.default_abi,
  276            /*return*/ ctypes.void_t,
  277            /*ptr*/    ctypes.voidptr_t);
  278        }
  279 
  280 
  281        // Other functions
  282        libc.declareLazyFFI(SysFile,  "access",
  283                            "access", ctypes.default_abi,
  284                            /*return*/ Type.negativeone_or_nothing,
  285                            /*path*/   Type.path,
  286                            /*mode*/   Type.int);
  287 
  288        libc.declareLazyFFI(SysFile,  "chdir",
  289                            "chdir", ctypes.default_abi,
  290                            /*return*/ Type.negativeone_or_nothing,
  291                            /*path*/   Type.path);
  292 
  293        libc.declareLazyFFI(SysFile,  "chmod",
  294                            "chmod", ctypes.default_abi,
  295                            /*return*/ Type.negativeone_or_nothing,
  296                            /*path*/   Type.path,
  297                            /*mode*/   Type.mode_t);
  298 
  299        libc.declareLazyFFI(SysFile,  "chown",
  300                            "chown", ctypes.default_abi,
  301                            /*return*/ Type.negativeone_or_nothing,
  302                            /*path*/   Type.path,
  303                            /*uid*/    Type.uid_t,
  304                            /*gid*/    Type.gid_t);
  305 
  306        libc.declareLazyFFI(SysFile,  "copyfile",
  307                            "copyfile", ctypes.default_abi,
  308                            /*return*/ Type.negativeone_or_nothing,
  309                            /*source*/ Type.path,
  310                            /*dest*/   Type.path,
  311                            /*state*/  Type.void_t.in_ptr, // Ignored atm
  312                            /*flags*/  Type.uint32_t);
  313 
  314        libc.declareLazyFFI(SysFile,  "dup",
  315                            "dup", ctypes.default_abi,
  316                            /*return*/ Type.negativeone_or_fd,
  317                            /*fd*/     Type.fd);
  318 
  319        if ("OSFILE_SIZEOF_DIR" in Const) {
  320          // On platforms for which |dirfd| is a macro
  321          SysFile.dirfd =
  322            function dirfd(DIRp) {
  323              return Type.DIR.in_ptr.implementation(DIRp).contents.dd_fd;
  324            };
  325        } else {
  326          // On platforms for which |dirfd| is a function
  327          libc.declareLazyFFI(SysFile,  "dirfd",
  328                              "dirfd", ctypes.default_abi,
  329                              /*return*/ Type.negativeone_or_fd,
  330                              /*dir*/    Type.DIR.in_ptr);
  331        }
  332 
  333        libc.declareLazyFFI(SysFile,  "chdir",
  334                            "chdir", ctypes.default_abi,
  335                            /*return*/ Type.negativeone_or_nothing,
  336                            /*path*/   Type.path);
  337 
  338        libc.declareLazyFFI(SysFile,  "fchdir",
  339                            "fchdir", ctypes.default_abi,
  340                            /*return*/ Type.negativeone_or_nothing,
  341                            /*fd*/     Type.fd);
  342 
  343        libc.declareLazyFFI(SysFile,  "fchmod",
  344                            "fchmod", ctypes.default_abi,
  345                            /*return*/ Type.negativeone_or_nothing,
  346                            /*fd*/     Type.fd,
  347                            /*mode*/   Type.mode_t);
  348 
  349        libc.declareLazyFFI(SysFile,  "fchown",
  350                            "fchown", ctypes.default_abi,
  351                            /*return*/ Type.negativeone_or_nothing,
  352                            /*fd*/     Type.fd,
  353                            /*uid_t*/  Type.uid_t,
  354                            /*gid_t*/  Type.gid_t);
  355 
  356        libc.declareLazyFFI(SysFile,  "fsync",
  357                            "fsync", ctypes.default_abi,
  358                            /*return*/ Type.negativeone_or_nothing,
  359                            /*fd*/     Type.fd);
  360 
  361        libc.declareLazyFFI(SysFile,  "getcwd",
  362                            "getcwd", ctypes.default_abi,
  363                            /*return*/ Type.out_path,
  364                            /*buf*/    Type.out_path,
  365                            /*size*/   Type.size_t);
  366 
  367        libc.declareLazyFFI(SysFile,  "getwd",
  368                            "getwd", ctypes.default_abi,
  369                            /*return*/ Type.out_path,
  370                            /*buf*/    Type.out_path);
  371 
  372        // Two variants of |getwd| which allocate the memory
  373        // dynamically.
  374 
  375        // Linux/Android version
  376        libc.declareLazyFFI(SysFile,  "get_current_dir_name",
  377                            "get_current_dir_name", ctypes.default_abi,
  378                            /*return*/ Type.out_path.releaseWithLazy(() =>
  379                              SysFile.free
  380                            ));
  381 
  382        // MacOS/BSD version (will return NULL on Linux/Android)
  383        libc.declareLazyFFI(SysFile,  "getwd_auto",
  384                            "getwd", ctypes.default_abi,
  385                            /*return*/ Type.out_path.releaseWithLazy(() =>
  386                              SysFile.free
  387                            ),
  388                            /*buf*/    Type.void_t.out_ptr);
  389 
  390        libc.declareLazyFFI(SysFile,  "fdatasync",
  391                            "fdatasync", ctypes.default_abi,
  392                            /*return*/ Type.negativeone_or_nothing,
  393                            /*fd*/     Type.fd); // Note: MacOS/BSD-specific
  394 
  395        libc.declareLazyFFI(SysFile,  "ftruncate",
  396                            "ftruncate", ctypes.default_abi,
  397                            /*return*/ Type.negativeone_or_nothing,
  398                            /*fd*/     Type.fd,
  399                            /*length*/ Type.off_t);
  400 
  401 
  402        libc.declareLazyFFI(SysFile,  "lchown",
  403                            "lchown", ctypes.default_abi,
  404                            /*return*/ Type.negativeone_or_nothing,
  405                            /*path*/   Type.path,
  406                            /*uid_t*/  Type.uid_t,
  407                            /*gid_t*/  Type.gid_t);
  408 
  409        libc.declareLazyFFI(SysFile,  "link",
  410                            "link", ctypes.default_abi,
  411                            /*return*/ Type.negativeone_or_nothing,
  412                            /*source*/ Type.path,
  413                            /*dest*/   Type.path);
  414 
  415        libc.declareLazyFFI(SysFile,  "lseek",
  416                            "lseek", ctypes.default_abi,
  417                            /*return*/ Type.off_t,
  418                            /*fd*/     Type.fd,
  419                            /*offset*/ Type.off_t,
  420                            /*whence*/ Type.int);
  421 
  422        libc.declareLazyFFI(SysFile,  "mkdir",
  423                            "mkdir", ctypes.default_abi,
  424                            /*return*/ Type.int,
  425                            /*path*/ Type.path,
  426                            /*mode*/ Type.int);
  427 
  428        libc.declareLazyFFI(SysFile,  "mkstemp",
  429                            "mkstemp", ctypes.default_abi,
  430                            /*return*/   Type.fd,
  431                            /*template*/ Type.out_path);
  432 
  433        libc.declareLazyFFI(SysFile,  "open",
  434                            "open", ctypes.default_abi,
  435                            /*return*/ Type.negativeone_or_fd,
  436                            /*path*/   Type.path,
  437                            /*oflags*/ Type.int,
  438                            /*mode*/   Type.int);
  439 
  440        if (OS.Constants.Sys.Name == "NetBSD") {
  441           libc.declareLazyFFI(SysFile,  "opendir",
  442                               "__opendir30", ctypes.default_abi,
  443                    /*return*/ Type.null_or_DIR_ptr,
  444                    /*path*/   Type.path);
  445        } else {
  446           libc.declareLazyFFI(SysFile,  "opendir",
  447                               "opendir", ctypes.default_abi,
  448                     /*return*/ Type.null_or_DIR_ptr,
  449                     /*path*/   Type.path);
  450        }
  451 
  452        libc.declareLazyFFI(SysFile,  "pread",
  453                                "pread", ctypes.default_abi,
  454                     /*return*/ Type.negativeone_or_ssize_t,
  455                     /*fd*/     Type.fd,
  456                     /*buf*/    Type.void_t.out_ptr,
  457                     /*nbytes*/ Type.size_t,
  458                     /*offset*/ Type.off_t);
  459 
  460        libc.declareLazyFFI(SysFile,  "pwrite",
  461                                "pwrite", ctypes.default_abi,
  462                     /*return*/ Type.negativeone_or_ssize_t,
  463                     /*fd*/     Type.fd,
  464                     /*buf*/    Type.void_t.in_ptr,
  465                     /*nbytes*/ Type.size_t,
  466                     /*offset*/ Type.off_t);
  467 
  468        libc.declareLazyFFI(SysFile,  "read",
  469                               "read", ctypes.default_abi,
  470                     /*return*/Type.negativeone_or_ssize_t,
  471                     /*fd*/    Type.fd,
  472                     /*buf*/   Type.void_t.out_ptr,
  473                     /*nbytes*/Type.size_t);
  474 
  475        libc.declareLazyFFI(SysFile,  "posix_fadvise",
  476                                "posix_fadvise", ctypes.default_abi,
  477                     /*return*/ Type.int,
  478                     /*fd*/     Type.fd,
  479                     /*offset*/ Type.off_t,
  480                     /*len*/    Type.off_t,
  481                     /*advise*/ Type.int);
  482 
  483        if (Const._DARWIN_FEATURE_64_BIT_INODE) {
  484          // Special case for MacOS X 10.5+
  485          // Symbol name "readdir" still exists but is used for a
  486          // deprecated function that does not match the
  487          // constants of |Const|.
  488          libc.declareLazyFFI(SysFile,  "readdir",
  489                                 "readdir$INODE64", ctypes.default_abi,
  490                      /*return*/ Type.null_or_dirent_ptr,
  491                       /*dir*/   Type.DIR.in_ptr); // For MacOS X
  492        } else if (OS.Constants.Sys.Name == "NetBSD") {
  493          libc.declareLazyFFI(SysFile,  "readdir",
  494                                 "__readdir30", ctypes.default_abi,
  495                       /*return*/Type.null_or_dirent_ptr,
  496                       /*dir*/   Type.DIR.in_ptr); // Other Unices
  497        } else {
  498          libc.declareLazyFFI(SysFile,  "readdir",
  499                                 "readdir", ctypes.default_abi,
  500                       /*return*/Type.null_or_dirent_ptr,
  501                       /*dir*/   Type.DIR.in_ptr); // Other Unices
  502        }
  503 
  504        libc.declareLazyFFI(SysFile,  "rename",
  505                                "rename", ctypes.default_abi,
  506                     /*return*/ Type.negativeone_or_nothing,
  507                     /*old*/    Type.path,
  508                     /*new*/    Type.path);
  509 
  510        libc.declareLazyFFI(SysFile,  "rmdir",
  511                                "rmdir", ctypes.default_abi,
  512                     /*return*/ Type.int,
  513                     /*path*/   Type.path);
  514 
  515        libc.declareLazyFFI(SysFile,  "splice",
  516                                "splice", ctypes.default_abi,
  517                     /*return*/ Type.long,
  518                     /*fd_in*/  Type.fd,
  519                     /*off_in*/ Type.off_t.in_ptr,
  520                     /*fd_out*/ Type.fd,
  521                     /*off_out*/Type.off_t.in_ptr,
  522                     /*len*/    Type.size_t,
  523                     /*flags*/  Type.unsigned_int); // Linux/Android-specific
  524 
  525        libc.declareLazyFFI(SysFile,  "statfs",
  526                                "statfs", ctypes.default_abi,
  527                     /*return*/ Type.negativeone_or_nothing,
  528                     /*path*/   Type.path,
  529                     /*buf*/    Type.statvfs.out_ptr); // Android,B2G
  530 
  531        libc.declareLazyFFI(SysFile,  "statvfs",
  532                                "statvfs", ctypes.default_abi,
  533                     /*return*/ Type.negativeone_or_nothing,
  534                     /*path*/   Type.path,
  535                     /*buf*/    Type.statvfs.out_ptr); // Other platforms
  536 
  537        libc.declareLazyFFI(SysFile,  "symlink",
  538                                "symlink", ctypes.default_abi,
  539                     /*return*/ Type.negativeone_or_nothing,
  540                     /*source*/ Type.path,
  541                     /*dest*/   Type.path);
  542 
  543        libc.declareLazyFFI(SysFile,  "truncate",
  544                               "truncate", ctypes.default_abi,
  545                     /*return*/Type.negativeone_or_nothing,
  546                     /*path*/  Type.path,
  547                     /*length*/ Type.off_t);
  548 
  549        libc.declareLazyFFI(SysFile,  "unlink",
  550                            "unlink", ctypes.default_abi,
  551                     /*return*/ Type.negativeone_or_nothing,
  552                     /*path*/ Type.path);
  553 
  554        libc.declareLazyFFI(SysFile,  "write",
  555                            "write", ctypes.default_abi,
  556                     /*return*/ Type.negativeone_or_ssize_t,
  557                     /*fd*/     Type.fd,
  558                     /*buf*/    Type.void_t.in_ptr,
  559                     /*nbytes*/ Type.size_t);
  560 
  561        // Weird cases that require special treatment
  562 
  563        // OSes use a variety of hacks to differentiate between
  564        // 32-bits and 64-bits versions of |stat|, |lstat|, |fstat|.
  565        if (Const._DARWIN_FEATURE_64_BIT_INODE) {
  566          // MacOS X 64-bits
  567          libc.declareLazyFFI(SysFile,  "stat",
  568                              "stat$INODE64", ctypes.default_abi,
  569                       /*return*/ Type.negativeone_or_nothing,
  570                       /*path*/   Type.path,
  571                       /*buf*/    Type.stat.out_ptr
  572                      );
  573          libc.declareLazyFFI(SysFile,  "lstat",
  574                              "lstat$INODE64", ctypes.default_abi,
  575                       /*return*/ Type.negativeone_or_nothing,
  576                       /*path*/   Type.path,
  577                       /*buf*/    Type.stat.out_ptr
  578                      );
  579          libc.declareLazyFFI(SysFile,  "fstat",
  580                              "fstat$INODE64", ctypes.default_abi,
  581                       /*return*/ Type.negativeone_or_nothing,
  582                       /*path*/   Type.fd,
  583                       /*buf*/    Type.stat.out_ptr
  584                      );
  585        } else if (Const._STAT_VER != undefined) {
  586          const ver = Const._STAT_VER;
  587          let xstat_name, lxstat_name, fxstat_name;
  588          // Linux, all widths
  589          xstat_name = "__xstat";
  590          lxstat_name = "__lxstat";
  591          fxstat_name = "__fxstat";
  592 
  593          let Stat = {};
  594          libc.declareLazyFFI(Stat,  "xstat",
  595                              xstat_name, ctypes.default_abi,
  596                       /*return*/    Type.negativeone_or_nothing,
  597                       /*_stat_ver*/ Type.int,
  598                       /*path*/      Type.path,
  599                       /*buf*/       Type.stat.out_ptr);
  600          libc.declareLazyFFI(Stat,  "lxstat",
  601                              lxstat_name, ctypes.default_abi,
  602                       /*return*/    Type.negativeone_or_nothing,
  603                       /*_stat_ver*/ Type.int,
  604                       /*path*/      Type.path,
  605                       /*buf*/       Type.stat.out_ptr);
  606          libc.declareLazyFFI(Stat, "fxstat",
  607                              fxstat_name, ctypes.default_abi,
  608                       /*return*/    Type.negativeone_or_nothing,
  609                       /*_stat_ver*/ Type.int,
  610                       /*fd*/        Type.fd,
  611                       /*buf*/       Type.stat.out_ptr);
  612 
  613 
  614          SysFile.stat = function stat(path, buf) {
  615            return Stat.xstat(ver, path, buf);
  616          };
  617 
  618          SysFile.lstat = function lstat(path, buf) {
  619            return Stat.lxstat(ver, path, buf);
  620          };
  621 
  622          SysFile.fstat = function fstat(fd, buf) {
  623            return Stat.fxstat(ver, fd, buf);
  624          };
  625        } else if (OS.Constants.Sys.Name == "NetBSD") {
  626          // NetBSD 5.0 and newer
  627          libc.declareLazyFFI(SysFile,  "stat",
  628                              "__stat50", ctypes.default_abi,
  629                       /*return*/ Type.negativeone_or_nothing,
  630                       /*path*/   Type.path,
  631                       /*buf*/    Type.stat.out_ptr
  632                      );
  633          libc.declareLazyFFI(SysFile,  "lstat",
  634                              "__lstat50", ctypes.default_abi,
  635                       /*return*/ Type.negativeone_or_nothing,
  636                       /*path*/   Type.path,
  637                       /*buf*/    Type.stat.out_ptr
  638                      );
  639          libc.declareLazyFFI(SysFile,  "fstat",
  640                              "__fstat50", ctypes.default_abi,
  641                       /*return*/ Type.negativeone_or_nothing,
  642                       /*fd*/     Type.fd,
  643                       /*buf*/    Type.stat.out_ptr
  644                      );
  645        } else {
  646          // Mac OS X 32-bits, other Unix
  647          libc.declareLazyFFI(SysFile,  "stat",
  648                              "stat", ctypes.default_abi,
  649                       /*return*/ Type.negativeone_or_nothing,
  650                       /*path*/   Type.path,
  651                       /*buf*/    Type.stat.out_ptr
  652                      );
  653          libc.declareLazyFFI(SysFile,  "lstat",
  654                              "lstat", ctypes.default_abi,
  655                       /*return*/ Type.negativeone_or_nothing,
  656                       /*path*/   Type.path,
  657                       /*buf*/    Type.stat.out_ptr
  658                      );
  659          libc.declareLazyFFI(SysFile,  "fstat",
  660                              "fstat", ctypes.default_abi,
  661                       /*return*/ Type.negativeone_or_nothing,
  662                       /*fd*/     Type.fd,
  663                       /*buf*/    Type.stat.out_ptr
  664                      );
  665        }
  666 
  667        // We cannot make a C array of CDataFinalizer, so
  668        // pipe cannot be directly defined as a C function.
  669 
  670        let Pipe = {};
  671        libc.declareLazyFFI(Pipe, "_pipe",
  672          "pipe", ctypes.default_abi,
  673          /*return*/ Type.negativeone_or_nothing,
  674          /*fds*/    new SharedAll.Type("two file descriptors",
  675              ctypes.ArrayType(ctypes.int, 2)));
  676 
  677        // A shared per-thread buffer used to communicate with |pipe|
  678        let _pipebuf = new (ctypes.ArrayType(ctypes.int, 2))();
  679 
  680        SysFile.pipe = function pipe(array) {
  681          let result = Pipe._pipe(_pipebuf);
  682          if (result == -1) {
  683            return result;
  684          }
  685          array[0] = ctypes.CDataFinalizer(_pipebuf[0], SysFile._close);
  686          array[1] = ctypes.CDataFinalizer(_pipebuf[1], SysFile._close);
  687          return result;
  688        };
  689 
  690        if (OS.Constants.Sys.Name == "NetBSD") {
  691            libc.declareLazyFFI(SysFile, "utimes",
  692                                "__utimes50", ctypes.default_abi,
  693                       /*return*/     Type.negativeone_or_nothing,
  694                       /*path*/       Type.path,
  695                       /*timeval[2]*/ Type.timevals.out_ptr
  696                       );
  697        } else {
  698            libc.declareLazyFFI(SysFile, "utimes",
  699                                "utimes", ctypes.default_abi,
  700                       /*return*/     Type.negativeone_or_nothing,
  701                       /*path*/       Type.path,
  702                       /*timeval[2]*/ Type.timevals.out_ptr
  703                       );
  704        }
  705        if (OS.Constants.Sys.Name == "NetBSD") {
  706            libc.declareLazyFFI(SysFile, "futimes",
  707                                "__futimes50", ctypes.default_abi,
  708                       /*return*/     Type.negativeone_or_nothing,
  709                       /*fd*/         Type.fd,
  710                       /*timeval[2]*/ Type.timevals.out_ptr
  711                       );
  712        } else {
  713            libc.declareLazyFFI(SysFile, "futimes",
  714                                "futimes", ctypes.default_abi,
  715                       /*return*/     Type.negativeone_or_nothing,
  716                       /*fd*/         Type.fd,
  717                       /*timeval[2]*/ Type.timevals.out_ptr
  718                       );
  719        }
  720      };
  721 
  722      exports.OS.Unix = {
  723        File: {
  724          _init: init
  725        }
  726      };
  727    })(this);
  728 }