deno_std icon indicating copy to clipboard operation
deno_std copied to clipboard

fs/copy fails to copy symlinks with `preserveTimestamps: true`

Open jhheider opened this issue 1 year ago • 5 comments

fs/copy fails to copy symlinks with preserveTimestamps: true

Steps to Reproduce

import { copy } from "https://deno.land/std/fs/mod.ts";

Deno.mkdirSync("foo");
Deno.createSync("foo/bar");
await copy("foo", "foo2", { preserveTimestamps: true });
Deno.symlinkSync("bar", "foo/baz");
await copy("foo", "foo3", { preserveTimestamps: true });
error: Uncaught (in promise) NotFound: No such file or directory (os error 2): utime '/Users/jacob/foo/foo3/baz'
    await Deno.utime(dest, statInfo.atime, statInfo.mtime);
    ^
    at async Object.utime (ext:deno_fs/30_fs.js:474:3)
    at async copySymLink (https://deno.land/[email protected]/fs/copy.ts:137:5)
    at async copyDir (https://deno.land/[email protected]/fs/copy.ts:195:7)
    at async copy (https://deno.land/[email protected]/fs/copy.ts:283:5)
    at async file:///Users/jacob/foo/foo.ts:7:1

Expected behavior

I'd expect it to skip the symlinks since utime fails for them on both linux and darwin.

Environment

  • OS: linux x86-64, darwin x86-64, linux aarch64, darwin aarch64
  • deno version: 1.33.4, 1.30.0 (just for double-checking)
  • std version: 0.192.0

jhheider avatar Jun 17 '23 00:06 jhheider

Your example worked fine for me.

foo:
.rw-r--r-- 0 joe joe 2023-06-16 21:10  bar
lrwxrwxrwx 3 joe joe 2023-06-16 21:10  baz -> bar

foo2:
.rw-r--r-- 0 joe joe 2023-06-16 21:10  bar

foo3:
.rw-r--r-- 0 joe joe 2023-06-16 21:10  bar
lrwxrwxrwx 3 joe joe 2023-06-16 21:10  baz -> bar

joehillen avatar Jun 17 '23 04:06 joehillen

Your filesystem wouldn't happen to be mounted with noatime would it?

joehillen avatar Jun 17 '23 04:06 joehillen

I'll have to check. It happens both in macOS and various Ubuntu Linux containers. Will update tomorrow.

jhheider avatar Jun 17 '23 04:06 jhheider

Nothing custom on my mac.

/dev/disk3s1s1 on / (apfs, sealed, local, read-only, journaled)
devfs on /dev (devfs, local, nobrowse)
/dev/disk3s6 on /System/Volumes/VM (apfs, local, noexec, journaled, noatime, nobrowse)
/dev/disk3s2 on /System/Volumes/Preboot (apfs, local, journaled, nobrowse)
/dev/disk3s4 on /System/Volumes/Update (apfs, local, journaled, nobrowse)
/dev/disk1s2 on /System/Volumes/xarts (apfs, local, noexec, journaled, noatime, nobrowse)
/dev/disk1s1 on /System/Volumes/iSCPreboot (apfs, local, journaled, nobrowse)
/dev/disk1s3 on /System/Volumes/Hardware (apfs, local, journaled, nobrowse)
/dev/disk3s5 on /System/Volumes/Data (apfs, local, journaled, nobrowse, protect)
map auto_home on /System/Volumes/Data/home (autofs, automounted, nobrowse)

Here's denoland/deno:latest:

$ docker run -it denoland/deno:latest sh
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
# deno
Deno 1.34.3
exit using ctrl+d, ctrl+c, or close()
REPL is running with all permissions allowed.
To specify permissions, run `deno repl` with allow flags.
> import { copy } from "https://deno.land/std/fs/mod.ts";

Deno.mkdirSync("foo");
Deno.createSync("foo/bar");
await copy("foo", "foo2", { preserveTimestamps: true });
Deno.symlinkSync("bar", "foo/baz");
await copy("foo", "foo3", { preserveTimestamps: true });
Warning Implicitly using latest version (0.192.0) for https://deno.land/std/fs/mod.ts
Uncaught NotFound: No such file or directory (os error 2): utime '/foo3/baz'
    at async Object.utime (ext:deno_fs/30_fs.js:475:3)
    at async copySymLink (https://deno.land/[email protected]/fs/copy.ts:137:5)
    at async copyDir (https://deno.land/[email protected]/fs/copy.ts:195:7)
    at async copy (https://deno.land/[email protected]/fs/copy.ts:283:5)
    at async <anonymous>:9:1

# mount
overlay on / type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/4CLOJDI53GO47GKXLRHC4WLZ5P:/var/lib/docker/overlay2/l/75T75WYL3VE4L6CGUAO7J3YAD6:/var/lib/docker/overlay2/l/SL4WBDRPGXKPJQLYDWZQJQEDL5:/var/lib/docker/overlay2/l/TS5HZS5DBXGAJP7F4BWSG5BV44:/var/lib/docker/overlay2/l/IUKRM4YGJU2VHS5WBKOUYSABUU:/var/lib/docker/overlay2/l/YV2ZTEHT4X6TJR4ZJQIL23NHVE:/var/lib/docker/overlay2/l/HRWJ33DS7E4LIAA3BMOLD63W3B,upperdir=/var/lib/docker/overlay2/f66f6e417a02de1a7158fd230776b53a6a7fb31df9d4de8476efbe7a2fa7efb3/diff,workdir=/var/lib/docker/overlay2/f66f6e417a02de1a7158fd230776b53a6a7fb31df9d4de8476efbe7a2fa7efb3/work)
...

jhheider avatar Jun 17 '23 13:06 jhheider

Interestingly, it does work fine on an rpi4 running ubuntu. This suggests that both macOS and docker running on macOS exhibit this behavior. Not tested: docker running on linux.

jhheider avatar Jun 18 '23 17:06 jhheider

This issue appears to be fixed, as the example snippet executes successfully. The matter of preserving symlink timestamps can be further discussed in #5083.

Please feel free to re-open, if needed.

iuioiua avatar Jun 26 '24 01:06 iuioiua