Bug 840887 - Fix behavior of DirectoryIterator when the directory doesn't exist - Unix version. r=froydnj
authorDavid Rajchenbach-Teller <dteller@mozilla.com>
Tue, 26 Feb 2013 12:07:42 -0500
changeset 133434 bd4206b887ffaba3b779218f29da7c48a0037f28
parent 133433 7c638eba3a46b48ebdcb70e6dadf8f281c01bb96
child 133435 692f9ca217450328cb8d31c96385a3b4f22a6ec0
push id2452
push userlsblakk@mozilla.com
push dateMon, 13 May 2013 16:59:38 +0000
treeherdermozilla-beta@d4b152d29d8d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs840887
milestone22.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 840887 - Fix behavior of DirectoryIterator when the directory doesn't exist - Unix version. r=froydnj
toolkit/components/osfile/osfile_unix_allthreads.jsm
toolkit/components/osfile/osfile_unix_front.jsm
--- a/toolkit/components/osfile/osfile_unix_allthreads.jsm
+++ b/toolkit/components/osfile/osfile_unix_allthreads.jsm
@@ -309,9 +309,13 @@ if (typeof Components != "undefined") {
   // Special constructors that need to be defined on all threads
   OSError.closed = function closed(operation) {
     return new OSError(operation, OS.Constants.libc.EBADF);
   };
 
   OSError.exists = function exists(operation) {
     return new OSError(operation, OS.Constants.libc.EEXIST);
   };
+
+  OSError.noSuchFile = function noSuchFile(operation) {
+    return new OSError(operation, OS.Constants.libc.ENOENT);
+  };
 })(this);
--- a/toolkit/components/osfile/osfile_unix_front.jsm
+++ b/toolkit/components/osfile/osfile_unix_front.jsm
@@ -602,34 +602,47 @@
       * @param {*=} options Ignored in this implementation.
       *
       * @throws {File.Error} If |path| does not represent a directory or
       * if the directory cannot be iterated.
       * @constructor
       */
      File.DirectoryIterator = function DirectoryIterator(path, options) {
        exports.OS.Shared.AbstractFile.AbstractIterator.call(this);
-       let dir = throw_on_null("DirectoryIterator", UnixFile.opendir(path));
-       this._dir = dir;
        this._path = path;
+       this._dir = UnixFile.opendir(this._path);
+       if (this._dir == null) {
+         let error = ctypes.errno;
+         if (error != OS.Constants.libc.ENOENT) {
+           throw new File.Error("DirectoryIterator", error);
+         }
+         this._exists = false;
+         this._closed = true;
+       } else {
+         this._exists = true;
+         this._closed = false;
+       }
      };
      File.DirectoryIterator.prototype = Object.create(exports.OS.Shared.AbstractFile.AbstractIterator.prototype);
 
      /**
       * Return the next entry in the directory, if any such entry is
       * available.
       *
       * Skip special directories "." and "..".
       *
       * @return {File.Entry} The next entry in the directory.
       * @throws {StopIteration} Once all files in the directory have been
       * encountered.
       */
      File.DirectoryIterator.prototype.next = function next() {
-       if (!this._dir) {
+       if (!this._exists) {
+         throw File.Error.noSuchFile("DirectoryIterator.prototype.next");
+       }
+       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();
@@ -643,21 +656,31 @@
        throw StopIteration;
      };
 
      /**
       * Close the iterator and recover all resources.
       * You should call this once you have finished iterating on a directory.
       */
      File.DirectoryIterator.prototype.close = function close() {
-       if (!this._dir) return;
+       if (this._closed) return;
+       this._closed = true;
        UnixFile.closedir(this._dir);
        this._dir = null;
      };
 
+    /**
+     * Determine whether the directory exists.
+     *
+     * @return {boolean}
+     */
+     File.DirectoryIterator.prototype.exists = function exists() {
+       return this._exists;
+     };
+
      /**
       * Return directory as |File|
       */
      File.DirectoryIterator.prototype.unixAsFile = function unixAsFile() {
        if (!this._dir) throw File.Error.closed();
        return error_or_file(UnixFile.dirfd(this._dir));
      };