1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/addon-sdk/source/lib/sdk/io/file.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,196 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +"use strict"; 1.9 + 1.10 +module.metadata = { 1.11 + "stability": "experimental" 1.12 +}; 1.13 + 1.14 +const {Cc,Ci,Cr} = require("chrome"); 1.15 +const byteStreams = require("./byte-streams"); 1.16 +const textStreams = require("./text-streams"); 1.17 + 1.18 +// Flags passed when opening a file. See nsprpub/pr/include/prio.h. 1.19 +const OPEN_FLAGS = { 1.20 + RDONLY: parseInt("0x01"), 1.21 + WRONLY: parseInt("0x02"), 1.22 + CREATE_FILE: parseInt("0x08"), 1.23 + APPEND: parseInt("0x10"), 1.24 + TRUNCATE: parseInt("0x20"), 1.25 + EXCL: parseInt("0x80") 1.26 +}; 1.27 + 1.28 +var dirsvc = Cc["@mozilla.org/file/directory_service;1"] 1.29 + .getService(Ci.nsIProperties); 1.30 + 1.31 +function MozFile(path) { 1.32 + var file = Cc['@mozilla.org/file/local;1'] 1.33 + .createInstance(Ci.nsILocalFile); 1.34 + file.initWithPath(path); 1.35 + return file; 1.36 +} 1.37 + 1.38 +function ensureReadable(file) { 1.39 + if (!file.isReadable()) 1.40 + throw new Error("path is not readable: " + file.path); 1.41 +} 1.42 + 1.43 +function ensureDir(file) { 1.44 + ensureExists(file); 1.45 + if (!file.isDirectory()) 1.46 + throw new Error("path is not a directory: " + file.path); 1.47 +} 1.48 + 1.49 +function ensureFile(file) { 1.50 + ensureExists(file); 1.51 + if (!file.isFile()) 1.52 + throw new Error("path is not a file: " + file.path); 1.53 +} 1.54 + 1.55 +function ensureExists(file) { 1.56 + if (!file.exists()) 1.57 + throw friendlyError(Cr.NS_ERROR_FILE_NOT_FOUND, file.path); 1.58 +} 1.59 + 1.60 +function friendlyError(errOrResult, filename) { 1.61 + var isResult = typeof(errOrResult) === "number"; 1.62 + var result = isResult ? errOrResult : errOrResult.result; 1.63 + switch (result) { 1.64 + case Cr.NS_ERROR_FILE_NOT_FOUND: 1.65 + return new Error("path does not exist: " + filename); 1.66 + } 1.67 + return isResult ? new Error("XPCOM error code: " + errOrResult) : errOrResult; 1.68 +} 1.69 + 1.70 +exports.exists = function exists(filename) { 1.71 + return MozFile(filename).exists(); 1.72 +}; 1.73 + 1.74 +exports.isFile = function isFile(filename) { 1.75 + return MozFile(filename).isFile(); 1.76 +}; 1.77 + 1.78 +exports.read = function read(filename, mode) { 1.79 + if (typeof(mode) !== "string") 1.80 + mode = ""; 1.81 + 1.82 + // Ensure mode is read-only. 1.83 + mode = /b/.test(mode) ? "b" : ""; 1.84 + 1.85 + var stream = exports.open(filename, mode); 1.86 + try { 1.87 + var str = stream.read(); 1.88 + } 1.89 + finally { 1.90 + stream.close(); 1.91 + } 1.92 + 1.93 + return str; 1.94 +}; 1.95 + 1.96 +exports.join = function join(base) { 1.97 + if (arguments.length < 2) 1.98 + throw new Error("need at least 2 args"); 1.99 + base = MozFile(base); 1.100 + for (var i = 1; i < arguments.length; i++) 1.101 + base.append(arguments[i]); 1.102 + return base.path; 1.103 +}; 1.104 + 1.105 +exports.dirname = function dirname(path) { 1.106 + var parent = MozFile(path).parent; 1.107 + return parent ? parent.path : ""; 1.108 +}; 1.109 + 1.110 +exports.basename = function basename(path) { 1.111 + var leafName = MozFile(path).leafName; 1.112 + 1.113 + // On Windows, leafName when the path is a volume letter and colon ("c:") is 1.114 + // the path itself. But such a path has no basename, so we want the empty 1.115 + // string. 1.116 + return leafName == path ? "" : leafName; 1.117 +}; 1.118 + 1.119 +exports.list = function list(path) { 1.120 + var file = MozFile(path); 1.121 + ensureDir(file); 1.122 + ensureReadable(file); 1.123 + 1.124 + var entries = file.directoryEntries; 1.125 + var entryNames = []; 1.126 + while(entries.hasMoreElements()) { 1.127 + var entry = entries.getNext(); 1.128 + entry.QueryInterface(Ci.nsIFile); 1.129 + entryNames.push(entry.leafName); 1.130 + } 1.131 + return entryNames; 1.132 +}; 1.133 + 1.134 +exports.open = function open(filename, mode) { 1.135 + var file = MozFile(filename); 1.136 + if (typeof(mode) !== "string") 1.137 + mode = ""; 1.138 + 1.139 + // File opened for write only. 1.140 + if (/w/.test(mode)) { 1.141 + if (file.exists()) 1.142 + ensureFile(file); 1.143 + var stream = Cc['@mozilla.org/network/file-output-stream;1']. 1.144 + createInstance(Ci.nsIFileOutputStream); 1.145 + var openFlags = OPEN_FLAGS.WRONLY | 1.146 + OPEN_FLAGS.CREATE_FILE | 1.147 + OPEN_FLAGS.TRUNCATE; 1.148 + var permFlags = parseInt("0644", 8); // u+rw go+r 1.149 + try { 1.150 + stream.init(file, openFlags, permFlags, 0); 1.151 + } 1.152 + catch (err) { 1.153 + throw friendlyError(err, filename); 1.154 + } 1.155 + return /b/.test(mode) ? 1.156 + new byteStreams.ByteWriter(stream) : 1.157 + new textStreams.TextWriter(stream); 1.158 + } 1.159 + 1.160 + // File opened for read only, the default. 1.161 + ensureFile(file); 1.162 + stream = Cc['@mozilla.org/network/file-input-stream;1']. 1.163 + createInstance(Ci.nsIFileInputStream); 1.164 + try { 1.165 + stream.init(file, OPEN_FLAGS.RDONLY, 0, 0); 1.166 + } 1.167 + catch (err) { 1.168 + throw friendlyError(err, filename); 1.169 + } 1.170 + return /b/.test(mode) ? 1.171 + new byteStreams.ByteReader(stream) : 1.172 + new textStreams.TextReader(stream); 1.173 +}; 1.174 + 1.175 +exports.remove = function remove(path) { 1.176 + var file = MozFile(path); 1.177 + ensureFile(file); 1.178 + file.remove(false); 1.179 +}; 1.180 + 1.181 +exports.mkpath = function mkpath(path) { 1.182 + var file = MozFile(path); 1.183 + if (!file.exists()) 1.184 + file.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755", 8)); // u+rwx go+rx 1.185 + else if (!file.isDirectory()) 1.186 + throw new Error("The path already exists and is not a directory: " + path); 1.187 +}; 1.188 + 1.189 +exports.rmdir = function rmdir(path) { 1.190 + var file = MozFile(path); 1.191 + ensureDir(file); 1.192 + try { 1.193 + file.remove(false); 1.194 + } 1.195 + catch (err) { 1.196 + // Bug 566950 explains why we're not catching a specific exception here. 1.197 + throw new Error("The directory is not empty: " + path); 1.198 + } 1.199 +};