toolkit/components/osfile/modules/osfile_unix_allthreads.jsm

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 /**
michael@0 6 * This module defines the thread-agnostic components of the Unix version
michael@0 7 * of OS.File. It depends on the thread-agnostic cross-platform components
michael@0 8 * of OS.File.
michael@0 9 *
michael@0 10 * It serves the following purposes:
michael@0 11 * - open libc;
michael@0 12 * - define OS.Unix.Error;
michael@0 13 * - define a few constants and types that need to be defined on all platforms.
michael@0 14 *
michael@0 15 * This module can be:
michael@0 16 * - opened from the main thread as a jsm module;
michael@0 17 * - opened from a chrome worker through require().
michael@0 18 */
michael@0 19
michael@0 20 "use strict";
michael@0 21
michael@0 22 let SharedAll;
michael@0 23 if (typeof Components != "undefined") {
michael@0 24 let Cu = Components.utils;
michael@0 25 // Module is opened as a jsm module
michael@0 26 Cu.import("resource://gre/modules/ctypes.jsm", this);
michael@0 27
michael@0 28 SharedAll = {};
michael@0 29 Cu.import("resource://gre/modules/osfile/osfile_shared_allthreads.jsm", SharedAll);
michael@0 30 this.exports = {};
michael@0 31 } else if (typeof "module" != "undefined" && typeof "require" != "undefined") {
michael@0 32 // Module is loaded with require()
michael@0 33 SharedAll = require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");
michael@0 34 } else {
michael@0 35 throw new Error("Please open this module with Component.utils.import or with require()");
michael@0 36 }
michael@0 37
michael@0 38 let LOG = SharedAll.LOG.bind(SharedAll, "Unix", "allthreads");
michael@0 39 let Const = SharedAll.Constants.libc;
michael@0 40
michael@0 41 // Open libc
michael@0 42 let libc = new SharedAll.Library("libc",
michael@0 43 "libc.so", "libSystem.B.dylib", "a.out");
michael@0 44 exports.libc = libc;
michael@0 45
michael@0 46 // Define declareFFI
michael@0 47 let declareFFI = SharedAll.declareFFI.bind(null, libc);
michael@0 48 exports.declareFFI = declareFFI;
michael@0 49
michael@0 50 // Define lazy binding
michael@0 51 let LazyBindings = {};
michael@0 52 libc.declareLazy(LazyBindings, "strerror",
michael@0 53 "strerror", ctypes.default_abi,
michael@0 54 /*return*/ ctypes.char.ptr,
michael@0 55 /*errnum*/ ctypes.int);
michael@0 56
michael@0 57 /**
michael@0 58 * A File-related error.
michael@0 59 *
michael@0 60 * To obtain a human-readable error message, use method |toString|.
michael@0 61 * To determine the cause of the error, use the various |becauseX|
michael@0 62 * getters. To determine the operation that failed, use field
michael@0 63 * |operation|.
michael@0 64 *
michael@0 65 * Additionally, this implementation offers a field
michael@0 66 * |unixErrno|, which holds the OS-specific error
michael@0 67 * constant. If you need this level of detail, you may match the value
michael@0 68 * of this field against the error constants of |OS.Constants.libc|.
michael@0 69 *
michael@0 70 * @param {string=} operation The operation that failed. If unspecified,
michael@0 71 * the name of the calling function is taken to be the operation that
michael@0 72 * failed.
michael@0 73 * @param {number=} lastError The OS-specific constant detailing the
michael@0 74 * reason of the error. If unspecified, this is fetched from the system
michael@0 75 * status.
michael@0 76 * @param {string=} path The file path that manipulated. If unspecified,
michael@0 77 * assign the empty string.
michael@0 78 *
michael@0 79 * @constructor
michael@0 80 * @extends {OS.Shared.Error}
michael@0 81 */
michael@0 82 let OSError = function OSError(operation = "unknown operation",
michael@0 83 errno = ctypes.errno, path = "") {
michael@0 84 operation = operation;
michael@0 85 SharedAll.OSError.call(this, operation, path);
michael@0 86 this.unixErrno = errno;
michael@0 87 };
michael@0 88 OSError.prototype = Object.create(SharedAll.OSError.prototype);
michael@0 89 OSError.prototype.toString = function toString() {
michael@0 90 return "Unix error " + this.unixErrno +
michael@0 91 " during operation " + this.operation +
michael@0 92 (this.path? " on file " + this.path : "") +
michael@0 93 " (" + LazyBindings.strerror(this.unixErrno).readString() + ")";
michael@0 94 };
michael@0 95
michael@0 96 /**
michael@0 97 * |true| if the error was raised because a file or directory
michael@0 98 * already exists, |false| otherwise.
michael@0 99 */
michael@0 100 Object.defineProperty(OSError.prototype, "becauseExists", {
michael@0 101 get: function becauseExists() {
michael@0 102 return this.unixErrno == Const.EEXIST;
michael@0 103 }
michael@0 104 });
michael@0 105 /**
michael@0 106 * |true| if the error was raised because a file or directory
michael@0 107 * does not exist, |false| otherwise.
michael@0 108 */
michael@0 109 Object.defineProperty(OSError.prototype, "becauseNoSuchFile", {
michael@0 110 get: function becauseNoSuchFile() {
michael@0 111 return this.unixErrno == Const.ENOENT;
michael@0 112 }
michael@0 113 });
michael@0 114
michael@0 115 /**
michael@0 116 * |true| if the error was raised because a directory is not empty
michael@0 117 * does not exist, |false| otherwise.
michael@0 118 */
michael@0 119 Object.defineProperty(OSError.prototype, "becauseNotEmpty", {
michael@0 120 get: function becauseNotEmpty() {
michael@0 121 return this.unixErrno == Const.ENOTEMPTY;
michael@0 122 }
michael@0 123 });
michael@0 124 /**
michael@0 125 * |true| if the error was raised because a file or directory
michael@0 126 * is closed, |false| otherwise.
michael@0 127 */
michael@0 128 Object.defineProperty(OSError.prototype, "becauseClosed", {
michael@0 129 get: function becauseClosed() {
michael@0 130 return this.unixErrno == Const.EBADF;
michael@0 131 }
michael@0 132 });
michael@0 133 /**
michael@0 134 * |true| if the error was raised because permission is denied to
michael@0 135 * access a file or directory, |false| otherwise.
michael@0 136 */
michael@0 137 Object.defineProperty(OSError.prototype, "becauseAccessDenied", {
michael@0 138 get: function becauseAccessDenied() {
michael@0 139 return this.unixErrno == Const.EACCES;
michael@0 140 }
michael@0 141 });
michael@0 142 /**
michael@0 143 * |true| if the error was raised because some invalid argument was passed,
michael@0 144 * |false| otherwise.
michael@0 145 */
michael@0 146 Object.defineProperty(OSError.prototype, "becauseInvalidArgument", {
michael@0 147 get: function becauseInvalidArgument() {
michael@0 148 return this.unixErrno == Const.EINVAL;
michael@0 149 }
michael@0 150 });
michael@0 151
michael@0 152 /**
michael@0 153 * Serialize an instance of OSError to something that can be
michael@0 154 * transmitted across threads (not necessarily a string).
michael@0 155 */
michael@0 156 OSError.toMsg = function toMsg(error) {
michael@0 157 return {
michael@0 158 operation: error.operation,
michael@0 159 unixErrno: error.unixErrno,
michael@0 160 path: error.path
michael@0 161 };
michael@0 162 };
michael@0 163
michael@0 164 /**
michael@0 165 * Deserialize a message back to an instance of OSError
michael@0 166 */
michael@0 167 OSError.fromMsg = function fromMsg(msg) {
michael@0 168 return new OSError(msg.operation, msg.unixErrno, msg.path);
michael@0 169 };
michael@0 170 exports.Error = OSError;
michael@0 171
michael@0 172 /**
michael@0 173 * Code shared by implementations of File.Info on Unix
michael@0 174 *
michael@0 175 * @constructor
michael@0 176 */
michael@0 177 let AbstractInfo = function AbstractInfo(path, isDir, isSymLink, size, lastAccessDate,
michael@0 178 lastModificationDate, unixLastStatusChangeDate,
michael@0 179 unixOwner, unixGroup, unixMode) {
michael@0 180 this._path = path;
michael@0 181 this._isDir = isDir;
michael@0 182 this._isSymlLink = isSymLink;
michael@0 183 this._size = size;
michael@0 184 this._lastAccessDate = lastAccessDate;
michael@0 185 this._lastModificationDate = lastModificationDate;
michael@0 186 this._unixLastStatusChangeDate = unixLastStatusChangeDate;
michael@0 187 this._unixOwner = unixOwner;
michael@0 188 this._unixGroup = unixGroup;
michael@0 189 this._unixMode = unixMode;
michael@0 190 };
michael@0 191
michael@0 192 AbstractInfo.prototype = {
michael@0 193 /**
michael@0 194 * The path of the file, used for error-reporting.
michael@0 195 *
michael@0 196 * @type {string}
michael@0 197 */
michael@0 198 get path() {
michael@0 199 return this._path;
michael@0 200 },
michael@0 201 /**
michael@0 202 * |true| if this file is a directory, |false| otherwise
michael@0 203 */
michael@0 204 get isDir() {
michael@0 205 return this._isDir;
michael@0 206 },
michael@0 207 /**
michael@0 208 * |true| if this file is a symbolink link, |false| otherwise
michael@0 209 */
michael@0 210 get isSymLink() {
michael@0 211 return this._isSymlLink;
michael@0 212 },
michael@0 213 /**
michael@0 214 * The size of the file, in bytes.
michael@0 215 *
michael@0 216 * Note that the result may be |NaN| if the size of the file cannot be
michael@0 217 * represented in JavaScript.
michael@0 218 *
michael@0 219 * @type {number}
michael@0 220 */
michael@0 221 get size() {
michael@0 222 return this._size;
michael@0 223 },
michael@0 224 /**
michael@0 225 * The date of last access to this file.
michael@0 226 *
michael@0 227 * Note that the definition of last access may depend on the
michael@0 228 * underlying operating system and file system.
michael@0 229 *
michael@0 230 * @type {Date}
michael@0 231 */
michael@0 232 get lastAccessDate() {
michael@0 233 return this._lastAccessDate;
michael@0 234 },
michael@0 235 /**
michael@0 236 * Return the date of last modification of this file.
michael@0 237 */
michael@0 238 get lastModificationDate() {
michael@0 239 return this._lastModificationDate;
michael@0 240 },
michael@0 241 /**
michael@0 242 * Return the date at which the status of this file was last modified
michael@0 243 * (this is the date of the latest write/renaming/mode change/...
michael@0 244 * of the file)
michael@0 245 */
michael@0 246 get unixLastStatusChangeDate() {
michael@0 247 return this._unixLastStatusChangeDate;
michael@0 248 },
michael@0 249 /*
michael@0 250 * Return the Unix owner of this file
michael@0 251 */
michael@0 252 get unixOwner() {
michael@0 253 return this._unixOwner;
michael@0 254 },
michael@0 255 /*
michael@0 256 * Return the Unix group of this file
michael@0 257 */
michael@0 258 get unixGroup() {
michael@0 259 return this._unixGroup;
michael@0 260 },
michael@0 261 /*
michael@0 262 * Return the Unix group of this file
michael@0 263 */
michael@0 264 get unixMode() {
michael@0 265 return this._unixMode;
michael@0 266 }
michael@0 267 };
michael@0 268 exports.AbstractInfo = AbstractInfo;
michael@0 269
michael@0 270 /**
michael@0 271 * Code shared by implementations of File.DirectoryIterator.Entry on Unix
michael@0 272 *
michael@0 273 * @constructor
michael@0 274 */
michael@0 275 let AbstractEntry = function AbstractEntry(isDir, isSymLink, name, path) {
michael@0 276 this._isDir = isDir;
michael@0 277 this._isSymlLink = isSymLink;
michael@0 278 this._name = name;
michael@0 279 this._path = path;
michael@0 280 };
michael@0 281
michael@0 282 AbstractEntry.prototype = {
michael@0 283 /**
michael@0 284 * |true| if the entry is a directory, |false| otherwise
michael@0 285 */
michael@0 286 get isDir() {
michael@0 287 return this._isDir;
michael@0 288 },
michael@0 289 /**
michael@0 290 * |true| if the entry is a directory, |false| otherwise
michael@0 291 */
michael@0 292 get isSymLink() {
michael@0 293 return this._isSymlLink;
michael@0 294 },
michael@0 295 /**
michael@0 296 * The name of the entry
michael@0 297 * @type {string}
michael@0 298 */
michael@0 299 get name() {
michael@0 300 return this._name;
michael@0 301 },
michael@0 302 /**
michael@0 303 * The full path to the entry
michael@0 304 */
michael@0 305 get path() {
michael@0 306 return this._path;
michael@0 307 }
michael@0 308 };
michael@0 309 exports.AbstractEntry = AbstractEntry;
michael@0 310
michael@0 311 // Special constants that need to be defined on all platforms
michael@0 312
michael@0 313 exports.POS_START = Const.SEEK_SET;
michael@0 314 exports.POS_CURRENT = Const.SEEK_CUR;
michael@0 315 exports.POS_END = Const.SEEK_END;
michael@0 316
michael@0 317 // Special types that need to be defined for communication
michael@0 318 // between threads
michael@0 319 let Type = Object.create(SharedAll.Type);
michael@0 320 exports.Type = Type;
michael@0 321
michael@0 322 /**
michael@0 323 * Native paths
michael@0 324 *
michael@0 325 * Under Unix, expressed as C strings
michael@0 326 */
michael@0 327 Type.path = Type.cstring.withName("[in] path");
michael@0 328 Type.out_path = Type.out_cstring.withName("[out] path");
michael@0 329
michael@0 330 // Special constructors that need to be defined on all threads
michael@0 331 OSError.closed = function closed(operation, path) {
michael@0 332 return new OSError(operation, Const.EBADF, path);
michael@0 333 };
michael@0 334
michael@0 335 OSError.exists = function exists(operation, path) {
michael@0 336 return new OSError(operation, Const.EEXIST, path);
michael@0 337 };
michael@0 338
michael@0 339 OSError.noSuchFile = function noSuchFile(operation, path) {
michael@0 340 return new OSError(operation, Const.ENOENT, path);
michael@0 341 };
michael@0 342
michael@0 343 OSError.invalidArgument = function invalidArgument(operation) {
michael@0 344 return new OSError(operation, Const.EINVAL);
michael@0 345 };
michael@0 346
michael@0 347 let EXPORTED_SYMBOLS = [
michael@0 348 "declareFFI",
michael@0 349 "libc",
michael@0 350 "Error",
michael@0 351 "AbstractInfo",
michael@0 352 "AbstractEntry",
michael@0 353 "Type",
michael@0 354 "POS_START",
michael@0 355 "POS_CURRENT",
michael@0 356 "POS_END"
michael@0 357 ];
michael@0 358
michael@0 359 //////////// Boilerplate
michael@0 360 if (typeof Components != "undefined") {
michael@0 361 this.EXPORTED_SYMBOLS = EXPORTED_SYMBOLS;
michael@0 362 for (let symbol of EXPORTED_SYMBOLS) {
michael@0 363 this[symbol] = exports[symbol];
michael@0 364 }
michael@0 365 }

mercurial