Repository: eza-community/eza (language: rust)

Issue:
bug: Size displayed for symlink is size of target
- The version of eza being used (`eza --version`)

v0.14.1 [+git]

- The command-line arguments you are using

eza -l

- Your operating system and hardware platform

Linux Mint 21.2

---

When using `ls -l`, symlink sizes are shown as a few bytes, presumably the actual size of the symlink file:

```
$ ls -l
total 4
lrwxrwxrwx 1 rsholmes rsholmes  23 Oct 14 21:32 xlink.x -> /home/rsholmes/test/x.x
-rw-rw-r-- 1 rsholmes rsholmes 854 Sep 16 11:13 x.x
```

But `eza -l` displays as the size for the symlink the size of the target, while displaying the symlink's permissions and timestamp:

```
$ eza -l
.rw-rw-r-- 854 rsholmes 16 Sep 11:13 x.x
lrwxrwxrwx 854 rsholmes 14 Oct 21:32 xlink.x -> /home/rsholmes/test/x.x
```

`eza -lX` does the same, while the permissions and timestamp change to the target's:

```
$ eza -lX
.rw-rw-r-- 854 rsholmes 16 Sep 11:13 x.x
lrw-rw-r-- 854 rsholmes 16 Sep 11:13 xlink.x -> /home/rsholmes/test/x.x
```

My expectation was that `eza -l` would display the same size as `ls -l` does, and that `eza -lX` would display the target size.



Discussion / hints:
Ohh, that might be what was the issue in #112 

