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.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +20 -0
  5. data/README.md +45 -0
  6. data/Rakefile +1 -0
  7. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Growl +0 -0
  8. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Growl +0 -0
  9. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Headers/Growl.h +5 -0
  10. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Headers/GrowlApplicationBridge.h +551 -0
  11. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Headers/GrowlDefines.h +341 -0
  12. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Resources/Info.plist +40 -0
  13. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/_CodeSignature/CodeResources +34 -0
  14. data/assets/MacGap.app/Contents/Info.plist +48 -0
  15. data/assets/MacGap.app/Contents/MacOS/MacGap +0 -0
  16. data/assets/MacGap.app/Contents/PkgInfo +1 -0
  17. data/assets/MacGap.app/Contents/Resources/_debugger.js +1718 -0
  18. data/assets/MacGap.app/Contents/Resources/_http_agent.js +310 -0
  19. data/assets/MacGap.app/Contents/Resources/_http_client.js +533 -0
  20. data/assets/MacGap.app/Contents/Resources/_http_common.js +222 -0
  21. data/assets/MacGap.app/Contents/Resources/_http_incoming.js +194 -0
  22. data/assets/MacGap.app/Contents/Resources/_http_outgoing.js +597 -0
  23. data/assets/MacGap.app/Contents/Resources/_http_server.js +510 -0
  24. data/assets/MacGap.app/Contents/Resources/_linklist.js +76 -0
  25. data/assets/MacGap.app/Contents/Resources/_stream_duplex.js +69 -0
  26. data/assets/MacGap.app/Contents/Resources/_stream_passthrough.js +41 -0
  27. data/assets/MacGap.app/Contents/Resources/_stream_readable.js +900 -0
  28. data/assets/MacGap.app/Contents/Resources/_stream_transform.js +204 -0
  29. data/assets/MacGap.app/Contents/Resources/_stream_writable.js +456 -0
  30. data/assets/MacGap.app/Contents/Resources/_tls_legacy.js +887 -0
  31. data/assets/MacGap.app/Contents/Resources/_tls_wrap.js +831 -0
  32. data/assets/MacGap.app/Contents/Resources/application.icns +0 -0
  33. data/assets/MacGap.app/Contents/Resources/assert.js +326 -0
  34. data/assets/MacGap.app/Contents/Resources/buffer.js +724 -0
  35. data/assets/MacGap.app/Contents/Resources/child_process.js +1107 -0
  36. data/assets/MacGap.app/Contents/Resources/cluster.js +613 -0
  37. data/assets/MacGap.app/Contents/Resources/console.js +108 -0
  38. data/assets/MacGap.app/Contents/Resources/constants.js +22 -0
  39. data/assets/MacGap.app/Contents/Resources/crypto.js +691 -0
  40. data/assets/MacGap.app/Contents/Resources/dgram.js +459 -0
  41. data/assets/MacGap.app/Contents/Resources/dns.js +274 -0
  42. data/assets/MacGap.app/Contents/Resources/domain.js +292 -0
  43. data/assets/MacGap.app/Contents/Resources/en.lproj/Credits.rtf +29 -0
  44. data/assets/MacGap.app/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  45. data/assets/MacGap.app/Contents/Resources/en.lproj/MainMenu.nib +0 -0
  46. data/assets/MacGap.app/Contents/Resources/en.lproj/Window.nib +0 -0
  47. data/assets/MacGap.app/Contents/Resources/events.js +312 -0
  48. data/assets/MacGap.app/Contents/Resources/freelist.js +43 -0
  49. data/assets/MacGap.app/Contents/Resources/fs.js +1732 -0
  50. data/assets/MacGap.app/Contents/Resources/http.js +119 -0
  51. data/assets/MacGap.app/Contents/Resources/https.js +134 -0
  52. data/assets/MacGap.app/Contents/Resources/module.js +529 -0
  53. data/assets/MacGap.app/Contents/Resources/net.js +1378 -0
  54. data/assets/MacGap.app/Contents/Resources/nodelike.js +195 -0
  55. data/assets/MacGap.app/Contents/Resources/os.js +64 -0
  56. data/assets/MacGap.app/Contents/Resources/path.js +517 -0
  57. data/assets/MacGap.app/Contents/Resources/public/index.html +38 -0
  58. data/assets/MacGap.app/Contents/Resources/punycode.js +507 -0
  59. data/assets/MacGap.app/Contents/Resources/querystring.js +206 -0
  60. data/assets/MacGap.app/Contents/Resources/readline.js +1311 -0
  61. data/assets/MacGap.app/Contents/Resources/repl.js +945 -0
  62. data/assets/MacGap.app/Contents/Resources/smalloc.js +90 -0
  63. data/assets/MacGap.app/Contents/Resources/stream.js +127 -0
  64. data/assets/MacGap.app/Contents/Resources/string_decoder.js +189 -0
  65. data/assets/MacGap.app/Contents/Resources/sys.js +24 -0
  66. data/assets/MacGap.app/Contents/Resources/timers.js +568 -0
  67. data/assets/MacGap.app/Contents/Resources/tls.js +220 -0
  68. data/assets/MacGap.app/Contents/Resources/tty.js +129 -0
  69. data/assets/MacGap.app/Contents/Resources/url.js +693 -0
  70. data/assets/MacGap.app/Contents/Resources/util.js +688 -0
  71. data/assets/MacGap.app/Contents/Resources/vm.js +73 -0
  72. data/assets/MacGap.app/Contents/Resources/zlib.js +524 -0
  73. data/assets/index.html +38 -0
  74. data/bin/macgyver +104 -0
  75. data/macgyver.gemspec +19 -0
  76. data/test/public/index.html +27 -0
  77. 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
+ }
@@ -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;