add an optional node to FS.ErrnoError, and use it in stat to tell if an error is about the relevant file - if not, it occurred when looking up its parents, and we should emit ENOTDIR; fixes #2669
This commit is contained in:
Родитель
17d260c5cf
Коммит
dcf835b803
|
@ -283,6 +283,10 @@ LibraryManager.library = {
|
|||
{{{ makeSetValue('buf', C_STRUCTS.stat.st_ino, 'stat.ino', 'i32') }}};
|
||||
return 0;
|
||||
} catch (e) {
|
||||
if (e.node && PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))) {
|
||||
// an error occurred while trying to look up the path; we should just report ENOTDIR
|
||||
e.setErrno(ERRNO_CODES.ENOTDIR);
|
||||
}
|
||||
FS.handleFSError(e);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -161,7 +161,7 @@ mergeInto(LibraryManager.library, {
|
|||
lookupNode: function(parent, name) {
|
||||
var err = FS.mayLookup(parent);
|
||||
if (err) {
|
||||
throw new FS.ErrnoError(err);
|
||||
throw new FS.ErrnoError(err, parent);
|
||||
}
|
||||
var hash = FS.hashName(parent.id, name);
|
||||
#if CASE_INSENSITIVE_FS
|
||||
|
@ -1299,14 +1299,18 @@ mergeInto(LibraryManager.library, {
|
|||
},
|
||||
ensureErrnoError: function() {
|
||||
if (FS.ErrnoError) return;
|
||||
FS.ErrnoError = function ErrnoError(errno) {
|
||||
this.errno = errno;
|
||||
for (var key in ERRNO_CODES) {
|
||||
if (ERRNO_CODES[key] === errno) {
|
||||
this.code = key;
|
||||
break;
|
||||
FS.ErrnoError = function ErrnoError(errno, node) {
|
||||
this.node = node;
|
||||
this.setErrno = function(errno) {
|
||||
this.errno = errno;
|
||||
for (var key in ERRNO_CODES) {
|
||||
if (ERRNO_CODES[key] === errno) {
|
||||
this.code = key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
this.setErrno(errno);
|
||||
this.message = ERRNO_MESSAGES[errno];
|
||||
#if ASSERTIONS
|
||||
if (this.stack) this.stack = demangleAll(this.stack);
|
||||
|
|
|
@ -3983,3 +3983,79 @@ main(const int argc, const char * const * const argv)
|
|||
test([])
|
||||
test(['-O1'])
|
||||
|
||||
def test_stat_fail_alongtheway(self):
|
||||
open('src.cpp', 'w').write(r'''
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CHECK(expression) \
|
||||
if(!(expression)) { \
|
||||
error = errno; \
|
||||
printf("FAIL: %s\n", #expression); fail = 1; \
|
||||
} else { \
|
||||
error = errno; \
|
||||
printf("pass: %s\n", #expression); \
|
||||
} \
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
int error;
|
||||
int fail = 0;
|
||||
CHECK(mkdir("path", 0777) == 0);
|
||||
CHECK(close(open("path/file", O_CREAT | O_WRONLY, 0644)) == 0);
|
||||
{
|
||||
struct stat st;
|
||||
CHECK(stat("path", &st) == 0);
|
||||
CHECK(st.st_mode = 0777);
|
||||
}
|
||||
{
|
||||
struct stat st;
|
||||
CHECK(stat("path/nosuchfile", &st) == -1);
|
||||
printf("info: errno=%d %s\n", error, strerror(error));
|
||||
CHECK(error == ENOENT);
|
||||
}
|
||||
{
|
||||
struct stat st;
|
||||
CHECK(stat("path/file", &st) == 0);
|
||||
CHECK(st.st_mode = 0666);
|
||||
}
|
||||
{
|
||||
struct stat st;
|
||||
CHECK(stat("path/file/impossible", &st) == -1);
|
||||
printf("info: errno=%d %s\n", error, strerror(error));
|
||||
CHECK(error == ENOTDIR);
|
||||
}
|
||||
{
|
||||
struct stat st;
|
||||
CHECK(lstat("path/file/impossible", &st) == -1);
|
||||
printf("info: errno=%d %s\n", error, strerror(error));
|
||||
CHECK(error == ENOTDIR);
|
||||
}
|
||||
return fail;
|
||||
}
|
||||
''')
|
||||
Popen([PYTHON, EMCC, 'src.cpp']).communicate()
|
||||
self.assertContained(r'''pass: mkdir("path", 0777) == 0
|
||||
pass: close(open("path/file", O_CREAT | O_WRONLY, 0644)) == 0
|
||||
pass: stat("path", &st) == 0
|
||||
pass: st.st_mode = 0777
|
||||
pass: stat("path/nosuchfile", &st) == -1
|
||||
info: errno=2 No such file or directory
|
||||
pass: error == ENOENT
|
||||
pass: stat("path/file", &st) == 0
|
||||
pass: st.st_mode = 0666
|
||||
pass: stat("path/file/impossible", &st) == -1
|
||||
info: errno=20 Not a directory
|
||||
pass: error == ENOTDIR
|
||||
pass: lstat("path/file/impossible", &st) == -1
|
||||
info: errno=20 Not a directory
|
||||
pass: error == ENOTDIR
|
||||
''', run_js('a.out.js'))
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче