addon-sdk/source/lib/sdk/io/file.js

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:be08f73ad893
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 "use strict";
6
7 module.metadata = {
8 "stability": "experimental"
9 };
10
11 const {Cc,Ci,Cr} = require("chrome");
12 const byteStreams = require("./byte-streams");
13 const textStreams = require("./text-streams");
14
15 // Flags passed when opening a file. See nsprpub/pr/include/prio.h.
16 const OPEN_FLAGS = {
17 RDONLY: parseInt("0x01"),
18 WRONLY: parseInt("0x02"),
19 CREATE_FILE: parseInt("0x08"),
20 APPEND: parseInt("0x10"),
21 TRUNCATE: parseInt("0x20"),
22 EXCL: parseInt("0x80")
23 };
24
25 var dirsvc = Cc["@mozilla.org/file/directory_service;1"]
26 .getService(Ci.nsIProperties);
27
28 function MozFile(path) {
29 var file = Cc['@mozilla.org/file/local;1']
30 .createInstance(Ci.nsILocalFile);
31 file.initWithPath(path);
32 return file;
33 }
34
35 function ensureReadable(file) {
36 if (!file.isReadable())
37 throw new Error("path is not readable: " + file.path);
38 }
39
40 function ensureDir(file) {
41 ensureExists(file);
42 if (!file.isDirectory())
43 throw new Error("path is not a directory: " + file.path);
44 }
45
46 function ensureFile(file) {
47 ensureExists(file);
48 if (!file.isFile())
49 throw new Error("path is not a file: " + file.path);
50 }
51
52 function ensureExists(file) {
53 if (!file.exists())
54 throw friendlyError(Cr.NS_ERROR_FILE_NOT_FOUND, file.path);
55 }
56
57 function friendlyError(errOrResult, filename) {
58 var isResult = typeof(errOrResult) === "number";
59 var result = isResult ? errOrResult : errOrResult.result;
60 switch (result) {
61 case Cr.NS_ERROR_FILE_NOT_FOUND:
62 return new Error("path does not exist: " + filename);
63 }
64 return isResult ? new Error("XPCOM error code: " + errOrResult) : errOrResult;
65 }
66
67 exports.exists = function exists(filename) {
68 return MozFile(filename).exists();
69 };
70
71 exports.isFile = function isFile(filename) {
72 return MozFile(filename).isFile();
73 };
74
75 exports.read = function read(filename, mode) {
76 if (typeof(mode) !== "string")
77 mode = "";
78
79 // Ensure mode is read-only.
80 mode = /b/.test(mode) ? "b" : "";
81
82 var stream = exports.open(filename, mode);
83 try {
84 var str = stream.read();
85 }
86 finally {
87 stream.close();
88 }
89
90 return str;
91 };
92
93 exports.join = function join(base) {
94 if (arguments.length < 2)
95 throw new Error("need at least 2 args");
96 base = MozFile(base);
97 for (var i = 1; i < arguments.length; i++)
98 base.append(arguments[i]);
99 return base.path;
100 };
101
102 exports.dirname = function dirname(path) {
103 var parent = MozFile(path).parent;
104 return parent ? parent.path : "";
105 };
106
107 exports.basename = function basename(path) {
108 var leafName = MozFile(path).leafName;
109
110 // On Windows, leafName when the path is a volume letter and colon ("c:") is
111 // the path itself. But such a path has no basename, so we want the empty
112 // string.
113 return leafName == path ? "" : leafName;
114 };
115
116 exports.list = function list(path) {
117 var file = MozFile(path);
118 ensureDir(file);
119 ensureReadable(file);
120
121 var entries = file.directoryEntries;
122 var entryNames = [];
123 while(entries.hasMoreElements()) {
124 var entry = entries.getNext();
125 entry.QueryInterface(Ci.nsIFile);
126 entryNames.push(entry.leafName);
127 }
128 return entryNames;
129 };
130
131 exports.open = function open(filename, mode) {
132 var file = MozFile(filename);
133 if (typeof(mode) !== "string")
134 mode = "";
135
136 // File opened for write only.
137 if (/w/.test(mode)) {
138 if (file.exists())
139 ensureFile(file);
140 var stream = Cc['@mozilla.org/network/file-output-stream;1'].
141 createInstance(Ci.nsIFileOutputStream);
142 var openFlags = OPEN_FLAGS.WRONLY |
143 OPEN_FLAGS.CREATE_FILE |
144 OPEN_FLAGS.TRUNCATE;
145 var permFlags = parseInt("0644", 8); // u+rw go+r
146 try {
147 stream.init(file, openFlags, permFlags, 0);
148 }
149 catch (err) {
150 throw friendlyError(err, filename);
151 }
152 return /b/.test(mode) ?
153 new byteStreams.ByteWriter(stream) :
154 new textStreams.TextWriter(stream);
155 }
156
157 // File opened for read only, the default.
158 ensureFile(file);
159 stream = Cc['@mozilla.org/network/file-input-stream;1'].
160 createInstance(Ci.nsIFileInputStream);
161 try {
162 stream.init(file, OPEN_FLAGS.RDONLY, 0, 0);
163 }
164 catch (err) {
165 throw friendlyError(err, filename);
166 }
167 return /b/.test(mode) ?
168 new byteStreams.ByteReader(stream) :
169 new textStreams.TextReader(stream);
170 };
171
172 exports.remove = function remove(path) {
173 var file = MozFile(path);
174 ensureFile(file);
175 file.remove(false);
176 };
177
178 exports.mkpath = function mkpath(path) {
179 var file = MozFile(path);
180 if (!file.exists())
181 file.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755", 8)); // u+rwx go+rx
182 else if (!file.isDirectory())
183 throw new Error("The path already exists and is not a directory: " + path);
184 };
185
186 exports.rmdir = function rmdir(path) {
187 var file = MozFile(path);
188 ensureDir(file);
189 try {
190 file.remove(false);
191 }
192 catch (err) {
193 // Bug 566950 explains why we're not catching a specific exception here.
194 throw new Error("The directory is not empty: " + path);
195 }
196 };

mercurial