macgyver 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.md +45 -0
- data/Rakefile +1 -0
- data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Growl +0 -0
- data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Growl +0 -0
- data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Headers/Growl.h +5 -0
- data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Headers/GrowlApplicationBridge.h +551 -0
- data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Headers/GrowlDefines.h +341 -0
- data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Resources/Info.plist +40 -0
- data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/_CodeSignature/CodeResources +34 -0
- data/assets/MacGap.app/Contents/Info.plist +48 -0
- data/assets/MacGap.app/Contents/MacOS/MacGap +0 -0
- data/assets/MacGap.app/Contents/PkgInfo +1 -0
- data/assets/MacGap.app/Contents/Resources/_debugger.js +1718 -0
- data/assets/MacGap.app/Contents/Resources/_http_agent.js +310 -0
- data/assets/MacGap.app/Contents/Resources/_http_client.js +533 -0
- data/assets/MacGap.app/Contents/Resources/_http_common.js +222 -0
- data/assets/MacGap.app/Contents/Resources/_http_incoming.js +194 -0
- data/assets/MacGap.app/Contents/Resources/_http_outgoing.js +597 -0
- data/assets/MacGap.app/Contents/Resources/_http_server.js +510 -0
- data/assets/MacGap.app/Contents/Resources/_linklist.js +76 -0
- data/assets/MacGap.app/Contents/Resources/_stream_duplex.js +69 -0
- data/assets/MacGap.app/Contents/Resources/_stream_passthrough.js +41 -0
- data/assets/MacGap.app/Contents/Resources/_stream_readable.js +900 -0
- data/assets/MacGap.app/Contents/Resources/_stream_transform.js +204 -0
- data/assets/MacGap.app/Contents/Resources/_stream_writable.js +456 -0
- data/assets/MacGap.app/Contents/Resources/_tls_legacy.js +887 -0
- data/assets/MacGap.app/Contents/Resources/_tls_wrap.js +831 -0
- data/assets/MacGap.app/Contents/Resources/application.icns +0 -0
- data/assets/MacGap.app/Contents/Resources/assert.js +326 -0
- data/assets/MacGap.app/Contents/Resources/buffer.js +724 -0
- data/assets/MacGap.app/Contents/Resources/child_process.js +1107 -0
- data/assets/MacGap.app/Contents/Resources/cluster.js +613 -0
- data/assets/MacGap.app/Contents/Resources/console.js +108 -0
- data/assets/MacGap.app/Contents/Resources/constants.js +22 -0
- data/assets/MacGap.app/Contents/Resources/crypto.js +691 -0
- data/assets/MacGap.app/Contents/Resources/dgram.js +459 -0
- data/assets/MacGap.app/Contents/Resources/dns.js +274 -0
- data/assets/MacGap.app/Contents/Resources/domain.js +292 -0
- data/assets/MacGap.app/Contents/Resources/en.lproj/Credits.rtf +29 -0
- data/assets/MacGap.app/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
- data/assets/MacGap.app/Contents/Resources/en.lproj/MainMenu.nib +0 -0
- data/assets/MacGap.app/Contents/Resources/en.lproj/Window.nib +0 -0
- data/assets/MacGap.app/Contents/Resources/events.js +312 -0
- data/assets/MacGap.app/Contents/Resources/freelist.js +43 -0
- data/assets/MacGap.app/Contents/Resources/fs.js +1732 -0
- data/assets/MacGap.app/Contents/Resources/http.js +119 -0
- data/assets/MacGap.app/Contents/Resources/https.js +134 -0
- data/assets/MacGap.app/Contents/Resources/module.js +529 -0
- data/assets/MacGap.app/Contents/Resources/net.js +1378 -0
- data/assets/MacGap.app/Contents/Resources/nodelike.js +195 -0
- data/assets/MacGap.app/Contents/Resources/os.js +64 -0
- data/assets/MacGap.app/Contents/Resources/path.js +517 -0
- data/assets/MacGap.app/Contents/Resources/public/index.html +38 -0
- data/assets/MacGap.app/Contents/Resources/punycode.js +507 -0
- data/assets/MacGap.app/Contents/Resources/querystring.js +206 -0
- data/assets/MacGap.app/Contents/Resources/readline.js +1311 -0
- data/assets/MacGap.app/Contents/Resources/repl.js +945 -0
- data/assets/MacGap.app/Contents/Resources/smalloc.js +90 -0
- data/assets/MacGap.app/Contents/Resources/stream.js +127 -0
- data/assets/MacGap.app/Contents/Resources/string_decoder.js +189 -0
- data/assets/MacGap.app/Contents/Resources/sys.js +24 -0
- data/assets/MacGap.app/Contents/Resources/timers.js +568 -0
- data/assets/MacGap.app/Contents/Resources/tls.js +220 -0
- data/assets/MacGap.app/Contents/Resources/tty.js +129 -0
- data/assets/MacGap.app/Contents/Resources/url.js +693 -0
- data/assets/MacGap.app/Contents/Resources/util.js +688 -0
- data/assets/MacGap.app/Contents/Resources/vm.js +73 -0
- data/assets/MacGap.app/Contents/Resources/zlib.js +524 -0
- data/assets/index.html +38 -0
- data/bin/macgyver +104 -0
- data/macgyver.gemspec +19 -0
- data/test/public/index.html +27 -0
- metadata +121 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
|
2
|
+
{\colortbl;\red255\green255\blue255;}
|
3
|
+
\paperw9840\paperh8400
|
4
|
+
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
|
5
|
+
|
6
|
+
\f0\b\fs24 \cf0 Engineering:
|
7
|
+
\b0 \
|
8
|
+
Some people\
|
9
|
+
\
|
10
|
+
|
11
|
+
\b Human Interface Design:
|
12
|
+
\b0 \
|
13
|
+
Some other people\
|
14
|
+
\
|
15
|
+
|
16
|
+
\b Testing:
|
17
|
+
\b0 \
|
18
|
+
Hopefully not nobody\
|
19
|
+
\
|
20
|
+
|
21
|
+
\b Documentation:
|
22
|
+
\b0 \
|
23
|
+
Whoever\
|
24
|
+
\
|
25
|
+
|
26
|
+
\b With special thanks to:
|
27
|
+
\b0 \
|
28
|
+
Mom\
|
29
|
+
}
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,312 @@
|
|
1
|
+
// Copyright Joyent, Inc. and other Node contributors.
|
2
|
+
//
|
3
|
+
// Permission is hereby granted, free of charge, to any person obtaining a
|
4
|
+
// copy of this software and associated documentation files (the
|
5
|
+
// "Software"), to deal in the Software without restriction, including
|
6
|
+
// without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
8
|
+
// persons to whom the Software is furnished to do so, subject to the
|
9
|
+
// following conditions:
|
10
|
+
//
|
11
|
+
// The above copyright notice and this permission notice shall be included
|
12
|
+
// in all copies or substantial portions of the Software.
|
13
|
+
//
|
14
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
15
|
+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
17
|
+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
18
|
+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
19
|
+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
20
|
+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
var domain;
|
23
|
+
var util = require('util');
|
24
|
+
|
25
|
+
function EventEmitter() {
|
26
|
+
EventEmitter.init.call(this);
|
27
|
+
}
|
28
|
+
module.exports = EventEmitter;
|
29
|
+
|
30
|
+
// Backwards-compat with node 0.10.x
|
31
|
+
EventEmitter.EventEmitter = EventEmitter;
|
32
|
+
|
33
|
+
EventEmitter.usingDomains = false;
|
34
|
+
|
35
|
+
EventEmitter.prototype.domain = undefined;
|
36
|
+
EventEmitter.prototype._events = undefined;
|
37
|
+
EventEmitter.prototype._maxListeners = undefined;
|
38
|
+
|
39
|
+
// By default EventEmitters will print a warning if more than 10 listeners are
|
40
|
+
// added to it. This is a useful default which helps finding memory leaks.
|
41
|
+
EventEmitter.defaultMaxListeners = 10;
|
42
|
+
|
43
|
+
EventEmitter.init = function() {
|
44
|
+
this.domain = null;
|
45
|
+
if (EventEmitter.usingDomains) {
|
46
|
+
// if there is an active domain, then attach to it.
|
47
|
+
domain = domain || require('domain');
|
48
|
+
if (domain.active && !(this instanceof domain.Domain)) {
|
49
|
+
this.domain = domain.active;
|
50
|
+
}
|
51
|
+
}
|
52
|
+
this._events = this._events || {};
|
53
|
+
this._maxListeners = this._maxListeners || undefined;
|
54
|
+
};
|
55
|
+
|
56
|
+
// Obviously not all Emitters should be limited to 10. This function allows
|
57
|
+
// that to be increased. Set to zero for unlimited.
|
58
|
+
EventEmitter.prototype.setMaxListeners = function(n) {
|
59
|
+
if (!util.isNumber(n) || n < 0 || isNaN(n))
|
60
|
+
throw TypeError('n must be a positive number');
|
61
|
+
this._maxListeners = n;
|
62
|
+
return this;
|
63
|
+
};
|
64
|
+
|
65
|
+
EventEmitter.prototype.emit = function(type) {
|
66
|
+
var er, handler, len, args, i, listeners;
|
67
|
+
|
68
|
+
if (!this._events)
|
69
|
+
this._events = {};
|
70
|
+
|
71
|
+
// If there is no 'error' event listener then throw.
|
72
|
+
if (type === 'error' && !this._events.error) {
|
73
|
+
er = arguments[1];
|
74
|
+
if (this.domain) {
|
75
|
+
if (!er)
|
76
|
+
er = new Error('Uncaught, unspecified "error" event.');
|
77
|
+
er.domainEmitter = this;
|
78
|
+
er.domain = this.domain;
|
79
|
+
er.domainThrown = false;
|
80
|
+
this.domain.emit('error', er);
|
81
|
+
} else if (er instanceof Error) {
|
82
|
+
throw er; // Unhandled 'error' event
|
83
|
+
} else {
|
84
|
+
throw Error('Uncaught, unspecified "error" event.');
|
85
|
+
}
|
86
|
+
return false;
|
87
|
+
}
|
88
|
+
|
89
|
+
handler = this._events[type];
|
90
|
+
|
91
|
+
if (util.isUndefined(handler))
|
92
|
+
return false;
|
93
|
+
|
94
|
+
if (this.domain && this !== process)
|
95
|
+
this.domain.enter();
|
96
|
+
|
97
|
+
if (util.isFunction(handler)) {
|
98
|
+
switch (arguments.length) {
|
99
|
+
// fast cases
|
100
|
+
case 1:
|
101
|
+
handler.call(this);
|
102
|
+
break;
|
103
|
+
case 2:
|
104
|
+
handler.call(this, arguments[1]);
|
105
|
+
break;
|
106
|
+
case 3:
|
107
|
+
handler.call(this, arguments[1], arguments[2]);
|
108
|
+
break;
|
109
|
+
// slower
|
110
|
+
default:
|
111
|
+
len = arguments.length;
|
112
|
+
args = new Array(len - 1);
|
113
|
+
for (i = 1; i < len; i++)
|
114
|
+
args[i - 1] = arguments[i];
|
115
|
+
handler.apply(this, args);
|
116
|
+
}
|
117
|
+
} else if (util.isObject(handler)) {
|
118
|
+
len = arguments.length;
|
119
|
+
args = new Array(len - 1);
|
120
|
+
for (i = 1; i < len; i++)
|
121
|
+
args[i - 1] = arguments[i];
|
122
|
+
|
123
|
+
listeners = handler.slice();
|
124
|
+
len = listeners.length;
|
125
|
+
for (i = 0; i < len; i++)
|
126
|
+
listeners[i].apply(this, args);
|
127
|
+
}
|
128
|
+
|
129
|
+
if (this.domain && this !== process)
|
130
|
+
this.domain.exit();
|
131
|
+
|
132
|
+
return true;
|
133
|
+
};
|
134
|
+
|
135
|
+
EventEmitter.prototype.addListener = function(type, listener) {
|
136
|
+
var m;
|
137
|
+
|
138
|
+
if (!util.isFunction(listener))
|
139
|
+
throw TypeError('listener must be a function');
|
140
|
+
|
141
|
+
if (!this._events)
|
142
|
+
this._events = {};
|
143
|
+
|
144
|
+
// To avoid recursion in the case that type === "newListener"! Before
|
145
|
+
// adding it to the listeners, first emit "newListener".
|
146
|
+
if (this._events.newListener)
|
147
|
+
this.emit('newListener', type,
|
148
|
+
util.isFunction(listener.listener) ?
|
149
|
+
listener.listener : listener);
|
150
|
+
|
151
|
+
if (!this._events[type])
|
152
|
+
// Optimize the case of one listener. Don't need the extra array object.
|
153
|
+
this._events[type] = listener;
|
154
|
+
else if (util.isObject(this._events[type]))
|
155
|
+
// If we've already got an array, just append.
|
156
|
+
this._events[type].push(listener);
|
157
|
+
else
|
158
|
+
// Adding the second element, need to change to array.
|
159
|
+
this._events[type] = [this._events[type], listener];
|
160
|
+
|
161
|
+
// Check for listener leak
|
162
|
+
if (util.isObject(this._events[type]) && !this._events[type].warned) {
|
163
|
+
var m;
|
164
|
+
if (!util.isUndefined(this._maxListeners)) {
|
165
|
+
m = this._maxListeners;
|
166
|
+
} else {
|
167
|
+
m = EventEmitter.defaultMaxListeners;
|
168
|
+
}
|
169
|
+
|
170
|
+
if (m && m > 0 && this._events[type].length > m) {
|
171
|
+
this._events[type].warned = true;
|
172
|
+
console.error('(node) warning: possible EventEmitter memory ' +
|
173
|
+
'leak detected. %d listeners added. ' +
|
174
|
+
'Use emitter.setMaxListeners() to increase limit.',
|
175
|
+
this._events[type].length);
|
176
|
+
console.trace();
|
177
|
+
}
|
178
|
+
}
|
179
|
+
|
180
|
+
return this;
|
181
|
+
};
|
182
|
+
|
183
|
+
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
|
184
|
+
|
185
|
+
EventEmitter.prototype.once = function(type, listener) {
|
186
|
+
if (!util.isFunction(listener))
|
187
|
+
throw TypeError('listener must be a function');
|
188
|
+
|
189
|
+
var fired = false;
|
190
|
+
|
191
|
+
function g() {
|
192
|
+
this.removeListener(type, g);
|
193
|
+
|
194
|
+
if (!fired) {
|
195
|
+
fired = true;
|
196
|
+
listener.apply(this, arguments);
|
197
|
+
}
|
198
|
+
}
|
199
|
+
|
200
|
+
g.listener = listener;
|
201
|
+
this.on(type, g);
|
202
|
+
|
203
|
+
return this;
|
204
|
+
};
|
205
|
+
|
206
|
+
// emits a 'removeListener' event iff the listener was removed
|
207
|
+
EventEmitter.prototype.removeListener = function(type, listener) {
|
208
|
+
var list, position, length, i;
|
209
|
+
|
210
|
+
if (!util.isFunction(listener))
|
211
|
+
throw TypeError('listener must be a function');
|
212
|
+
|
213
|
+
if (!this._events || !this._events[type])
|
214
|
+
return this;
|
215
|
+
|
216
|
+
list = this._events[type];
|
217
|
+
length = list.length;
|
218
|
+
position = -1;
|
219
|
+
|
220
|
+
if (list === listener ||
|
221
|
+
(util.isFunction(list.listener) && list.listener === listener)) {
|
222
|
+
delete this._events[type];
|
223
|
+
if (this._events.removeListener)
|
224
|
+
this.emit('removeListener', type, listener);
|
225
|
+
|
226
|
+
} else if (util.isObject(list)) {
|
227
|
+
for (i = length; i-- > 0;) {
|
228
|
+
if (list[i] === listener ||
|
229
|
+
(list[i].listener && list[i].listener === listener)) {
|
230
|
+
position = i;
|
231
|
+
break;
|
232
|
+
}
|
233
|
+
}
|
234
|
+
|
235
|
+
if (position < 0)
|
236
|
+
return this;
|
237
|
+
|
238
|
+
if (list.length === 1) {
|
239
|
+
list.length = 0;
|
240
|
+
delete this._events[type];
|
241
|
+
} else {
|
242
|
+
list.splice(position, 1);
|
243
|
+
}
|
244
|
+
|
245
|
+
if (this._events.removeListener)
|
246
|
+
this.emit('removeListener', type, listener);
|
247
|
+
}
|
248
|
+
|
249
|
+
return this;
|
250
|
+
};
|
251
|
+
|
252
|
+
EventEmitter.prototype.removeAllListeners = function(type) {
|
253
|
+
var key, listeners;
|
254
|
+
|
255
|
+
if (!this._events)
|
256
|
+
return this;
|
257
|
+
|
258
|
+
// not listening for removeListener, no need to emit
|
259
|
+
if (!this._events.removeListener) {
|
260
|
+
if (arguments.length === 0)
|
261
|
+
this._events = {};
|
262
|
+
else if (this._events[type])
|
263
|
+
delete this._events[type];
|
264
|
+
return this;
|
265
|
+
}
|
266
|
+
|
267
|
+
// emit removeListener for all listeners on all events
|
268
|
+
if (arguments.length === 0) {
|
269
|
+
for (key in this._events) {
|
270
|
+
if (key === 'removeListener') continue;
|
271
|
+
this.removeAllListeners(key);
|
272
|
+
}
|
273
|
+
this.removeAllListeners('removeListener');
|
274
|
+
this._events = {};
|
275
|
+
return this;
|
276
|
+
}
|
277
|
+
|
278
|
+
listeners = this._events[type];
|
279
|
+
|
280
|
+
if (util.isFunction(listeners)) {
|
281
|
+
this.removeListener(type, listeners);
|
282
|
+
} else if (Array.isArray(listeners)) {
|
283
|
+
// LIFO order
|
284
|
+
while (listeners.length)
|
285
|
+
this.removeListener(type, listeners[listeners.length - 1]);
|
286
|
+
}
|
287
|
+
delete this._events[type];
|
288
|
+
|
289
|
+
return this;
|
290
|
+
};
|
291
|
+
|
292
|
+
EventEmitter.prototype.listeners = function(type) {
|
293
|
+
var ret;
|
294
|
+
if (!this._events || !this._events[type])
|
295
|
+
ret = [];
|
296
|
+
else if (util.isFunction(this._events[type]))
|
297
|
+
ret = [this._events[type]];
|
298
|
+
else
|
299
|
+
ret = this._events[type].slice();
|
300
|
+
return ret;
|
301
|
+
};
|
302
|
+
|
303
|
+
EventEmitter.listenerCount = function(emitter, type) {
|
304
|
+
var ret;
|
305
|
+
if (!emitter._events || !emitter._events[type])
|
306
|
+
ret = 0;
|
307
|
+
else if (util.isFunction(emitter._events[type]))
|
308
|
+
ret = 1;
|
309
|
+
else
|
310
|
+
ret = emitter._events[type].length;
|
311
|
+
return ret;
|
312
|
+
};
|
@@ -0,0 +1,43 @@
|
|
1
|
+
// Copyright Joyent, Inc. and other Node contributors.
|
2
|
+
//
|
3
|
+
// Permission is hereby granted, free of charge, to any person obtaining a
|
4
|
+
// copy of this software and associated documentation files (the
|
5
|
+
// "Software"), to deal in the Software without restriction, including
|
6
|
+
// without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
8
|
+
// persons to whom the Software is furnished to do so, subject to the
|
9
|
+
// following conditions:
|
10
|
+
//
|
11
|
+
// The above copyright notice and this permission notice shall be included
|
12
|
+
// in all copies or substantial portions of the Software.
|
13
|
+
//
|
14
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
15
|
+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
17
|
+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
18
|
+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
19
|
+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
20
|
+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
// This is a free list to avoid creating so many of the same object.
|
23
|
+
exports.FreeList = function(name, max, constructor) {
|
24
|
+
this.name = name;
|
25
|
+
this.constructor = constructor;
|
26
|
+
this.max = max;
|
27
|
+
this.list = [];
|
28
|
+
};
|
29
|
+
|
30
|
+
|
31
|
+
exports.FreeList.prototype.alloc = function() {
|
32
|
+
//debug("alloc " + this.name + " " + this.list.length);
|
33
|
+
return this.list.length ? this.list.shift() :
|
34
|
+
this.constructor.apply(this, arguments);
|
35
|
+
};
|
36
|
+
|
37
|
+
|
38
|
+
exports.FreeList.prototype.free = function(obj) {
|
39
|
+
//debug("free " + this.name + " " + this.list.length);
|
40
|
+
if (this.list.length < this.max) {
|
41
|
+
this.list.push(obj);
|
42
|
+
}
|
43
|
+
};
|
@@ -0,0 +1,1732 @@
|
|
1
|
+
// Copyright Joyent, Inc. and other Node contributors.
|
2
|
+
//
|
3
|
+
// Permission is hereby granted, free of charge, to any person obtaining a
|
4
|
+
// copy of this software and associated documentation files (the
|
5
|
+
// "Software"), to deal in the Software without restriction, including
|
6
|
+
// without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
8
|
+
// persons to whom the Software is furnished to do so, subject to the
|
9
|
+
// following conditions:
|
10
|
+
//
|
11
|
+
// The above copyright notice and this permission notice shall be included
|
12
|
+
// in all copies or substantial portions of the Software.
|
13
|
+
//
|
14
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
15
|
+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
17
|
+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
18
|
+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
19
|
+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
20
|
+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
// Maintainers, keep in mind that octal literals are not allowed
|
23
|
+
// in strict mode. Use the decimal value and add a comment with
|
24
|
+
// the octal value. Example:
|
25
|
+
//
|
26
|
+
// var mode = 438; /* mode=0666 */
|
27
|
+
|
28
|
+
var util = require('util');
|
29
|
+
var pathModule = require('path');
|
30
|
+
|
31
|
+
var binding = process.binding('fs');
|
32
|
+
var constants = process.binding('constants');
|
33
|
+
var fs = exports;
|
34
|
+
var Stream = require('stream').Stream;
|
35
|
+
var EventEmitter = require('events').EventEmitter;
|
36
|
+
|
37
|
+
var Readable = Stream.Readable;
|
38
|
+
var Writable = Stream.Writable;
|
39
|
+
|
40
|
+
var kMinPoolSpace = 128;
|
41
|
+
var kMaxLength = require('smalloc').kMaxLength;
|
42
|
+
|
43
|
+
var O_APPEND = constants.O_APPEND || 0;
|
44
|
+
var O_CREAT = constants.O_CREAT || 0;
|
45
|
+
var O_DIRECTORY = constants.O_DIRECTORY || 0;
|
46
|
+
var O_EXCL = constants.O_EXCL || 0;
|
47
|
+
var O_NOCTTY = constants.O_NOCTTY || 0;
|
48
|
+
var O_NOFOLLOW = constants.O_NOFOLLOW || 0;
|
49
|
+
var O_RDONLY = constants.O_RDONLY || 0;
|
50
|
+
var O_RDWR = constants.O_RDWR || 0;
|
51
|
+
var O_SYMLINK = constants.O_SYMLINK || 0;
|
52
|
+
var O_SYNC = constants.O_SYNC || 0;
|
53
|
+
var O_TRUNC = constants.O_TRUNC || 0;
|
54
|
+
var O_WRONLY = constants.O_WRONLY || 0;
|
55
|
+
|
56
|
+
var isWindows = process.platform === 'win32';
|
57
|
+
|
58
|
+
var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG);
|
59
|
+
var errnoException = util._errnoException;
|
60
|
+
|
61
|
+
|
62
|
+
function rethrow() {
|
63
|
+
// Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and
|
64
|
+
// is fairly slow to generate.
|
65
|
+
if (DEBUG) {
|
66
|
+
var backtrace = new Error;
|
67
|
+
return function(err) {
|
68
|
+
if (err) {
|
69
|
+
backtrace.stack = err.name + ': ' + err.message +
|
70
|
+
backtrace.stack.substr(backtrace.name.length);
|
71
|
+
err = backtrace;
|
72
|
+
throw err;
|
73
|
+
}
|
74
|
+
};
|
75
|
+
}
|
76
|
+
|
77
|
+
return function(err) {
|
78
|
+
if (err) {
|
79
|
+
throw err; // Forgot a callback but don't know where? Use NODE_DEBUG=fs
|
80
|
+
}
|
81
|
+
};
|
82
|
+
}
|
83
|
+
|
84
|
+
function maybeCallback(cb) {
|
85
|
+
return util.isFunction(cb) ? cb : rethrow();
|
86
|
+
}
|
87
|
+
|
88
|
+
// Ensure that callbacks run in the global context. Only use this function
|
89
|
+
// for callbacks that are passed to the binding layer, callbacks that are
|
90
|
+
// invoked from JS already run in the proper scope.
|
91
|
+
function makeCallback(cb) {
|
92
|
+
if (!util.isFunction(cb)) {
|
93
|
+
return rethrow();
|
94
|
+
}
|
95
|
+
|
96
|
+
return function() {
|
97
|
+
return cb.apply(null, arguments);
|
98
|
+
};
|
99
|
+
}
|
100
|
+
|
101
|
+
function assertEncoding(encoding) {
|
102
|
+
if (encoding && !Buffer.isEncoding(encoding)) {
|
103
|
+
throw new Error('Unknown encoding: ' + encoding);
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
function nullCheck(path, callback) {
|
108
|
+
if (('' + path).indexOf('\u0000') !== -1) {
|
109
|
+
var er = new Error('Path must be a string without null bytes.');
|
110
|
+
if (!callback)
|
111
|
+
throw er;
|
112
|
+
process.nextTick(function() {
|
113
|
+
callback(er);
|
114
|
+
});
|
115
|
+
return false;
|
116
|
+
}
|
117
|
+
return true;
|
118
|
+
}
|
119
|
+
|
120
|
+
fs.Stats = binding.Stats;
|
121
|
+
|
122
|
+
fs.Stats.prototype._checkModeProperty = function(property) {
|
123
|
+
return ((this.mode & constants.S_IFMT) === property);
|
124
|
+
};
|
125
|
+
|
126
|
+
fs.Stats.prototype.isDirectory = function() {
|
127
|
+
return this._checkModeProperty(constants.S_IFDIR);
|
128
|
+
};
|
129
|
+
|
130
|
+
fs.Stats.prototype.isFile = function() {
|
131
|
+
return this._checkModeProperty(constants.S_IFREG);
|
132
|
+
};
|
133
|
+
|
134
|
+
fs.Stats.prototype.isBlockDevice = function() {
|
135
|
+
return this._checkModeProperty(constants.S_IFBLK);
|
136
|
+
};
|
137
|
+
|
138
|
+
fs.Stats.prototype.isCharacterDevice = function() {
|
139
|
+
return this._checkModeProperty(constants.S_IFCHR);
|
140
|
+
};
|
141
|
+
|
142
|
+
fs.Stats.prototype.isSymbolicLink = function() {
|
143
|
+
return this._checkModeProperty(constants.S_IFLNK);
|
144
|
+
};
|
145
|
+
|
146
|
+
fs.Stats.prototype.isFIFO = function() {
|
147
|
+
return this._checkModeProperty(constants.S_IFIFO);
|
148
|
+
};
|
149
|
+
|
150
|
+
fs.Stats.prototype.isSocket = function() {
|
151
|
+
return this._checkModeProperty(constants.S_IFSOCK);
|
152
|
+
};
|
153
|
+
|
154
|
+
fs.exists = function(path, callback) {
|
155
|
+
if (!nullCheck(path, cb)) return;
|
156
|
+
binding.stat(pathModule._makeLong(path), cb);
|
157
|
+
function cb(err, stats) {
|
158
|
+
if (callback) callback(err ? false : true);
|
159
|
+
}
|
160
|
+
};
|
161
|
+
|
162
|
+
fs.existsSync = function(path) {
|
163
|
+
try {
|
164
|
+
nullCheck(path);
|
165
|
+
binding.stat(pathModule._makeLong(path));
|
166
|
+
return true;
|
167
|
+
} catch (e) {
|
168
|
+
return false;
|
169
|
+
}
|
170
|
+
};
|
171
|
+
|
172
|
+
fs.readFile = function(path, options, callback_) {
|
173
|
+
var callback = maybeCallback(arguments[arguments.length - 1]);
|
174
|
+
|
175
|
+
if (util.isFunction(options) || !options) {
|
176
|
+
options = { encoding: null, flag: 'r' };
|
177
|
+
} else if (util.isString(options)) {
|
178
|
+
options = { encoding: options, flag: 'r' };
|
179
|
+
} else if (!util.isObject(options)) {
|
180
|
+
throw new TypeError('Bad arguments');
|
181
|
+
}
|
182
|
+
|
183
|
+
var encoding = options.encoding;
|
184
|
+
assertEncoding(encoding);
|
185
|
+
|
186
|
+
// first, stat the file, so we know the size.
|
187
|
+
var size;
|
188
|
+
var buffer; // single buffer with file data
|
189
|
+
var buffers; // list for when size is unknown
|
190
|
+
var pos = 0;
|
191
|
+
var fd;
|
192
|
+
|
193
|
+
var flag = options.flag || 'r';
|
194
|
+
fs.open(path, flag, 438 /*=0666*/, function(er, fd_) {
|
195
|
+
if (er) return callback(er);
|
196
|
+
fd = fd_;
|
197
|
+
|
198
|
+
fs.fstat(fd, function(er, st) {
|
199
|
+
if (er) return callback(er);
|
200
|
+
size = st.size;
|
201
|
+
if (size === 0) {
|
202
|
+
// the kernel lies about many files.
|
203
|
+
// Go ahead and try to read some bytes.
|
204
|
+
buffers = [];
|
205
|
+
return read();
|
206
|
+
}
|
207
|
+
|
208
|
+
if (size > kMaxLength)
|
209
|
+
throw new RangeError('File size is greater than possible Buffer: ' +
|
210
|
+
'0x3FFFFFFF bytes');
|
211
|
+
|
212
|
+
buffer = new Buffer(size);
|
213
|
+
read();
|
214
|
+
});
|
215
|
+
});
|
216
|
+
|
217
|
+
function read() {
|
218
|
+
if (size === 0) {
|
219
|
+
buffer = new Buffer(8192);
|
220
|
+
fs.read(fd, buffer, 0, 8192, -1, afterRead);
|
221
|
+
} else {
|
222
|
+
fs.read(fd, buffer, pos, size - pos, -1, afterRead);
|
223
|
+
}
|
224
|
+
}
|
225
|
+
|
226
|
+
function afterRead(er, bytesRead) {
|
227
|
+
if (er) {
|
228
|
+
return fs.close(fd, function(er2) {
|
229
|
+
return callback(er);
|
230
|
+
});
|
231
|
+
}
|
232
|
+
|
233
|
+
if (bytesRead === 0) {
|
234
|
+
return close();
|
235
|
+
}
|
236
|
+
|
237
|
+
pos += bytesRead;
|
238
|
+
if (size !== 0) {
|
239
|
+
if (pos === size) close();
|
240
|
+
else read();
|
241
|
+
} else {
|
242
|
+
// unknown size, just read until we don't get bytes.
|
243
|
+
buffers.push(buffer.slice(0, bytesRead));
|
244
|
+
read();
|
245
|
+
}
|
246
|
+
}
|
247
|
+
|
248
|
+
function close() {
|
249
|
+
fs.close(fd, function(er) {
|
250
|
+
if (size === 0) {
|
251
|
+
// collected the data into the buffers list.
|
252
|
+
buffer = Buffer.concat(buffers, pos);
|
253
|
+
} else if (pos < size) {
|
254
|
+
buffer = buffer.slice(0, pos);
|
255
|
+
}
|
256
|
+
|
257
|
+
if (encoding) buffer = buffer.toString(encoding);
|
258
|
+
return callback(er, buffer);
|
259
|
+
});
|
260
|
+
}
|
261
|
+
};
|
262
|
+
|
263
|
+
fs.readFileSync = function(path, options) {
|
264
|
+
if (!options) {
|
265
|
+
options = { encoding: null, flag: 'r' };
|
266
|
+
} else if (util.isString(options)) {
|
267
|
+
options = { encoding: options, flag: 'r' };
|
268
|
+
} else if (!util.isObject(options)) {
|
269
|
+
throw new TypeError('Bad arguments');
|
270
|
+
}
|
271
|
+
|
272
|
+
var encoding = options.encoding;
|
273
|
+
assertEncoding(encoding);
|
274
|
+
|
275
|
+
var flag = options.flag || 'r';
|
276
|
+
var fd = fs.openSync(path, flag, 438 /*=0666*/);
|
277
|
+
|
278
|
+
var size;
|
279
|
+
var threw = true;
|
280
|
+
try {
|
281
|
+
size = fs.fstatSync(fd).size;
|
282
|
+
threw = false;
|
283
|
+
} finally {
|
284
|
+
if (threw) fs.closeSync(fd);
|
285
|
+
}
|
286
|
+
|
287
|
+
var pos = 0;
|
288
|
+
var buffer; // single buffer with file data
|
289
|
+
var buffers; // list for when size is unknown
|
290
|
+
|
291
|
+
if (size === 0) {
|
292
|
+
buffers = [];
|
293
|
+
} else {
|
294
|
+
buffer = new Buffer(size);
|
295
|
+
}
|
296
|
+
|
297
|
+
var done = false;
|
298
|
+
while (!done) {
|
299
|
+
var threw = true;
|
300
|
+
try {
|
301
|
+
if (size !== 0) {
|
302
|
+
var bytesRead = fs.readSync(fd, buffer, pos, size - pos);
|
303
|
+
} else {
|
304
|
+
// the kernel lies about many files.
|
305
|
+
// Go ahead and try to read some bytes.
|
306
|
+
buffer = new Buffer(8192);
|
307
|
+
var bytesRead = fs.readSync(fd, buffer, 0, 8192);
|
308
|
+
if (bytesRead) {
|
309
|
+
buffers.push(buffer.slice(0, bytesRead));
|
310
|
+
}
|
311
|
+
}
|
312
|
+
threw = false;
|
313
|
+
} finally {
|
314
|
+
if (threw) fs.closeSync(fd);
|
315
|
+
}
|
316
|
+
|
317
|
+
pos += bytesRead;
|
318
|
+
done = (bytesRead === 0) || (size !== 0 && pos >= size);
|
319
|
+
}
|
320
|
+
|
321
|
+
fs.closeSync(fd);
|
322
|
+
|
323
|
+
if (size === 0) {
|
324
|
+
// data was collected into the buffers list.
|
325
|
+
buffer = Buffer.concat(buffers, pos);
|
326
|
+
} else if (pos < size) {
|
327
|
+
buffer = buffer.slice(0, pos);
|
328
|
+
}
|
329
|
+
|
330
|
+
if (encoding) buffer = buffer.toString(encoding);
|
331
|
+
return buffer;
|
332
|
+
};
|
333
|
+
|
334
|
+
|
335
|
+
// Used by binding.open and friends
|
336
|
+
function stringToFlags(flag) {
|
337
|
+
// Only mess with strings
|
338
|
+
if (!util.isString(flag)) {
|
339
|
+
return flag;
|
340
|
+
}
|
341
|
+
|
342
|
+
switch (flag) {
|
343
|
+
case 'r' : return O_RDONLY;
|
344
|
+
case 'rs' : return O_RDONLY | O_SYNC;
|
345
|
+
case 'r+' : return O_RDWR;
|
346
|
+
case 'rs+' : return O_RDWR | O_SYNC;
|
347
|
+
|
348
|
+
case 'w' : return O_TRUNC | O_CREAT | O_WRONLY;
|
349
|
+
case 'wx' : // fall through
|
350
|
+
case 'xw' : return O_TRUNC | O_CREAT | O_WRONLY | O_EXCL;
|
351
|
+
|
352
|
+
case 'w+' : return O_TRUNC | O_CREAT | O_RDWR;
|
353
|
+
case 'wx+': // fall through
|
354
|
+
case 'xw+': return O_TRUNC | O_CREAT | O_RDWR | O_EXCL;
|
355
|
+
|
356
|
+
case 'a' : return O_APPEND | O_CREAT | O_WRONLY;
|
357
|
+
case 'ax' : // fall through
|
358
|
+
case 'xa' : return O_APPEND | O_CREAT | O_WRONLY | O_EXCL;
|
359
|
+
|
360
|
+
case 'a+' : return O_APPEND | O_CREAT | O_RDWR;
|
361
|
+
case 'ax+': // fall through
|
362
|
+
case 'xa+': return O_APPEND | O_CREAT | O_RDWR | O_EXCL;
|
363
|
+
}
|
364
|
+
|
365
|
+
throw new Error('Unknown file open flag: ' + flag);
|
366
|
+
}
|
367
|
+
|
368
|
+
// exported but hidden, only used by test/simple/test-fs-open-flags.js
|
369
|
+
Object.defineProperty(exports, '_stringToFlags', {
|
370
|
+
enumerable: false,
|
371
|
+
value: stringToFlags
|
372
|
+
});
|
373
|
+
|
374
|
+
|
375
|
+
// Yes, the follow could be easily DRYed up but I provide the explicit
|
376
|
+
// list to make the arguments clear.
|
377
|
+
|
378
|
+
fs.close = function(fd, callback) {
|
379
|
+
binding.close(fd, makeCallback(callback));
|
380
|
+
};
|
381
|
+
|
382
|
+
fs.closeSync = function(fd) {
|
383
|
+
return binding.close(fd);
|
384
|
+
};
|
385
|
+
|
386
|
+
function modeNum(m, def) {
|
387
|
+
if (util.isNumber(m))
|
388
|
+
return m;
|
389
|
+
if (util.isString(m))
|
390
|
+
return parseInt(m, 8);
|
391
|
+
if (def)
|
392
|
+
return modeNum(def);
|
393
|
+
return undefined;
|
394
|
+
}
|
395
|
+
|
396
|
+
fs.open = function(path, flags, mode, callback) {
|
397
|
+
callback = makeCallback(arguments[arguments.length - 1]);
|
398
|
+
mode = modeNum(mode, 438 /*=0666*/);
|
399
|
+
|
400
|
+
if (!nullCheck(path, callback)) return;
|
401
|
+
binding.open(pathModule._makeLong(path),
|
402
|
+
stringToFlags(flags),
|
403
|
+
mode,
|
404
|
+
callback);
|
405
|
+
};
|
406
|
+
|
407
|
+
fs.openSync = function(path, flags, mode) {
|
408
|
+
mode = modeNum(mode, 438 /*=0666*/);
|
409
|
+
nullCheck(path);
|
410
|
+
return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
|
411
|
+
};
|
412
|
+
|
413
|
+
fs.read = function(fd, buffer, offset, length, position, callback) {
|
414
|
+
if (!util.isBuffer(buffer)) {
|
415
|
+
// legacy string interface (fd, length, position, encoding, callback)
|
416
|
+
var cb = arguments[4],
|
417
|
+
encoding = arguments[3];
|
418
|
+
|
419
|
+
assertEncoding(encoding);
|
420
|
+
|
421
|
+
position = arguments[2];
|
422
|
+
length = arguments[1];
|
423
|
+
buffer = new Buffer(length);
|
424
|
+
offset = 0;
|
425
|
+
|
426
|
+
callback = function(err, bytesRead) {
|
427
|
+
if (!cb) return;
|
428
|
+
|
429
|
+
var str = (bytesRead > 0) ? buffer.toString(encoding, 0, bytesRead) : '';
|
430
|
+
|
431
|
+
(cb)(err, str, bytesRead);
|
432
|
+
};
|
433
|
+
}
|
434
|
+
|
435
|
+
function wrapper(err, bytesRead) {
|
436
|
+
// Retain a reference to buffer so that it can't be GC'ed too soon.
|
437
|
+
callback && callback(err, bytesRead || 0, buffer);
|
438
|
+
}
|
439
|
+
|
440
|
+
binding.read(fd, buffer, offset, length, position, wrapper);
|
441
|
+
};
|
442
|
+
|
443
|
+
fs.readSync = function(fd, buffer, offset, length, position) {
|
444
|
+
var legacy = false;
|
445
|
+
if (!util.isBuffer(buffer)) {
|
446
|
+
// legacy string interface (fd, length, position, encoding, callback)
|
447
|
+
legacy = true;
|
448
|
+
var encoding = arguments[3];
|
449
|
+
|
450
|
+
assertEncoding(encoding);
|
451
|
+
|
452
|
+
position = arguments[2];
|
453
|
+
length = arguments[1];
|
454
|
+
buffer = new Buffer(length);
|
455
|
+
|
456
|
+
offset = 0;
|
457
|
+
}
|
458
|
+
|
459
|
+
var r = binding.read(fd, buffer, offset, length, position);
|
460
|
+
if (!legacy) {
|
461
|
+
return r;
|
462
|
+
}
|
463
|
+
|
464
|
+
var str = (r > 0) ? buffer.toString(encoding, 0, r) : '';
|
465
|
+
return [str, r];
|
466
|
+
};
|
467
|
+
|
468
|
+
// usage:
|
469
|
+
// fs.write(fd, buffer, offset, length[, position], callback);
|
470
|
+
// OR
|
471
|
+
// fs.write(fd, string[, position[, encoding]], callback);
|
472
|
+
fs.write = function(fd, buffer, offset, length, position, callback) {
|
473
|
+
if (util.isBuffer(buffer)) {
|
474
|
+
// if no position is passed then assume null
|
475
|
+
if (util.isFunction(position)) {
|
476
|
+
callback = position;
|
477
|
+
position = null;
|
478
|
+
}
|
479
|
+
callback = maybeCallback(callback);
|
480
|
+
var wrapper = function(err, written) {
|
481
|
+
// Retain a reference to buffer so that it can't be GC'ed too soon.
|
482
|
+
callback(err, written || 0, buffer);
|
483
|
+
};
|
484
|
+
return binding.writeBuffer(fd, buffer, offset, length, position, wrapper);
|
485
|
+
}
|
486
|
+
|
487
|
+
if (util.isString(buffer))
|
488
|
+
buffer += '';
|
489
|
+
if (!util.isFunction(position)) {
|
490
|
+
if (util.isFunction(offset)) {
|
491
|
+
position = offset;
|
492
|
+
offset = null;
|
493
|
+
} else {
|
494
|
+
position = length;
|
495
|
+
}
|
496
|
+
length = 'utf8';
|
497
|
+
}
|
498
|
+
callback = maybeCallback(position);
|
499
|
+
position = function(err, written) {
|
500
|
+
// retain reference to string in case it's external
|
501
|
+
callback(err, written || 0, buffer);
|
502
|
+
};
|
503
|
+
return binding.writeString(fd, buffer, offset, length, position);
|
504
|
+
};
|
505
|
+
|
506
|
+
// usage:
|
507
|
+
// fs.writeSync(fd, buffer, offset, length[, position]);
|
508
|
+
// OR
|
509
|
+
// fs.writeSync(fd, string[, position[, encoding]]);
|
510
|
+
fs.writeSync = function(fd, buffer, offset, length, position) {
|
511
|
+
if (util.isBuffer(buffer)) {
|
512
|
+
if (util.isUndefined(position))
|
513
|
+
position = null;
|
514
|
+
return binding.writeBuffer(fd, buffer, offset, length, position);
|
515
|
+
}
|
516
|
+
if (!util.isString(buffer))
|
517
|
+
buffer += '';
|
518
|
+
if (util.isUndefined(offset))
|
519
|
+
offset = null;
|
520
|
+
return binding.writeString(fd, buffer, offset, length, position);
|
521
|
+
};
|
522
|
+
|
523
|
+
fs.rename = function(oldPath, newPath, callback) {
|
524
|
+
callback = makeCallback(callback);
|
525
|
+
if (!nullCheck(oldPath, callback)) return;
|
526
|
+
if (!nullCheck(newPath, callback)) return;
|
527
|
+
binding.rename(pathModule._makeLong(oldPath),
|
528
|
+
pathModule._makeLong(newPath),
|
529
|
+
callback);
|
530
|
+
};
|
531
|
+
|
532
|
+
fs.renameSync = function(oldPath, newPath) {
|
533
|
+
nullCheck(oldPath);
|
534
|
+
nullCheck(newPath);
|
535
|
+
return binding.rename(pathModule._makeLong(oldPath),
|
536
|
+
pathModule._makeLong(newPath));
|
537
|
+
};
|
538
|
+
|
539
|
+
fs.truncate = function(path, len, callback) {
|
540
|
+
if (util.isNumber(path)) {
|
541
|
+
// legacy
|
542
|
+
return fs.ftruncate(path, len, callback);
|
543
|
+
}
|
544
|
+
if (util.isFunction(len)) {
|
545
|
+
callback = len;
|
546
|
+
len = 0;
|
547
|
+
} else if (util.isUndefined(len)) {
|
548
|
+
len = 0;
|
549
|
+
}
|
550
|
+
callback = maybeCallback(callback);
|
551
|
+
fs.open(path, 'r+', function(er, fd) {
|
552
|
+
if (er) return callback(er);
|
553
|
+
binding.ftruncate(fd, len, function(er) {
|
554
|
+
fs.close(fd, function(er2) {
|
555
|
+
callback(er || er2);
|
556
|
+
});
|
557
|
+
});
|
558
|
+
});
|
559
|
+
};
|
560
|
+
|
561
|
+
fs.truncateSync = function(path, len) {
|
562
|
+
if (util.isNumber(path)) {
|
563
|
+
// legacy
|
564
|
+
return fs.ftruncateSync(path, len);
|
565
|
+
}
|
566
|
+
if (util.isUndefined(len)) {
|
567
|
+
len = 0;
|
568
|
+
}
|
569
|
+
// allow error to be thrown, but still close fd.
|
570
|
+
var fd = fs.openSync(path, 'r+');
|
571
|
+
try {
|
572
|
+
var ret = fs.ftruncateSync(fd, len);
|
573
|
+
} finally {
|
574
|
+
fs.closeSync(fd);
|
575
|
+
}
|
576
|
+
return ret;
|
577
|
+
};
|
578
|
+
|
579
|
+
fs.ftruncate = function(fd, len, callback) {
|
580
|
+
if (util.isFunction(len)) {
|
581
|
+
callback = len;
|
582
|
+
len = 0;
|
583
|
+
} else if (util.isUndefined(len)) {
|
584
|
+
len = 0;
|
585
|
+
}
|
586
|
+
binding.ftruncate(fd, len, makeCallback(callback));
|
587
|
+
};
|
588
|
+
|
589
|
+
fs.ftruncateSync = function(fd, len) {
|
590
|
+
if (util.isUndefined(len)) {
|
591
|
+
len = 0;
|
592
|
+
}
|
593
|
+
return binding.ftruncate(fd, len);
|
594
|
+
};
|
595
|
+
|
596
|
+
fs.rmdir = function(path, callback) {
|
597
|
+
callback = makeCallback(callback);
|
598
|
+
if (!nullCheck(path, callback)) return;
|
599
|
+
binding.rmdir(pathModule._makeLong(path), callback);
|
600
|
+
};
|
601
|
+
|
602
|
+
fs.rmdirSync = function(path) {
|
603
|
+
nullCheck(path);
|
604
|
+
return binding.rmdir(pathModule._makeLong(path));
|
605
|
+
};
|
606
|
+
|
607
|
+
fs.fdatasync = function(fd, callback) {
|
608
|
+
binding.fdatasync(fd, makeCallback(callback));
|
609
|
+
};
|
610
|
+
|
611
|
+
fs.fdatasyncSync = function(fd) {
|
612
|
+
return binding.fdatasync(fd);
|
613
|
+
};
|
614
|
+
|
615
|
+
fs.fsync = function(fd, callback) {
|
616
|
+
binding.fsync(fd, makeCallback(callback));
|
617
|
+
};
|
618
|
+
|
619
|
+
fs.fsyncSync = function(fd) {
|
620
|
+
return binding.fsync(fd);
|
621
|
+
};
|
622
|
+
|
623
|
+
fs.mkdir = function(path, mode, callback) {
|
624
|
+
if (util.isFunction(mode)) callback = mode;
|
625
|
+
callback = makeCallback(callback);
|
626
|
+
if (!nullCheck(path, callback)) return;
|
627
|
+
binding.mkdir(pathModule._makeLong(path),
|
628
|
+
modeNum(mode, 511 /*=0777*/),
|
629
|
+
callback);
|
630
|
+
};
|
631
|
+
|
632
|
+
fs.mkdirSync = function(path, mode) {
|
633
|
+
nullCheck(path);
|
634
|
+
return binding.mkdir(pathModule._makeLong(path),
|
635
|
+
modeNum(mode, 511 /*=0777*/));
|
636
|
+
};
|
637
|
+
|
638
|
+
fs.readdir = function(path, callback) {
|
639
|
+
callback = makeCallback(callback);
|
640
|
+
if (!nullCheck(path, callback)) return;
|
641
|
+
binding.readdir(pathModule._makeLong(path), callback);
|
642
|
+
};
|
643
|
+
|
644
|
+
fs.readdirSync = function(path) {
|
645
|
+
nullCheck(path);
|
646
|
+
return binding.readdir(pathModule._makeLong(path));
|
647
|
+
};
|
648
|
+
|
649
|
+
fs.fstat = function(fd, callback) {
|
650
|
+
binding.fstat(fd, makeCallback(callback));
|
651
|
+
};
|
652
|
+
|
653
|
+
fs.lstat = function(path, callback) {
|
654
|
+
callback = makeCallback(callback);
|
655
|
+
if (!nullCheck(path, callback)) return;
|
656
|
+
binding.lstat(pathModule._makeLong(path), callback);
|
657
|
+
};
|
658
|
+
|
659
|
+
fs.stat = function(path, callback) {
|
660
|
+
callback = makeCallback(callback);
|
661
|
+
if (!nullCheck(path, callback)) return;
|
662
|
+
binding.stat(pathModule._makeLong(path), callback);
|
663
|
+
};
|
664
|
+
|
665
|
+
fs.fstatSync = function(fd) {
|
666
|
+
return binding.fstat(fd);
|
667
|
+
};
|
668
|
+
|
669
|
+
fs.lstatSync = function(path) {
|
670
|
+
nullCheck(path);
|
671
|
+
return binding.lstat(pathModule._makeLong(path));
|
672
|
+
};
|
673
|
+
|
674
|
+
fs.statSync = function(path) {
|
675
|
+
nullCheck(path);
|
676
|
+
return binding.stat(pathModule._makeLong(path));
|
677
|
+
};
|
678
|
+
|
679
|
+
fs.readlink = function(path, callback) {
|
680
|
+
callback = makeCallback(callback);
|
681
|
+
if (!nullCheck(path, callback)) return;
|
682
|
+
binding.readlink(pathModule._makeLong(path), callback);
|
683
|
+
};
|
684
|
+
|
685
|
+
fs.readlinkSync = function(path) {
|
686
|
+
nullCheck(path);
|
687
|
+
return binding.readlink(pathModule._makeLong(path));
|
688
|
+
};
|
689
|
+
|
690
|
+
function preprocessSymlinkDestination(path, type) {
|
691
|
+
if (!isWindows) {
|
692
|
+
// No preprocessing is needed on Unix.
|
693
|
+
return path;
|
694
|
+
} else if (type === 'junction') {
|
695
|
+
// Junctions paths need to be absolute and \\?\-prefixed.
|
696
|
+
return pathModule._makeLong(path);
|
697
|
+
} else {
|
698
|
+
// Windows symlinks don't tolerate forward slashes.
|
699
|
+
return ('' + path).replace(/\//g, '\\');
|
700
|
+
}
|
701
|
+
}
|
702
|
+
|
703
|
+
fs.symlink = function(destination, path, type_, callback) {
|
704
|
+
var type = (util.isString(type_) ? type_ : null);
|
705
|
+
var callback = makeCallback(arguments[arguments.length - 1]);
|
706
|
+
|
707
|
+
if (!nullCheck(destination, callback)) return;
|
708
|
+
if (!nullCheck(path, callback)) return;
|
709
|
+
|
710
|
+
binding.symlink(preprocessSymlinkDestination(destination, type),
|
711
|
+
pathModule._makeLong(path),
|
712
|
+
type,
|
713
|
+
callback);
|
714
|
+
};
|
715
|
+
|
716
|
+
fs.symlinkSync = function(destination, path, type) {
|
717
|
+
type = (util.isString(type) ? type : null);
|
718
|
+
|
719
|
+
nullCheck(destination);
|
720
|
+
nullCheck(path);
|
721
|
+
|
722
|
+
return binding.symlink(preprocessSymlinkDestination(destination, type),
|
723
|
+
pathModule._makeLong(path),
|
724
|
+
type);
|
725
|
+
};
|
726
|
+
|
727
|
+
fs.link = function(srcpath, dstpath, callback) {
|
728
|
+
callback = makeCallback(callback);
|
729
|
+
if (!nullCheck(srcpath, callback)) return;
|
730
|
+
if (!nullCheck(dstpath, callback)) return;
|
731
|
+
|
732
|
+
binding.link(pathModule._makeLong(srcpath),
|
733
|
+
pathModule._makeLong(dstpath),
|
734
|
+
callback);
|
735
|
+
};
|
736
|
+
|
737
|
+
fs.linkSync = function(srcpath, dstpath) {
|
738
|
+
nullCheck(srcpath);
|
739
|
+
nullCheck(dstpath);
|
740
|
+
return binding.link(pathModule._makeLong(srcpath),
|
741
|
+
pathModule._makeLong(dstpath));
|
742
|
+
};
|
743
|
+
|
744
|
+
fs.unlink = function(path, callback) {
|
745
|
+
callback = makeCallback(callback);
|
746
|
+
if (!nullCheck(path, callback)) return;
|
747
|
+
binding.unlink(pathModule._makeLong(path), callback);
|
748
|
+
};
|
749
|
+
|
750
|
+
fs.unlinkSync = function(path) {
|
751
|
+
nullCheck(path);
|
752
|
+
return binding.unlink(pathModule._makeLong(path));
|
753
|
+
};
|
754
|
+
|
755
|
+
fs.fchmod = function(fd, mode, callback) {
|
756
|
+
binding.fchmod(fd, modeNum(mode), makeCallback(callback));
|
757
|
+
};
|
758
|
+
|
759
|
+
fs.fchmodSync = function(fd, mode) {
|
760
|
+
return binding.fchmod(fd, modeNum(mode));
|
761
|
+
};
|
762
|
+
|
763
|
+
if (constants.hasOwnProperty('O_SYMLINK')) {
|
764
|
+
fs.lchmod = function(path, mode, callback) {
|
765
|
+
callback = maybeCallback(callback);
|
766
|
+
fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) {
|
767
|
+
if (err) {
|
768
|
+
callback(err);
|
769
|
+
return;
|
770
|
+
}
|
771
|
+
// prefer to return the chmod error, if one occurs,
|
772
|
+
// but still try to close, and report closing errors if they occur.
|
773
|
+
fs.fchmod(fd, mode, function(err) {
|
774
|
+
fs.close(fd, function(err2) {
|
775
|
+
callback(err || err2);
|
776
|
+
});
|
777
|
+
});
|
778
|
+
});
|
779
|
+
};
|
780
|
+
|
781
|
+
fs.lchmodSync = function(path, mode) {
|
782
|
+
var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK);
|
783
|
+
|
784
|
+
// prefer to return the chmod error, if one occurs,
|
785
|
+
// but still try to close, and report closing errors if they occur.
|
786
|
+
var err, err2;
|
787
|
+
try {
|
788
|
+
var ret = fs.fchmodSync(fd, mode);
|
789
|
+
} catch (er) {
|
790
|
+
err = er;
|
791
|
+
}
|
792
|
+
try {
|
793
|
+
fs.closeSync(fd);
|
794
|
+
} catch (er) {
|
795
|
+
err2 = er;
|
796
|
+
}
|
797
|
+
if (err || err2) throw (err || err2);
|
798
|
+
return ret;
|
799
|
+
};
|
800
|
+
}
|
801
|
+
|
802
|
+
|
803
|
+
fs.chmod = function(path, mode, callback) {
|
804
|
+
callback = makeCallback(callback);
|
805
|
+
if (!nullCheck(path, callback)) return;
|
806
|
+
binding.chmod(pathModule._makeLong(path),
|
807
|
+
modeNum(mode),
|
808
|
+
callback);
|
809
|
+
};
|
810
|
+
|
811
|
+
fs.chmodSync = function(path, mode) {
|
812
|
+
nullCheck(path);
|
813
|
+
return binding.chmod(pathModule._makeLong(path), modeNum(mode));
|
814
|
+
};
|
815
|
+
|
816
|
+
if (constants.hasOwnProperty('O_SYMLINK')) {
|
817
|
+
fs.lchown = function(path, uid, gid, callback) {
|
818
|
+
callback = maybeCallback(callback);
|
819
|
+
fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) {
|
820
|
+
if (err) {
|
821
|
+
callback(err);
|
822
|
+
return;
|
823
|
+
}
|
824
|
+
fs.fchown(fd, uid, gid, callback);
|
825
|
+
});
|
826
|
+
};
|
827
|
+
|
828
|
+
fs.lchownSync = function(path, uid, gid) {
|
829
|
+
var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK);
|
830
|
+
return fs.fchownSync(fd, uid, gid);
|
831
|
+
};
|
832
|
+
}
|
833
|
+
|
834
|
+
fs.fchown = function(fd, uid, gid, callback) {
|
835
|
+
binding.fchown(fd, uid, gid, makeCallback(callback));
|
836
|
+
};
|
837
|
+
|
838
|
+
fs.fchownSync = function(fd, uid, gid) {
|
839
|
+
return binding.fchown(fd, uid, gid);
|
840
|
+
};
|
841
|
+
|
842
|
+
fs.chown = function(path, uid, gid, callback) {
|
843
|
+
callback = makeCallback(callback);
|
844
|
+
if (!nullCheck(path, callback)) return;
|
845
|
+
binding.chown(pathModule._makeLong(path), uid, gid, callback);
|
846
|
+
};
|
847
|
+
|
848
|
+
fs.chownSync = function(path, uid, gid) {
|
849
|
+
nullCheck(path);
|
850
|
+
return binding.chown(pathModule._makeLong(path), uid, gid);
|
851
|
+
};
|
852
|
+
|
853
|
+
// converts Date or number to a fractional UNIX timestamp
|
854
|
+
function toUnixTimestamp(time) {
|
855
|
+
if (util.isNumber(time)) {
|
856
|
+
return time;
|
857
|
+
}
|
858
|
+
if (util.isDate(time)) {
|
859
|
+
// convert to 123.456 UNIX timestamp
|
860
|
+
return time.getTime() / 1000;
|
861
|
+
}
|
862
|
+
throw new Error('Cannot parse time: ' + time);
|
863
|
+
}
|
864
|
+
|
865
|
+
// exported for unit tests, not for public consumption
|
866
|
+
fs._toUnixTimestamp = toUnixTimestamp;
|
867
|
+
|
868
|
+
fs.utimes = function(path, atime, mtime, callback) {
|
869
|
+
callback = makeCallback(callback);
|
870
|
+
if (!nullCheck(path, callback)) return;
|
871
|
+
binding.utimes(pathModule._makeLong(path),
|
872
|
+
toUnixTimestamp(atime),
|
873
|
+
toUnixTimestamp(mtime),
|
874
|
+
callback);
|
875
|
+
};
|
876
|
+
|
877
|
+
fs.utimesSync = function(path, atime, mtime) {
|
878
|
+
nullCheck(path);
|
879
|
+
atime = toUnixTimestamp(atime);
|
880
|
+
mtime = toUnixTimestamp(mtime);
|
881
|
+
binding.utimes(pathModule._makeLong(path), atime, mtime);
|
882
|
+
};
|
883
|
+
|
884
|
+
fs.futimes = function(fd, atime, mtime, callback) {
|
885
|
+
atime = toUnixTimestamp(atime);
|
886
|
+
mtime = toUnixTimestamp(mtime);
|
887
|
+
binding.futimes(fd, atime, mtime, makeCallback(callback));
|
888
|
+
};
|
889
|
+
|
890
|
+
fs.futimesSync = function(fd, atime, mtime) {
|
891
|
+
atime = toUnixTimestamp(atime);
|
892
|
+
mtime = toUnixTimestamp(mtime);
|
893
|
+
binding.futimes(fd, atime, mtime);
|
894
|
+
};
|
895
|
+
|
896
|
+
function writeAll(fd, buffer, offset, length, position, callback) {
|
897
|
+
callback = maybeCallback(arguments[arguments.length - 1]);
|
898
|
+
|
899
|
+
// write(fd, buffer, offset, length, position, callback)
|
900
|
+
fs.write(fd, buffer, offset, length, position, function(writeErr, written) {
|
901
|
+
if (writeErr) {
|
902
|
+
fs.close(fd, function() {
|
903
|
+
if (callback) callback(writeErr);
|
904
|
+
});
|
905
|
+
} else {
|
906
|
+
if (written === length) {
|
907
|
+
fs.close(fd, callback);
|
908
|
+
} else {
|
909
|
+
offset += written;
|
910
|
+
length -= written;
|
911
|
+
position += written;
|
912
|
+
writeAll(fd, buffer, offset, length, position, callback);
|
913
|
+
}
|
914
|
+
}
|
915
|
+
});
|
916
|
+
}
|
917
|
+
|
918
|
+
fs.writeFile = function(path, data, options, callback) {
|
919
|
+
var callback = maybeCallback(arguments[arguments.length - 1]);
|
920
|
+
|
921
|
+
if (util.isFunction(options) || !options) {
|
922
|
+
options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'w' };
|
923
|
+
} else if (util.isString(options)) {
|
924
|
+
options = { encoding: options, mode: 438, flag: 'w' };
|
925
|
+
} else if (!util.isObject(options)) {
|
926
|
+
throw new TypeError('Bad arguments');
|
927
|
+
}
|
928
|
+
|
929
|
+
assertEncoding(options.encoding);
|
930
|
+
|
931
|
+
var flag = options.flag || 'w';
|
932
|
+
fs.open(path, options.flag || 'w', options.mode, function(openErr, fd) {
|
933
|
+
if (openErr) {
|
934
|
+
if (callback) callback(openErr);
|
935
|
+
} else {
|
936
|
+
var buffer = util.isBuffer(data) ? data : new Buffer('' + data,
|
937
|
+
options.encoding || 'utf8');
|
938
|
+
var position = /a/.test(flag) ? null : 0;
|
939
|
+
writeAll(fd, buffer, 0, buffer.length, position, callback);
|
940
|
+
}
|
941
|
+
});
|
942
|
+
};
|
943
|
+
|
944
|
+
fs.writeFileSync = function(path, data, options) {
|
945
|
+
if (!options) {
|
946
|
+
options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'w' };
|
947
|
+
} else if (util.isString(options)) {
|
948
|
+
options = { encoding: options, mode: 438, flag: 'w' };
|
949
|
+
} else if (!util.isObject(options)) {
|
950
|
+
throw new TypeError('Bad arguments');
|
951
|
+
}
|
952
|
+
|
953
|
+
assertEncoding(options.encoding);
|
954
|
+
|
955
|
+
var flag = options.flag || 'w';
|
956
|
+
var fd = fs.openSync(path, flag, options.mode);
|
957
|
+
if (!util.isBuffer(data)) {
|
958
|
+
data = new Buffer('' + data, options.encoding || 'utf8');
|
959
|
+
}
|
960
|
+
var written = 0;
|
961
|
+
var length = data.length;
|
962
|
+
var position = /a/.test(flag) ? null : 0;
|
963
|
+
try {
|
964
|
+
while (written < length) {
|
965
|
+
written += fs.writeSync(fd, data, written, length - written, position);
|
966
|
+
position += written;
|
967
|
+
}
|
968
|
+
} finally {
|
969
|
+
fs.closeSync(fd);
|
970
|
+
}
|
971
|
+
};
|
972
|
+
|
973
|
+
fs.appendFile = function(path, data, options, callback_) {
|
974
|
+
var callback = maybeCallback(arguments[arguments.length - 1]);
|
975
|
+
|
976
|
+
if (util.isFunction(options) || !options) {
|
977
|
+
options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'a' };
|
978
|
+
} else if (util.isString(options)) {
|
979
|
+
options = { encoding: options, mode: 438, flag: 'a' };
|
980
|
+
} else if (!util.isObject(options)) {
|
981
|
+
throw new TypeError('Bad arguments');
|
982
|
+
}
|
983
|
+
|
984
|
+
if (!options.flag)
|
985
|
+
options = util._extend({ flag: 'a' }, options);
|
986
|
+
fs.writeFile(path, data, options, callback);
|
987
|
+
};
|
988
|
+
|
989
|
+
fs.appendFileSync = function(path, data, options) {
|
990
|
+
if (!options) {
|
991
|
+
options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'a' };
|
992
|
+
} else if (util.isString(options)) {
|
993
|
+
options = { encoding: options, mode: 438, flag: 'a' };
|
994
|
+
} else if (!util.isObject(options)) {
|
995
|
+
throw new TypeError('Bad arguments');
|
996
|
+
}
|
997
|
+
if (!options.flag)
|
998
|
+
options = util._extend({ flag: 'a' }, options);
|
999
|
+
|
1000
|
+
fs.writeFileSync(path, data, options);
|
1001
|
+
};
|
1002
|
+
|
1003
|
+
function FSWatcher() {
|
1004
|
+
EventEmitter.call(this);
|
1005
|
+
|
1006
|
+
var self = this;
|
1007
|
+
var FSEvent = process.binding('fs_event_wrap').FSEvent;
|
1008
|
+
this._handle = new FSEvent();
|
1009
|
+
this._handle.owner = this;
|
1010
|
+
|
1011
|
+
this._handle.onchange = function(status, event, filename) {
|
1012
|
+
if (status < 0) {
|
1013
|
+
self._handle.close();
|
1014
|
+
self.emit('error', errnoException(status, 'watch'));
|
1015
|
+
} else {
|
1016
|
+
self.emit('change', event, filename);
|
1017
|
+
}
|
1018
|
+
};
|
1019
|
+
}
|
1020
|
+
util.inherits(FSWatcher, EventEmitter);
|
1021
|
+
|
1022
|
+
FSWatcher.prototype.start = function(filename, persistent, recursive) {
|
1023
|
+
nullCheck(filename);
|
1024
|
+
var err = this._handle.start(pathModule._makeLong(filename),
|
1025
|
+
persistent,
|
1026
|
+
recursive);
|
1027
|
+
if (err) {
|
1028
|
+
this._handle.close();
|
1029
|
+
throw errnoException(err, 'watch');
|
1030
|
+
}
|
1031
|
+
};
|
1032
|
+
|
1033
|
+
FSWatcher.prototype.close = function() {
|
1034
|
+
this._handle.close();
|
1035
|
+
};
|
1036
|
+
|
1037
|
+
fs.watch = function(filename) {
|
1038
|
+
nullCheck(filename);
|
1039
|
+
var watcher;
|
1040
|
+
var options;
|
1041
|
+
var listener;
|
1042
|
+
|
1043
|
+
if (util.isObject(arguments[1])) {
|
1044
|
+
options = arguments[1];
|
1045
|
+
listener = arguments[2];
|
1046
|
+
} else {
|
1047
|
+
options = {};
|
1048
|
+
listener = arguments[1];
|
1049
|
+
}
|
1050
|
+
|
1051
|
+
if (util.isUndefined(options.persistent)) options.persistent = true;
|
1052
|
+
if (util.isUndefined(options.recursive)) options.recursive = false;
|
1053
|
+
|
1054
|
+
watcher = new FSWatcher();
|
1055
|
+
watcher.start(filename, options.persistent, options.recursive);
|
1056
|
+
|
1057
|
+
if (listener) {
|
1058
|
+
watcher.addListener('change', listener);
|
1059
|
+
}
|
1060
|
+
|
1061
|
+
return watcher;
|
1062
|
+
};
|
1063
|
+
|
1064
|
+
|
1065
|
+
// Stat Change Watchers
|
1066
|
+
|
1067
|
+
function StatWatcher() {
|
1068
|
+
EventEmitter.call(this);
|
1069
|
+
|
1070
|
+
var self = this;
|
1071
|
+
this._handle = new binding.StatWatcher();
|
1072
|
+
|
1073
|
+
// uv_fs_poll is a little more powerful than ev_stat but we curb it for
|
1074
|
+
// the sake of backwards compatibility
|
1075
|
+
var oldStatus = -1;
|
1076
|
+
|
1077
|
+
this._handle.onchange = function(current, previous, newStatus) {
|
1078
|
+
if (oldStatus === -1 &&
|
1079
|
+
newStatus === -1 &&
|
1080
|
+
current.nlink === previous.nlink) return;
|
1081
|
+
|
1082
|
+
oldStatus = newStatus;
|
1083
|
+
self.emit('change', current, previous);
|
1084
|
+
};
|
1085
|
+
|
1086
|
+
this._handle.onstop = function() {
|
1087
|
+
self.emit('stop');
|
1088
|
+
};
|
1089
|
+
}
|
1090
|
+
util.inherits(StatWatcher, EventEmitter);
|
1091
|
+
|
1092
|
+
|
1093
|
+
StatWatcher.prototype.start = function(filename, persistent, interval) {
|
1094
|
+
nullCheck(filename);
|
1095
|
+
this._handle.start(pathModule._makeLong(filename), persistent, interval);
|
1096
|
+
};
|
1097
|
+
|
1098
|
+
|
1099
|
+
StatWatcher.prototype.stop = function() {
|
1100
|
+
this._handle.stop();
|
1101
|
+
};
|
1102
|
+
|
1103
|
+
|
1104
|
+
var statWatchers = {};
|
1105
|
+
function inStatWatchers(filename) {
|
1106
|
+
return Object.prototype.hasOwnProperty.call(statWatchers, filename) &&
|
1107
|
+
statWatchers[filename];
|
1108
|
+
}
|
1109
|
+
|
1110
|
+
|
1111
|
+
fs.watchFile = function(filename) {
|
1112
|
+
nullCheck(filename);
|
1113
|
+
var stat;
|
1114
|
+
var listener;
|
1115
|
+
|
1116
|
+
var options = {
|
1117
|
+
// Poll interval in milliseconds. 5007 is what libev used to use. It's
|
1118
|
+
// a little on the slow side but let's stick with it for now to keep
|
1119
|
+
// behavioral changes to a minimum.
|
1120
|
+
interval: 5007,
|
1121
|
+
persistent: true
|
1122
|
+
};
|
1123
|
+
|
1124
|
+
if (util.isObject(arguments[1])) {
|
1125
|
+
options = util._extend(options, arguments[1]);
|
1126
|
+
listener = arguments[2];
|
1127
|
+
} else {
|
1128
|
+
listener = arguments[1];
|
1129
|
+
}
|
1130
|
+
|
1131
|
+
if (!listener) {
|
1132
|
+
throw new Error('watchFile requires a listener function');
|
1133
|
+
}
|
1134
|
+
|
1135
|
+
if (inStatWatchers(filename)) {
|
1136
|
+
stat = statWatchers[filename];
|
1137
|
+
} else {
|
1138
|
+
stat = statWatchers[filename] = new StatWatcher();
|
1139
|
+
stat.start(filename, options.persistent, options.interval);
|
1140
|
+
}
|
1141
|
+
stat.addListener('change', listener);
|
1142
|
+
return stat;
|
1143
|
+
};
|
1144
|
+
|
1145
|
+
fs.unwatchFile = function(filename, listener) {
|
1146
|
+
nullCheck(filename);
|
1147
|
+
if (!inStatWatchers(filename)) return;
|
1148
|
+
|
1149
|
+
var stat = statWatchers[filename];
|
1150
|
+
|
1151
|
+
if (util.isFunction(listener)) {
|
1152
|
+
stat.removeListener('change', listener);
|
1153
|
+
} else {
|
1154
|
+
stat.removeAllListeners('change');
|
1155
|
+
}
|
1156
|
+
|
1157
|
+
if (EventEmitter.listenerCount(stat, 'change') === 0) {
|
1158
|
+
stat.stop();
|
1159
|
+
statWatchers[filename] = undefined;
|
1160
|
+
}
|
1161
|
+
};
|
1162
|
+
|
1163
|
+
// Regexp that finds the next partion of a (partial) path
|
1164
|
+
// result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
|
1165
|
+
if (isWindows) {
|
1166
|
+
var nextPartRe = /(.*?)(?:[\/\\]+|$)/g;
|
1167
|
+
} else {
|
1168
|
+
var nextPartRe = /(.*?)(?:[\/]+|$)/g;
|
1169
|
+
}
|
1170
|
+
|
1171
|
+
// Regex to find the device root, including trailing slash. E.g. 'c:\\'.
|
1172
|
+
if (isWindows) {
|
1173
|
+
var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/;
|
1174
|
+
} else {
|
1175
|
+
var splitRootRe = /^[\/]*/;
|
1176
|
+
}
|
1177
|
+
|
1178
|
+
fs.realpathSync = function realpathSync(p, cache) {
|
1179
|
+
// make p is absolute
|
1180
|
+
p = pathModule.resolve(p);
|
1181
|
+
|
1182
|
+
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
|
1183
|
+
return cache[p];
|
1184
|
+
}
|
1185
|
+
|
1186
|
+
var original = p,
|
1187
|
+
seenLinks = {},
|
1188
|
+
knownHard = {};
|
1189
|
+
|
1190
|
+
// current character position in p
|
1191
|
+
var pos;
|
1192
|
+
// the partial path so far, including a trailing slash if any
|
1193
|
+
var current;
|
1194
|
+
// the partial path without a trailing slash (except when pointing at a root)
|
1195
|
+
var base;
|
1196
|
+
// the partial path scanned in the previous round, with slash
|
1197
|
+
var previous;
|
1198
|
+
|
1199
|
+
start();
|
1200
|
+
|
1201
|
+
function start() {
|
1202
|
+
// Skip over roots
|
1203
|
+
var m = splitRootRe.exec(p);
|
1204
|
+
pos = m[0].length;
|
1205
|
+
current = m[0];
|
1206
|
+
base = m[0];
|
1207
|
+
previous = '';
|
1208
|
+
|
1209
|
+
// On windows, check that the root exists. On unix there is no need.
|
1210
|
+
if (isWindows && !knownHard[base]) {
|
1211
|
+
fs.lstatSync(base);
|
1212
|
+
knownHard[base] = true;
|
1213
|
+
}
|
1214
|
+
}
|
1215
|
+
|
1216
|
+
// walk down the path, swapping out linked pathparts for their real
|
1217
|
+
// values
|
1218
|
+
// NB: p.length changes.
|
1219
|
+
while (pos < p.length) {
|
1220
|
+
// find the next part
|
1221
|
+
nextPartRe.lastIndex = pos;
|
1222
|
+
var result = nextPartRe.exec(p);
|
1223
|
+
previous = current;
|
1224
|
+
current += result[0];
|
1225
|
+
base = previous + result[1];
|
1226
|
+
pos = nextPartRe.lastIndex;
|
1227
|
+
|
1228
|
+
// continue if not a symlink
|
1229
|
+
if (knownHard[base] || (cache && cache[base] === base)) {
|
1230
|
+
continue;
|
1231
|
+
}
|
1232
|
+
|
1233
|
+
var resolvedLink;
|
1234
|
+
if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
|
1235
|
+
// some known symbolic link. no need to stat again.
|
1236
|
+
resolvedLink = cache[base];
|
1237
|
+
} else {
|
1238
|
+
var stat = fs.lstatSync(base);
|
1239
|
+
if (!stat.isSymbolicLink()) {
|
1240
|
+
knownHard[base] = true;
|
1241
|
+
if (cache) cache[base] = base;
|
1242
|
+
continue;
|
1243
|
+
}
|
1244
|
+
|
1245
|
+
// read the link if it wasn't read before
|
1246
|
+
// dev/ino always return 0 on windows, so skip the check.
|
1247
|
+
var linkTarget = null;
|
1248
|
+
if (!isWindows) {
|
1249
|
+
var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
|
1250
|
+
if (seenLinks.hasOwnProperty(id)) {
|
1251
|
+
linkTarget = seenLinks[id];
|
1252
|
+
}
|
1253
|
+
}
|
1254
|
+
if (util.isNull(linkTarget)) {
|
1255
|
+
fs.statSync(base);
|
1256
|
+
linkTarget = fs.readlinkSync(base);
|
1257
|
+
}
|
1258
|
+
resolvedLink = pathModule.resolve(previous, linkTarget);
|
1259
|
+
// track this, if given a cache.
|
1260
|
+
if (cache) cache[base] = resolvedLink;
|
1261
|
+
if (!isWindows) seenLinks[id] = linkTarget;
|
1262
|
+
}
|
1263
|
+
|
1264
|
+
// resolve the link, then start over
|
1265
|
+
p = pathModule.resolve(resolvedLink, p.slice(pos));
|
1266
|
+
start();
|
1267
|
+
}
|
1268
|
+
|
1269
|
+
if (cache) cache[original] = p;
|
1270
|
+
|
1271
|
+
return p;
|
1272
|
+
};
|
1273
|
+
|
1274
|
+
|
1275
|
+
fs.realpath = function realpath(p, cache, cb) {
|
1276
|
+
if (!util.isFunction(cb)) {
|
1277
|
+
cb = maybeCallback(cache);
|
1278
|
+
cache = null;
|
1279
|
+
}
|
1280
|
+
|
1281
|
+
// make p is absolute
|
1282
|
+
p = pathModule.resolve(p);
|
1283
|
+
|
1284
|
+
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
|
1285
|
+
return process.nextTick(cb.bind(null, null, cache[p]));
|
1286
|
+
}
|
1287
|
+
|
1288
|
+
var original = p,
|
1289
|
+
seenLinks = {},
|
1290
|
+
knownHard = {};
|
1291
|
+
|
1292
|
+
// current character position in p
|
1293
|
+
var pos;
|
1294
|
+
// the partial path so far, including a trailing slash if any
|
1295
|
+
var current;
|
1296
|
+
// the partial path without a trailing slash (except when pointing at a root)
|
1297
|
+
var base;
|
1298
|
+
// the partial path scanned in the previous round, with slash
|
1299
|
+
var previous;
|
1300
|
+
|
1301
|
+
start();
|
1302
|
+
|
1303
|
+
function start() {
|
1304
|
+
// Skip over roots
|
1305
|
+
var m = splitRootRe.exec(p);
|
1306
|
+
pos = m[0].length;
|
1307
|
+
current = m[0];
|
1308
|
+
base = m[0];
|
1309
|
+
previous = '';
|
1310
|
+
|
1311
|
+
// On windows, check that the root exists. On unix there is no need.
|
1312
|
+
if (isWindows && !knownHard[base]) {
|
1313
|
+
fs.lstat(base, function(err) {
|
1314
|
+
if (err) return cb(err);
|
1315
|
+
knownHard[base] = true;
|
1316
|
+
LOOP();
|
1317
|
+
});
|
1318
|
+
} else {
|
1319
|
+
process.nextTick(LOOP);
|
1320
|
+
}
|
1321
|
+
}
|
1322
|
+
|
1323
|
+
// walk down the path, swapping out linked pathparts for their real
|
1324
|
+
// values
|
1325
|
+
function LOOP() {
|
1326
|
+
// stop if scanned past end of path
|
1327
|
+
if (pos >= p.length) {
|
1328
|
+
if (cache) cache[original] = p;
|
1329
|
+
return cb(null, p);
|
1330
|
+
}
|
1331
|
+
|
1332
|
+
// find the next part
|
1333
|
+
nextPartRe.lastIndex = pos;
|
1334
|
+
var result = nextPartRe.exec(p);
|
1335
|
+
previous = current;
|
1336
|
+
current += result[0];
|
1337
|
+
base = previous + result[1];
|
1338
|
+
pos = nextPartRe.lastIndex;
|
1339
|
+
|
1340
|
+
// continue if not a symlink
|
1341
|
+
if (knownHard[base] || (cache && cache[base] === base)) {
|
1342
|
+
return process.nextTick(LOOP);
|
1343
|
+
}
|
1344
|
+
|
1345
|
+
if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
|
1346
|
+
// known symbolic link. no need to stat again.
|
1347
|
+
return gotResolvedLink(cache[base]);
|
1348
|
+
}
|
1349
|
+
|
1350
|
+
return fs.lstat(base, gotStat);
|
1351
|
+
}
|
1352
|
+
|
1353
|
+
function gotStat(err, stat) {
|
1354
|
+
if (err) return cb(err);
|
1355
|
+
|
1356
|
+
// if not a symlink, skip to the next path part
|
1357
|
+
if (!stat.isSymbolicLink()) {
|
1358
|
+
knownHard[base] = true;
|
1359
|
+
if (cache) cache[base] = base;
|
1360
|
+
return process.nextTick(LOOP);
|
1361
|
+
}
|
1362
|
+
|
1363
|
+
// stat & read the link if not read before
|
1364
|
+
// call gotTarget as soon as the link target is known
|
1365
|
+
// dev/ino always return 0 on windows, so skip the check.
|
1366
|
+
if (!isWindows) {
|
1367
|
+
var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
|
1368
|
+
if (seenLinks.hasOwnProperty(id)) {
|
1369
|
+
return gotTarget(null, seenLinks[id], base);
|
1370
|
+
}
|
1371
|
+
}
|
1372
|
+
fs.stat(base, function(err) {
|
1373
|
+
if (err) return cb(err);
|
1374
|
+
|
1375
|
+
fs.readlink(base, function(err, target) {
|
1376
|
+
if (!isWindows) seenLinks[id] = target;
|
1377
|
+
gotTarget(err, target);
|
1378
|
+
});
|
1379
|
+
});
|
1380
|
+
}
|
1381
|
+
|
1382
|
+
function gotTarget(err, target, base) {
|
1383
|
+
if (err) return cb(err);
|
1384
|
+
|
1385
|
+
var resolvedLink = pathModule.resolve(previous, target);
|
1386
|
+
if (cache) cache[base] = resolvedLink;
|
1387
|
+
gotResolvedLink(resolvedLink);
|
1388
|
+
}
|
1389
|
+
|
1390
|
+
function gotResolvedLink(resolvedLink) {
|
1391
|
+
// resolve the link, then start over
|
1392
|
+
p = pathModule.resolve(resolvedLink, p.slice(pos));
|
1393
|
+
start();
|
1394
|
+
}
|
1395
|
+
};
|
1396
|
+
|
1397
|
+
|
1398
|
+
|
1399
|
+
var pool;
|
1400
|
+
|
1401
|
+
function allocNewPool(poolSize) {
|
1402
|
+
pool = new Buffer(poolSize);
|
1403
|
+
pool.used = 0;
|
1404
|
+
}
|
1405
|
+
|
1406
|
+
|
1407
|
+
|
1408
|
+
fs.createReadStream = function(path, options) {
|
1409
|
+
return new ReadStream(path, options);
|
1410
|
+
};
|
1411
|
+
|
1412
|
+
util.inherits(ReadStream, Readable);
|
1413
|
+
fs.ReadStream = ReadStream;
|
1414
|
+
|
1415
|
+
function ReadStream(path, options) {
|
1416
|
+
if (!(this instanceof ReadStream))
|
1417
|
+
return new ReadStream(path, options);
|
1418
|
+
|
1419
|
+
// a little bit bigger buffer and water marks by default
|
1420
|
+
options = util._extend({
|
1421
|
+
highWaterMark: 64 * 1024
|
1422
|
+
}, options || {});
|
1423
|
+
|
1424
|
+
Readable.call(this, options);
|
1425
|
+
|
1426
|
+
this.path = path;
|
1427
|
+
this.fd = options.hasOwnProperty('fd') ? options.fd : null;
|
1428
|
+
this.flags = options.hasOwnProperty('flags') ? options.flags : 'r';
|
1429
|
+
this.mode = options.hasOwnProperty('mode') ? options.mode : 438; /*=0666*/
|
1430
|
+
|
1431
|
+
this.start = options.hasOwnProperty('start') ? options.start : undefined;
|
1432
|
+
this.end = options.hasOwnProperty('end') ? options.end : undefined;
|
1433
|
+
this.autoClose = options.hasOwnProperty('autoClose') ?
|
1434
|
+
options.autoClose : true;
|
1435
|
+
this.pos = undefined;
|
1436
|
+
|
1437
|
+
if (!util.isUndefined(this.start)) {
|
1438
|
+
if (!util.isNumber(this.start)) {
|
1439
|
+
throw TypeError('start must be a Number');
|
1440
|
+
}
|
1441
|
+
if (util.isUndefined(this.end)) {
|
1442
|
+
this.end = Infinity;
|
1443
|
+
} else if (!util.isNumber(this.end)) {
|
1444
|
+
throw TypeError('end must be a Number');
|
1445
|
+
}
|
1446
|
+
|
1447
|
+
if (this.start > this.end) {
|
1448
|
+
throw new Error('start must be <= end');
|
1449
|
+
}
|
1450
|
+
|
1451
|
+
this.pos = this.start;
|
1452
|
+
}
|
1453
|
+
|
1454
|
+
if (!util.isNumber(this.fd))
|
1455
|
+
this.open();
|
1456
|
+
|
1457
|
+
this.on('end', function() {
|
1458
|
+
if (this.autoClose) {
|
1459
|
+
this.destroy();
|
1460
|
+
}
|
1461
|
+
});
|
1462
|
+
}
|
1463
|
+
|
1464
|
+
fs.FileReadStream = fs.ReadStream; // support the legacy name
|
1465
|
+
|
1466
|
+
ReadStream.prototype.open = function() {
|
1467
|
+
var self = this;
|
1468
|
+
fs.open(this.path, this.flags, this.mode, function(er, fd) {
|
1469
|
+
if (er) {
|
1470
|
+
if (self.autoClose) {
|
1471
|
+
self.destroy();
|
1472
|
+
}
|
1473
|
+
self.emit('error', er);
|
1474
|
+
return;
|
1475
|
+
}
|
1476
|
+
|
1477
|
+
self.fd = fd;
|
1478
|
+
self.emit('open', fd);
|
1479
|
+
// start the flow of data.
|
1480
|
+
self.read();
|
1481
|
+
});
|
1482
|
+
};
|
1483
|
+
|
1484
|
+
ReadStream.prototype._read = function(n) {
|
1485
|
+
if (!util.isNumber(this.fd))
|
1486
|
+
return this.once('open', function() {
|
1487
|
+
this._read(n);
|
1488
|
+
});
|
1489
|
+
|
1490
|
+
if (this.destroyed)
|
1491
|
+
return;
|
1492
|
+
|
1493
|
+
if (!pool || pool.length - pool.used < kMinPoolSpace) {
|
1494
|
+
// discard the old pool.
|
1495
|
+
pool = null;
|
1496
|
+
allocNewPool(this._readableState.highWaterMark);
|
1497
|
+
}
|
1498
|
+
|
1499
|
+
// Grab another reference to the pool in the case that while we're
|
1500
|
+
// in the thread pool another read() finishes up the pool, and
|
1501
|
+
// allocates a new one.
|
1502
|
+
var thisPool = pool;
|
1503
|
+
var toRead = Math.min(pool.length - pool.used, n);
|
1504
|
+
var start = pool.used;
|
1505
|
+
|
1506
|
+
if (!util.isUndefined(this.pos))
|
1507
|
+
toRead = Math.min(this.end - this.pos + 1, toRead);
|
1508
|
+
|
1509
|
+
// already read everything we were supposed to read!
|
1510
|
+
// treat as EOF.
|
1511
|
+
if (toRead <= 0)
|
1512
|
+
return this.push(null);
|
1513
|
+
|
1514
|
+
// the actual read.
|
1515
|
+
var self = this;
|
1516
|
+
fs.read(this.fd, pool, pool.used, toRead, this.pos, onread);
|
1517
|
+
|
1518
|
+
// move the pool positions, and internal position for reading.
|
1519
|
+
if (!util.isUndefined(this.pos))
|
1520
|
+
this.pos += toRead;
|
1521
|
+
pool.used += toRead;
|
1522
|
+
|
1523
|
+
function onread(er, bytesRead) {
|
1524
|
+
if (er) {
|
1525
|
+
if (self.autoClose) {
|
1526
|
+
self.destroy();
|
1527
|
+
}
|
1528
|
+
self.emit('error', er);
|
1529
|
+
} else {
|
1530
|
+
var b = null;
|
1531
|
+
if (bytesRead > 0)
|
1532
|
+
b = thisPool.slice(start, start + bytesRead);
|
1533
|
+
|
1534
|
+
self.push(b);
|
1535
|
+
}
|
1536
|
+
}
|
1537
|
+
};
|
1538
|
+
|
1539
|
+
|
1540
|
+
ReadStream.prototype.destroy = function() {
|
1541
|
+
if (this.destroyed)
|
1542
|
+
return;
|
1543
|
+
this.destroyed = true;
|
1544
|
+
|
1545
|
+
if (util.isNumber(this.fd))
|
1546
|
+
this.close();
|
1547
|
+
};
|
1548
|
+
|
1549
|
+
|
1550
|
+
ReadStream.prototype.close = function(cb) {
|
1551
|
+
var self = this;
|
1552
|
+
if (cb)
|
1553
|
+
this.once('close', cb);
|
1554
|
+
if (this.closed || !util.isNumber(this.fd)) {
|
1555
|
+
if (!util.isNumber(this.fd)) {
|
1556
|
+
this.once('open', close);
|
1557
|
+
return;
|
1558
|
+
}
|
1559
|
+
return process.nextTick(this.emit.bind(this, 'close'));
|
1560
|
+
}
|
1561
|
+
this.closed = true;
|
1562
|
+
close();
|
1563
|
+
|
1564
|
+
function close(fd) {
|
1565
|
+
fs.close(fd || self.fd, function(er) {
|
1566
|
+
if (er)
|
1567
|
+
self.emit('error', er);
|
1568
|
+
else
|
1569
|
+
self.emit('close');
|
1570
|
+
});
|
1571
|
+
self.fd = null;
|
1572
|
+
}
|
1573
|
+
};
|
1574
|
+
|
1575
|
+
|
1576
|
+
|
1577
|
+
|
1578
|
+
fs.createWriteStream = function(path, options) {
|
1579
|
+
return new WriteStream(path, options);
|
1580
|
+
};
|
1581
|
+
|
1582
|
+
util.inherits(WriteStream, Writable);
|
1583
|
+
fs.WriteStream = WriteStream;
|
1584
|
+
function WriteStream(path, options) {
|
1585
|
+
if (!(this instanceof WriteStream))
|
1586
|
+
return new WriteStream(path, options);
|
1587
|
+
|
1588
|
+
options = options || {};
|
1589
|
+
|
1590
|
+
Writable.call(this, options);
|
1591
|
+
|
1592
|
+
this.path = path;
|
1593
|
+
this.fd = null;
|
1594
|
+
|
1595
|
+
this.fd = options.hasOwnProperty('fd') ? options.fd : null;
|
1596
|
+
this.flags = options.hasOwnProperty('flags') ? options.flags : 'w';
|
1597
|
+
this.mode = options.hasOwnProperty('mode') ? options.mode : 438; /*=0666*/
|
1598
|
+
|
1599
|
+
this.start = options.hasOwnProperty('start') ? options.start : undefined;
|
1600
|
+
this.pos = undefined;
|
1601
|
+
this.bytesWritten = 0;
|
1602
|
+
|
1603
|
+
if (!util.isUndefined(this.start)) {
|
1604
|
+
if (!util.isNumber(this.start)) {
|
1605
|
+
throw TypeError('start must be a Number');
|
1606
|
+
}
|
1607
|
+
if (this.start < 0) {
|
1608
|
+
throw new Error('start must be >= zero');
|
1609
|
+
}
|
1610
|
+
|
1611
|
+
this.pos = this.start;
|
1612
|
+
}
|
1613
|
+
|
1614
|
+
if (!util.isNumber(this.fd))
|
1615
|
+
this.open();
|
1616
|
+
|
1617
|
+
// dispose on finish.
|
1618
|
+
this.once('finish', this.close);
|
1619
|
+
}
|
1620
|
+
|
1621
|
+
fs.FileWriteStream = fs.WriteStream; // support the legacy name
|
1622
|
+
|
1623
|
+
|
1624
|
+
WriteStream.prototype.open = function() {
|
1625
|
+
fs.open(this.path, this.flags, this.mode, function(er, fd) {
|
1626
|
+
if (er) {
|
1627
|
+
this.destroy();
|
1628
|
+
this.emit('error', er);
|
1629
|
+
return;
|
1630
|
+
}
|
1631
|
+
|
1632
|
+
this.fd = fd;
|
1633
|
+
this.emit('open', fd);
|
1634
|
+
}.bind(this));
|
1635
|
+
};
|
1636
|
+
|
1637
|
+
|
1638
|
+
WriteStream.prototype._write = function(data, encoding, cb) {
|
1639
|
+
if (!util.isBuffer(data))
|
1640
|
+
return this.emit('error', new Error('Invalid data'));
|
1641
|
+
|
1642
|
+
if (!util.isNumber(this.fd))
|
1643
|
+
return this.once('open', function() {
|
1644
|
+
this._write(data, encoding, cb);
|
1645
|
+
});
|
1646
|
+
|
1647
|
+
var self = this;
|
1648
|
+
fs.write(this.fd, data, 0, data.length, this.pos, function(er, bytes) {
|
1649
|
+
if (er) {
|
1650
|
+
self.destroy();
|
1651
|
+
return cb(er);
|
1652
|
+
}
|
1653
|
+
self.bytesWritten += bytes;
|
1654
|
+
cb();
|
1655
|
+
});
|
1656
|
+
|
1657
|
+
if (!util.isUndefined(this.pos))
|
1658
|
+
this.pos += data.length;
|
1659
|
+
};
|
1660
|
+
|
1661
|
+
|
1662
|
+
WriteStream.prototype.destroy = ReadStream.prototype.destroy;
|
1663
|
+
WriteStream.prototype.close = ReadStream.prototype.close;
|
1664
|
+
|
1665
|
+
// There is no shutdown() for files.
|
1666
|
+
WriteStream.prototype.destroySoon = WriteStream.prototype.end;
|
1667
|
+
|
1668
|
+
|
1669
|
+
// SyncWriteStream is internal. DO NOT USE.
|
1670
|
+
// Temporary hack for process.stdout and process.stderr when piped to files.
|
1671
|
+
function SyncWriteStream(fd) {
|
1672
|
+
Stream.call(this);
|
1673
|
+
|
1674
|
+
this.fd = fd;
|
1675
|
+
this.writable = true;
|
1676
|
+
this.readable = false;
|
1677
|
+
}
|
1678
|
+
|
1679
|
+
util.inherits(SyncWriteStream, Stream);
|
1680
|
+
|
1681
|
+
|
1682
|
+
// Export
|
1683
|
+
fs.SyncWriteStream = SyncWriteStream;
|
1684
|
+
|
1685
|
+
|
1686
|
+
SyncWriteStream.prototype.write = function(data, arg1, arg2) {
|
1687
|
+
var encoding, cb;
|
1688
|
+
|
1689
|
+
// parse arguments
|
1690
|
+
if (arg1) {
|
1691
|
+
if (util.isString(arg1)) {
|
1692
|
+
encoding = arg1;
|
1693
|
+
cb = arg2;
|
1694
|
+
} else if (util.isFunction(arg1)) {
|
1695
|
+
cb = arg1;
|
1696
|
+
} else {
|
1697
|
+
throw new Error('bad arg');
|
1698
|
+
}
|
1699
|
+
}
|
1700
|
+
assertEncoding(encoding);
|
1701
|
+
|
1702
|
+
// Change strings to buffers. SLOW
|
1703
|
+
if (util.isString(data)) {
|
1704
|
+
data = new Buffer(data, encoding);
|
1705
|
+
}
|
1706
|
+
|
1707
|
+
fs.writeSync(this.fd, data, 0, data.length);
|
1708
|
+
|
1709
|
+
if (cb) {
|
1710
|
+
process.nextTick(cb);
|
1711
|
+
}
|
1712
|
+
|
1713
|
+
return true;
|
1714
|
+
};
|
1715
|
+
|
1716
|
+
|
1717
|
+
SyncWriteStream.prototype.end = function(data, arg1, arg2) {
|
1718
|
+
if (data) {
|
1719
|
+
this.write(data, arg1, arg2);
|
1720
|
+
}
|
1721
|
+
this.destroy();
|
1722
|
+
};
|
1723
|
+
|
1724
|
+
|
1725
|
+
SyncWriteStream.prototype.destroy = function() {
|
1726
|
+
fs.closeSync(this.fd);
|
1727
|
+
this.fd = null;
|
1728
|
+
this.emit('close');
|
1729
|
+
return true;
|
1730
|
+
};
|
1731
|
+
|
1732
|
+
SyncWriteStream.prototype.destroySoon = SyncWriteStream.prototype.destroy;
|