aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormax99x <max99x@gmail.com>2011-07-22 21:36:14 +0300
committermax99x <max99x@gmail.com>2011-07-22 23:31:57 +0300
commit5f9646ca267736036e87afc965e665539eed3578 (patch)
tree29f7928e8e37fc7a968434b8fad87d25ce2b5e8f
parent4f25c5b69954137557da89973f10d121cdb4a980 (diff)
Added FS.analyzePath() which will simplify some library functions.
-rw-r--r--src/library.js113
-rw-r--r--tests/filesystem/output.txt208
-rw-r--r--tests/filesystem/src.js46
-rw-r--r--tests/runner.py11
4 files changed, 344 insertions, 34 deletions
diff --git a/src/library.js b/src/library.js
index 1347eb67..edcfb425 100644
--- a/src/library.js
+++ b/src/library.js
@@ -50,7 +50,7 @@ LibraryManager.library = {
absolutePath: function(relative, base) {
if (typeof relative !== 'string') return null;
if (base === undefined) base = FS.currentPath;
- else if (relative[0] == '/') base = '';
+ if (relative && relative[0] == '/') base = '';
var full = base + '/' + relative;
var parts = full.split('/').reverse();
var absolute = [''];
@@ -66,45 +66,90 @@ LibraryManager.library = {
}
return absolute.length == 1 ? '/' : absolute.join('/');
},
+ // Analyzes a relative or absolute path returning a description, containing:
+ // isRoot: Whether the path points to the root.
+ // exists: Whether the object at the path exists.
+ // error: If !exists, this will contain the errno code of the cause.
+ // name: The base name of the object (null if !parentExists).
+ // path: The absolute path to the object, with all links resolved.
+ // object: The filesystem record of the object referenced by the path.
+ // parentExists: Whether the parent of the object exist and is a folder.
+ // parentPath: The absolute path to the parent folder.
+ // parentObject: The filesystem record of the parent folder.
+ analyzePath: function(path, dontResolveLastLink, linksVisited) {
+ var ret = {
+ isRoot: false,
+ exists: false,
+ error: 0,
+ name: null,
+ path: null,
+ object: null,
+ parentExists: false,
+ parentPath: null,
+ parentObject: null
+ };
+ path = FS.absolutePath(path);
+ if (path == '/') {
+ ret.isRoot = true;
+ ret.exists = ret.parentExists = true;
+ ret.name = '/';
+ ret.path = ret.parentPath = '/';
+ ret.object = ret.parentObject = FS.root;
+ } else if (path !== null) {
+ linksVisited = linksVisited || 0;
+ path = path.slice(1).split('/');
+ var current = FS.root;
+ var traversed = [''];
+ while (path.length) {
+ if (path.length == 1 && current.isFolder) {
+ ret.parentExists = true;
+ ret.parentPath = traversed.length == 1 ? '/' : traversed.join('/');
+ ret.parentObject = current;
+ ret.name = path[0];
+ }
+ var target = path.shift();
+ if (!current.isFolder) {
+ ret.error = ERRNO_CODES.ENOTDIR;
+ break;
+ } else if (!current.read) {
+ ret.error = ERRNO_CODES.EACCES;
+ break;
+ } else if (!current.contents.hasOwnProperty(target)) {
+ ret.error = ERRNO_CODES.ENOENT;
+ break;
+ }
+ current = current.contents[target];
+ if (current.link && !(dontResolveLastLink && path.length == 0)) {
+ if (linksVisited > 40) { // Usual Linux SYMLOOP_MAX.
+ ret.error = ERRNO_CODES.ELOOP;
+ break;
+ }
+ var link = FS.absolutePath(current.link, traversed.join('/'));
+ return FS.analyzePath([link].concat(path).join('/'),
+ dontResolveLastLink, linksVisited + 1);
+ }
+ traversed.push(target);
+ if (path.length == 0) {
+ ret.exists = true;
+ ret.path = traversed.join('/');
+ ret.object = current;
+ }
+ }
+ return ret;
+ }
+ return ret;
+ },
// Finds the file system object at a given path. If dontResolveLastLink is
// set to true and the object is a symbolic link, it will be returned as is
// instead of being resolved. Links embedded in the path as still resolved.
findObject: function(path, dontResolveLastLink) {
- var linksVisited = 0;
- path = FS.absolutePath(path);
- if (path === null) {
- ___setErrNo(ERRNO_CODES.ENOENT);
+ var ret = FS.analyzePath(path, dontResolveLastLink);
+ if (ret.exists) {
+ return ret.object;
+ } else {
+ ___setErrNo(ret.error);
return null;
}
- if (path == '/') return FS.root;
- path = path.split('/').reverse();
- path.pop();
- var current = FS.root;
- var traversed = [''];
- while (path.length) {
- var target = path.pop();
- if (!current.isFolder) {
- ___setErrNo(ERRNO_CODES.ENOTDIR);
- return null;
- } else if (!current.read) {
- ___setErrNo(ERRNO_CODES.EACCES);
- return null;
- } else if (!current.contents.hasOwnProperty(target)) {
- ___setErrNo(ERRNO_CODES.ENOENT);
- return null;
- }
- current = current.contents[target];
- if (current.link && !(dontResolveLastLink && path.length == 0)) {
- var link = FS.absolutePath(current.link, traversed.join('/'));
- current = FS.findObject(link, dontResolveLastLink);
- if (++linksVisited > 40) { // Usual Linux SYMLOOP_MAX.
- ___setErrNo(ERRNO_CODES.ELOOP);
- return null;
- }
- }
- traversed.push(target);
- }
- return current;
},
// Creates a file system record: file, link, device or folder.
createObject: function(parent, name, properties, canRead, canWrite) {
diff --git a/tests/filesystem/output.txt b/tests/filesystem/output.txt
new file mode 100644
index 00000000..dd58133c
--- /dev/null
+++ b/tests/filesystem/output.txt
@@ -0,0 +1,208 @@
+
+ isRoot: false
+ exists: true
+ error: 0
+ path: /abc
+ name: abc
+ object.contents: ["123","456","deviceA","localLink","rootLink","relativeLink"]
+ parentExists: true
+ parentPath: /
+ parentObject.contents: ["forbidden","abc","def"]
+
+/
+ isRoot: true
+ exists: true
+ error: 0
+ path: /
+ name: /
+ object.contents: ["forbidden","abc","def"]
+ parentExists: true
+ parentPath: /
+ parentObject.contents: ["forbidden","abc","def"]
+
+.
+ isRoot: false
+ exists: true
+ error: 0
+ path: /abc
+ name: abc
+ object.contents: ["123","456","deviceA","localLink","rootLink","relativeLink"]
+ parentExists: true
+ parentPath: /
+ parentObject.contents: ["forbidden","abc","def"]
+
+..
+ isRoot: true
+ exists: true
+ error: 0
+ path: /
+ name: /
+ object.contents: ["forbidden","abc","def"]
+ parentExists: true
+ parentPath: /
+ parentObject.contents: ["forbidden","abc","def"]
+
+../..
+ isRoot: true
+ exists: true
+ error: 0
+ path: /
+ name: /
+ object.contents: ["forbidden","abc","def"]
+ parentExists: true
+ parentPath: /
+ parentObject.contents: ["forbidden","abc","def"]
+
+/abc
+ isRoot: false
+ exists: true
+ error: 0
+ path: /abc
+ name: abc
+ object.contents: ["123","456","deviceA","localLink","rootLink","relativeLink"]
+ parentExists: true
+ parentPath: /
+ parentObject.contents: ["forbidden","abc","def"]
+
+/abc/123
+ isRoot: false
+ exists: true
+ error: 0
+ path: /abc/123
+ name: 123
+ object.contents: []
+ parentExists: true
+ parentPath: /abc
+ parentObject.contents: ["123","456","deviceA","localLink","rootLink","relativeLink"]
+
+/abc/noexist
+ isRoot: false
+ exists: false
+ error: 2
+ path: null
+ name: noexist
+ object.contents: null
+ parentExists: true
+ parentPath: /abc
+ parentObject.contents: ["123","456","deviceA","localLink","rootLink","relativeLink"]
+
+/abc/deviceA
+ isRoot: false
+ exists: true
+ error: 0
+ path: /abc/deviceA
+ name: deviceA
+ object.contents: []
+ parentExists: true
+ parentPath: /abc
+ parentObject.contents: ["123","456","deviceA","localLink","rootLink","relativeLink"]
+
+/abc/localLink
+ isRoot: false
+ exists: true
+ error: 0
+ path: /abc/123
+ name: 123
+ object.contents: []
+ parentExists: true
+ parentPath: /abc
+ parentObject.contents: ["123","456","deviceA","localLink","rootLink","relativeLink"]
+
+/abc/rootLink
+ isRoot: true
+ exists: true
+ error: 0
+ path: /
+ name: /
+ object.contents: ["forbidden","abc","def"]
+ parentExists: true
+ parentPath: /
+ parentObject.contents: ["forbidden","abc","def"]
+
+/abc/relativeLink
+ isRoot: false
+ exists: true
+ error: 0
+ path: /def
+ name: def
+ object.contents: ["789","deviceB"]
+ parentExists: true
+ parentPath: /
+ parentObject.contents: ["forbidden","abc","def"]
+
+/abc/relativeLink/deviceB
+ isRoot: false
+ exists: true
+ error: 0
+ path: /def/deviceB
+ name: deviceB
+ object.contents: []
+ parentExists: true
+ parentPath: /def
+ parentObject.contents: ["789","deviceB"]
+
+/abc/rootLink/noexist
+ isRoot: false
+ exists: false
+ error: 2
+ path: null
+ name: noexist
+ object.contents: null
+ parentExists: true
+ parentPath: /
+ parentObject.contents: ["forbidden","abc","def"]
+
+/abc/rootLink/abc/noexist
+ isRoot: false
+ exists: false
+ error: 2
+ path: null
+ name: noexist
+ object.contents: null
+ parentExists: true
+ parentPath: /abc
+ parentObject.contents: ["123","456","deviceA","localLink","rootLink","relativeLink"]
+
+/forbidden
+ isRoot: false
+ exists: true
+ error: 0
+ path: /forbidden
+ name: forbidden
+ object.contents: ["test"]
+ parentExists: true
+ parentPath: /
+ parentObject.contents: ["forbidden","abc","def"]
+
+/forbidden/test
+ isRoot: false
+ exists: false
+ error: 13
+ path: null
+ name: test
+ object.contents: null
+ parentExists: true
+ parentPath: /forbidden
+ parentObject.contents: ["test"]
+
+/forbidden/noexist
+ isRoot: false
+ exists: false
+ error: 13
+ path: null
+ name: noexist
+ object.contents: null
+ parentExists: true
+ parentPath: /forbidden
+ parentObject.contents: ["test"]
+
+/noexist1/noexist2
+ isRoot: false
+ exists: false
+ error: 2
+ path: null
+ name: null
+ object.contents: null
+ parentExists: false
+ parentPath: null
+ parentObject.contents: null
diff --git a/tests/filesystem/src.js b/tests/filesystem/src.js
new file mode 100644
index 00000000..5fdef564
--- /dev/null
+++ b/tests/filesystem/src.js
@@ -0,0 +1,46 @@
+FS.createFolder('/', 'forbidden', false, false);
+FS.createFolder('/forbidden', 'test', true, true);
+FS.createPath('/', 'abc/123', true, true);
+FS.createPath('/', 'abc/456', true, true);
+FS.createPath('/', 'def/789', true, true);
+FS.createDevice('/abc', 'deviceA', function() {}, function() {});
+FS.createDevice('/def', 'deviceB', function() {}, function() {});
+FS.createLink('/abc', 'localLink', '123', true, true);
+FS.createLink('/abc', 'rootLink', '/', true, true);
+FS.createLink('/abc', 'relativeLink', '../def', true, true);
+
+function explore(path) {
+ print(path);
+ var ret = FS.analyzePath(path);
+ print(' isRoot: ' + ret.isRoot);
+ print(' exists: ' + ret.exists);
+ print(' error: ' + ret.error);
+ print(' path: ' + ret.path);
+ print(' name: ' + ret.name);
+ print(' object.contents: ' + (ret.object && JSON.stringify(Object.keys(ret.object.contents || {}))));
+ print(' parentExists: ' + ret.parentExists);
+ print(' parentPath: ' + ret.parentPath);
+ print(' parentObject.contents: ' + (ret.parentObject && JSON.stringify(Object.keys(ret.parentObject.contents))));
+ print('');
+}
+
+FS.currentPath = '/abc';
+explore('');
+explore('/');
+explore('.');
+explore('..');
+explore('../..');
+explore('/abc');
+explore('/abc/123');
+explore('/abc/noexist');
+explore('/abc/deviceA');
+explore('/abc/localLink');
+explore('/abc/rootLink');
+explore('/abc/relativeLink');
+explore('/abc/relativeLink/deviceB');
+explore('/abc/rootLink/noexist');
+explore('/abc/rootLink/abc/noexist');
+explore('/forbidden');
+explore('/forbidden/test');
+explore('/forbidden/noexist');
+explore('/noexist1/noexist2');
diff --git a/tests/runner.py b/tests/runner.py
index 99ab9974..b673b45c 100644
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -2404,6 +2404,17 @@ if 'benchmark' not in sys.argv:
'''
self.do_test(src, re.sub('(^|\n)\s+', '\\1', expected), post_build=addPreRunAndChecks)
+ def test_fs_base(self):
+ global INCLUDE_FULL_LIBRARY; INCLUDE_FULL_LIBRARY = 1
+ def addJS(filename):
+ src = open(filename, 'r').read().replace(
+ '// {{PRE_RUN_ADDITIONS}}',
+ open(path_from_root('tests', 'filesystem', 'src.js'), 'r').read())
+ open(filename, 'w').write(src)
+ src = 'int main() {return 0;}\n'
+ expected = open(path_from_root('tests', 'filesystem', 'output.txt'), 'r').read()
+ self.do_test(src, expected, post_build=addJS)
+
### 'Big' tests
def test_fannkuch(self):