Merge pull request #373 from humphd/9p-filer
Update Filer to support Plan 9 virtio filesystem API in v86
This commit is contained in:
commit
2e90fdae0c
107
README.md
107
README.md
|
@ -294,6 +294,10 @@ var fs = new Filer.FileSystem();
|
||||||
* [fs.close(fd, callback)](#close)
|
* [fs.close(fd, callback)](#close)
|
||||||
* [fs.open(path, flags, [mode], callback)](#open)
|
* [fs.open(path, flags, [mode], callback)](#open)
|
||||||
* [fs.utimes(path, atime, mtime, callback)](#utimes)
|
* [fs.utimes(path, atime, mtime, callback)](#utimes)
|
||||||
|
* [fs.chown(path, uid, gid, callback)](#chown)
|
||||||
|
* [fs.fchown(fd, uid, gid, callback)](#fchown)
|
||||||
|
* [fs.chmod(path, mode, callback)](#chmod)
|
||||||
|
* [fs.fchmod(fd, mode, callback)](#fchmod)
|
||||||
* [fs.futimes(fd, atime, mtime, callback)](#fsutimes)
|
* [fs.futimes(fd, atime, mtime, callback)](#fsutimes)
|
||||||
* [fs.fsync(fd, callback)](#fsync)
|
* [fs.fsync(fd, callback)](#fsync)
|
||||||
* [fs.write(fd, buffer, offset, length, position, callback)](#write)
|
* [fs.write(fd, buffer, offset, length, position, callback)](#write)
|
||||||
|
@ -399,12 +403,17 @@ Callback gets `(error, stats)`, where `stats` is an object with the following pr
|
||||||
{
|
{
|
||||||
node: <string> // internal node id (unique)
|
node: <string> // internal node id (unique)
|
||||||
dev: <string> // file system name
|
dev: <string> // file system name
|
||||||
|
name: <string> // the entry's name (basename)
|
||||||
size: <number> // file size in bytes
|
size: <number> // file size in bytes
|
||||||
nlinks: <number> // number of links
|
nlinks: <number> // number of links
|
||||||
atime: <number> // last access time
|
atime: <number> // last access time
|
||||||
mtime: <number> // last modified time
|
mtime: <number> // last modified time
|
||||||
ctime: <number> // creation time
|
ctime: <number> // creation time
|
||||||
type: <string> // file type (FILE, DIRECTORY, SYMLINK)
|
type: <string> // file type (FILE, DIRECTORY, SYMLINK),
|
||||||
|
gid: <number> // group name
|
||||||
|
uid: <number> // owner name
|
||||||
|
mode: <number> // permissions
|
||||||
|
version: <number> // version of the node
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -749,6 +758,89 @@ fs.open('/myfile.txt', function(err, fd) {
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### fs.chown(path, uid, gid, callback)<a name="chown"></a>
|
||||||
|
|
||||||
|
Changes the owner and group of a file. Asynchronous [chown(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/chown.html). Callback gets no additional arguments. Both `uid` (user id) and `gid` (group id) arguments should be a JavaScript Number. By default, `0x0` is used (i.e., `root:root` ownership).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
fs.chown('/myfile.txt', 500, 500, function(err) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
// /myfile.txt is now owned by user with id 500, group 500
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### fs.fchown(fd, uid, gid, callback)<a name="fchown"></a>
|
||||||
|
|
||||||
|
Changes the owner and group of a file. Asynchronous [chown(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/chown.html). Callback gets no additional arguments. Both `uid` (user id) and `gid` (group id) arguments should be a JavaScript Number. By default, `0x0` is used (i.e., `root:root` ownership).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
fs.open('/myfile.txt', function(err, fd) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
fs.fchown(fd, 500, 500, function(err) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
// /myfile.txt is now owned by user with id 500, group 500
|
||||||
|
|
||||||
|
fs.close(fd);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### fs.chmod(path, mode, callback)<a name="chmod"></a>
|
||||||
|
|
||||||
|
Changes the mode of a file. Asynchronous [chmod(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/chmod.html). Callback gets no additional arguments. The `mode` argument should be a JavaScript Number, which combines file type and permission information. Here are a list of common values useful for setting the `mode`:
|
||||||
|
|
||||||
|
* File type `S_IFREG=0x8000`
|
||||||
|
* Dir type `S_IFDIR=0x4000`
|
||||||
|
* Link type `S_IFLNK=0xA000`
|
||||||
|
|
||||||
|
* Permissions `755=0x1ED`
|
||||||
|
* Permissions `644=0x1A4`
|
||||||
|
* Permissions `777=0x1FF`
|
||||||
|
* Permissions `666=0x1B6`
|
||||||
|
|
||||||
|
By default, directories use `(0x4000 | 0x1ED)` and files use `(0x8000 | 0x1A4)`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// S_IFREG | 0o777
|
||||||
|
var mode = 0x8000 | 0x1FF
|
||||||
|
fs.chmod('/myfile.txt', mode, function(err) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
// /myfile.txt is a regular file with permissions 777
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### fs.fchmod(fd, mode, callback)<a name="fchmod"></a>
|
||||||
|
|
||||||
|
Changes the mode of a file. Asynchronous [chmod(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/chmod.html). Callback gets no additional arguments. The `mode` argument should be a JavaScript Number, which combines file type and permission information. By default, `755` (dir) and `644` (file) are used.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
fs.open('/myfile.txt', function(err, fd) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
// S_IFREG | 0o777
|
||||||
|
var mode = 0x8000 | 0x1FF
|
||||||
|
fs.fchmod(fd, mode, function(err) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
// /myfile.txt is a regular file with permissions 777
|
||||||
|
|
||||||
|
fs.close(fd);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
#### fs.fsync(fd, callback)<a name="fsync"></a>
|
#### fs.fsync(fd, callback)<a name="fsync"></a>
|
||||||
|
|
||||||
NOTE: Not yet implemented, see https://github.com/filerjs/filer/issues/87
|
NOTE: Not yet implemented, see https://github.com/filerjs/filer/issues/87
|
||||||
|
@ -1263,17 +1355,8 @@ sh.find('/app/user', {
|
||||||
#### sh.ls(dir, [options], callback)<a name="ls"></a>
|
#### sh.ls(dir, [options], callback)<a name="ls"></a>
|
||||||
|
|
||||||
Get the listing of a directory, returning an array of directory entries
|
Get the listing of a directory, returning an array of directory entries
|
||||||
in the following form:
|
in the same form as [fs.stat()](#stat), with the exception that a new Array named
|
||||||
```
|
`contents` is added for directory entries, containing child entries.
|
||||||
{
|
|
||||||
path: <String> the basename of the directory entry
|
|
||||||
links: <Number> the number of links to the entry
|
|
||||||
size: <Number> the size in bytes of the entry
|
|
||||||
modified: <Number> the last modified date/time
|
|
||||||
type: <String> the type of the entry
|
|
||||||
contents: <Array> an optional array of child entries, if this entry is itself a directory
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
By default `sh.ls()` gives a shallow listing. If you want to follow
|
By default `sh.ls()` gives a shallow listing. If you want to follow
|
||||||
directories as they are encountered, use the `recursive=true` option. NOTE:
|
directories as they are encountered, use the `recursive=true` option. NOTE:
|
||||||
|
|
|
@ -1,21 +1,150 @@
|
||||||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.FilerBuffer = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.FilerBuffer = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||||
|
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||||
|
|
||||||
|
;(function (exports) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Arr = (typeof Uint8Array !== 'undefined')
|
||||||
|
? Uint8Array
|
||||||
|
: Array
|
||||||
|
|
||||||
|
var PLUS = '+'.charCodeAt(0)
|
||||||
|
var SLASH = '/'.charCodeAt(0)
|
||||||
|
var NUMBER = '0'.charCodeAt(0)
|
||||||
|
var LOWER = 'a'.charCodeAt(0)
|
||||||
|
var UPPER = 'A'.charCodeAt(0)
|
||||||
|
var PLUS_URL_SAFE = '-'.charCodeAt(0)
|
||||||
|
var SLASH_URL_SAFE = '_'.charCodeAt(0)
|
||||||
|
|
||||||
|
function decode (elt) {
|
||||||
|
var code = elt.charCodeAt(0)
|
||||||
|
if (code === PLUS ||
|
||||||
|
code === PLUS_URL_SAFE)
|
||||||
|
return 62 // '+'
|
||||||
|
if (code === SLASH ||
|
||||||
|
code === SLASH_URL_SAFE)
|
||||||
|
return 63 // '/'
|
||||||
|
if (code < NUMBER)
|
||||||
|
return -1 //no match
|
||||||
|
if (code < NUMBER + 10)
|
||||||
|
return code - NUMBER + 26 + 26
|
||||||
|
if (code < UPPER + 26)
|
||||||
|
return code - UPPER
|
||||||
|
if (code < LOWER + 26)
|
||||||
|
return code - LOWER + 26
|
||||||
|
}
|
||||||
|
|
||||||
|
function b64ToByteArray (b64) {
|
||||||
|
var i, j, l, tmp, placeHolders, arr
|
||||||
|
|
||||||
|
if (b64.length % 4 > 0) {
|
||||||
|
throw new Error('Invalid string. Length must be a multiple of 4')
|
||||||
|
}
|
||||||
|
|
||||||
|
// the number of equal signs (place holders)
|
||||||
|
// if there are two placeholders, than the two characters before it
|
||||||
|
// represent one byte
|
||||||
|
// if there is only one, then the three characters before it represent 2 bytes
|
||||||
|
// this is just a cheap hack to not do indexOf twice
|
||||||
|
var len = b64.length
|
||||||
|
placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
|
||||||
|
|
||||||
|
// base64 is 4/3 + up to two characters of the original data
|
||||||
|
arr = new Arr(b64.length * 3 / 4 - placeHolders)
|
||||||
|
|
||||||
|
// if there are placeholders, only get up to the last complete 4 chars
|
||||||
|
l = placeHolders > 0 ? b64.length - 4 : b64.length
|
||||||
|
|
||||||
|
var L = 0
|
||||||
|
|
||||||
|
function push (v) {
|
||||||
|
arr[L++] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0, j = 0; i < l; i += 4, j += 3) {
|
||||||
|
tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
|
||||||
|
push((tmp & 0xFF0000) >> 16)
|
||||||
|
push((tmp & 0xFF00) >> 8)
|
||||||
|
push(tmp & 0xFF)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (placeHolders === 2) {
|
||||||
|
tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
|
||||||
|
push(tmp & 0xFF)
|
||||||
|
} else if (placeHolders === 1) {
|
||||||
|
tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
|
||||||
|
push((tmp >> 8) & 0xFF)
|
||||||
|
push(tmp & 0xFF)
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
|
function uint8ToBase64 (uint8) {
|
||||||
|
var i,
|
||||||
|
extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
|
||||||
|
output = "",
|
||||||
|
temp, length
|
||||||
|
|
||||||
|
function encode (num) {
|
||||||
|
return lookup.charAt(num)
|
||||||
|
}
|
||||||
|
|
||||||
|
function tripletToBase64 (num) {
|
||||||
|
return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
|
||||||
|
}
|
||||||
|
|
||||||
|
// go through the array every three bytes, we'll deal with trailing stuff later
|
||||||
|
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
|
||||||
|
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
|
||||||
|
output += tripletToBase64(temp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// pad the end with zeros, but make sure to not forget the extra bytes
|
||||||
|
switch (extraBytes) {
|
||||||
|
case 1:
|
||||||
|
temp = uint8[uint8.length - 1]
|
||||||
|
output += encode(temp >> 2)
|
||||||
|
output += encode((temp << 4) & 0x3F)
|
||||||
|
output += '=='
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
|
||||||
|
output += encode(temp >> 10)
|
||||||
|
output += encode((temp >> 4) & 0x3F)
|
||||||
|
output += encode((temp << 2) & 0x3F)
|
||||||
|
output += '='
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.toByteArray = b64ToByteArray
|
||||||
|
exports.fromByteArray = uint8ToBase64
|
||||||
|
}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
|
||||||
|
|
||||||
|
},{}],2:[function(require,module,exports){
|
||||||
|
(function (global){
|
||||||
/*!
|
/*!
|
||||||
* The buffer module from node.js, for the browser.
|
* The buffer module from node.js, for the browser.
|
||||||
*
|
*
|
||||||
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
|
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
|
||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
/* eslint-disable no-proto */
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
var base64 = require('base64-js')
|
var base64 = require('base64-js')
|
||||||
var ieee754 = require('ieee754')
|
var ieee754 = require('ieee754')
|
||||||
var isArray = require('is-array')
|
var isArray = require('isarray')
|
||||||
|
|
||||||
exports.Buffer = Buffer
|
exports.Buffer = Buffer
|
||||||
exports.SlowBuffer = SlowBuffer
|
exports.SlowBuffer = SlowBuffer
|
||||||
exports.INSPECT_MAX_BYTES = 50
|
exports.INSPECT_MAX_BYTES = 50
|
||||||
Buffer.poolSize = 8192 // not used by this implementation
|
Buffer.poolSize = 8192 // not used by this implementation
|
||||||
|
|
||||||
var kMaxLength = 0x3fffffff
|
|
||||||
var rootParent = {}
|
var rootParent = {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,32 +155,49 @@ var rootParent = {}
|
||||||
* Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
|
* Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
|
||||||
* Opera 11.6+, iOS 4.2+.
|
* Opera 11.6+, iOS 4.2+.
|
||||||
*
|
*
|
||||||
|
* Due to various browser bugs, sometimes the Object implementation will be used even
|
||||||
|
* when the browser supports typed arrays.
|
||||||
|
*
|
||||||
* Note:
|
* Note:
|
||||||
*
|
*
|
||||||
* - Implementation must support adding new properties to `Uint8Array` instances.
|
* - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
|
||||||
* Firefox 4-29 lacked support, fixed in Firefox 30+.
|
|
||||||
* See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
|
* See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
|
||||||
*
|
*
|
||||||
|
* - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property
|
||||||
|
* on objects.
|
||||||
|
*
|
||||||
* - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
|
* - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
|
||||||
*
|
*
|
||||||
* - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
|
* - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
|
||||||
* incorrect length in some situations.
|
* incorrect length in some situations.
|
||||||
*
|
|
||||||
* We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they will
|
* We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
|
||||||
* get the Object implementation, which is slower but will work correctly.
|
* get the Object implementation, which is slower but behaves correctly.
|
||||||
*/
|
*/
|
||||||
Buffer.TYPED_ARRAY_SUPPORT = (function () {
|
Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
|
||||||
|
? global.TYPED_ARRAY_SUPPORT
|
||||||
|
: typedArraySupport()
|
||||||
|
|
||||||
|
function typedArraySupport () {
|
||||||
|
function Bar () {}
|
||||||
try {
|
try {
|
||||||
var buf = new ArrayBuffer(0)
|
var arr = new Uint8Array(1)
|
||||||
var arr = new Uint8Array(buf)
|
|
||||||
arr.foo = function () { return 42 }
|
arr.foo = function () { return 42 }
|
||||||
|
arr.constructor = Bar
|
||||||
return arr.foo() === 42 && // typed array instances can be augmented
|
return arr.foo() === 42 && // typed array instances can be augmented
|
||||||
|
arr.constructor === Bar && // constructor can be set
|
||||||
typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
|
typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
|
||||||
new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
|
arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
})()
|
}
|
||||||
|
|
||||||
|
function kMaxLength () {
|
||||||
|
return Buffer.TYPED_ARRAY_SUPPORT
|
||||||
|
? 0x7fffffff
|
||||||
|
: 0x3fffffff
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class: Buffer
|
* Class: Buffer
|
||||||
|
@ -72,8 +218,10 @@ function Buffer (arg) {
|
||||||
return new Buffer(arg)
|
return new Buffer(arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Buffer.TYPED_ARRAY_SUPPORT) {
|
||||||
this.length = 0
|
this.length = 0
|
||||||
this.parent = undefined
|
this.parent = undefined
|
||||||
|
}
|
||||||
|
|
||||||
// Common case.
|
// Common case.
|
||||||
if (typeof arg === 'number') {
|
if (typeof arg === 'number') {
|
||||||
|
@ -119,9 +267,14 @@ function fromObject (that, object) {
|
||||||
throw new TypeError('must start with number, buffer, array or string')
|
throw new TypeError('must start with number, buffer, array or string')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof ArrayBuffer !== 'undefined' && object.buffer instanceof ArrayBuffer) {
|
if (typeof ArrayBuffer !== 'undefined') {
|
||||||
|
if (object.buffer instanceof ArrayBuffer) {
|
||||||
return fromTypedArray(that, object)
|
return fromTypedArray(that, object)
|
||||||
}
|
}
|
||||||
|
if (object instanceof ArrayBuffer) {
|
||||||
|
return fromArrayBuffer(that, object)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (object.length) return fromArrayLike(that, object)
|
if (object.length) return fromArrayLike(that, object)
|
||||||
|
|
||||||
|
@ -157,6 +310,18 @@ function fromTypedArray (that, array) {
|
||||||
return that
|
return that
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fromArrayBuffer (that, array) {
|
||||||
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
||||||
|
// Return an augmented `Uint8Array` instance, for best performance
|
||||||
|
array.byteLength
|
||||||
|
that = Buffer._augment(new Uint8Array(array))
|
||||||
|
} else {
|
||||||
|
// Fallback: Return an object instance of the Buffer class
|
||||||
|
that = fromTypedArray(that, new Uint8Array(array))
|
||||||
|
}
|
||||||
|
return that
|
||||||
|
}
|
||||||
|
|
||||||
function fromArrayLike (that, array) {
|
function fromArrayLike (that, array) {
|
||||||
var length = checked(array.length) | 0
|
var length = checked(array.length) | 0
|
||||||
that = allocate(that, length)
|
that = allocate(that, length)
|
||||||
|
@ -184,10 +349,20 @@ function fromJsonObject (that, object) {
|
||||||
return that
|
return that
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
||||||
|
Buffer.prototype.__proto__ = Uint8Array.prototype
|
||||||
|
Buffer.__proto__ = Uint8Array
|
||||||
|
} else {
|
||||||
|
// pre-set for values that may exist in the future
|
||||||
|
Buffer.prototype.length = undefined
|
||||||
|
Buffer.prototype.parent = undefined
|
||||||
|
}
|
||||||
|
|
||||||
function allocate (that, length) {
|
function allocate (that, length) {
|
||||||
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
||||||
// Return an augmented `Uint8Array` instance, for best performance
|
// Return an augmented `Uint8Array` instance, for best performance
|
||||||
that = Buffer._augment(new Uint8Array(length))
|
that = Buffer._augment(new Uint8Array(length))
|
||||||
|
that.__proto__ = Buffer.prototype
|
||||||
} else {
|
} else {
|
||||||
// Fallback: Return an object instance of the Buffer class
|
// Fallback: Return an object instance of the Buffer class
|
||||||
that.length = length
|
that.length = length
|
||||||
|
@ -203,9 +378,9 @@ function allocate (that, length) {
|
||||||
function checked (length) {
|
function checked (length) {
|
||||||
// Note: cannot use `length < kMaxLength` here because that fails when
|
// Note: cannot use `length < kMaxLength` here because that fails when
|
||||||
// length is NaN (which is otherwise coerced to zero.)
|
// length is NaN (which is otherwise coerced to zero.)
|
||||||
if (length >= kMaxLength) {
|
if (length >= kMaxLength()) {
|
||||||
throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
|
throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
|
||||||
'size: 0x' + kMaxLength.toString(16) + ' bytes')
|
'size: 0x' + kMaxLength().toString(16) + ' bytes')
|
||||||
}
|
}
|
||||||
return length | 0
|
return length | 0
|
||||||
}
|
}
|
||||||
|
@ -274,8 +449,6 @@ Buffer.concat = function concat (list, length) {
|
||||||
|
|
||||||
if (list.length === 0) {
|
if (list.length === 0) {
|
||||||
return new Buffer(0)
|
return new Buffer(0)
|
||||||
} else if (list.length === 1) {
|
|
||||||
return list[0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var i
|
var i
|
||||||
|
@ -297,39 +470,43 @@ Buffer.concat = function concat (list, length) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function byteLength (string, encoding) {
|
function byteLength (string, encoding) {
|
||||||
if (typeof string !== 'string') string = String(string)
|
if (typeof string !== 'string') string = '' + string
|
||||||
|
|
||||||
if (string.length === 0) return 0
|
var len = string.length
|
||||||
|
if (len === 0) return 0
|
||||||
|
|
||||||
switch (encoding || 'utf8') {
|
// Use a for loop to avoid recursion
|
||||||
|
var loweredCase = false
|
||||||
|
for (;;) {
|
||||||
|
switch (encoding) {
|
||||||
case 'ascii':
|
case 'ascii':
|
||||||
case 'binary':
|
case 'binary':
|
||||||
|
// Deprecated
|
||||||
case 'raw':
|
case 'raw':
|
||||||
return string.length
|
case 'raws':
|
||||||
|
return len
|
||||||
|
case 'utf8':
|
||||||
|
case 'utf-8':
|
||||||
|
return utf8ToBytes(string).length
|
||||||
case 'ucs2':
|
case 'ucs2':
|
||||||
case 'ucs-2':
|
case 'ucs-2':
|
||||||
case 'utf16le':
|
case 'utf16le':
|
||||||
case 'utf-16le':
|
case 'utf-16le':
|
||||||
return string.length * 2
|
return len * 2
|
||||||
case 'hex':
|
case 'hex':
|
||||||
return string.length >>> 1
|
return len >>> 1
|
||||||
case 'utf8':
|
|
||||||
case 'utf-8':
|
|
||||||
return utf8ToBytes(string).length
|
|
||||||
case 'base64':
|
case 'base64':
|
||||||
return base64ToBytes(string).length
|
return base64ToBytes(string).length
|
||||||
default:
|
default:
|
||||||
return string.length
|
if (loweredCase) return utf8ToBytes(string).length // assume utf8
|
||||||
|
encoding = ('' + encoding).toLowerCase()
|
||||||
|
loweredCase = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Buffer.byteLength = byteLength
|
Buffer.byteLength = byteLength
|
||||||
|
|
||||||
// pre-set for values that may exist in the future
|
function slowToString (encoding, start, end) {
|
||||||
Buffer.prototype.length = undefined
|
|
||||||
Buffer.prototype.parent = undefined
|
|
||||||
|
|
||||||
// toString(encoding, start=0, end=buffer.length)
|
|
||||||
Buffer.prototype.toString = function toString (encoding, start, end) {
|
|
||||||
var loweredCase = false
|
var loweredCase = false
|
||||||
|
|
||||||
start = start | 0
|
start = start | 0
|
||||||
|
@ -372,6 +549,13 @@ Buffer.prototype.toString = function toString (encoding, start, end) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Buffer.prototype.toString = function toString () {
|
||||||
|
var length = this.length | 0
|
||||||
|
if (length === 0) return ''
|
||||||
|
if (arguments.length === 0) return utf8Slice(this, 0, length)
|
||||||
|
return slowToString.apply(this, arguments)
|
||||||
|
}
|
||||||
|
|
||||||
Buffer.prototype.equals = function equals (b) {
|
Buffer.prototype.equals = function equals (b) {
|
||||||
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
|
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
|
||||||
if (this === b) return true
|
if (this === b) return true
|
||||||
|
@ -435,13 +619,13 @@ Buffer.prototype.indexOf = function indexOf (val, byteOffset) {
|
||||||
throw new TypeError('val must be string, number or Buffer')
|
throw new TypeError('val must be string, number or Buffer')
|
||||||
}
|
}
|
||||||
|
|
||||||
// `get` will be removed in Node 0.13+
|
// `get` is deprecated
|
||||||
Buffer.prototype.get = function get (offset) {
|
Buffer.prototype.get = function get (offset) {
|
||||||
console.log('.get() is deprecated. Access using array indexes instead.')
|
console.log('.get() is deprecated. Access using array indexes instead.')
|
||||||
return this.readUInt8(offset)
|
return this.readUInt8(offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// `set` will be removed in Node 0.13+
|
// `set` is deprecated
|
||||||
Buffer.prototype.set = function set (v, offset) {
|
Buffer.prototype.set = function set (v, offset) {
|
||||||
console.log('.set() is deprecated. Access using array indexes instead.')
|
console.log('.set() is deprecated. Access using array indexes instead.')
|
||||||
return this.writeUInt8(v, offset)
|
return this.writeUInt8(v, offset)
|
||||||
|
@ -582,20 +766,99 @@ function base64Slice (buf, start, end) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function utf8Slice (buf, start, end) {
|
function utf8Slice (buf, start, end) {
|
||||||
var res = ''
|
|
||||||
var tmp = ''
|
|
||||||
end = Math.min(buf.length, end)
|
end = Math.min(buf.length, end)
|
||||||
|
var res = []
|
||||||
|
|
||||||
for (var i = start; i < end; i++) {
|
var i = start
|
||||||
if (buf[i] <= 0x7F) {
|
while (i < end) {
|
||||||
res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i])
|
var firstByte = buf[i]
|
||||||
tmp = ''
|
var codePoint = null
|
||||||
} else {
|
var bytesPerSequence = (firstByte > 0xEF) ? 4
|
||||||
tmp += '%' + buf[i].toString(16)
|
: (firstByte > 0xDF) ? 3
|
||||||
|
: (firstByte > 0xBF) ? 2
|
||||||
|
: 1
|
||||||
|
|
||||||
|
if (i + bytesPerSequence <= end) {
|
||||||
|
var secondByte, thirdByte, fourthByte, tempCodePoint
|
||||||
|
|
||||||
|
switch (bytesPerSequence) {
|
||||||
|
case 1:
|
||||||
|
if (firstByte < 0x80) {
|
||||||
|
codePoint = firstByte
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
secondByte = buf[i + 1]
|
||||||
|
if ((secondByte & 0xC0) === 0x80) {
|
||||||
|
tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
|
||||||
|
if (tempCodePoint > 0x7F) {
|
||||||
|
codePoint = tempCodePoint
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 3:
|
||||||
|
secondByte = buf[i + 1]
|
||||||
|
thirdByte = buf[i + 2]
|
||||||
|
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
|
||||||
|
tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
|
||||||
|
if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
|
||||||
|
codePoint = tempCodePoint
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 4:
|
||||||
|
secondByte = buf[i + 1]
|
||||||
|
thirdByte = buf[i + 2]
|
||||||
|
fourthByte = buf[i + 3]
|
||||||
|
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
|
||||||
|
tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
|
||||||
|
if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
|
||||||
|
codePoint = tempCodePoint
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res + decodeUtf8Char(tmp)
|
if (codePoint === null) {
|
||||||
|
// we did not generate a valid codePoint so insert a
|
||||||
|
// replacement char (U+FFFD) and advance only 1 byte
|
||||||
|
codePoint = 0xFFFD
|
||||||
|
bytesPerSequence = 1
|
||||||
|
} else if (codePoint > 0xFFFF) {
|
||||||
|
// encode to utf16 (surrogate pair dance)
|
||||||
|
codePoint -= 0x10000
|
||||||
|
res.push(codePoint >>> 10 & 0x3FF | 0xD800)
|
||||||
|
codePoint = 0xDC00 | codePoint & 0x3FF
|
||||||
|
}
|
||||||
|
|
||||||
|
res.push(codePoint)
|
||||||
|
i += bytesPerSequence
|
||||||
|
}
|
||||||
|
|
||||||
|
return decodeCodePointsArray(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Based on http://stackoverflow.com/a/22747272/680742, the browser with
|
||||||
|
// the lowest limit is Chrome, with 0x10000 args.
|
||||||
|
// We go 1 magnitude less, for safety
|
||||||
|
var MAX_ARGUMENTS_LENGTH = 0x1000
|
||||||
|
|
||||||
|
function decodeCodePointsArray (codePoints) {
|
||||||
|
var len = codePoints.length
|
||||||
|
if (len <= MAX_ARGUMENTS_LENGTH) {
|
||||||
|
return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode in chunks to avoid "call stack size exceeded".
|
||||||
|
var res = ''
|
||||||
|
var i = 0
|
||||||
|
while (i < len) {
|
||||||
|
res += String.fromCharCode.apply(
|
||||||
|
String,
|
||||||
|
codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
function asciiSlice (buf, start, end) {
|
function asciiSlice (buf, start, end) {
|
||||||
|
@ -884,7 +1147,7 @@ Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
|
||||||
offset = offset | 0
|
offset = offset | 0
|
||||||
if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
|
if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
|
||||||
if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
|
if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
|
||||||
this[offset] = value
|
this[offset] = (value & 0xff)
|
||||||
return offset + 1
|
return offset + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -901,7 +1164,7 @@ Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert
|
||||||
offset = offset | 0
|
offset = offset | 0
|
||||||
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
|
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
|
||||||
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
||||||
this[offset] = value
|
this[offset] = (value & 0xff)
|
||||||
this[offset + 1] = (value >>> 8)
|
this[offset + 1] = (value >>> 8)
|
||||||
} else {
|
} else {
|
||||||
objectWriteUInt16(this, value, offset, true)
|
objectWriteUInt16(this, value, offset, true)
|
||||||
|
@ -915,7 +1178,7 @@ Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert
|
||||||
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
|
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
|
||||||
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
||||||
this[offset] = (value >>> 8)
|
this[offset] = (value >>> 8)
|
||||||
this[offset + 1] = value
|
this[offset + 1] = (value & 0xff)
|
||||||
} else {
|
} else {
|
||||||
objectWriteUInt16(this, value, offset, false)
|
objectWriteUInt16(this, value, offset, false)
|
||||||
}
|
}
|
||||||
|
@ -937,7 +1200,7 @@ Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert
|
||||||
this[offset + 3] = (value >>> 24)
|
this[offset + 3] = (value >>> 24)
|
||||||
this[offset + 2] = (value >>> 16)
|
this[offset + 2] = (value >>> 16)
|
||||||
this[offset + 1] = (value >>> 8)
|
this[offset + 1] = (value >>> 8)
|
||||||
this[offset] = value
|
this[offset] = (value & 0xff)
|
||||||
} else {
|
} else {
|
||||||
objectWriteUInt32(this, value, offset, true)
|
objectWriteUInt32(this, value, offset, true)
|
||||||
}
|
}
|
||||||
|
@ -952,7 +1215,7 @@ Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert
|
||||||
this[offset] = (value >>> 24)
|
this[offset] = (value >>> 24)
|
||||||
this[offset + 1] = (value >>> 16)
|
this[offset + 1] = (value >>> 16)
|
||||||
this[offset + 2] = (value >>> 8)
|
this[offset + 2] = (value >>> 8)
|
||||||
this[offset + 3] = value
|
this[offset + 3] = (value & 0xff)
|
||||||
} else {
|
} else {
|
||||||
objectWriteUInt32(this, value, offset, false)
|
objectWriteUInt32(this, value, offset, false)
|
||||||
}
|
}
|
||||||
|
@ -1005,7 +1268,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
|
||||||
if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
|
if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
|
||||||
if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
|
if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
|
||||||
if (value < 0) value = 0xff + value + 1
|
if (value < 0) value = 0xff + value + 1
|
||||||
this[offset] = value
|
this[offset] = (value & 0xff)
|
||||||
return offset + 1
|
return offset + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1014,7 +1277,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert)
|
||||||
offset = offset | 0
|
offset = offset | 0
|
||||||
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
|
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
|
||||||
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
||||||
this[offset] = value
|
this[offset] = (value & 0xff)
|
||||||
this[offset + 1] = (value >>> 8)
|
this[offset + 1] = (value >>> 8)
|
||||||
} else {
|
} else {
|
||||||
objectWriteUInt16(this, value, offset, true)
|
objectWriteUInt16(this, value, offset, true)
|
||||||
|
@ -1028,7 +1291,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert)
|
||||||
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
|
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
|
||||||
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
||||||
this[offset] = (value >>> 8)
|
this[offset] = (value >>> 8)
|
||||||
this[offset + 1] = value
|
this[offset + 1] = (value & 0xff)
|
||||||
} else {
|
} else {
|
||||||
objectWriteUInt16(this, value, offset, false)
|
objectWriteUInt16(this, value, offset, false)
|
||||||
}
|
}
|
||||||
|
@ -1040,7 +1303,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert)
|
||||||
offset = offset | 0
|
offset = offset | 0
|
||||||
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
|
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
|
||||||
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
||||||
this[offset] = value
|
this[offset] = (value & 0xff)
|
||||||
this[offset + 1] = (value >>> 8)
|
this[offset + 1] = (value >>> 8)
|
||||||
this[offset + 2] = (value >>> 16)
|
this[offset + 2] = (value >>> 16)
|
||||||
this[offset + 3] = (value >>> 24)
|
this[offset + 3] = (value >>> 24)
|
||||||
|
@ -1059,7 +1322,7 @@ Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert)
|
||||||
this[offset] = (value >>> 24)
|
this[offset] = (value >>> 24)
|
||||||
this[offset + 1] = (value >>> 16)
|
this[offset + 1] = (value >>> 16)
|
||||||
this[offset + 2] = (value >>> 8)
|
this[offset + 2] = (value >>> 8)
|
||||||
this[offset + 3] = value
|
this[offset + 3] = (value & 0xff)
|
||||||
} else {
|
} else {
|
||||||
objectWriteUInt32(this, value, offset, false)
|
objectWriteUInt32(this, value, offset, false)
|
||||||
}
|
}
|
||||||
|
@ -1130,9 +1393,16 @@ Buffer.prototype.copy = function copy (target, targetStart, start, end) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var len = end - start
|
var len = end - start
|
||||||
|
var i
|
||||||
|
|
||||||
if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
|
if (this === target && start < targetStart && targetStart < end) {
|
||||||
for (var i = 0; i < len; i++) {
|
// descending copy from end
|
||||||
|
for (i = len - 1; i >= 0; i--) {
|
||||||
|
target[i + targetStart] = this[i + start]
|
||||||
|
}
|
||||||
|
} else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
|
||||||
|
// ascending copy from start
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
target[i + targetStart] = this[i + start]
|
target[i + targetStart] = this[i + start]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1208,7 +1478,7 @@ Buffer._augment = function _augment (arr) {
|
||||||
// save reference to original Uint8Array set method before overwriting
|
// save reference to original Uint8Array set method before overwriting
|
||||||
arr._set = arr.set
|
arr._set = arr.set
|
||||||
|
|
||||||
// deprecated, will be removed in node 0.13+
|
// deprecated
|
||||||
arr.get = BP.get
|
arr.get = BP.get
|
||||||
arr.set = BP.set
|
arr.set = BP.set
|
||||||
|
|
||||||
|
@ -1264,7 +1534,7 @@ Buffer._augment = function _augment (arr) {
|
||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
||||||
var INVALID_BASE64_RE = /[^+\/0-9A-z\-]/g
|
var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
|
||||||
|
|
||||||
function base64clean (str) {
|
function base64clean (str) {
|
||||||
// Node strips out invalid characters like \n and \t from the string, base64-js does not
|
// Node strips out invalid characters like \n and \t from the string, base64-js does not
|
||||||
|
@ -1294,28 +1564,15 @@ function utf8ToBytes (string, units) {
|
||||||
var length = string.length
|
var length = string.length
|
||||||
var leadSurrogate = null
|
var leadSurrogate = null
|
||||||
var bytes = []
|
var bytes = []
|
||||||
var i = 0
|
|
||||||
|
|
||||||
for (; i < length; i++) {
|
for (var i = 0; i < length; i++) {
|
||||||
codePoint = string.charCodeAt(i)
|
codePoint = string.charCodeAt(i)
|
||||||
|
|
||||||
// is surrogate component
|
// is surrogate component
|
||||||
if (codePoint > 0xD7FF && codePoint < 0xE000) {
|
if (codePoint > 0xD7FF && codePoint < 0xE000) {
|
||||||
// last char was a lead
|
// last char was a lead
|
||||||
if (leadSurrogate) {
|
if (!leadSurrogate) {
|
||||||
// 2 leads in a row
|
|
||||||
if (codePoint < 0xDC00) {
|
|
||||||
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
|
||||||
leadSurrogate = codePoint
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
// valid surrogate pair
|
|
||||||
codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000
|
|
||||||
leadSurrogate = null
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// no lead yet
|
// no lead yet
|
||||||
|
|
||||||
if (codePoint > 0xDBFF) {
|
if (codePoint > 0xDBFF) {
|
||||||
// unexpected trail
|
// unexpected trail
|
||||||
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
||||||
|
@ -1324,18 +1581,30 @@ function utf8ToBytes (string, units) {
|
||||||
// unpaired lead
|
// unpaired lead
|
||||||
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
||||||
continue
|
continue
|
||||||
} else {
|
}
|
||||||
|
|
||||||
// valid lead
|
// valid lead
|
||||||
leadSurrogate = codePoint
|
leadSurrogate = codePoint
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2 leads in a row
|
||||||
|
if (codePoint < 0xDC00) {
|
||||||
|
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
||||||
|
leadSurrogate = codePoint
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// valid surrogate pair
|
||||||
|
codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
|
||||||
} else if (leadSurrogate) {
|
} else if (leadSurrogate) {
|
||||||
// valid bmp char, but last char was a lead
|
// valid bmp char, but last char was a lead
|
||||||
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
||||||
leadSurrogate = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
leadSurrogate = null
|
||||||
|
|
||||||
// encode utf8
|
// encode utf8
|
||||||
if (codePoint < 0x80) {
|
if (codePoint < 0x80) {
|
||||||
if ((units -= 1) < 0) break
|
if ((units -= 1) < 0) break
|
||||||
|
@ -1353,7 +1622,7 @@ function utf8ToBytes (string, units) {
|
||||||
codePoint >> 0x6 & 0x3F | 0x80,
|
codePoint >> 0x6 & 0x3F | 0x80,
|
||||||
codePoint & 0x3F | 0x80
|
codePoint & 0x3F | 0x80
|
||||||
)
|
)
|
||||||
} else if (codePoint < 0x200000) {
|
} else if (codePoint < 0x110000) {
|
||||||
if ((units -= 4) < 0) break
|
if ((units -= 4) < 0) break
|
||||||
bytes.push(
|
bytes.push(
|
||||||
codePoint >> 0x12 | 0xF0,
|
codePoint >> 0x12 | 0xF0,
|
||||||
|
@ -1406,144 +1675,18 @@ function blitBuffer (src, dst, offset, length) {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeUtf8Char (str) {
|
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||||||
try {
|
},{"base64-js":1,"ieee754":4,"isarray":3}],3:[function(require,module,exports){
|
||||||
return decodeURIComponent(str)
|
var toString = {}.toString;
|
||||||
} catch (err) {
|
|
||||||
return String.fromCharCode(0xFFFD) // UTF 8 invalid char
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
},{"base64-js":2,"ieee754":3,"is-array":4}],2:[function(require,module,exports){
|
module.exports = Array.isArray || function (arr) {
|
||||||
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
return toString.call(arr) == '[object Array]';
|
||||||
|
};
|
||||||
|
|
||||||
;(function (exports) {
|
},{}],4:[function(require,module,exports){
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var Arr = (typeof Uint8Array !== 'undefined')
|
|
||||||
? Uint8Array
|
|
||||||
: Array
|
|
||||||
|
|
||||||
var PLUS = '+'.charCodeAt(0)
|
|
||||||
var SLASH = '/'.charCodeAt(0)
|
|
||||||
var NUMBER = '0'.charCodeAt(0)
|
|
||||||
var LOWER = 'a'.charCodeAt(0)
|
|
||||||
var UPPER = 'A'.charCodeAt(0)
|
|
||||||
var PLUS_URL_SAFE = '-'.charCodeAt(0)
|
|
||||||
var SLASH_URL_SAFE = '_'.charCodeAt(0)
|
|
||||||
|
|
||||||
function decode (elt) {
|
|
||||||
var code = elt.charCodeAt(0)
|
|
||||||
if (code === PLUS ||
|
|
||||||
code === PLUS_URL_SAFE)
|
|
||||||
return 62 // '+'
|
|
||||||
if (code === SLASH ||
|
|
||||||
code === SLASH_URL_SAFE)
|
|
||||||
return 63 // '/'
|
|
||||||
if (code < NUMBER)
|
|
||||||
return -1 //no match
|
|
||||||
if (code < NUMBER + 10)
|
|
||||||
return code - NUMBER + 26 + 26
|
|
||||||
if (code < UPPER + 26)
|
|
||||||
return code - UPPER
|
|
||||||
if (code < LOWER + 26)
|
|
||||||
return code - LOWER + 26
|
|
||||||
}
|
|
||||||
|
|
||||||
function b64ToByteArray (b64) {
|
|
||||||
var i, j, l, tmp, placeHolders, arr
|
|
||||||
|
|
||||||
if (b64.length % 4 > 0) {
|
|
||||||
throw new Error('Invalid string. Length must be a multiple of 4')
|
|
||||||
}
|
|
||||||
|
|
||||||
// the number of equal signs (place holders)
|
|
||||||
// if there are two placeholders, than the two characters before it
|
|
||||||
// represent one byte
|
|
||||||
// if there is only one, then the three characters before it represent 2 bytes
|
|
||||||
// this is just a cheap hack to not do indexOf twice
|
|
||||||
var len = b64.length
|
|
||||||
placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
|
|
||||||
|
|
||||||
// base64 is 4/3 + up to two characters of the original data
|
|
||||||
arr = new Arr(b64.length * 3 / 4 - placeHolders)
|
|
||||||
|
|
||||||
// if there are placeholders, only get up to the last complete 4 chars
|
|
||||||
l = placeHolders > 0 ? b64.length - 4 : b64.length
|
|
||||||
|
|
||||||
var L = 0
|
|
||||||
|
|
||||||
function push (v) {
|
|
||||||
arr[L++] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0, j = 0; i < l; i += 4, j += 3) {
|
|
||||||
tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
|
|
||||||
push((tmp & 0xFF0000) >> 16)
|
|
||||||
push((tmp & 0xFF00) >> 8)
|
|
||||||
push(tmp & 0xFF)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (placeHolders === 2) {
|
|
||||||
tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
|
|
||||||
push(tmp & 0xFF)
|
|
||||||
} else if (placeHolders === 1) {
|
|
||||||
tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
|
|
||||||
push((tmp >> 8) & 0xFF)
|
|
||||||
push(tmp & 0xFF)
|
|
||||||
}
|
|
||||||
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
|
|
||||||
function uint8ToBase64 (uint8) {
|
|
||||||
var i,
|
|
||||||
extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
|
|
||||||
output = "",
|
|
||||||
temp, length
|
|
||||||
|
|
||||||
function encode (num) {
|
|
||||||
return lookup.charAt(num)
|
|
||||||
}
|
|
||||||
|
|
||||||
function tripletToBase64 (num) {
|
|
||||||
return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
|
|
||||||
}
|
|
||||||
|
|
||||||
// go through the array every three bytes, we'll deal with trailing stuff later
|
|
||||||
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
|
|
||||||
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
|
|
||||||
output += tripletToBase64(temp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// pad the end with zeros, but make sure to not forget the extra bytes
|
|
||||||
switch (extraBytes) {
|
|
||||||
case 1:
|
|
||||||
temp = uint8[uint8.length - 1]
|
|
||||||
output += encode(temp >> 2)
|
|
||||||
output += encode((temp << 4) & 0x3F)
|
|
||||||
output += '=='
|
|
||||||
break
|
|
||||||
case 2:
|
|
||||||
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
|
|
||||||
output += encode(temp >> 10)
|
|
||||||
output += encode((temp >> 4) & 0x3F)
|
|
||||||
output += encode((temp << 2) & 0x3F)
|
|
||||||
output += '='
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.toByteArray = b64ToByteArray
|
|
||||||
exports.fromByteArray = uint8ToBase64
|
|
||||||
}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
|
|
||||||
|
|
||||||
},{}],3:[function(require,module,exports){
|
|
||||||
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
|
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
|
||||||
var e, m
|
var e, m
|
||||||
var eLen = nBytes * 8 - mLen - 1
|
var eLen = (nBytes * 8) - mLen - 1
|
||||||
var eMax = (1 << eLen) - 1
|
var eMax = (1 << eLen) - 1
|
||||||
var eBias = eMax >> 1
|
var eBias = eMax >> 1
|
||||||
var nBits = -7
|
var nBits = -7
|
||||||
|
@ -1556,12 +1699,12 @@ exports.read = function (buffer, offset, isLE, mLen, nBytes) {
|
||||||
e = s & ((1 << (-nBits)) - 1)
|
e = s & ((1 << (-nBits)) - 1)
|
||||||
s >>= (-nBits)
|
s >>= (-nBits)
|
||||||
nBits += eLen
|
nBits += eLen
|
||||||
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
|
for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {}
|
||||||
|
|
||||||
m = e & ((1 << (-nBits)) - 1)
|
m = e & ((1 << (-nBits)) - 1)
|
||||||
e >>= (-nBits)
|
e >>= (-nBits)
|
||||||
nBits += mLen
|
nBits += mLen
|
||||||
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
|
for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {}
|
||||||
|
|
||||||
if (e === 0) {
|
if (e === 0) {
|
||||||
e = 1 - eBias
|
e = 1 - eBias
|
||||||
|
@ -1576,7 +1719,7 @@ exports.read = function (buffer, offset, isLE, mLen, nBytes) {
|
||||||
|
|
||||||
exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
|
exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
|
||||||
var e, m, c
|
var e, m, c
|
||||||
var eLen = nBytes * 8 - mLen - 1
|
var eLen = (nBytes * 8) - mLen - 1
|
||||||
var eMax = (1 << eLen) - 1
|
var eMax = (1 << eLen) - 1
|
||||||
var eBias = eMax >> 1
|
var eBias = eMax >> 1
|
||||||
var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
|
var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
|
||||||
|
@ -1609,7 +1752,7 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
|
||||||
m = 0
|
m = 0
|
||||||
e = eMax
|
e = eMax
|
||||||
} else if (e + eBias >= 1) {
|
} else if (e + eBias >= 1) {
|
||||||
m = (value * c - 1) * Math.pow(2, mLen)
|
m = ((value * c) - 1) * Math.pow(2, mLen)
|
||||||
e = e + eBias
|
e = e + eBias
|
||||||
} else {
|
} else {
|
||||||
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
|
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
|
||||||
|
@ -1626,41 +1769,6 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
|
||||||
buffer[offset + i - d] |= s * 128
|
buffer[offset + i - d] |= s * 128
|
||||||
}
|
}
|
||||||
|
|
||||||
},{}],4:[function(require,module,exports){
|
|
||||||
|
|
||||||
/**
|
|
||||||
* isArray
|
|
||||||
*/
|
|
||||||
|
|
||||||
var isArray = Array.isArray;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* toString
|
|
||||||
*/
|
|
||||||
|
|
||||||
var str = Object.prototype.toString;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not the given `val`
|
|
||||||
* is an array.
|
|
||||||
*
|
|
||||||
* example:
|
|
||||||
*
|
|
||||||
* isArray([]);
|
|
||||||
* // > true
|
|
||||||
* isArray(arguments);
|
|
||||||
* // > false
|
|
||||||
* isArray('');
|
|
||||||
* // > false
|
|
||||||
*
|
|
||||||
* @param {mixed} val
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = isArray || function (val) {
|
|
||||||
return !! val && '[object Array]' == str.call(val);
|
|
||||||
};
|
|
||||||
|
|
||||||
},{}],5:[function(require,module,exports){
|
},{}],5:[function(require,module,exports){
|
||||||
(function (Buffer){
|
(function (Buffer){
|
||||||
function FilerBuffer (subject, encoding, nonZero) {
|
function FilerBuffer (subject, encoding, nonZero) {
|
||||||
|
@ -1688,5 +1796,5 @@ Object.keys(Buffer).forEach(function (p) {
|
||||||
module.exports = FilerBuffer;
|
module.exports = FilerBuffer;
|
||||||
|
|
||||||
}).call(this,require("buffer").Buffer)
|
}).call(this,require("buffer").Buffer)
|
||||||
},{"buffer":1}]},{},[5])(5)
|
},{"buffer":2}]},{},[5])(5)
|
||||||
});
|
});
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -1,2 +1,2 @@
|
||||||
/*! filer 0.0.44 2017-05-25 */
|
/*! filer 0.0.44 2018-06-25 */
|
||||||
!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.Path=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b,c){function d(a,b){for(var c=0,d=a.length-1;d>=0;d--){var e=a[d];"."===e?a.splice(d,1):".."===e?(a.splice(d,1),c++):c&&(a.splice(d,1),c--)}if(b)for(;c--;c)a.unshift("..");return a}function e(){for(var a="",b=!1,c=arguments.length-1;c>=-1&&!b;c--){var e=c>=0?arguments[c]:"/";"string"==typeof e&&e&&(a=e+"/"+a,b="/"===e.charAt(0))}return a=d(a.split("/").filter(function(a){return!!a}),!b).join("/"),(b?"/":"")+a||"."}function f(a){var b="/"===a.charAt(0);"/"===a.substr(-1);return a=d(a.split("/").filter(function(a){return!!a}),!b).join("/"),a||b||(a="."),(b?"/":"")+a}function g(){var a=Array.prototype.slice.call(arguments,0);return f(a.filter(function(a,b){return a&&"string"==typeof a}).join("/"))}function h(a,b){function c(a){for(var b=0;b<a.length&&""===a[b];b++);for(var c=a.length-1;c>=0&&""===a[c];c--);return b>c?[]:a.slice(b,c-b+1)}a=e(a).substr(1),b=e(b).substr(1);for(var d=c(a.split("/")),f=c(b.split("/")),g=Math.min(d.length,f.length),h=g,i=0;g>i;i++)if(d[i]!==f[i]){h=i;break}for(var j=[],i=h;i<d.length;i++)j.push("..");return j=j.concat(f.slice(h)),j.join("/")}function i(a){var b=q(a),c=b[0],d=b[1];return c||d?(d&&(d=d.substr(0,d.length-1)),c+d):"."}function j(a,b){var c=q(a)[2];return b&&c.substr(-1*b.length)===b&&(c=c.substr(0,c.length-b.length)),""===c?"/":c}function k(a){return q(a)[3]}function l(a){return"/"===a.charAt(0)?!0:!1}function m(a){return-1!==(""+a).indexOf("\x00")?!0:!1}function n(a){return a.replace(/\/*$/,"/")}function o(a){return a=a.replace(/\/*$/,""),""===a?"/":a}var p=/^(\/?)([\s\S]+\/(?!$)|\/)?((?:\.{1,2}$|[\s\S]+?)?(\.[^.\/]*)?)$/,q=function(a){var b=p.exec(a);return[b[1]||"",b[2]||"",b[3]||"",b[4]||""]};b.exports={normalize:f,resolve:e,join:g,relative:h,sep:"/",delimiter:":",dirname:i,basename:j,extname:k,isAbsolute:l,isNull:m,addTrailing:n,removeTrailing:o}},{}]},{},[1])(1)});
|
!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.Path=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c||a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b,c){function d(a,b){for(var c=0,d=a.length-1;d>=0;d--){var e=a[d];"."===e?a.splice(d,1):".."===e?(a.splice(d,1),c++):c&&(a.splice(d,1),c--)}if(b)for(;c--;c)a.unshift("..");return a}function e(){for(var a="",b=!1,c=arguments.length-1;c>=-1&&!b;c--){var e=c>=0?arguments[c]:"/";"string"==typeof e&&e&&(a=e+"/"+a,b="/"===e.charAt(0))}return a=d(a.split("/").filter(function(a){return!!a}),!b).join("/"),(b?"/":"")+a||"."}function f(a){var b="/"===a.charAt(0);a.substr(-1);return a=d(a.split("/").filter(function(a){return!!a}),!b).join("/"),a||b||(a="."),(b?"/":"")+a}function g(){return f(Array.prototype.slice.call(arguments,0).filter(function(a,b){return a&&"string"==typeof a}).join("/"))}function h(a,b){function c(a){for(var b=0;b<a.length&&""===a[b];b++);for(var c=a.length-1;c>=0&&""===a[c];c--);return b>c?[]:a.slice(b,c-b+1)}a=e(a).substr(1),b=e(b).substr(1);for(var d=c(a.split("/")),f=c(b.split("/")),g=Math.min(d.length,f.length),h=g,i=0;i<g;i++)if(d[i]!==f[i]){h=i;break}for(var j=[],i=h;i<d.length;i++)j.push("..");return j=j.concat(f.slice(h)),j.join("/")}function i(a){var b=q(a),c=b[0],d=b[1];return c||d?(d&&(d=d.substr(0,d.length-1)),c+d):"."}function j(a,b){var c=q(a)[2];return b&&c.substr(-1*b.length)===b&&(c=c.substr(0,c.length-b.length)),""===c?"/":c}function k(a){return q(a)[3]}function l(a){return"/"===a.charAt(0)}function m(a){return-1!==(""+a).indexOf("\0")}function n(a){return a.replace(/\/*$/,"/")}function o(a){return a=a.replace(/\/*$/,""),""===a?"/":a}var p=/^(\/?)([\s\S]+\/(?!$)|\/)?((?:\.{1,2}$|[\s\S]+?)?(\.[^.\/]*)?)$/,q=function(a){var b=p.exec(a);return[b[1]||"",b[2]||"",b[3]||"",b[4]||""]};b.exports={normalize:f,resolve:e,join:g,relative:h,sep:"/",delimiter:":",dirname:i,basename:j,extname:k,isAbsolute:l,isNull:m,addTrailing:n,removeTrailing:o}},{}]},{},[1])(1)});
|
File diff suppressed because it is too large
Load Diff
|
@ -19,10 +19,19 @@ module.exports = {
|
||||||
WSQL_SIZE: 5 * 1024 * 1024,
|
WSQL_SIZE: 5 * 1024 * 1024,
|
||||||
WSQL_DESC: "FileSystem Storage",
|
WSQL_DESC: "FileSystem Storage",
|
||||||
|
|
||||||
MODE_FILE: 'FILE',
|
NODE_TYPE_FILE: 'FILE',
|
||||||
MODE_DIRECTORY: 'DIRECTORY',
|
NODE_TYPE_DIRECTORY: 'DIRECTORY',
|
||||||
MODE_SYMBOLIC_LINK: 'SYMLINK',
|
NODE_TYPE_SYMBOLIC_LINK: 'SYMLINK',
|
||||||
MODE_META: 'META',
|
NODE_TYPE_META: 'META',
|
||||||
|
|
||||||
|
S_IFREG: 0x8000,
|
||||||
|
S_IFDIR: 0x4000,
|
||||||
|
S_IFLNK: 0xA000,
|
||||||
|
|
||||||
|
DEFAULT_DIR_PERMISSIONS: 0x1ED, // 755
|
||||||
|
DEFAULT_FILE_PERMISSIONS: 0x1A4, // 644
|
||||||
|
FULL_READ_WRITE_EXEC_PERMISSIONS: 0x1FF, // 777
|
||||||
|
READ_WRITE_PERMISSIONS: 0x1B6, /// 666
|
||||||
|
|
||||||
SYMLOOP_MAX: 10,
|
SYMLOOP_MAX: 10,
|
||||||
|
|
||||||
|
@ -76,5 +85,49 @@ module.exports = {
|
||||||
ENVIRONMENT: {
|
ENVIRONMENT: {
|
||||||
TMP: '/tmp',
|
TMP: '/tmp',
|
||||||
PATH: ''
|
PATH: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
// Duplicate Node's fs.constants
|
||||||
|
fsConstants: {
|
||||||
|
O_RDONLY: 0,
|
||||||
|
O_WRONLY: 1,
|
||||||
|
O_RDWR: 2,
|
||||||
|
S_IFMT: 61440,
|
||||||
|
S_IFREG: 32768,
|
||||||
|
S_IFDIR: 16384,
|
||||||
|
S_IFCHR: 8192,
|
||||||
|
S_IFBLK: 24576,
|
||||||
|
S_IFIFO: 4096,
|
||||||
|
S_IFLNK: 40960,
|
||||||
|
S_IFSOCK: 49152,
|
||||||
|
O_CREAT: 512,
|
||||||
|
O_EXCL: 2048,
|
||||||
|
O_NOCTTY: 131072,
|
||||||
|
O_TRUNC: 1024,
|
||||||
|
O_APPEND: 8,
|
||||||
|
O_DIRECTORY: 1048576,
|
||||||
|
O_NOFOLLOW: 256,
|
||||||
|
O_SYNC: 128,
|
||||||
|
O_DSYNC: 4194304,
|
||||||
|
O_SYMLINK: 2097152,
|
||||||
|
O_NONBLOCK: 4,
|
||||||
|
S_IRWXU: 448,
|
||||||
|
S_IRUSR: 256,
|
||||||
|
S_IWUSR: 128,
|
||||||
|
S_IXUSR: 64,
|
||||||
|
S_IRWXG: 56,
|
||||||
|
S_IRGRP: 32,
|
||||||
|
S_IWGRP: 16,
|
||||||
|
S_IXGRP: 8,
|
||||||
|
S_IRWXO: 7,
|
||||||
|
S_IROTH: 4,
|
||||||
|
S_IWOTH: 2,
|
||||||
|
S_IXOTH: 1,
|
||||||
|
F_OK: 0,
|
||||||
|
R_OK: 4,
|
||||||
|
W_OK: 2,
|
||||||
|
X_OK: 1,
|
||||||
|
UV_FS_COPYFILE_EXCL: 1,
|
||||||
|
COPYFILE_EXCL: 1
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
var MODE_FILE = require('./constants.js').MODE_FILE;
|
var NODE_TYPE_FILE = require('./constants.js').NODE_TYPE_FILE;
|
||||||
|
|
||||||
module.exports = function DirectoryEntry(id, type) {
|
module.exports = function DirectoryEntry(id, type) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.type = type || MODE_FILE;
|
this.type = type || NODE_TYPE_FILE;
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,10 +8,14 @@ var isAbsolutePath = Path.isAbsolute;
|
||||||
var isNullPath = Path.isNull;
|
var isNullPath = Path.isNull;
|
||||||
|
|
||||||
var Constants = require('../constants.js');
|
var Constants = require('../constants.js');
|
||||||
var MODE_FILE = Constants.MODE_FILE;
|
var NODE_TYPE_FILE = Constants.NODE_TYPE_FILE;
|
||||||
var MODE_DIRECTORY = Constants.MODE_DIRECTORY;
|
var NODE_TYPE_DIRECTORY = Constants.NODE_TYPE_DIRECTORY;
|
||||||
var MODE_SYMBOLIC_LINK = Constants.MODE_SYMBOLIC_LINK;
|
var NODE_TYPE_SYMBOLIC_LINK = Constants.NODE_TYPE_SYMBOLIC_LINK;
|
||||||
var MODE_META = Constants.MODE_META;
|
var NODE_TYPE_META = Constants.NODE_TYPE_META;
|
||||||
|
|
||||||
|
var DEFAULT_FILE_PERMISSIONS = Constants.DEFAULT_FILE_PERMISSIONS;
|
||||||
|
var DEFAULT_DIR_PERMISSIONS = Constants.DEFAULT_DIR_PERMISSIONS;
|
||||||
|
var FULL_READ_WRITE_EXEC_PERMISSIONS = Constants.FULL_READ_WRITE_EXEC_PERMISSIONS;
|
||||||
|
|
||||||
var ROOT_DIRECTORY_NAME = Constants.ROOT_DIRECTORY_NAME;
|
var ROOT_DIRECTORY_NAME = Constants.ROOT_DIRECTORY_NAME;
|
||||||
var SUPER_NODE_ID = Constants.SUPER_NODE_ID;
|
var SUPER_NODE_ID = Constants.SUPER_NODE_ID;
|
||||||
|
@ -91,9 +95,9 @@ function update_node_times(context, path, node, times, callback) {
|
||||||
*/
|
*/
|
||||||
// in: file or directory path
|
// in: file or directory path
|
||||||
// out: new node representing file/directory
|
// out: new node representing file/directory
|
||||||
function make_node(context, path, mode, callback) {
|
function make_node(context, path, type, callback) {
|
||||||
if(mode !== MODE_DIRECTORY && mode !== MODE_FILE) {
|
if(type !== NODE_TYPE_DIRECTORY && type !== NODE_TYPE_FILE) {
|
||||||
return callback(new Errors.EINVAL('mode must be a directory or file', path));
|
return callback(new Errors.EINVAL('type must be a directory or file', path));
|
||||||
}
|
}
|
||||||
|
|
||||||
path = normalize(path);
|
path = normalize(path);
|
||||||
|
@ -108,7 +112,7 @@ function make_node(context, path, mode, callback) {
|
||||||
function create_node_in_parent(error, parentDirectoryNode) {
|
function create_node_in_parent(error, parentDirectoryNode) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else if(parentDirectoryNode.mode !== MODE_DIRECTORY) {
|
} else if(parentDirectoryNode.type !== NODE_TYPE_DIRECTORY) {
|
||||||
callback(new Errors.ENOTDIR('a component of the path prefix is not a directory', path));
|
callback(new Errors.ENOTDIR('a component of the path prefix is not a directory', path));
|
||||||
} else {
|
} else {
|
||||||
parentNode = parentDirectoryNode;
|
parentNode = parentDirectoryNode;
|
||||||
|
@ -133,7 +137,10 @@ function make_node(context, path, mode, callback) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else {
|
} else {
|
||||||
parentNodeData = result;
|
parentNodeData = result;
|
||||||
Node.create({guid: context.guid, mode: mode}, function(error, result) {
|
Node.create({
|
||||||
|
guid: context.guid,
|
||||||
|
type: type
|
||||||
|
}, function(error, result) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
return;
|
return;
|
||||||
|
@ -160,7 +167,7 @@ function make_node(context, path, mode, callback) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else {
|
} else {
|
||||||
parentNodeData[name] = new DirectoryEntry(node.id, mode);
|
parentNodeData[name] = new DirectoryEntry(node.id, type);
|
||||||
context.putObject(parentNode.data, parentNodeData, update_time);
|
context.putObject(parentNode.data, parentNodeData, update_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,7 +193,7 @@ function find_node(context, path, callback) {
|
||||||
function read_root_directory_node(error, superNode) {
|
function read_root_directory_node(error, superNode) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else if(!superNode || superNode.mode !== MODE_META || !superNode.rnode) {
|
} else if(!superNode || superNode.type !== NODE_TYPE_META || !superNode.rnode) {
|
||||||
callback(new Errors.EFILESYSTEMERROR());
|
callback(new Errors.EFILESYSTEMERROR());
|
||||||
} else {
|
} else {
|
||||||
context.getObject(superNode.rnode, check_root_directory_node);
|
context.getObject(superNode.rnode, check_root_directory_node);
|
||||||
|
@ -208,7 +215,7 @@ function find_node(context, path, callback) {
|
||||||
function read_parent_directory_data(error, parentDirectoryNode) {
|
function read_parent_directory_data(error, parentDirectoryNode) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else if(parentDirectoryNode.mode !== MODE_DIRECTORY || !parentDirectoryNode.data) {
|
} else if(parentDirectoryNode.type !== NODE_TYPE_DIRECTORY || !parentDirectoryNode.data) {
|
||||||
callback(new Errors.ENOTDIR('a component of the path prefix is not a directory', path));
|
callback(new Errors.ENOTDIR('a component of the path prefix is not a directory', path));
|
||||||
} else {
|
} else {
|
||||||
context.getObject(parentDirectoryNode.data, get_node_from_parent_directory_data);
|
context.getObject(parentDirectoryNode.data, get_node_from_parent_directory_data);
|
||||||
|
@ -234,7 +241,7 @@ function find_node(context, path, callback) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else {
|
} else {
|
||||||
if(node.mode == MODE_SYMBOLIC_LINK) {
|
if(node.type === NODE_TYPE_SYMBOLIC_LINK) {
|
||||||
followedCount++;
|
followedCount++;
|
||||||
if(followedCount > SYMLOOP_MAX){
|
if(followedCount > SYMLOOP_MAX){
|
||||||
callback(new Errors.ELOOP(null, path));
|
callback(new Errors.ELOOP(null, path));
|
||||||
|
@ -251,14 +258,14 @@ function find_node(context, path, callback) {
|
||||||
data = normalize(data);
|
data = normalize(data);
|
||||||
parentPath = dirname(data);
|
parentPath = dirname(data);
|
||||||
name = basename(data);
|
name = basename(data);
|
||||||
if(ROOT_DIRECTORY_NAME == name) {
|
if(ROOT_DIRECTORY_NAME === name) {
|
||||||
context.getObject(SUPER_NODE_ID, read_root_directory_node);
|
context.getObject(SUPER_NODE_ID, read_root_directory_node);
|
||||||
} else {
|
} else {
|
||||||
find_node(context, parentPath, read_parent_directory_data);
|
find_node(context, parentPath, read_parent_directory_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ROOT_DIRECTORY_NAME == name) {
|
if(ROOT_DIRECTORY_NAME === name) {
|
||||||
context.getObject(SUPER_NODE_ID, read_root_directory_node);
|
context.getObject(SUPER_NODE_ID, read_root_directory_node);
|
||||||
} else {
|
} else {
|
||||||
find_node(context, parentPath, read_parent_directory_data);
|
find_node(context, parentPath, read_parent_directory_data);
|
||||||
|
@ -326,7 +333,11 @@ function ensure_root_directory(context, callback) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else {
|
} else {
|
||||||
Node.create({guid: context.guid, id: superNode.rnode, mode: MODE_DIRECTORY}, function(error, result) {
|
Node.create({
|
||||||
|
guid: context.guid,
|
||||||
|
id: superNode.rnode,
|
||||||
|
type: NODE_TYPE_DIRECTORY
|
||||||
|
}, function(error, result) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
return;
|
return;
|
||||||
|
@ -387,7 +398,10 @@ function make_directory(context, path, callback) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else {
|
} else {
|
||||||
parentDirectoryData = result;
|
parentDirectoryData = result;
|
||||||
Node.create({guid: context.guid, mode: MODE_DIRECTORY}, function(error, result) {
|
Node.create({
|
||||||
|
guid: context.guid,
|
||||||
|
type: NODE_TYPE_DIRECTORY
|
||||||
|
}, function(error, result) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
return;
|
return;
|
||||||
|
@ -421,7 +435,7 @@ function make_directory(context, path, callback) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else {
|
} else {
|
||||||
parentDirectoryData[name] = new DirectoryEntry(directoryNode.id, MODE_DIRECTORY);
|
parentDirectoryData[name] = new DirectoryEntry(directoryNode.id, NODE_TYPE_DIRECTORY);
|
||||||
context.putObject(parentDirectoryNode.data, parentDirectoryData, update_time);
|
context.putObject(parentDirectoryNode.data, parentDirectoryData, update_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -454,7 +468,7 @@ function remove_directory(context, path, callback) {
|
||||||
function check_if_node_exists(error, result) {
|
function check_if_node_exists(error, result) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else if(ROOT_DIRECTORY_NAME == name) {
|
} else if(ROOT_DIRECTORY_NAME === name) {
|
||||||
callback(new Errors.EBUSY(null, path));
|
callback(new Errors.EBUSY(null, path));
|
||||||
} else if(!_(result).has(name)) {
|
} else if(!_(result).has(name)) {
|
||||||
callback(new Errors.ENOENT(null, path));
|
callback(new Errors.ENOENT(null, path));
|
||||||
|
@ -468,7 +482,7 @@ function remove_directory(context, path, callback) {
|
||||||
function check_if_node_is_directory(error, result) {
|
function check_if_node_is_directory(error, result) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else if(result.mode != MODE_DIRECTORY) {
|
} else if(result.type !== NODE_TYPE_DIRECTORY) {
|
||||||
callback(new Errors.ENOTDIR(null, path));
|
callback(new Errors.ENOTDIR(null, path));
|
||||||
} else {
|
} else {
|
||||||
directoryNode = result;
|
directoryNode = result;
|
||||||
|
@ -535,7 +549,7 @@ function open_file(context, path, flags, callback) {
|
||||||
|
|
||||||
var followedCount = 0;
|
var followedCount = 0;
|
||||||
|
|
||||||
if(ROOT_DIRECTORY_NAME == name) {
|
if(ROOT_DIRECTORY_NAME === name) {
|
||||||
if(_(flags).contains(O_WRITE)) {
|
if(_(flags).contains(O_WRITE)) {
|
||||||
callback(new Errors.EISDIR('the named file is a directory and O_WRITE is set', path));
|
callback(new Errors.EISDIR('the named file is a directory and O_WRITE is set', path));
|
||||||
} else {
|
} else {
|
||||||
|
@ -548,7 +562,7 @@ function open_file(context, path, flags, callback) {
|
||||||
function read_directory_data(error, result) {
|
function read_directory_data(error, result) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else if(result.mode !== MODE_DIRECTORY) {
|
} else if(result.type !== NODE_TYPE_DIRECTORY) {
|
||||||
callback(new Errors.ENOENT(null, path));
|
callback(new Errors.ENOENT(null, path));
|
||||||
} else {
|
} else {
|
||||||
directoryNode = result;
|
directoryNode = result;
|
||||||
|
@ -566,7 +580,7 @@ function open_file(context, path, flags, callback) {
|
||||||
callback(new Errors.ENOENT('O_CREATE and O_EXCLUSIVE are set, and the named file exists', path));
|
callback(new Errors.ENOENT('O_CREATE and O_EXCLUSIVE are set, and the named file exists', path));
|
||||||
} else {
|
} else {
|
||||||
directoryEntry = directoryData[name];
|
directoryEntry = directoryData[name];
|
||||||
if(directoryEntry.type == MODE_DIRECTORY && _(flags).contains(O_WRITE)) {
|
if(directoryEntry.type === NODE_TYPE_DIRECTORY && _(flags).contains(O_WRITE)) {
|
||||||
callback(new Errors.EISDIR('the named file is a directory and O_WRITE is set', path));
|
callback(new Errors.EISDIR('the named file is a directory and O_WRITE is set', path));
|
||||||
} else {
|
} else {
|
||||||
context.getObject(directoryEntry.id, check_if_symbolic_link);
|
context.getObject(directoryEntry.id, check_if_symbolic_link);
|
||||||
|
@ -587,7 +601,7 @@ function open_file(context, path, flags, callback) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else {
|
} else {
|
||||||
var node = result;
|
var node = result;
|
||||||
if(node.mode == MODE_SYMBOLIC_LINK) {
|
if(node.type === NODE_TYPE_SYMBOLIC_LINK) {
|
||||||
followedCount++;
|
followedCount++;
|
||||||
if(followedCount > SYMLOOP_MAX){
|
if(followedCount > SYMLOOP_MAX){
|
||||||
callback(new Errors.ELOOP(null, path));
|
callback(new Errors.ELOOP(null, path));
|
||||||
|
@ -604,7 +618,7 @@ function open_file(context, path, flags, callback) {
|
||||||
data = normalize(data);
|
data = normalize(data);
|
||||||
parentPath = dirname(data);
|
parentPath = dirname(data);
|
||||||
name = basename(data);
|
name = basename(data);
|
||||||
if(ROOT_DIRECTORY_NAME == name) {
|
if(ROOT_DIRECTORY_NAME === name) {
|
||||||
if(_(flags).contains(O_WRITE)) {
|
if(_(flags).contains(O_WRITE)) {
|
||||||
callback(new Errors.EISDIR('the named file is a directory and O_WRITE is set', path));
|
callback(new Errors.EISDIR('the named file is a directory and O_WRITE is set', path));
|
||||||
} else {
|
} else {
|
||||||
|
@ -624,7 +638,10 @@ function open_file(context, path, flags, callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function write_file_node() {
|
function write_file_node() {
|
||||||
Node.create({guid: context.guid, mode: MODE_FILE}, function(error, result) {
|
Node.create({
|
||||||
|
guid: context.guid,
|
||||||
|
type: NODE_TYPE_FILE
|
||||||
|
}, function(error, result) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
return;
|
return;
|
||||||
|
@ -658,7 +675,7 @@ function open_file(context, path, flags, callback) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else {
|
} else {
|
||||||
directoryData[name] = new DirectoryEntry(fileNode.id, MODE_FILE);
|
directoryData[name] = new DirectoryEntry(fileNode.id, NODE_TYPE_FILE);
|
||||||
context.putObject(directoryNode.data, directoryData, update_time);
|
context.putObject(directoryNode.data, directoryData, update_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -813,7 +830,7 @@ function read_data(context, ofd, buffer, offset, length, position, callback) {
|
||||||
function read_file_data(error, result) {
|
function read_file_data(error, result) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else if(result.mode === 'DIRECTORY') {
|
} else if(result.type === NODE_TYPE_DIRECTORY) {
|
||||||
callback(new Errors.EISDIR('the named file is a directory', ofd.path));
|
callback(new Errors.EISDIR('the named file is a directory', ofd.path));
|
||||||
} else {
|
} else {
|
||||||
fileNode = result;
|
fileNode = result;
|
||||||
|
@ -842,7 +859,7 @@ function lstat_file(context, path, callback) {
|
||||||
var directoryNode;
|
var directoryNode;
|
||||||
var directoryData;
|
var directoryData;
|
||||||
|
|
||||||
if(ROOT_DIRECTORY_NAME == name) {
|
if(ROOT_DIRECTORY_NAME === name) {
|
||||||
find_node(context, path, callback);
|
find_node(context, path, callback);
|
||||||
} else {
|
} else {
|
||||||
find_node(context, parentPath, read_directory_data);
|
find_node(context, parentPath, read_directory_data);
|
||||||
|
@ -879,18 +896,20 @@ function link_node(context, oldpath, newpath, callback) {
|
||||||
newpath = normalize(newpath);
|
newpath = normalize(newpath);
|
||||||
var newname = basename(newpath);
|
var newname = basename(newpath);
|
||||||
var newParentPath = dirname(newpath);
|
var newParentPath = dirname(newpath);
|
||||||
|
var ctime = Date.now();
|
||||||
|
|
||||||
var oldDirectoryNode;
|
var oldDirectoryNode;
|
||||||
var oldDirectoryData;
|
var oldDirectoryData;
|
||||||
var newDirectoryNode;
|
var newDirectoryNode;
|
||||||
var newDirectoryData;
|
var newDirectoryData;
|
||||||
|
var fileNodeID;
|
||||||
var fileNode;
|
var fileNode;
|
||||||
|
|
||||||
function update_time(error) {
|
function update_time(error) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else {
|
} else {
|
||||||
update_node_times(context, newpath, fileNode, { ctime: Date.now() }, callback);
|
update_node_times(context, newpath, fileNode, { ctime: ctime }, callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -904,11 +923,11 @@ function link_node(context, oldpath, newpath, callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function read_directory_entry(error, result) {
|
function read_file_node(error, result) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else {
|
} else {
|
||||||
context.getObject(newDirectoryData[newname].id, update_file_node);
|
context.getObject(fileNodeID, update_file_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -921,7 +940,8 @@ function link_node(context, oldpath, newpath, callback) {
|
||||||
callback(new Errors.EEXIST('newpath resolves to an existing file', newname));
|
callback(new Errors.EEXIST('newpath resolves to an existing file', newname));
|
||||||
} else {
|
} else {
|
||||||
newDirectoryData[newname] = oldDirectoryData[oldname];
|
newDirectoryData[newname] = oldDirectoryData[oldname];
|
||||||
context.putObject(newDirectoryNode.data, newDirectoryData, read_directory_entry);
|
fileNodeID = newDirectoryData[newname].id;
|
||||||
|
context.putObject(newDirectoryNode.data, newDirectoryData, read_file_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -942,7 +962,7 @@ function link_node(context, oldpath, newpath, callback) {
|
||||||
oldDirectoryData = result;
|
oldDirectoryData = result;
|
||||||
if(!_(oldDirectoryData).has(oldname)) {
|
if(!_(oldDirectoryData).has(oldname)) {
|
||||||
callback(new Errors.ENOENT('a component of either path prefix does not exist', oldname));
|
callback(new Errors.ENOENT('a component of either path prefix does not exist', oldname));
|
||||||
} else if(oldDirectoryData[oldname].type === 'DIRECTORY') {
|
} else if(oldDirectoryData[oldname].type === NODE_TYPE_DIRECTORY) {
|
||||||
callback(new Errors.EPERM('oldpath refers to a directory'));
|
callback(new Errors.EPERM('oldpath refers to a directory'));
|
||||||
} else {
|
} else {
|
||||||
find_node(context, newParentPath, read_new_directory_data);
|
find_node(context, newParentPath, read_new_directory_data);
|
||||||
|
@ -1010,7 +1030,7 @@ function unlink_node(context, path, callback) {
|
||||||
function check_if_node_is_directory(error, result) {
|
function check_if_node_is_directory(error, result) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else if(result.mode === 'DIRECTORY') {
|
} else if(result.type === NODE_TYPE_DIRECTORY) {
|
||||||
callback(new Errors.EPERM('unlink not permitted on directories', name));
|
callback(new Errors.EPERM('unlink not permitted on directories', name));
|
||||||
} else {
|
} else {
|
||||||
update_file_node(null, result);
|
update_file_node(null, result);
|
||||||
|
@ -1062,7 +1082,7 @@ function read_directory(context, path, callback) {
|
||||||
function read_directory_data(error, result) {
|
function read_directory_data(error, result) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else if(result.mode !== MODE_DIRECTORY) {
|
} else if(result.type !== NODE_TYPE_DIRECTORY) {
|
||||||
callback(new Errors.ENOTDIR(null, path));
|
callback(new Errors.ENOTDIR(null, path));
|
||||||
} else {
|
} else {
|
||||||
directoryNode = result;
|
directoryNode = result;
|
||||||
|
@ -1082,7 +1102,7 @@ function make_symbolic_link(context, srcpath, dstpath, callback) {
|
||||||
var directoryData;
|
var directoryData;
|
||||||
var fileNode;
|
var fileNode;
|
||||||
|
|
||||||
if(ROOT_DIRECTORY_NAME == name) {
|
if(ROOT_DIRECTORY_NAME === name) {
|
||||||
callback(new Errors.EEXIST(null, name));
|
callback(new Errors.EEXIST(null, name));
|
||||||
} else {
|
} else {
|
||||||
find_node(context, parentPath, read_directory_data);
|
find_node(context, parentPath, read_directory_data);
|
||||||
|
@ -1111,15 +1131,27 @@ function make_symbolic_link(context, srcpath, dstpath, callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function write_file_node() {
|
function write_file_node() {
|
||||||
Node.create({guid: context.guid, mode: MODE_SYMBOLIC_LINK}, function(error, result) {
|
Node.create({
|
||||||
|
guid: context.guid,
|
||||||
|
type: NODE_TYPE_SYMBOLIC_LINK
|
||||||
|
}, function(error, result) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fileNode = result;
|
fileNode = result;
|
||||||
fileNode.nlinks += 1;
|
fileNode.nlinks += 1;
|
||||||
|
|
||||||
|
// If the srcpath isn't absolute, resolve it relative to the dstpath
|
||||||
|
// but store both versions, since we'll use the relative one in readlink().
|
||||||
|
if(!isAbsolutePath(srcpath)) {
|
||||||
|
fileNode.symlink_relpath = srcpath;
|
||||||
|
srcpath = Path.resolve(parentPath, srcpath);
|
||||||
|
}
|
||||||
|
|
||||||
fileNode.size = srcpath.length;
|
fileNode.size = srcpath.length;
|
||||||
fileNode.data = srcpath;
|
fileNode.data = srcpath;
|
||||||
|
|
||||||
context.putObject(fileNode.id, fileNode, update_directory_data);
|
context.putObject(fileNode.id, fileNode, update_directory_data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1137,7 +1169,7 @@ function make_symbolic_link(context, srcpath, dstpath, callback) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else {
|
} else {
|
||||||
directoryData[name] = new DirectoryEntry(fileNode.id, MODE_SYMBOLIC_LINK);
|
directoryData[name] = new DirectoryEntry(fileNode.id, NODE_TYPE_SYMBOLIC_LINK);
|
||||||
context.putObject(directoryNode.data, directoryData, update_time);
|
context.putObject(directoryNode.data, directoryData, update_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1175,14 +1207,17 @@ function read_link(context, path, callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_if_symbolic(error, result) {
|
function check_if_symbolic(error, fileNode) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else {
|
} else {
|
||||||
if(result.mode != MODE_SYMBOLIC_LINK) {
|
if(fileNode.type !== NODE_TYPE_SYMBOLIC_LINK) {
|
||||||
callback(new Errors.EINVAL('path not a symbolic link', path));
|
callback(new Errors.EINVAL('path not a symbolic link', path));
|
||||||
} else {
|
} else {
|
||||||
callback(null, result.data);
|
// If we were originally given a relative path, return that now vs. the
|
||||||
|
// absolute path we've generated and use elsewhere internally.
|
||||||
|
var target = fileNode.symlink_relpath ? fileNode.symlink_relpath : fileNode.data;
|
||||||
|
callback(null, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1196,7 +1231,7 @@ function truncate_file(context, path, length, callback) {
|
||||||
function read_file_data (error, node) {
|
function read_file_data (error, node) {
|
||||||
if (error) {
|
if (error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else if(node.mode == MODE_DIRECTORY ) {
|
} else if(node.type === NODE_TYPE_DIRECTORY ) {
|
||||||
callback(new Errors.EISDIR(null, path));
|
callback(new Errors.EISDIR(null, path));
|
||||||
} else{
|
} else{
|
||||||
fileNode = node;
|
fileNode = node;
|
||||||
|
@ -1252,7 +1287,7 @@ function ftruncate_file(context, ofd, length, callback) {
|
||||||
function read_file_data (error, node) {
|
function read_file_data (error, node) {
|
||||||
if (error) {
|
if (error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else if(node.mode == MODE_DIRECTORY ) {
|
} else if(node.type === NODE_TYPE_DIRECTORY ) {
|
||||||
callback(new Errors.EISDIR());
|
callback(new Errors.EISDIR());
|
||||||
} else{
|
} else{
|
||||||
fileNode = node;
|
fileNode = node;
|
||||||
|
@ -1315,7 +1350,7 @@ function utimes_file(context, path, atime, mtime, callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof atime != 'number' || typeof mtime != 'number') {
|
if (typeof atime !== 'number' || typeof mtime !== 'number') {
|
||||||
callback(new Errors.EINVAL('atime and mtime must be number', path));
|
callback(new Errors.EINVAL('atime and mtime must be number', path));
|
||||||
}
|
}
|
||||||
else if (atime < 0 || mtime < 0) {
|
else if (atime < 0 || mtime < 0) {
|
||||||
|
@ -1336,7 +1371,7 @@ function futimes_file(context, ofd, atime, mtime, callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof atime != 'number' || typeof mtime != 'number') {
|
if (typeof atime !== 'number' || typeof mtime !== 'number') {
|
||||||
callback(new Errors.EINVAL('atime and mtime must be a number'));
|
callback(new Errors.EINVAL('atime and mtime must be a number'));
|
||||||
}
|
}
|
||||||
else if (atime < 0 || mtime < 0) {
|
else if (atime < 0 || mtime < 0) {
|
||||||
|
@ -1357,7 +1392,7 @@ function setxattr_file(context, path, name, value, flag, callback) {
|
||||||
set_extended_attribute(context, path, node, name, value, flag, callback);
|
set_extended_attribute(context, path, node, name, value, flag, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof name != 'string') {
|
if (typeof name !== 'string') {
|
||||||
callback(new Errors.EINVAL('attribute name must be a string', path));
|
callback(new Errors.EINVAL('attribute name must be a string', path));
|
||||||
}
|
}
|
||||||
else if (!name) {
|
else if (!name) {
|
||||||
|
@ -1413,7 +1448,7 @@ function getxattr_file (context, path, name, callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof name != 'string') {
|
if (typeof name !== 'string') {
|
||||||
callback(new Errors.EINVAL('attribute name must be a string', path));
|
callback(new Errors.EINVAL('attribute name must be a string', path));
|
||||||
}
|
}
|
||||||
else if (!name) {
|
else if (!name) {
|
||||||
|
@ -1441,7 +1476,7 @@ function fgetxattr_file (context, ofd, name, callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof name != 'string') {
|
if (typeof name !== 'string') {
|
||||||
callback(new Errors.EINVAL());
|
callback(new Errors.EINVAL());
|
||||||
}
|
}
|
||||||
else if (!name) {
|
else if (!name) {
|
||||||
|
@ -1516,7 +1551,7 @@ function fremovexattr_file (context, ofd, name, callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof name != 'string') {
|
if (typeof name !== 'string') {
|
||||||
callback(new Errors.EINVAL('attribute name must be a string'));
|
callback(new Errors.EINVAL('attribute name must be a string'));
|
||||||
}
|
}
|
||||||
else if (!name) {
|
else if (!name) {
|
||||||
|
@ -1545,14 +1580,19 @@ function validate_file_options(options, enc, fileMode){
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
function pathCheck(path, callback) {
|
function pathCheck(path, allowRelative, callback) {
|
||||||
var err;
|
var err;
|
||||||
|
|
||||||
|
if(typeof allowRelative === 'function') {
|
||||||
|
callback = allowRelative;
|
||||||
|
allowRelative = false;
|
||||||
|
}
|
||||||
|
|
||||||
if(!path) {
|
if(!path) {
|
||||||
err = new Errors.EINVAL('Path must be a string', path);
|
err = new Errors.EINVAL('Path must be a string', path);
|
||||||
} else if(isNullPath(path)) {
|
} else if(isNullPath(path)) {
|
||||||
err = new Errors.EINVAL('Path must be a string without null bytes.', path);
|
err = new Errors.EINVAL('Path must be a string without null bytes.', path);
|
||||||
} else if(!isAbsolutePath(path)) {
|
} else if(!allowRelative && !isAbsolutePath(path)) {
|
||||||
err = new Errors.EINVAL('Path must be absolute.', path);
|
err = new Errors.EINVAL('Path must be absolute.', path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1565,8 +1605,22 @@ function pathCheck(path, callback) {
|
||||||
|
|
||||||
|
|
||||||
function open(fs, context, path, flags, mode, callback) {
|
function open(fs, context, path, flags, mode, callback) {
|
||||||
// NOTE: we support the same signature as node with a `mode` arg,
|
/**
|
||||||
// but ignore it.
|
* NOTE: we support the same signature as node with a `mode` arg,
|
||||||
|
* but ignore it. We need to add it. Here is what node.js does:
|
||||||
|
* function open(path, flags, mode, callback) {
|
||||||
|
* path = getPathFromURL(path);
|
||||||
|
* validatePath(path);
|
||||||
|
* const flagsNumber = stringToFlags(flags);
|
||||||
|
* if (arguments.length < 4) {
|
||||||
|
* callback = makeCallback(mode);
|
||||||
|
* mode = 0o666;
|
||||||
|
* } else {
|
||||||
|
* mode = validateAndMaskMode(mode, 'mode', 0o666);
|
||||||
|
* callback = makeCallback(callback);
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
callback = arguments[arguments.length - 1];
|
callback = arguments[arguments.length - 1];
|
||||||
if(!pathCheck(path, callback)) return;
|
if(!pathCheck(path, callback)) return;
|
||||||
|
|
||||||
|
@ -1603,14 +1657,20 @@ function close(fs, context, fd, callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mknod(fs, context, path, mode, callback) {
|
function mknod(fs, context, path, type, callback) {
|
||||||
if(!pathCheck(path, callback)) return;
|
if(!pathCheck(path, callback)) return;
|
||||||
make_node(context, path, mode, callback);
|
make_node(context, path, type, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mkdir(fs, context, path, mode, callback) {
|
function mkdir(fs, context, path, mode, callback) {
|
||||||
// NOTE: we support passing a mode arg, but we ignore it internally for now.
|
if (arguments.length < 5) {
|
||||||
callback = arguments[arguments.length - 1];
|
callback = mode;
|
||||||
|
mode = FULL_READ_WRITE_EXEC_PERMISSIONS;
|
||||||
|
} else {
|
||||||
|
mode = validateAndMaskMode(mode, FULL_READ_WRITE_EXEC_PERMISSIONS, callback);
|
||||||
|
if(!mode) return;
|
||||||
|
}
|
||||||
|
|
||||||
if(!pathCheck(path, callback)) return;
|
if(!pathCheck(path, callback)) return;
|
||||||
make_directory(context, path, callback);
|
make_directory(context, path, callback);
|
||||||
}
|
}
|
||||||
|
@ -1627,7 +1687,7 @@ function stat(fs, context, path, callback) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else {
|
} else {
|
||||||
var stats = new Stats(result, fs.name);
|
var stats = new Stats(path, result, fs.name);
|
||||||
callback(null, stats);
|
callback(null, stats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1640,7 +1700,7 @@ function fstat(fs, context, fd, callback) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else {
|
} else {
|
||||||
var stats = new Stats(result, fs.name);
|
var stats = new Stats(ofd.path, result, fs.name);
|
||||||
callback(null, stats);
|
callback(null, stats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1713,7 +1773,7 @@ function readFile(fs, context, path, options, callback) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
var stats = new Stats(fstatResult, fs.name);
|
var stats = new Stats(ofd.path, fstatResult, fs.name);
|
||||||
|
|
||||||
if(stats.isDirectory()) {
|
if(stats.isDirectory()) {
|
||||||
cleanup();
|
cleanup();
|
||||||
|
@ -1841,6 +1901,121 @@ function exists(fs, context, path, callback) {
|
||||||
stat(fs, context, path, cb);
|
stat(fs, context, path, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Based on https://github.com/nodejs/node/blob/c700cc42da9cf73af9fec2098520a6c0a631d901/lib/internal/validators.js#L21
|
||||||
|
var octalReg = /^[0-7]+$/;
|
||||||
|
var modeDesc = 'must be a 32-bit unsigned integer or an octal string';
|
||||||
|
function isUint32(value) {
|
||||||
|
return value === (value >>> 0);
|
||||||
|
}
|
||||||
|
// Validator for mode_t (the S_* constants). Valid numbers or octal strings
|
||||||
|
// will be masked with 0o777 to be consistent with the behavior in POSIX APIs.
|
||||||
|
function validateAndMaskMode(value, def, callback) {
|
||||||
|
if(typeof def === 'function') {
|
||||||
|
callback = def;
|
||||||
|
def = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUint32(value)) {
|
||||||
|
return value & FULL_READ_WRITE_EXEC_PERMISSIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
if (!Number.isInteger(value)) {
|
||||||
|
callback(new Errors.EINVAL('mode not a valid an integer value', value));
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// 2 ** 32 === 4294967296
|
||||||
|
callback(new Errors.EINVAL('mode not a valid an integer value', value));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
if (!octalReg.test(value)) {
|
||||||
|
callback(new Errors.EINVAL('mode not a valid octal string', value));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var parsed = parseInt(value, 8);
|
||||||
|
return parsed & FULL_READ_WRITE_EXEC_PERMISSIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(BridgeAR): Only return `def` in case `value === null`
|
||||||
|
if (def !== undefined) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(new Errors.EINVAL('mode not valid', value));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function chmod_file(context, path, mode, callback) {
|
||||||
|
path = normalize(path);
|
||||||
|
|
||||||
|
function update_mode(error, node) {
|
||||||
|
if (error) {
|
||||||
|
callback(error);
|
||||||
|
} else {
|
||||||
|
Node.setMode(mode, node);
|
||||||
|
update_node_times(context, path, node, { mtime: Date.now() }, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof mode !== 'number') {
|
||||||
|
callback(new Errors.EINVAL('mode must be number', path));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
find_node(context, path, update_mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function fchmod_file(context, ofd, mode, callback) {
|
||||||
|
function update_mode(error, node) {
|
||||||
|
if (error) {
|
||||||
|
callback(error);
|
||||||
|
} else {
|
||||||
|
node.mode = mode;
|
||||||
|
update_node_times(context, ofd.path, node, { mtime: Date.now() }, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof mode !== 'number') {
|
||||||
|
callback(new Errors.EINVAL('mode must be a number'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ofd.getNode(context, update_mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function chown_file(context, path, uid, gid, callback) {
|
||||||
|
path = normalize(path);
|
||||||
|
|
||||||
|
function update_owner(error, node) {
|
||||||
|
if (error) {
|
||||||
|
callback(error);
|
||||||
|
} else {
|
||||||
|
node.uid = uid;
|
||||||
|
node.gid = gid;
|
||||||
|
update_node_times(context, path, node, { mtime: Date.now() }, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
find_node(context, path, update_owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fchown_file(context, ofd, uid, gid, callback) {
|
||||||
|
function update_owner(error, node) {
|
||||||
|
if (error) {
|
||||||
|
callback(error);
|
||||||
|
} else {
|
||||||
|
node.uid = uid;
|
||||||
|
node.gid = gid;
|
||||||
|
update_node_times(context, ofd.path, node, { mtime: Date.now() }, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ofd.getNode(context, update_owner);
|
||||||
|
}
|
||||||
|
|
||||||
function getxattr(fs, context, path, name, callback) {
|
function getxattr(fs, context, path, name, callback) {
|
||||||
if (!pathCheck(path, callback)) return;
|
if (!pathCheck(path, callback)) return;
|
||||||
getxattr_file(context, path, name, callback);
|
getxattr_file(context, path, name, callback);
|
||||||
|
@ -1972,6 +2147,58 @@ function futimes(fs, context, fd, atime, mtime, callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function chmod(fs, context, path, mode, callback) {
|
||||||
|
if(!pathCheck(path, callback)) return;
|
||||||
|
mode = validateAndMaskMode(mode, 'mode');
|
||||||
|
if(!mode) return;
|
||||||
|
|
||||||
|
chmod_file(context, path, mode, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fchmod(fs, context, fd, mode, callback) {
|
||||||
|
mode = validateAndMaskMode(mode, 'mode');
|
||||||
|
if(!mode) return;
|
||||||
|
|
||||||
|
var ofd = fs.openFiles[fd];
|
||||||
|
if(!ofd) {
|
||||||
|
callback(new Errors.EBADF());
|
||||||
|
} else if(!_(ofd.flags).contains(O_WRITE)) {
|
||||||
|
callback(new Errors.EBADF('descriptor does not permit writing'));
|
||||||
|
} else {
|
||||||
|
fchmod_file(context, ofd, mode, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function chown(fs, context, path, uid, gid, callback) {
|
||||||
|
if(!pathCheck(path, callback)) return;
|
||||||
|
if(!isUint32(uid)) {
|
||||||
|
return callback(new Errors.EINVAL('uid must be a valid integer', uid));
|
||||||
|
}
|
||||||
|
if(!isUint32(gid)) {
|
||||||
|
return callback(new Errors.EINVAL('gid must be a valid integer', gid));
|
||||||
|
}
|
||||||
|
|
||||||
|
chown_file(context, path, uid, gid, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fchown(fs, context, fd, uid, gid, callback) {
|
||||||
|
if(!isUint32(uid)) {
|
||||||
|
return callback(new Errors.EINVAL('uid must be a valid integer', uid));
|
||||||
|
}
|
||||||
|
if(!isUint32(gid)) {
|
||||||
|
return callback(new Errors.EINVAL('gid must be a valid integer', gid));
|
||||||
|
}
|
||||||
|
|
||||||
|
var ofd = fs.openFiles[fd];
|
||||||
|
if(!ofd) {
|
||||||
|
callback(new Errors.EBADF());
|
||||||
|
} else if(!_(ofd.flags).contains(O_WRITE)) {
|
||||||
|
callback(new Errors.EBADF('descriptor does not permit writing'));
|
||||||
|
} else {
|
||||||
|
fchown_file(context, ofd, uid, gid, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function rename(fs, context, oldpath, newpath, callback) {
|
function rename(fs, context, oldpath, newpath, callback) {
|
||||||
if(!pathCheck(oldpath, callback)) return;
|
if(!pathCheck(oldpath, callback)) return;
|
||||||
if(!pathCheck(newpath, callback)) return;
|
if(!pathCheck(newpath, callback)) return;
|
||||||
|
@ -1985,12 +2212,15 @@ function rename(fs, context, oldpath, newpath, callback) {
|
||||||
var newName = Path.basename(newpath);
|
var newName = Path.basename(newpath);
|
||||||
var oldParentDirectory, oldParentData;
|
var oldParentDirectory, oldParentData;
|
||||||
var newParentDirectory, newParentData;
|
var newParentDirectory, newParentData;
|
||||||
|
var ctime = Date.now();
|
||||||
|
var fileNode;
|
||||||
|
|
||||||
function update_times(error, newNode) {
|
function update_times(error, result) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else {
|
} else {
|
||||||
update_node_times(context, newpath, newNode, { ctime: Date.now() }, callback);
|
fileNode = result;
|
||||||
|
update_node_times(context, newpath, fileNode, { ctime: ctime }, callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2074,7 +2304,7 @@ function rename(fs, context, oldpath, newpath, callback) {
|
||||||
function check_node_type(error, node) {
|
function check_node_type(error, node) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else if(node.mode === 'DIRECTORY') {
|
} else if(node.type === NODE_TYPE_DIRECTORY) {
|
||||||
find_node(context, oldParentPath, read_parent_directory_data);
|
find_node(context, oldParentPath, read_parent_directory_data);
|
||||||
} else {
|
} else {
|
||||||
link_node(context, oldpath, newpath, unlink_old_file);
|
link_node(context, oldpath, newpath, unlink_old_file);
|
||||||
|
@ -2087,8 +2317,13 @@ function rename(fs, context, oldpath, newpath, callback) {
|
||||||
function symlink(fs, context, srcpath, dstpath, type, callback) {
|
function symlink(fs, context, srcpath, dstpath, type, callback) {
|
||||||
// NOTE: we support passing the `type` arg, but ignore it.
|
// NOTE: we support passing the `type` arg, but ignore it.
|
||||||
callback = arguments[arguments.length - 1];
|
callback = arguments[arguments.length - 1];
|
||||||
if(!pathCheck(srcpath, callback)) return;
|
|
||||||
|
// Special Case: allow srcpath to be relative, which we normally don't permit.
|
||||||
|
// If the srcpath is relative, we assume it's relative to the dirpath of
|
||||||
|
// dstpath.
|
||||||
|
if(!pathCheck(srcpath, true, callback)) return;
|
||||||
if(!pathCheck(dstpath, callback)) return;
|
if(!pathCheck(dstpath, callback)) return;
|
||||||
|
|
||||||
make_symbolic_link(context, srcpath, dstpath, callback);
|
make_symbolic_link(context, srcpath, dstpath, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2104,7 +2339,7 @@ function lstat(fs, context, path, callback) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
} else {
|
} else {
|
||||||
var stats = new Stats(result, fs.name);
|
var stats = new Stats(path, result, fs.name);
|
||||||
callback(null, stats);
|
callback(null, stats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2139,6 +2374,10 @@ function ftruncate(fs, context, fd, length, callback) {
|
||||||
module.exports = {
|
module.exports = {
|
||||||
ensureRootDirectory: ensure_root_directory,
|
ensureRootDirectory: ensure_root_directory,
|
||||||
open: open,
|
open: open,
|
||||||
|
chmod: chmod,
|
||||||
|
fchmod: fchmod,
|
||||||
|
chown: chown,
|
||||||
|
fchown: fchown,
|
||||||
close: close,
|
close: close,
|
||||||
mknod: mknod,
|
mknod: mknod,
|
||||||
mkdir: mkdir,
|
mkdir: mkdir,
|
||||||
|
|
|
@ -94,6 +94,9 @@ function FileSystem(options, callback) {
|
||||||
fs.stdout = STDOUT;
|
fs.stdout = STDOUT;
|
||||||
fs.stderr = STDERR;
|
fs.stderr = STDERR;
|
||||||
|
|
||||||
|
// Expose Node's fs.constants to users
|
||||||
|
fs.constants = Constants.fsConstants;
|
||||||
|
|
||||||
// Expose Shell constructor
|
// Expose Shell constructor
|
||||||
this.Shell = Shell.bind(undefined, this);
|
this.Shell = Shell.bind(undefined, this);
|
||||||
|
|
||||||
|
@ -268,6 +271,10 @@ FileSystem.providers = providers;
|
||||||
*/
|
*/
|
||||||
[
|
[
|
||||||
'open',
|
'open',
|
||||||
|
'chmod',
|
||||||
|
'fchmod',
|
||||||
|
'chown',
|
||||||
|
'fchown',
|
||||||
'close',
|
'close',
|
||||||
'mknod',
|
'mknod',
|
||||||
'mkdir',
|
'mkdir',
|
||||||
|
|
44
src/node.js
44
src/node.js
|
@ -1,10 +1,36 @@
|
||||||
var MODE_FILE = require('./constants.js').MODE_FILE;
|
var NODE_TYPE_FILE = require('./constants.js').NODE_TYPE_FILE;
|
||||||
|
var NODE_TYPE_DIRECTORY = require('./constants.js').NODE_TYPE_DIRECTORY;
|
||||||
|
var NODE_TYPE_SYMBOLIC_LINK = require('./constants.js').NODE_TYPE_SYMBOLIC_LINK;
|
||||||
|
var NODE_TYPE_META = require('./constants.js').NODE_TYPE_META;
|
||||||
|
|
||||||
|
var ROOT_DIRECTORY_NAME = require('./constants.js').ROOT_DIRECTORY_NAME;
|
||||||
|
|
||||||
|
var S_IFREG = require('./constants.js').S_IFREG;
|
||||||
|
var S_IFDIR = require('./constants.js').S_IFDIR;
|
||||||
|
var S_IFLNK = require('./constants.js').S_IFLNK;
|
||||||
|
|
||||||
|
var DEFAULT_FILE_PERMISSIONS = require('./constants.js').DEFAULT_FILE_PERMISSIONS;
|
||||||
|
var DEFAULT_DIR_PERMISSIONS = require('./constants.js').DEFAULT_DIR_PERMISSIONS;
|
||||||
|
|
||||||
|
function getMode(type, mode) {
|
||||||
|
switch(type) {
|
||||||
|
case NODE_TYPE_DIRECTORY:
|
||||||
|
return (mode || DEFAULT_DIR_PERMISSIONS) | S_IFDIR;
|
||||||
|
case NODE_TYPE_SYMBOLIC_LINK:
|
||||||
|
return (mode || DEFAULT_FILE_PERMISSIONS) | S_IFLNK;
|
||||||
|
/* jshint -W086 */
|
||||||
|
case NODE_TYPE_FILE:
|
||||||
|
// falls through
|
||||||
|
default:
|
||||||
|
return (mode || DEFAULT_FILE_PERMISSIONS) | S_IFREG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Node(options) {
|
function Node(options) {
|
||||||
var now = Date.now();
|
var now = Date.now();
|
||||||
|
|
||||||
this.id = options.id;
|
this.id = options.id;
|
||||||
this.mode = options.mode || MODE_FILE; // node type (file, directory, etc)
|
this.type = options.type || NODE_TYPE_FILE; // node type (file, directory, etc)
|
||||||
this.size = options.size || 0; // size (bytes for files, entries for directories)
|
this.size = options.size || 0; // size (bytes for files, entries for directories)
|
||||||
this.atime = options.atime || now; // access time (will mirror ctime after creation)
|
this.atime = options.atime || now; // access time (will mirror ctime after creation)
|
||||||
this.ctime = options.ctime || now; // creation/change time
|
this.ctime = options.ctime || now; // creation/change time
|
||||||
|
@ -12,10 +38,13 @@ function Node(options) {
|
||||||
this.flags = options.flags || []; // file flags
|
this.flags = options.flags || []; // file flags
|
||||||
this.xattrs = options.xattrs || {}; // extended attributes
|
this.xattrs = options.xattrs || {}; // extended attributes
|
||||||
this.nlinks = options.nlinks || 0; // links count
|
this.nlinks = options.nlinks || 0; // links count
|
||||||
this.version = options.version || 0; // node version
|
|
||||||
this.blksize = undefined; // block size
|
|
||||||
this.nblocks = 1; // blocks count
|
|
||||||
this.data = options.data; // id for data object
|
this.data = options.data; // id for data object
|
||||||
|
this.version = options.version || 1;
|
||||||
|
|
||||||
|
// permissions and flags
|
||||||
|
this.mode = options.mode || (getMode(this.type));
|
||||||
|
this.uid = options.uid || 0x0; // owner name
|
||||||
|
this.gid = options.gid || 0x0; // group name
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the options object has an id on property,
|
// Make sure the options object has an id on property,
|
||||||
|
@ -50,4 +79,9 @@ Node.create = function(options, callback) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Update the node's mode (permissions), taking file type bits into account.
|
||||||
|
Node.setMode = function(mode, node) {
|
||||||
|
node.mode = getMode(node.type, mode);
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = Node;
|
module.exports = Node;
|
||||||
|
|
|
@ -89,12 +89,7 @@ IndexedDBContext.prototype.putObject = function(key, value, callback) {
|
||||||
this._put(key, value, callback);
|
this._put(key, value, callback);
|
||||||
};
|
};
|
||||||
IndexedDBContext.prototype.putBuffer = function(key, uint8BackedBuffer, callback) {
|
IndexedDBContext.prototype.putBuffer = function(key, uint8BackedBuffer, callback) {
|
||||||
var buf;
|
var buf = uint8BackedBuffer.buffer;
|
||||||
if(!Buffer._useTypedArrays) { // workaround for fxos 1.3
|
|
||||||
buf = uint8BackedBuffer.toArrayBuffer();
|
|
||||||
} else {
|
|
||||||
buf = uint8BackedBuffer.buffer;
|
|
||||||
}
|
|
||||||
this._put(key, buf, callback);
|
this._put(key, buf, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -233,16 +233,10 @@ Shell.prototype.ls = function(dir, options, callback) {
|
||||||
callback(error);
|
callback(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var entry = {
|
var entry = stats;
|
||||||
path: Path.basename(name),
|
|
||||||
links: stats.nlinks,
|
|
||||||
size: stats.size,
|
|
||||||
modified: stats.mtime,
|
|
||||||
type: stats.type
|
|
||||||
};
|
|
||||||
|
|
||||||
if(options.recursive && stats.type === 'DIRECTORY') {
|
if(options.recursive && stats.type === 'DIRECTORY') {
|
||||||
list(Path.join(pathname, entry.path), function(error, items) {
|
list(Path.join(pathname, entry.name), function(error, items) {
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
return;
|
return;
|
||||||
|
|
18
src/stats.js
18
src/stats.js
|
@ -1,26 +1,32 @@
|
||||||
var Constants = require('./constants.js');
|
var Constants = require('./constants.js');
|
||||||
|
var Path = require('./path.js');
|
||||||
|
|
||||||
function Stats(fileNode, devName) {
|
function Stats(path, fileNode, devName) {
|
||||||
this.node = fileNode.id;
|
|
||||||
this.dev = devName;
|
this.dev = devName;
|
||||||
|
this.node = fileNode.id;
|
||||||
|
this.type = fileNode.type;
|
||||||
this.size = fileNode.size;
|
this.size = fileNode.size;
|
||||||
this.nlinks = fileNode.nlinks;
|
this.nlinks = fileNode.nlinks;
|
||||||
this.atime = fileNode.atime;
|
this.atime = fileNode.atime;
|
||||||
this.mtime = fileNode.mtime;
|
this.mtime = fileNode.mtime;
|
||||||
this.ctime = fileNode.ctime;
|
this.ctime = fileNode.ctime;
|
||||||
this.type = fileNode.mode;
|
this.version = fileNode.version;
|
||||||
|
this.mode = fileNode.mode;
|
||||||
|
this.uid = fileNode.uid;
|
||||||
|
this.gid = fileNode.gid;
|
||||||
|
this.name = Path.basename(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Stats.prototype.isFile = function() {
|
Stats.prototype.isFile = function() {
|
||||||
return this.type === Constants.MODE_FILE;
|
return this.type === Constants.NODE_TYPE_FILE;
|
||||||
};
|
};
|
||||||
|
|
||||||
Stats.prototype.isDirectory = function() {
|
Stats.prototype.isDirectory = function() {
|
||||||
return this.type === Constants.MODE_DIRECTORY;
|
return this.type === Constants.NODE_TYPE_DIRECTORY;
|
||||||
};
|
};
|
||||||
|
|
||||||
Stats.prototype.isSymbolicLink = function() {
|
Stats.prototype.isSymbolicLink = function() {
|
||||||
return this.type === Constants.MODE_SYMBOLIC_LINK;
|
return this.type === Constants.NODE_TYPE_SYMBOLIC_LINK;
|
||||||
};
|
};
|
||||||
|
|
||||||
// These will always be false in Filer.
|
// These will always be false in Filer.
|
||||||
|
|
|
@ -4,7 +4,7 @@ function SuperNode(options) {
|
||||||
var now = Date.now();
|
var now = Date.now();
|
||||||
|
|
||||||
this.id = Constants.SUPER_NODE_ID;
|
this.id = Constants.SUPER_NODE_ID;
|
||||||
this.mode = Constants.MODE_META;
|
this.type = Constants.NODE_TYPE_META;
|
||||||
this.atime = options.atime || now;
|
this.atime = options.atime || now;
|
||||||
this.ctime = options.ctime || now;
|
this.ctime = options.ctime || now;
|
||||||
this.mtime = options.mtime || now;
|
this.mtime = options.mtime || now;
|
||||||
|
|
|
@ -39,6 +39,8 @@ require("./spec/time-flags.spec");
|
||||||
require("./spec/fs.watch.spec");
|
require("./spec/fs.watch.spec");
|
||||||
require("./spec/errors.spec");
|
require("./spec/errors.spec");
|
||||||
require("./spec/fs.shell.spec");
|
require("./spec/fs.shell.spec");
|
||||||
|
require("./spec/fs.chmod.spec");
|
||||||
|
require("./spec/fs.chown.spec")
|
||||||
|
|
||||||
// Filer.FileSystem.providers.*
|
// Filer.FileSystem.providers.*
|
||||||
require("./spec/providers/providers.spec");
|
require("./spec/providers/providers.spec");
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
var Filer = require('../..');
|
||||||
|
var util = require('../lib/test-utils.js');
|
||||||
|
var expect = require('chai').expect;
|
||||||
|
|
||||||
|
describe('fs.chmod, fs.fchmod', function() {
|
||||||
|
beforeEach(util.setup);
|
||||||
|
afterEach(util.cleanup);
|
||||||
|
|
||||||
|
it('should be functions', function() {
|
||||||
|
var fs = util.fs();
|
||||||
|
expect(typeof fs.chmod).to.equal('function');
|
||||||
|
expect(typeof fs.fchmod).to.equal('function');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should automatically set mode=755 for a directory', function(done) {
|
||||||
|
var fs = util.fs();
|
||||||
|
|
||||||
|
fs.mkdir('/dir', function(err) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
fs.stat('/dir', function(err, stats) {
|
||||||
|
if(err) throw err;
|
||||||
|
expect(stats.mode & 0o755).to.equal(0o755);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should automatically set mode=644 for a file', function(done) {
|
||||||
|
var fs = util.fs();
|
||||||
|
|
||||||
|
fs.open('/file', 'w', function(err, fd) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
fs.fstat(fd, function(err, stats) {
|
||||||
|
if(err) throw err;
|
||||||
|
expect(stats.mode & 0o644).to.equal(0o644);
|
||||||
|
fs.close(fd, done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow for updating mode of a given file', function(done) {
|
||||||
|
var fs = util.fs();
|
||||||
|
|
||||||
|
fs.open('/file', 'w', function(err, fd) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
fs.fchmod(fd, 0o777, function(err) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
fs.fstat(fd, function(err, stats) {
|
||||||
|
if(err) throw err;
|
||||||
|
expect(stats.mode & 0o777).to.equal(0o777);
|
||||||
|
|
||||||
|
fs.close(fd, function(err) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
fs.chmod('/file', 0o444, function(err) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
fs.stat('/file', function(err, stats) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
expect(stats.mode & 0o444).to.equal(0o444);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,65 @@
|
||||||
|
var Filer = require('../..');
|
||||||
|
var util = require('../lib/test-utils.js');
|
||||||
|
var expect = require('chai').expect;
|
||||||
|
|
||||||
|
describe('fs.chown, fs.fchown', function() {
|
||||||
|
beforeEach(util.setup);
|
||||||
|
afterEach(util.cleanup);
|
||||||
|
|
||||||
|
it('should be functions', function() {
|
||||||
|
var fs = util.fs();
|
||||||
|
expect(typeof fs.chown).to.equal('function');
|
||||||
|
expect(typeof fs.fchown).to.equal('function');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should automatically set a file\s uid and gid to 0 (i.e., root)', function(done) {
|
||||||
|
var fs = util.fs();
|
||||||
|
|
||||||
|
fs.open('/file', 'w', function(err, fd) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
fs.fstat(fd, function(err, stats) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
expect(stats.uid).to.equal(0);
|
||||||
|
expect(stats.gid).to.equal(0);
|
||||||
|
fs.close(fd, done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow updating gid and uid for a file', function(done) {
|
||||||
|
var fs = util.fs();
|
||||||
|
|
||||||
|
fs.open('/file', 'w', function(err, fd) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
fs.fchown(fd, 1001, 1001, function(err) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
fs.fstat(fd, function(err, stats) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
expect(stats.uid).to.equal(1001);
|
||||||
|
expect(stats.gid).to.equal(1001);
|
||||||
|
|
||||||
|
fs.close(fd, function(err) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
fs.chown('/file', 500, 500, function(err) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
fs.stat('/file', function(err, stats) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
expect(stats.uid).to.equal(500);
|
||||||
|
expect(stats.gid).to.equal(500);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -42,6 +42,30 @@ describe('fs.link', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should create hard link to identical data node', function(done) {
|
||||||
|
var fs = util.fs();
|
||||||
|
var contents = "Hello World!";
|
||||||
|
|
||||||
|
fs.writeFile('/file', contents, function(err) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
fs.link('/file', '/hlink', function(err) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
fs.readFile('/file', 'utf8', function(err, fileData) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
fs.readFile('/hlink', 'utf8', function(err, hlinkData) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
expect(fileData).to.equal(hlinkData);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should not follow symbolic links', function(done) {
|
it('should not follow symbolic links', function(done) {
|
||||||
var fs = util.fs();
|
var fs = util.fs();
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
var Filer = require('../..');
|
var Filer = require('../..');
|
||||||
|
var Path = Filer.Path;
|
||||||
var util = require('../lib/test-utils.js');
|
var util = require('../lib/test-utils.js');
|
||||||
var expect = require('chai').expect;
|
var expect = require('chai').expect;
|
||||||
|
|
||||||
|
@ -256,4 +257,41 @@ describe('fs.stats', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('generated name property', function() {
|
||||||
|
beforeEach(util.setup);
|
||||||
|
afterEach(util.cleanup);
|
||||||
|
|
||||||
|
it('should correct return name for a file', function(done) {
|
||||||
|
var fs = util.fs();
|
||||||
|
var filepath = '/a';
|
||||||
|
|
||||||
|
fs.writeFile(filepath, 'data', function(err) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
fs.stat(filepath, function(err, stats) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
expect(stats.name).to.equal(Path.basename(filepath));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correct return name for an fd', function(done) {
|
||||||
|
var fs = util.fs();
|
||||||
|
var filepath = '/a';
|
||||||
|
|
||||||
|
fs.open(filepath, 'w', function(err, fd) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
fs.fstat(fd, function(err, stats) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
expect(stats.name).to.equal(Path.basename(filepath));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
|
@ -26,7 +26,6 @@ describe("node.js tests: https://github.com/joyent/node/blob/master/test/simple/
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
fn.apply(fs, args);
|
fn.apply(fs, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,11 +48,10 @@ describe("node.js tests: https://github.com/joyent/node/blob/master/test/simple/
|
||||||
check(fs.appendFile, '/foo\u0000bar');
|
check(fs.appendFile, '/foo\u0000bar');
|
||||||
check(fs.truncate, '/foo\u0000bar');
|
check(fs.truncate, '/foo\u0000bar');
|
||||||
check(fs.utimes, '/foo\u0000bar', 0, 0);
|
check(fs.utimes, '/foo\u0000bar', 0, 0);
|
||||||
// TODO - need to be implemented still...
|
// Not implemented
|
||||||
// check(fs.realpath, '/foo\u0000bar');
|
// check(fs.realpath, '/foo\u0000bar');
|
||||||
// check(fs.chmod, '/foo\u0000bar', '0644');
|
check(fs.chmod, '/foo\u0000bar', '0644');
|
||||||
// check(fs.chown, '/foo\u0000bar', 12, 34);
|
check(fs.chown, '/foo\u0000bar', 12, 34);
|
||||||
// check(fs.realpath, '/foo\u0000bar');
|
|
||||||
|
|
||||||
checks.forEach(function(fn){
|
checks.forEach(function(fn){
|
||||||
fn();
|
fn();
|
||||||
|
|
|
@ -40,18 +40,18 @@ describe('FileSystemShell.ls', function() {
|
||||||
expect(list.length).to.equal(2);
|
expect(list.length).to.equal(2);
|
||||||
|
|
||||||
var item0 = list[0];
|
var item0 = list[0];
|
||||||
expect(item0.path).to.equal('file');
|
expect(item0.name).to.equal('file');
|
||||||
expect(item0.links).to.equal(1);
|
expect(item0.nlinks).to.equal(1);
|
||||||
expect(item0.size).to.equal(1);
|
expect(item0.size).to.equal(1);
|
||||||
expect(item0.modified).to.be.a('number');
|
expect(item0.mtime).to.be.a('number');
|
||||||
expect(item0.type).to.equal('FILE');
|
expect(item0.type).to.equal('FILE');
|
||||||
expect(item0.contents).not.to.exist;
|
expect(item0.contents).not.to.exist;
|
||||||
|
|
||||||
var item1 = list[1];
|
var item1 = list[1];
|
||||||
expect(item1.path).to.equal('file2');
|
expect(item1.name).to.equal('file2');
|
||||||
expect(item1.links).to.equal(1);
|
expect(item1.nlinks).to.equal(1);
|
||||||
expect(item1.size).to.equal(2);
|
expect(item1.size).to.equal(2);
|
||||||
expect(item1.modified).to.be.a('number');
|
expect(item1.mtime).to.be.a('number');
|
||||||
expect(item1.type).to.equal('FILE');
|
expect(item1.type).to.equal('FILE');
|
||||||
expect(item0.contents).not.to.exist;
|
expect(item0.contents).not.to.exist;
|
||||||
|
|
||||||
|
@ -84,19 +84,19 @@ describe('FileSystemShell.ls', function() {
|
||||||
|
|
||||||
// We shouldn't rely on the order we'll get the listing
|
// We shouldn't rely on the order we'll get the listing
|
||||||
list.forEach(function(item, i, arr) {
|
list.forEach(function(item, i, arr) {
|
||||||
switch(item.path) {
|
switch(item.name) {
|
||||||
case 'dir2':
|
case 'dir2':
|
||||||
expect(item.links).to.equal(1);
|
expect(item.nlinks).to.equal(1);
|
||||||
expect(item.size).to.be.a('number');
|
expect(item.size).to.be.a('number');
|
||||||
expect(item.modified).to.be.a('number');
|
expect(item.mtime).to.be.a('number');
|
||||||
expect(item.type).to.equal('DIRECTORY');
|
expect(item.type).to.equal('DIRECTORY');
|
||||||
expect(item.contents).not.to.exist;
|
expect(item.contents).not.to.exist;
|
||||||
break;
|
break;
|
||||||
case 'file':
|
case 'file':
|
||||||
case 'file2':
|
case 'file2':
|
||||||
expect(item.links).to.equal(1);
|
expect(item.nlinks).to.equal(1);
|
||||||
expect(item.size).to.equal(1);
|
expect(item.size).to.equal(1);
|
||||||
expect(item.modified).to.be.a('number');
|
expect(item.mtime).to.be.a('number');
|
||||||
expect(item.type).to.equal('FILE');
|
expect(item.type).to.equal('FILE');
|
||||||
expect(item.contents).not.to.exist;
|
expect(item.contents).not.to.exist;
|
||||||
break;
|
break;
|
||||||
|
@ -143,27 +143,27 @@ describe('FileSystemShell.ls', function() {
|
||||||
|
|
||||||
// We shouldn't rely on the order we'll get the listing
|
// We shouldn't rely on the order we'll get the listing
|
||||||
list.forEach(function(item, i, arr) {
|
list.forEach(function(item, i, arr) {
|
||||||
switch(item.path) {
|
switch(item.name) {
|
||||||
case 'dir2':
|
case 'dir2':
|
||||||
expect(item.links).to.equal(1);
|
expect(item.nlinks).to.equal(1);
|
||||||
expect(item.size).to.be.a('number');
|
expect(item.size).to.be.a('number');
|
||||||
expect(item.modified).to.be.a('number');
|
expect(item.mtime).to.be.a('number');
|
||||||
expect(item.type).to.equal('DIRECTORY');
|
expect(item.type).to.equal('DIRECTORY');
|
||||||
expect(item.contents).to.exist;
|
expect(item.contents).to.exist;
|
||||||
expect(item.contents.length).to.equal(1);
|
expect(item.contents.length).to.equal(1);
|
||||||
var contents0 = item.contents[0];
|
var contents0 = item.contents[0];
|
||||||
expect(contents0.path).to.equal('file');
|
expect(contents0.name).to.equal('file');
|
||||||
expect(contents0.links).to.equal(1);
|
expect(contents0.nlinks).to.equal(1);
|
||||||
expect(contents0.size).to.equal(1);
|
expect(contents0.size).to.equal(1);
|
||||||
expect(contents0.modified).to.be.a('number');
|
expect(contents0.mtime).to.be.a('number');
|
||||||
expect(contents0.type).to.equal('FILE');
|
expect(contents0.type).to.equal('FILE');
|
||||||
expect(contents0.contents).not.to.exist;
|
expect(contents0.contents).not.to.exist;
|
||||||
break;
|
break;
|
||||||
case 'file':
|
case 'file':
|
||||||
case 'file2':
|
case 'file2':
|
||||||
expect(item.links).to.equal(1);
|
expect(item.nlinks).to.equal(1);
|
||||||
expect(item.size).to.equal(1);
|
expect(item.size).to.equal(1);
|
||||||
expect(item.modified).to.be.a('number');
|
expect(item.mtime).to.be.a('number');
|
||||||
expect(item.type).to.equal('FILE');
|
expect(item.type).to.equal('FILE');
|
||||||
expect(item.contents).not.to.exist;
|
expect(item.contents).not.to.exist;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue