Bug 861829 Fix symbol names of *stat on Solaris, make |dirent| work on Solaris r=dteller
authorGinn Chen <Ginn.Chen@Oracle.COM>
Thu, 25 Apr 2013 10:08:31 +0800
changeset 129822 3ef3b7592a531825954d4930275c18c3e7ebf2e2
parent 129821 064b6605f850da00d7b7e48ffd717ca877314cfc
child 129823 0f87eee6f792aa65953a9e91b767d5e334f489ed
push id24590
push userryanvm@gmail.com
push dateFri, 26 Apr 2013 01:39:07 +0000
treeherdermozilla-central@7f68735fc8da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdteller
bugs861829
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 861829 Fix symbol names of *stat on Solaris, make |dirent| work on Solaris r=dteller
toolkit/components/osfile/osfile_unix_back.jsm
toolkit/components/osfile/osfile_unix_front.jsm
toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
--- a/toolkit/components/osfile/osfile_unix_back.jsm
+++ b/toolkit/components/osfile/osfile_unix_back.jsm
@@ -112,22 +112,33 @@
        // (computed in C from the C data structures) that give us the layout.
        // The structure we compute looks like
        //  { int8_t[...] before_d_type; // ignored content
        //    int8_t      d_type       ;
        //    int8_t[...] before_d_name; // ignored content
        //    char[...]   d_name;
        //    };
        {
+         let d_name_extra_size = 0;
+         if (OS.Constants.libc.OSFILE_SIZEOF_DIRENT_D_NAME < 8) {
+           // d_name is defined like "char d_name[1];" on some platforms
+           // (e.g. Solaris), we need to give it more size for our structure.
+           d_name_extra_size = 256;
+         }
+
          let dirent = new OS.Shared.HollowStructure("dirent",
-           OS.Constants.libc.OSFILE_SIZEOF_DIRENT);
-         dirent.add_field_at(OS.Constants.libc.OSFILE_OFFSETOF_DIRENT_D_TYPE,
-           "d_type", ctypes.uint8_t);
+           OS.Constants.libc.OSFILE_SIZEOF_DIRENT + d_name_extra_size);
+         if (OS.Constants.libc.OSFILE_OFFSETOF_DIRENT_D_TYPE != undefined) {
+           // |dirent| doesn't have d_type on some platforms (e.g. Solaris).
+           dirent.add_field_at(OS.Constants.libc.OSFILE_OFFSETOF_DIRENT_D_TYPE,
+             "d_type", ctypes.uint8_t);
+         }
          dirent.add_field_at(OS.Constants.libc.OSFILE_OFFSETOF_DIRENT_D_NAME,
-           "d_name", ctypes.ArrayType(ctypes.char, OS.Constants.libc.OSFILE_SIZEOF_DIRENT_D_NAME));
+           "d_name", ctypes.ArrayType(ctypes.char,
+             OS.Constants.libc.OSFILE_SIZEOF_DIRENT_D_NAME + d_name_extra_size));
 
          // We now have built |dirent|.
          Types.dirent = dirent.getType();
        }
        Types.null_or_dirent_ptr =
          new Type("null_of_dirent",
                   Types.dirent.out_ptr.implementation);
 
