eza-community / eza

A modern alternative to ls
https://eza.rocks
European Union Public License 1.2
11.35k stars 204 forks source link

bug: eza output wrong child items in directory symbolic link on windows. #1025

Open ulic-youthlic opened 3 months ago

ulic-youthlic commented 3 months ago

Hi,

basically, I created a folder type symlink using mklink that comes with windows command prompt, and when I go to that symlink and use eza, eza prints the wrong subitems.


Steps to reproduce:

  1. Open cmd.
  2. Create a test folder.
    • md test1
  3. Create a temporary file for testing.
    • echo test > test1\temp.txt
  4. Create a symlink.
    • mklink /D test2 test1
  5. Go to the folder type symbolic link.
    • cd test2
  6. Use the self-contained dir to view the files in the folder.
    • dir
      1. Use eza to view the files under the folder.
    • eza -l

Screenshots:


Platform Information:


thx.

ulic-youthlic commented 3 months ago

Specifically, eza will have no problems if symbolic links are created using pwersehll's New-Item -ItemType symboliclink -Target "D:\Code\test1" -Path "D:\Code\test2".

MartinFillon commented 3 months ago

Hello, would you mind running EZA_DEBUG=1 eza -l, and sendingthe output in codeblock as I cannot test in a windows environnement. But I might be able to discern why is this happening

ulic-youthlic commented 3 months ago

Hi, I created a test, pointing to c (using a relative adress form). Here is the output:

[INFO eza] matching on exa.run
[DEBUG eza] Running with options: Options {
    dir_action: List,
    filter: FileFilter {
        list_dirs_first: false,
        sort_field: Name(
            AaBbCc,
        ),
        flags: [],
        dot_filter: JustFiles,
        ignore_patterns: IgnorePatterns {
            patterns: [],
        },
        git_ignore: Off,
    },
    view: View {
        mode: Details(
            Options {
                table: Some(
                    Options {
                        size_format: DecimalBytes,
                        time_format: DefaultFormat,
                        user_format: Name,
                        group_format: Regular,
                        flags_format: Long,
                        columns: Columns {
                            time_types: TimeTypes {
                                modified: true,
                                changed: false,
                                accessed: false,
                                created: false,
                            },
                            inode: false,
                            links: false,
                            blocksize: false,
                            group: false,
                            git: false,
                            subdir_git_repos: false,
                            subdir_git_repos_no_stat: false,
                            octal: false,
                            security_context: false,
                            file_flags: false,
                            permissions: true,
                            filesize: true,
                            user: true,
                        },
                    },
                ),
                header: false,
                xattr: false,
                secattr: false,
                mounts: false,
                color_scale: ColorScaleOptions {
                    mode: Gradient,
                    min_luminance: 40,
                    size: false,
                    age: false,
                },
            },
        ),
        width: Automatic,
        file_style: Options {
            classify: JustFilenames,
            show_icons: Never,
            quote_style: QuoteSpaces,
            embed_hyperlinks: Off,
            absolute: Off,
            is_a_tty: true,
        },
        deref_links: false,
        total_size: false,
    },
    theme: Options {
        use_colours: Automatic,
        colour_scale: ColorScaleOptions {
            mode: Gradient,
            min_luminance: 40,
            size: false,
            age: false,
        },
        definitions: Definitions {
            ls: None,
            exa: None,
        },
    },
    stdin: Args,
}
[DEBUG eza::fs::file] Statting file "."
[DEBUG eza::fs::file] deref_links false
[DEBUG eza::fs::file] Reading link "."
[ERROR eza::fs::file] Error following link "c": Os {
    code: 2,
    kind: NotFound,
    message: "系统找不到指定的文件。",
}
[DEBUG eza::output::table] Creating table with columns: [Permissions, FileSize, Timestamp(Modified)]
[DEBUG eza::fs::file] Reading link "."
[ERROR eza::fs::file] Error following link "c": Os {
    code: 2,
    kind: NotFound,
    message: "系统找不到指定的文件。",
}
[DEBUG eza::output::details] file_name TextCell { contents: TextCellContents([AnsiGenericString { style: Style { fg(Cyan) }, string: ".", oscontrol: None }, AnsiGenericString { style: Style {}, string: " ", oscontrol: None }, AnsiGenericString { style: Style { fg(Red) }, string: "->", oscontrol: None }, AnsiGenericString { style: Style {}, string: " ", oscontrol: None }, AnsiGenericString { style: Style { fg(Red), underline }, string: "c", oscontrol: None }]), width: DisplayWidth(6) }
l---- 0 20 Jun 14:06 . -> c

These reported errors indicate that eza doesn't seem to support resolving relative addresses in symbolic links; I tried creating that link using an absolute address and found that eza worked fine. Of course, I'm not asking eza to add symbolic links for resolving relative links (although I don't really know why it hasn't), as it seems that symbolic links for relative addresses seem to be something rather outdated:

Specifically, eza will have no problems if symbolic links are created using pwersehll's New-Item -ItemType symboliclink -Target "D:\Code\test1" -Path "D:\Code\test2".

As mentioned in that comment, PowerShell also allows the creation of symbolic links, but New-Item already enforces the use of absolute addresse as Target. Anyway, it seems that only cmd's dir now supports resolving symbolic links to relative addresses.


thx your reply

MartinFillon commented 3 months ago

Hey just added some debug infos to the program on the linked branch so that we get more infos, but it seems that the problem might come from path resolving or metadata resolving

ulic-youthlic commented 3 months ago

Hi, i clone the repo and checkout to branch 1025-bug. The following is the output:

