Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ See docs/process.md for more on how version tagging works.
-----------------------
- libunwind was updated to LLVM 19.1.4. (#22394)
- mimalloc was updated to 2.1.7. (#21548)
- The file system was updated to independently track atime, mtime and ctime
instead of using the same time for all three.
- mimalloc was updated to 2.1.7. (#21548)

3.1.72 - 11/19/24
-----------------
Expand Down
70 changes: 28 additions & 42 deletions src/library_fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,60 +174,46 @@ FS.staticInit();
path = PATH_FS.resolve(path);

if (!path) return { path: '', node: null };
opts.follow_mount ??= true

var defaults = {
follow_mount: true,
recurse_count: 0
};
opts = Object.assign(defaults, opts)

if (opts.recurse_count > 8) { // max recursive lookup of 8
throw new FS.ErrnoError({{{ cDefs.ELOOP }}});
}
// limit max consecutive symlinks to 40 (SYMLOOP_MAX).
linkloop: for (var nlinks = 0; nlinks < 40; nlinks++) {
// split the absolute path
var parts = path.split('/').filter((p) => !!p);

// split the absolute path
var parts = path.split('/').filter((p) => !!p);
// start at the root
var current = FS.root;
var current_path = '/';

// start at the root
var current = FS.root;
var current_path = '/';

for (var i = 0; i < parts.length; i++) {
var islast = (i === parts.length-1);
if (islast && opts.parent) {
// stop resolving
break;
}
for (var i = 0; i < parts.length; i++) {
var islast = (i === parts.length-1);
if (islast && opts.parent) {
// stop resolving
break;
}

current = FS.lookupNode(current, parts[i]);
current_path = PATH.join2(current_path, parts[i]);
current = FS.lookupNode(current, parts[i]);
current_path = PATH.join2(current_path, parts[i]);

// jump to the mount's root node if this is a mountpoint
if (FS.isMountpoint(current)) {
if (!islast || (islast && opts.follow_mount)) {
// jump to the mount's root node if this is a mountpoint
if (FS.isMountpoint(current) && (!islast || opts.follow_mount)) {
current = current.mounted.root;
}
}

// by default, lookupPath will not follow a symlink if it is the final path component.
// setting opts.follow = true will override this behavior.
if (!islast || opts.follow) {
var count = 0;
while (FS.isLink(current.mode)) {
var link = FS.readlink(current_path);
current_path = PATH_FS.resolve(PATH.dirname(current_path), link);

var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count + 1 });
current = lookup.node;

if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX).
throw new FS.ErrnoError({{{ cDefs.ELOOP }}});
// by default, lookupPath will not follow a symlink if it is the final path component.
// setting opts.follow = true will override this behavior.
if (FS.isLink(current.mode) && (!islast || opts.follow)) {
if (!current.node_ops.readlink) {
throw new FS.ErrnoError({{{ cDefs.ENOSYS }}});
}
var link = current.node_ops.readlink(current);
path = PATH_FS.resolve(PATH.dirname(current_path), link, ...parts.slice(i + 1));
continue linkloop;
}
}
return { path: current_path, node: current };
}

return { path: current_path, node: current };
throw new FS.ErrnoError({{{ cDefs.ELOOP }}});
},
getPath(node) {
var path;
Expand Down