@@ -499,31 +510,43 @@
          UnixFile.fstat =
            declareFFI("fstat$INODE64", ctypes.default_abi,
                       /*return*/ Types.negativeone_or_nothing,
                       /*path*/   Types.fd,
                       /*buf*/    Types.stat.out_ptr
                      );
        } else if (OS.Constants.libc._STAT_VER != undefined) {
          const ver = OS.Constants.libc._STAT_VER;
-         // Linux, all widths
+         let xstat_name, lxstat_name, fxstat_name
+         if (OS.Constants.Sys.Name == "SunOS") {
+           // Solaris
+           xstat_name = "_xstat";
+           lxstat_name = "_lxstat";
+           fxstat_name = "_fxstat";
+         } else {
+           // Linux, all widths
+           xstat_name = "__xstat";
+           lxstat_name = "__lxstat";
+           fxstat_name = "__fxstat";
+         }
+
          let xstat =
-           declareFFI("__xstat", ctypes.default_abi,
+           declareFFI(xstat_name, ctypes.default_abi,
                       /*return*/    Types.negativeone_or_nothing,
                       /*_stat_ver*/ Types.int,
                       /*path*/      Types.path,
                       /*buf*/       Types.stat.out_ptr);
          let lxstat =
-           declareFFI("__lxstat", ctypes.default_abi,
+           declareFFI(lxstat_name, ctypes.default_abi,
                       /*return*/    Types.negativeone_or_nothing,
                       /*_stat_ver*/ Types.int,
                       /*path*/      Types.path,
                       /*buf*/       Types.stat.out_ptr);
          let fxstat =
-           declareFFI("__fxstat", ctypes.default_abi,
+           declareFFI(fxstat_name, ctypes.default_abi,
                       /*return*/    Types.negativeone_or_nothing,
                       /*_stat_ver*/ Types.int,
                       /*fd*/        Types.fd,
                       /*buf*/       Types.stat.out_ptr);
 
          UnixFile.stat = function stat(path, buf) {
            return xstat(ver, path, buf);
          };
--- a/toolkit/components/osfile/osfile_unix_front.jsm
+++ b/toolkit/components/osfile/osfile_unix_front.jsm
@@ -630,23 +630,34 @@
        }
        if (this._closed) {
          throw StopIteration;
        }
        for (let entry = UnixFile.readdir(this._dir);
             entry != null && !entry.isNull();
             entry = UnixFile.readdir(this._dir)) {
          let contents = entry.contents;
-         if (contents.d_type == OS.Constants.libc.DT_DIR) {
-           let name = contents.d_name.readString();
-           if (name == "." || name == "..") {
-             continue;
-           }
+         let name = contents.d_name.readString();
+         if (name == "." || name == "..") {
+           continue;
          }
-         return new File.DirectoryIterator.Entry(contents, this._path);
+
+         let isDir, isSymLink;
+         if (!("d_type" in contents)) {
+           // |dirent| doesn't have d_type on some platforms (e.g. Solaris).
+           let path = OS.Unix.Path.join(this._path, name);
+           throw_on_negative("lstat", UnixFile.lstat(path, gStatDataPtr));
+           isDir = (gStatData.st_mode & OS.Constants.libc.S_IFMT) == OS.Constants.libc.S_IFDIR;
+           isSymLink = (gStatData.st_mode & OS.Constants.libc.S_IFMT) == OS.Constants.libc.S_IFLNK;
+         } else {
+           isDir = contents.d_type == OS.Constants.libc.DT_DIR;
+           isSymLink = contents.d_type == OS.Constants.libc.DT_LNK;
+         }
+
+         return new File.DirectoryIterator.Entry(isDir, isSymLink, name, this._path);
        }
        this.close();
        throw StopIteration;
      };
 
      /**
       * Close the iterator and recover all resources.
       * You should call this once you have finished iterating on a directory.
@@ -673,22 +684,19 @@
      File.DirectoryIterator.prototype.unixAsFile = function unixAsFile() {
        if (!this._dir) throw File.Error.closed();
        return error_or_file(UnixFile.dirfd(this._dir));
      };
 
      /**
       * An entry in a directory.
       */
-     File.DirectoryIterator.Entry = function Entry(unix_entry, parent) {
+     File.DirectoryIterator.Entry = function Entry(isDir, isSymLink, name, parent) {
        // Copy the relevant part of |unix_entry| to ensure that
        // our data is not overwritten prematurely.
-       let isDir = unix_entry.d_type == OS.Constants.libc.DT_DIR;
-       let isSymLink = unix_entry.d_type == OS.Constants.libc.DT_LNK;
-       let name = unix_entry.d_name.readString();
        this._parent = parent;
        let path = OS.Unix.Path.join(this._parent, name);
 
        exports.OS.Shared.Unix.AbstractEntry.call(this, isDir, isSymLink, name, path);
      };
      File.DirectoryIterator.Entry.prototype = Object.create(exports.OS.Shared.Unix.AbstractEntry.prototype);
 
      /**
@@ -711,17 +719,17 @@
        return serialized;
      };
 
      let gStatData = new OS.Shared.Type.stat.implementation();
      let gStatDataPtr = gStatData.address();
      let MODE_MASK = 4095 /*= 07777*/;
      File.Info = function Info(stat) {
        let isDir = (stat.st_mode & OS.Constants.libc.S_IFMT) == OS.Constants.libc.S_IFDIR;
-       let isSymLink = (stat.st_mode & OS.Constants.libc.S_IFMT) == OS.Constants.S_IFLNK;
+       let isSymLink = (stat.st_mode & OS.Constants.libc.S_IFMT) == OS.Constants.libc.S_IFLNK;
        let size = exports.OS.Shared.Type.size_t.importFromC(stat.st_size);
 
        let lastAccessDate = new Date(stat.st_atime * 1000);
        let lastModificationDate = new Date(stat.st_mtime * 1000);
        let unixLastStatusChangeDate = new Date(stat.st_ctime * 1000);
 
        let unixOwner = exports.OS.Shared.Type.uid_t.importFromC(stat.st_uid);
        let unixGroup = exports.OS.Shared.Type.gid_t.importFromC(stat.st_gid);
--- a/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
+++ b/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
@@ -639,16 +639,21 @@ let test_iter = maketest("iter", functio
     // Ensure that we have the same entries with |reference_dir_contents|
     let referenceEntries = new Set();
     for (let entry of reference_dir_contents(currentDir)) {
       referenceEntries.add(entry);
     }
     test.is(referenceEntries.size, allFiles1.length, "All the entries in the directory have been listed");
     for (let entry of allFiles1) {
       test.ok(referenceEntries.has(entry.path), "File " + entry.path + " effectively exists");
+      // Ensure that we have correct isDir and isSymLink
+      // Current directory is {objdir}/_tests/testing/mochitest/, assume it has some dirs and symlinks.
+      var f = new FileUtils.File(entry.path);
+      test.is(entry.isDir, f.isDirectory(), "Get file " + entry.path + " isDir correctly");
+      test.is(entry.isSymLink, f.isSymlink(), "Get file " + entry.path + " isSymLink correctly");
     }
 
     yield iterator.close();
     test.info("Closed iterator");
 
     test.info("Double closing DirectoryIterator");
     iterator = new OS.File.DirectoryIterator(currentDir);
     yield iterator.close();