Fix patch:
diff --git a/src/fs/file.rs b/src/fs/file.rs
index c0f6de1db..ade6b3c5b 100644
--- a/src/fs/file.rs
+++ b/src/fs/file.rs
@@ -432,12 +432,18 @@ impl<'dir> File<'dir> {
     /// This actual size the file takes up on disk, in bytes.
     #[cfg(unix)]
     pub fn blocksize(&self) -> f::Blocksize {
-        if self.is_file() || self.is_link() {
+        if self.deref_links && self.is_link() {
+            match self.link_target() {
+                FileTarget::Ok(f) => f.blocksize(),
+                _ => f::Blocksize::None,
+            }
+        } else if self.is_file() {
             // Note that metadata.blocks returns the number of blocks
             // for 512 byte blocks according to the POSIX standard
             // even though the physical block size may be different.
             f::Blocksize::Some(self.metadata.blocks() * 512)
         } else {
+            // directory or symlinks
             f::Blocksize::None
         }
     }
@@ -481,14 +487,11 @@ impl<'dir> File<'dir> {
     /// itself.
     #[cfg(unix)]
     pub fn size(&self) -> f::Size {
-        if self.is_link() {
-            let target = self.link_target();
-            if let FileTarget::Ok(target) = target {
-                return target.size();
+        if self.deref_links && self.is_link() {
+            match self.link_target() {
+                FileTarget::Ok(f) => f.size(),
+                _ => f::Size::None,
             }
-        }
-        if self.is_directory() {
-            f::Size::None
         } else if self.is_char_device() || self.is_block_device() {
             let device_id = self.metadata.rdev();
 
@@ -497,20 +500,17 @@ impl<'dir> File<'dir> {
             // the "as u32" cast are not needed.  We turn off the warning to
             // allow it to compile cleanly on Linux.
             #[allow(trivial_numeric_casts)]
-            #[allow(clippy::unnecessary_cast)]
-            #[allow(clippy::useless_conversion)]
+            #[allow(clippy::unnecessary_cast, clippy::useless_conversion)]
             f::Size::DeviceIDs(f::DeviceIDs {
                 // SAFETY: Calling libc function to decompose the device_id
                 major: unsafe { libc::major(device_id.try_into().unwrap()) } as u32,
                 minor: unsafe { libc::minor(device_id.try_into().unwrap()) } as u32,
             })
-        } else if self.is_link() && self.deref_links {
-            match self.link_target() {
-                FileTarget::Ok(f) => f.size(),
-                _ => f::Size::None,
-            }
-        } else {
+        } else if self.is_file() {
             f::Size::Some(self.metadata.len())
+        } else {
+            // directory and symlink
+            f::Size::None
         }
     }
 


Test patch:
diff --git a/tests/cmd/long_blocksize_dereference_symlink.toml b/tests/cmd/long_blocksize_dereference_symlink.toml
new file mode 100644
index 000000000..53c0625c6
--- /dev/null
+++ b/tests/cmd/long_blocksize_dereference_symlink.toml
@@ -0,0 +1,2 @@
+bin.name = "eza"
+args = "tests/itest/vagrant/debug --long --blocksize --dereference"
diff --git a/tests/cmd/long_blocksize_dereference_symlink_nix.stderr b/tests/cmd/long_blocksize_dereference_symlink_nix.stderr
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/cmd/long_blocksize_dereference_symlink_nix.stdout b/tests/cmd/long_blocksize_dereference_symlink_nix.stdout
new file mode 100644
index 000000000..cf0efb38d
--- /dev/null
+++ b/tests/cmd/long_blocksize_dereference_symlink_nix.stdout
@@ -0,0 +1,3 @@
+.rw-r--r-- 0 ariasuni 20 oct.  15:38 a
+lrw-r--r-- 0 ariasuni 20 oct.  15:38 symlink -> a
+---------- - -        -              symlink-broken -> ./b
diff --git a/tests/cmd/long_blocksize_symlink.toml b/tests/cmd/long_blocksize_symlink.toml
new file mode 100644
index 000000000..5e02b8801
--- /dev/null
+++ b/tests/cmd/long_blocksize_symlink.toml
@@ -0,0 +1,2 @@
+bin.name = "eza"
+args = "tests/itest/vagrant/debug --long --blocksize"
diff --git a/tests/cmd/long_blocksize_symlink_nix.stderr b/tests/cmd/long_blocksize_symlink_nix.stderr
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/cmd/long_blocksize_symlink_nix.stdout b/tests/cmd/long_blocksize_symlink_nix.stdout
new file mode 100644
index 000000000..a80f0b3eb
--- /dev/null
+++ b/tests/cmd/long_blocksize_symlink_nix.stdout
@@ -0,0 +1,3 @@
+.rw-r--r-- 0 ariasuni 20 oct.  15:38 a
+lrwxrwxrwx - ariasuni 17 oct.  18:35 symlink -> a
+lrwxrwxrwx - ariasuni 20 oct.  15:38 symlink-broken -> ./b
diff --git a/tests/cmd/recursive_long_unix.stdout b/tests/cmd/recursive_long_unix.stdout
index 16313857d..6db23dbc6 100644
--- a/tests/cmd/recursive_long_unix.stdout
+++ b/tests/cmd/recursive_long_unix.stdout
@@ -33,7 +33,9 @@ dev
 log
 
 tests/itest/vagrant/debug:
-symlinking -> a
+a
+symlink -> a
+symlink-broken -> ./b
 
 tests/itest/vagrant/dev:
 main.bf
diff --git a/tests/cmd/recursive_unix.stdout b/tests/cmd/recursive_unix.stdout
index 16313857d..6db23dbc6 100644
--- a/tests/cmd/recursive_unix.stdout
+++ b/tests/cmd/recursive_unix.stdout
@@ -33,7 +33,9 @@ dev
 log
 
 tests/itest/vagrant/debug:
-symlinking -> a
+a
+symlink -> a
+symlink-broken -> ./b
 
 tests/itest/vagrant/dev:
 main.bf
diff --git a/tests/cmd/tree_long_unix.stdout b/tests/cmd/tree_long_unix.stdout
index 2ea6bd949..b2c7d0dc4 100644
--- a/tests/cmd/tree_long_unix.stdout
+++ b/tests/cmd/tree_long_unix.stdout
@@ -24,7 +24,9 @@ tests/itest
 ├── q
 └── vagrant
    ├── debug
-   │  └── symlinking -> a
+   │  ├── a
+   │  ├── symlink -> a
+   │  └── symlink-broken -> ./b
    ├── dev
    │  └── main.bf
    └── log
diff --git a/tests/cmd/tree_unix.stdout b/tests/cmd/tree_unix.stdout
index 2ea6bd949..b2c7d0dc4 100644
--- a/tests/cmd/tree_unix.stdout
+++ b/tests/cmd/tree_unix.stdout
@@ -24,7 +24,9 @@ tests/itest
 ├── q
 └── vagrant
    ├── debug
-   │  └── symlinking -> a
+   │  ├── a
+   │  ├── symlink -> a
+   │  └── symlink-broken -> ./b
    ├── dev
    │  └── main.bf
    └── log
diff --git a/tests/itest/vagrant/debug/a b/tests/itest/vagrant/debug/a
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/itest/vagrant/debug/symlinking b/tests/itest/vagrant/debug/symlink
similarity index 100%
rename from tests/itest/vagrant/debug/symlinking
rename to tests/itest/vagrant/debug/symlink
diff --git a/tests/itest/vagrant/debug/symlink-broken b/tests/itest/vagrant/debug/symlink-broken
new file mode 120000
index 000000000..f8423c52d
--- /dev/null
+++ b/tests/itest/vagrant/debug/symlink-broken
@@ -0,0 +1,1 @@
+./b
\ No newline at end of file