[INFO eza] matching on exa.run
[DEBUG eza] Running with options: Options {
    dir_action: List,
    filter: FileFilter {
        list_dirs_first: false,
        sort_field: Name(
            AaBbCc,
        ),
        flags: [],
        dot_filter: JustFiles,
        ignore_patterns: IgnorePatterns {
            patterns: [],
        },
        git_ignore: Off,
    },
    view: View {
        mode: Details(
            Options {
                table: Some(
                    Options {
                        size_format: DecimalBytes,
                        time_format: DefaultFormat,
                        user_format: Name,
                        group_format: Regular,
                        flags_format: Long,
                        columns: Columns {
                            time_types: TimeTypes {
                                modified: true,
                                changed: false,
                                accessed: false,
                                created: false,
                            },
                            inode: false,
                            links: false,
                            blocksize: false,
                            group: false,
                            git: false,
                            subdir_git_repos: false,
                            subdir_git_repos_no_stat: false,
                            octal: false,
                            security_context: false,
                            file_flags: false,
                            permissions: true,
                            filesize: true,
                            user: true,
                        },
                    },
                ),
                header: false,
                xattr: false,
                secattr: false,
                mounts: false,
                color_scale: ColorScaleOptions {
                    mode: Gradient,
                    min_luminance: 40,
                    size: false,
                    age: false,
                },
            },
        ),
        width: Automatic,
        file_style: Options {
            classify: JustFilenames,
            show_icons: Never,
            quote_style: QuoteSpaces,
            embed_hyperlinks: Off,
            absolute: Off,
            is_a_tty: true,
        },
        deref_links: false,
        total_size: false,
    },
    theme: Options {
        use_colours: Automatic,
        colour_scale: ColorScaleOptions {
            mode: Gradient,
            min_luminance: 40,
            size: false,
            age: false,
        },
        definitions: Definitions {
            ls: None,
            exa: None,
        },
    },
    stdin: Args,
}
[DEBUG eza::fs::file] Statting file "."
[DEBUG eza::fs::file] deref_links false
[DEBUG eza::fs::file] Reading link "."
[DEBUG eza::fs::file] Error 系统找不到指定的文件。 (os error 2) following "c"
[ERROR eza::fs::file] Error following link "c": Os {
    code: 2,
    kind: NotFound,
    message: "系统找不到指定的文件。",
}
[DEBUG eza::output::table] Creating table with columns: [Permissions, FileSize, Timestamp(Modified)]
[DEBUG eza::fs::file] Reading link "."
[DEBUG eza::fs::file] Error 系统找不到指定的文件。 (os error 2) following "c"
[ERROR eza::fs::file] Error following link "c": Os {
    code: 2,
    kind: NotFound,
    message: "系统找不到指定的文件。",
}
[DEBUG eza::output::details] file_name TextCell { contents: TextCellContents([AnsiGenericString { style: Style { fg(Cyan) }, string: ".", oscontrol: None }, AnsiGenericString { style: Style {}, string: " ", oscontrol: None }, AnsiGenericString { style: Style { fg(Red) }, string: "->", oscontrol: None }, AnsiGenericString { style: Style {}, string: " ", oscontrol: None }, AnsiGenericString { style: Style { fg(Red), underline }, string: "c", oscontrol: None }]), width: DisplayWidth(6) }
l---- 0 20 Jun 15:43 . -> c
MartinFillon commented 3 months ago

Okay so as I expected this looks like a rust std lib error, where it cannot find the file.

ChrisDenton commented 3 months ago

The debug output neglects to print the absolute_path being given to std::fs::metadata https://github.com/eza-community/eza/blob/7e21ed993c490f91bd4434bb4061ca007aedaf64/src/fs/file.rs#L421

My guess would be there's something interesting about that path.

ChrisDenton commented 3 months ago

Ah I think I understand the issue. This is caused by the difference between . on Windows and POSIX. In POSIX it's a real file that exists (if only in the mind of the kernel). Whereas on Windows there is no .. It's resolved by parsing the path.

So on Windows C:\path\to\dir\. is really just a fancy way of writing C:\path\to\dir (i.e. it's resolved just by modifying the path, the filesystem and kernel don't know anything about it). Whereas in POSIX /path/to/dir/. is an actual file you can stat or whatever that links to /path/to/dir. Mostly this difference doesn't matter but if C:\path\to\dir is a symlink then this causes confusion because the code assumes it's a POSIX . link. Instead it's reading the link from the parent dir.

So to try to put it more clearly reading test2\. reads the link from test2. This link is relative to test2's parent, not from test2 itself. Hence it's not found when looking within test2.

ulic-youthlic commented 3 months ago

That may be right, when I created a c folder inside test, I ran eza inside test and it showed the contents of the c folder I created, not the c folder that test was originally pointing to. This means that when I run eza in test, my cwd is still inside test, but it is looking for a c folder here.

MartinFillon commented 3 months ago

Ah I think I understand the issue. This is caused by the difference between . on Windows and POSIX. In POSIX it's a real file that exists (if only in the mind of the kernel). Whereas on Windows there is no .. It's resolved by parsing the path.

Is there a known way to resolve this that you might know of ?

ChrisDenton commented 3 months ago

I'm not familiar enough with eza's code base to say with any confidence. I'm not clear why it's trying to stat .. That's not normally shown, right? In any case it might be that . and .. need to be treated specially. I.e. decide that they are always considered links to their respective parent.

MartinFillon commented 3 months ago

Oh okay I see, we will need some special case handling i guess.

Thoughts @PThorpe92 @cafkafk @gierens ?

cafkafk commented 2 months ago

Oh okay I see, we will need some special case handling i guess.

Thoughts @PThorpe92 @cafkafk @gierens ?

Honestly I'm not sure I fully understand the issue, but one way would maybe be to create separate code for unix/windows targets that deal with this. Likely something a windows user would have to do.

MartinFillon commented 2 months ago

yes thats indeed what we need to have in order for those links to be handled