macgyver 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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;