1 /* Copyright 2015-present Samsung Electronics Co., Ltd. and other contributors
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
18 var constants = require('constants');
19 var util = require('util');
20 var fsBuiltin = process.binding(process.binding.fs);
23 var O_APPEND = constants.O_APPEND;
24 var O_CREAT = constants.O_CREAT;
25 var O_EXCL = constants.O_EXCL;
26 var O_RDONLY = constants.O_RDONLY;
27 var O_RDWR = constants.O_RDWR;
28 var O_SYNC = constants.O_SYNC;
29 var O_TRUNC = constants.O_TRUNC;
30 var O_WRONLY = constants.O_WRONLY;
33 fs.Stats = function(stat) {
35 this.mode = stat.mode;
36 this.nlink = stat.nlink;
39 this.rdev = stat.rdev;
40 this.blksize = stat.blksize;
42 this.size = stat.size;
43 this.blocks = stat.blocks;
47 fs.Stats.prototype.isDirectory = function() {
48 return ((this.mode & constants.S_IFMT) === constants.S_IFDIR);
52 fs.Stats.prototype.isFile = function() {
53 return ((this.mode & constants.S_IFMT) === constants.S_IFREG);
57 fsBuiltin._createStat = function(stat) {
58 return new fs.Stats(stat);
62 fs.exists = function(path, callback) {
63 if (!path || !path.length) {
64 process.nextTick(function () {
65 if (callback) callback(false);
70 var cb = function(err, stat) {
71 if (callback) callback(err ? false : true);
74 fsBuiltin.stat(checkArgString(path, 'path'),
75 checkArgFunction(cb, 'callback'));
79 fs.existsSync = function(path) {
80 if (!path || !path.length) {
85 fsBuiltin.stat(checkArgString(path, 'path'));
93 fs.stat = function(path, callback) {
94 fsBuiltin.stat(checkArgString(path, 'path'),
95 checkArgFunction(callback, 'callback'));
99 fs.statSync = function(path) {
100 return fsBuiltin.stat(checkArgString(path, 'path'));
104 fs.fstat = function(fd, callback) {
105 fsBuiltin.fstat(checkArgNumber(fd, 'fd'),
106 checkArgFunction(callback, 'callback'));
110 fs.fstatSync = function(fd) {
111 return fsBuiltin.fstat(checkArgNumber(fd, 'fd'));
115 fs.close = function(fd, callback) {
116 fsBuiltin.close(checkArgNumber(fd, 'fd'),
117 checkArgFunction(callback, 'callback'));
121 fs.closeSync = function(fd) {
122 fsBuiltin.close(checkArgNumber(fd, 'fd'));
126 fs.open = function(path, flags, mode, callback) {
127 fsBuiltin.open(checkArgString(path, 'path'),
129 convertMode(mode, 438),
130 checkArgFunction(arguments[arguments.length - 1]), 'callback');
134 fs.openSync = function(path, flags, mode) {
135 return fsBuiltin.open(checkArgString(path, 'path'),
137 convertMode(mode, 438));
141 fs.read = function(fd, buffer, offset, length, position, callback) {
142 callback = checkArgFunction(callback, 'callback');
144 var cb = function(err, bytesRead) {
145 callback(err, bytesRead || 0, buffer);
148 return fsBuiltin.read(checkArgNumber(fd, 'fd'),
149 checkArgBuffer(buffer, 'buffer'),
150 checkArgNumber(offset, 'offset'),
151 checkArgNumber(length, 'length'),
152 checkArgNumber(position, 'position'),
157 fs.readSync = function(fd, buffer, offset, length, position) {
158 if (util.isNullOrUndefined(position)) {
161 return fsBuiltin.read(checkArgNumber(fd, 'fd'),
162 checkArgBuffer(buffer, 'buffer'),
163 checkArgNumber(offset, 'offset'),
164 checkArgNumber(length, 'length'),
165 checkArgNumber(position, 'position'));
169 fs.write = function(fd, buffer, offset, length, position, callback) {
170 if (util.isFunction(position)) {
172 position = -1; // write at current position.
175 callback = checkArgFunction(callback, 'callback');
177 var cb = function(err, written) {
178 callback(err, written, buffer);
181 return fsBuiltin.write(checkArgNumber(fd, 'fd'),
182 checkArgBuffer(buffer, 'buffer'),
183 checkArgNumber(offset, 'offset'),
184 checkArgNumber(length, 'length'),
185 checkArgNumber(position, 'position'),
190 fs.writeSync = function(fd, buffer, offset, length, position) {
191 if (util.isNullOrUndefined(position)) {
192 position = -1; // write at current position.
195 return fsBuiltin.write(checkArgNumber(fd, 'fd'),
196 checkArgBuffer(buffer, 'buffer'),
197 checkArgNumber(offset, 'offset'),
198 checkArgNumber(length, 'length'),
199 checkArgNumber(position, 'position'));
203 fs.readFile = function(path, callback) {
204 checkArgString(path);
205 checkArgFunction(callback);
210 fs.open(path, 'r', function(err, _fd) {
212 return callback(err);
222 var read = function() {
223 // Read segment of data.
224 var buffer = new Buffer(1023);
225 fs.read(fd, buffer, 0, 1023, -1, afterRead);
228 var afterRead = function(err, bytesRead, buffer) {
230 fs.close(fd, function(err) {
231 return callback(err);
235 if (bytesRead === 0) {
240 buffers.push(buffer.slice(0, bytesRead));
245 var close = function() {
246 fs.close(fd, function(err) {
247 return callback(err, Buffer.concat(buffers));
253 fs.readFileSync = function(path) {
254 checkArgString(path);
256 var fd = fs.openSync(path, 'r', 438);
261 var buffer = new Buffer(1023);
262 var bytesRead = fs.readSync(fd, buffer, 0, 1023);
264 buffers.push(buffer.slice(0, bytesRead));
274 return Buffer.concat(buffers);
278 fs.writeFile = function(path, data, callback) {
279 checkArgString(path);
280 checkArgBuffer(data);
281 checkArgFunction(callback);
287 fs.open(path, 'w', function(err, _fd) {
289 return callback(err);
299 var write = function() {
300 var tryN = (len - bytesWritten) >= 1024 ? 1023 : (len - bytesWritten);
301 fs.write(fd, data, bytesWritten, tryN, bytesWritten, afterWrite);
304 var afterWrite = function(err, n) {
306 fs.close(fd, function(err) {
307 return callback(err);
311 if (n <= 0 || bytesWritten + n == len) {
313 fs.close(fd, function(err) {
325 fs.writeFileSync = function(path, data) {
326 checkArgString(path);
327 checkArgBuffer(data);
329 var fd = fs.openSync(path, 'w');
330 var len = data.length;
331 var bytesWritten = 0;
335 var tryN = (len - bytesWritten) >= 1024 ? 1023 : (len - bytesWritten);
336 var n = fs.writeSync(fd, data, bytesWritten, tryN, bytesWritten);
338 if (bytesWritten == len) {
350 fs.mkdir = function(path, mode, callback) {
351 if (util.isFunction(mode)) callback = mode;
352 checkArgString(path, 'path');
353 checkArgFunction(callback, 'callback');
354 fsBuiltin.mkdir(path, convertMode(mode, 511), callback);
358 fs.mkdirSync = function(path, mode) {
359 return fsBuiltin.mkdir(checkArgString(path, 'path'),
360 convertMode(mode, 511));
364 fs.rmdir = function(path, callback) {
365 checkArgString(path, 'path');
366 checkArgFunction(callback, 'callback');
367 fsBuiltin.rmdir(path, callback);
371 fs.rmdirSync = function(path) {
372 return fsBuiltin.rmdir(checkArgString(path, 'path'));
376 fs.unlink = function(path, callback) {
377 checkArgString(path);
378 checkArgFunction(callback);
379 fsBuiltin.unlink(path, callback);
383 fs.unlinkSync = function(path) {
384 return fsBuiltin.unlink(checkArgString(path, 'path'));
388 fs.rename = function(oldPath, newPath, callback) {
389 checkArgString(oldPath);
390 checkArgString(newPath);
391 checkArgFunction(callback);
392 fsBuiltin.rename(oldPath, newPath, callback);
396 fs.renameSync = function(oldPath, newPath) {
397 checkArgString(oldPath);
398 checkArgString(newPath);
399 fsBuiltin.rename(oldPath, newPath);
403 fs.readdir = function(path, callback) {
404 checkArgString(path);
405 checkArgFunction(callback);
406 fsBuiltin.readdir(path, callback);
410 fs.readdirSync = function(path) {
411 return fsBuiltin.readdir(checkArgString(path, 'path'));
415 function convertFlags(flag) {
416 if (util.isString(flag)) {
418 case 'r': return O_RDONLY;
420 case 'sr': return O_RDONLY | O_SYNC;
422 case 'r+': return O_RDWR;
424 case 'sr+': return O_RDWR | O_SYNC;
426 case 'w': return O_TRUNC | O_CREAT | O_WRONLY;
428 case 'xw': return O_TRUNC | O_CREAT | O_WRONLY | O_EXCL;
430 case 'w+': return O_TRUNC | O_CREAT | O_RDWR;
432 case 'xw+': return O_TRUNC | O_CREAT | O_RDWR | O_EXCL;
434 case 'a': return O_APPEND | O_CREAT | O_WRONLY;
436 case 'xa': return O_APPEND | O_CREAT | O_WRONLY | O_EXCL;
438 case 'a+': return O_APPEND | O_CREAT | O_RDWR;
440 case 'xa+': return O_APPEND | O_CREAT | O_RDWR | O_EXCL;
443 throw new TypeError('Bad argument: flags');
447 function convertMode(mode, def) {
448 if (util.isNumber(mode)) {
450 } else if (util.isString(mode)) {
451 return parseInt(mode);
453 return convertMode(def);
459 function checkArgType(value, name, checkFunc) {
460 if (checkFunc(value)) {
463 throw new TypeError('Bad arguments: ' + name);
468 function checkArgBuffer(value, name) {
469 return checkArgType(value, name, util.isBuffer);
473 function checkArgNumber(value, name) {
474 return checkArgType(value, name, util.isNumber);
478 function checkArgString(value, name) {
479 return checkArgType(value, name, util.isString);
483 function checkArgFunction(value, name) {
484 return checkArgType(value, name, util.isFunction);