summaryrefslogtreecommitdiffstats
path: root/toolkit/components/osfile/modules/osfile_unix_allthreads.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/osfile/modules/osfile_unix_allthreads.jsm')
-rw-r--r--toolkit/components/osfile/modules/osfile_unix_allthreads.jsm375
1 files changed, 375 insertions, 0 deletions
diff --git a/toolkit/components/osfile/modules/osfile_unix_allthreads.jsm b/toolkit/components/osfile/modules/osfile_unix_allthreads.jsm
new file mode 100644
index 000000000..632f9c40b
--- /dev/null
+++ b/toolkit/components/osfile/modules/osfile_unix_allthreads.jsm
@@ -0,0 +1,375 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * This module defines the thread-agnostic components of the Unix version
+ * of OS.File. It depends on the thread-agnostic cross-platform components
+ * of OS.File.
+ *
+ * It serves the following purposes:
+ * - open libc;
+ * - define OS.Unix.Error;
+ * - define a few constants and types that need to be defined on all platforms.
+ *
+ * This module can be:
+ * - opened from the main thread as a jsm module;
+ * - opened from a chrome worker through require().
+ */
+
+"use strict";
+
+var SharedAll;
+if (typeof Components != "undefined") {
+ let Cu = Components.utils;
+ // Module is opened as a jsm module
+ Cu.import("resource://gre/modules/ctypes.jsm", this);
+
+ SharedAll = {};
+ Cu.import("resource://gre/modules/osfile/osfile_shared_allthreads.jsm", SharedAll);
+ this.exports = {};
+} else if (typeof module != "undefined" && typeof require != "undefined") {
+ // Module is loaded with require()
+ SharedAll = require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");
+} else {
+ throw new Error("Please open this module with Component.utils.import or with require()");
+}
+
+var LOG = SharedAll.LOG.bind(SharedAll, "Unix", "allthreads");
+var Const = SharedAll.Constants.libc;
+
+// Open libc
+var libc = new SharedAll.Library("libc",
+ "libc.so", "libSystem.B.dylib", "a.out");
+exports.libc = libc;
+
+// Define declareFFI
+var declareFFI = SharedAll.declareFFI.bind(null, libc);
+exports.declareFFI = declareFFI;
+
+// Define lazy binding
+var LazyBindings = {};
+libc.declareLazy(LazyBindings, "strerror",
+ "strerror", ctypes.default_abi,
+ /*return*/ ctypes.char.ptr,
+ /*errnum*/ ctypes.int);
+
+/**
+ * A File-related error.
+ *
+ * To obtain a human-readable error message, use method |toString|.
+ * To determine the cause of the error, use the various |becauseX|
+ * getters. To determine the operation that failed, use field
+ * |operation|.
+ *
+ * Additionally, this implementation offers a field
+ * |unixErrno|, which holds the OS-specific error
+ * constant. If you need this level of detail, you may match the value
+ * of this field against the error constants of |OS.Constants.libc|.
+ *
+ * @param {string=} operation The operation that failed. If unspecified,
+ * the name of the calling function is taken to be the operation that
+ * failed.
+ * @param {number=} lastError The OS-specific constant detailing the
+ * reason of the error. If unspecified, this is fetched from the system
+ * status.
+ * @param {string=} path The file path that manipulated. If unspecified,
+ * assign the empty string.
+ *
+ * @constructor
+ * @extends {OS.Shared.Error}
+ */
+var OSError = function OSError(operation = "unknown operation",
+ errno = ctypes.errno, path = "") {
+ SharedAll.OSError.call(this, operation, path);
+ this.unixErrno = errno;
+};
+OSError.prototype = Object.create(SharedAll.OSError.prototype);
+OSError.prototype.toString = function toString() {
+ return "Unix error " + this.unixErrno +
+ " during operation " + this.operation +
+ (this.path? " on file " + this.path : "") +
+ " (" + LazyBindings.strerror(this.unixErrno).readString() + ")";
+};
+OSError.prototype.toMsg = function toMsg() {
+ return OSError.toMsg(this);
+};
+
+/**
+ * |true| if the error was raised because a file or directory
+ * already exists, |false| otherwise.
+ */
+Object.defineProperty(OSError.prototype, "becauseExists", {
+ get: function becauseExists() {
+ return this.unixErrno == Const.EEXIST;
+ }
+});
+/**
+ * |true| if the error was raised because a file or directory
+ * does not exist, |false| otherwise.
+ */
+Object.defineProperty(OSError.prototype, "becauseNoSuchFile", {
+ get: function becauseNoSuchFile() {
+ return this.unixErrno == Const.ENOENT;
+ }
+});
+
+/**
+ * |true| if the error was raised because a directory is not empty
+ * does not exist, |false| otherwise.
+ */
+ Object.defineProperty(OSError.prototype, "becauseNotEmpty", {
+ get: function becauseNotEmpty() {
+ return this.unixErrno == Const.ENOTEMPTY;
+ }
+ });
+/**
+ * |true| if the error was raised because a file or directory
+ * is closed, |false| otherwise.
+ */
+Object.defineProperty(OSError.prototype, "becauseClosed", {
+ get: function becauseClosed() {
+ return this.unixErrno == Const.EBADF;
+ }
+});
+/**
+ * |true| if the error was raised because permission is denied to
+ * access a file or directory, |false| otherwise.
+ */
+Object.defineProperty(OSError.prototype, "becauseAccessDenied", {
+ get: function becauseAccessDenied() {
+ return this.unixErrno == Const.EACCES;
+ }
+});
+/**
+ * |true| if the error was raised because some invalid argument was passed,
+ * |false| otherwise.
+ */
+Object.defineProperty(OSError.prototype, "becauseInvalidArgument", {
+ get: function becauseInvalidArgument() {
+ return this.unixErrno == Const.EINVAL;
+ }
+});
+
+/**
+ * Serialize an instance of OSError to something that can be
+ * transmitted across threads (not necessarily a string).
+ */
+OSError.toMsg = function toMsg(error) {
+ return {
+ exn: "OS.File.Error",
+ fileName: error.moduleName,
+ lineNumber: error.lineNumber,
+ stack: error.moduleStack,
+ operation: error.operation,
+ unixErrno: error.unixErrno,
+ path: error.path
+ };
+};
+
+/**
+ * Deserialize a message back to an instance of OSError
+ */
+OSError.fromMsg = function fromMsg(msg) {
+ let error = new OSError(msg.operation, msg.unixErrno, msg.path);
+ error.stack = msg.stack;
+ error.fileName = msg.fileName;
+ error.lineNumber = msg.lineNumber;
+ return error;
+};
+exports.Error = OSError;
+
+/**
+ * Code shared by implementations of File.Info on Unix
+ *
+ * @constructor
+*/
+var AbstractInfo = function AbstractInfo(path, isDir, isSymLink, size, lastAccessDate,
+ lastModificationDate, unixLastStatusChangeDate,
+ unixOwner, unixGroup, unixMode) {
+ this._path = path;
+ this._isDir = isDir;
+ this._isSymlLink = isSymLink;
+ this._size = size;
+ this._lastAccessDate = lastAccessDate;
+ this._lastModificationDate = lastModificationDate;
+ this._unixLastStatusChangeDate = unixLastStatusChangeDate;
+ this._unixOwner = unixOwner;
+ this._unixGroup = unixGroup;
+ this._unixMode = unixMode;
+};
+
+AbstractInfo.prototype = {
+ /**
+ * The path of the file, used for error-reporting.
+ *
+ * @type {string}
+ */
+ get path() {
+ return this._path;
+ },
+ /**
+ * |true| if this file is a directory, |false| otherwise
+ */
+ get isDir() {
+ return this._isDir;
+ },
+ /**
+ * |true| if this file is a symbolink link, |false| otherwise
+ */
+ get isSymLink() {
+ return this._isSymlLink;
+ },
+ /**
+ * The size of the file, in bytes.
+ *
+ * Note that the result may be |NaN| if the size of the file cannot be
+ * represented in JavaScript.
+ *
+ * @type {number}
+ */
+ get size() {
+ return this._size;
+ },
+ /**
+ * The date of last access to this file.
+ *
+ * Note that the definition of last access may depend on the
+ * underlying operating system and file system.
+ *
+ * @type {Date}
+ */
+ get lastAccessDate() {
+ return this._lastAccessDate;
+ },
+ /**
+ * Return the date of last modification of this file.
+ */
+ get lastModificationDate() {
+ return this._lastModificationDate;
+ },
+ /**
+ * Return the date at which the status of this file was last modified
+ * (this is the date of the latest write/renaming/mode change/...
+ * of the file)
+ */
+ get unixLastStatusChangeDate() {
+ return this._unixLastStatusChangeDate;
+ },
+ /*
+ * Return the Unix owner of this file
+ */
+ get unixOwner() {
+ return this._unixOwner;
+ },
+ /*
+ * Return the Unix group of this file
+ */
+ get unixGroup() {
+ return this._unixGroup;
+ },
+ /*
+ * Return the Unix group of this file
+ */
+ get unixMode() {
+ return this._unixMode;
+ }
+};
+exports.AbstractInfo = AbstractInfo;
+
+/**
+ * Code shared by implementations of File.DirectoryIterator.Entry on Unix
+ *
+ * @constructor
+*/
+var AbstractEntry = function AbstractEntry(isDir, isSymLink, name, path) {
+ this._isDir = isDir;
+ this._isSymlLink = isSymLink;
+ this._name = name;
+ this._path = path;
+};
+
+AbstractEntry.prototype = {
+ /**
+ * |true| if the entry is a directory, |false| otherwise
+ */
+ get isDir() {
+ return this._isDir;
+ },
+ /**
+ * |true| if the entry is a directory, |false| otherwise
+ */
+ get isSymLink() {
+ return this._isSymlLink;
+ },
+ /**
+ * The name of the entry
+ * @type {string}
+ */
+ get name() {
+ return this._name;
+ },
+ /**
+ * The full path to the entry
+ */
+ get path() {
+ return this._path;
+ }
+};
+exports.AbstractEntry = AbstractEntry;
+
+// Special constants that need to be defined on all platforms
+
+exports.POS_START = Const.SEEK_SET;
+exports.POS_CURRENT = Const.SEEK_CUR;
+exports.POS_END = Const.SEEK_END;
+
+// Special types that need to be defined for communication
+// between threads
+var Type = Object.create(SharedAll.Type);
+exports.Type = Type;
+
+/**
+ * Native paths
+ *
+ * Under Unix, expressed as C strings
+ */
+Type.path = Type.cstring.withName("[in] path");
+Type.out_path = Type.out_cstring.withName("[out] path");
+
+// Special constructors that need to be defined on all threads
+OSError.closed = function closed(operation, path) {
+ return new OSError(operation, Const.EBADF, path);
+};
+
+OSError.exists = function exists(operation, path) {
+ return new OSError(operation, Const.EEXIST, path);
+};
+
+OSError.noSuchFile = function noSuchFile(operation, path) {
+ return new OSError(operation, Const.ENOENT, path);
+};
+
+OSError.invalidArgument = function invalidArgument(operation) {
+ return new OSError(operation, Const.EINVAL);
+};
+
+var EXPORTED_SYMBOLS = [
+ "declareFFI",
+ "libc",
+ "Error",
+ "AbstractInfo",
+ "AbstractEntry",
+ "Type",
+ "POS_START",
+ "POS_CURRENT",
+ "POS_END"
+];
+
+//////////// Boilerplate
+if (typeof Components != "undefined") {
+ this.EXPORTED_SYMBOLS = EXPORTED_SYMBOLS;
+ for (let symbol of EXPORTED_SYMBOLS) {
+ this[symbol] = exports[symbol];
+ }
+}