On 30/08/2025 09:15, Peter Laan wrote:
Hi,
I'm a GNU/Linux noob so maybe I'm doing something wrong. But see the
attached image for badly formatted output from ls -s1 --block-size=\'k. The
columns are not always aligned. This only happens when you have large files
in the directory. Everything looks fine with --block-size=k.
I'm running Arch with the latest updates. ls version 9.7.
The issue is that printf("*s", width, multi_byte_string) doesn't count
width appropriately. In your sv_SE.UTF-8 locale, the number grouping
character is 3 UTF8 bytes which messes up the alignment.
The attached should address this,
which I'll push later today.
Marking this as done.
thanks,
PadraigFrom 673ffd38184cd21e04e56f4b0ead2b6ef74c9f2f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <[email protected]>
Date: Sun, 31 Aug 2025 14:29:56 +0100
Subject: [PATCH] ls: fix alignment with locale formatted --size
Fix allocated size alignment in locales with multi-byte grouping chars.
Tested with: LC_ALL=sv_SE.utf8 ls --size --block-size=\'k
* src/ls.c (print_file_name_and_frills): Don't rely on
printf("%*s", width, string) to pad multi-byte strings appropriately.
Instead work out the padding required and use:
printf("%*s%s", padding, "", string) to pad multi-byte appropriately.
* NEWS: Mention the bug fix.
---
NEWS | 4 ++++
src/ls.c | 16 ++++++++++++----
2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/NEWS b/NEWS
index 988cb96a8..24430cedb 100644
--- a/NEWS
+++ b/NEWS
@@ -35,6 +35,10 @@ GNU coreutils NEWS -*- outline -*-
a confusing error about changing permissions.
[This bug was present in "the beginning".]
+ "ls --size --block-size=\'k" could misalign output in locales
+ with multi-byte thousands grouping characters.
+ [This bug was present in "the beginning".]
+
'od --strings' with '-N' now works correctly. Previously od might
write a NUL byte after a heap buffer, or output invalid addresses.
[These bugs were present in "the beginning".]
diff --git a/src/ls.c b/src/ls.c
index d9faddee4..882752fe1 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -4869,10 +4869,18 @@ print_file_name_and_frills (const struct fileinfo *f, size_t start_col)
format_inode (buf, f));
if (print_block_size)
- printf ("%*s ", format == with_commas ? 0 : block_size_width,
- ! f->stat_ok ? "?"
- : human_readable (STP_NBLOCKS (&f->stat), buf, human_output_opts,
- ST_NBLOCKSIZE, output_block_size));
+ {
+ char const *blocks =
+ (! f->stat_ok
+ ? "?"
+ : human_readable (STP_NBLOCKS (&f->stat), buf, human_output_opts,
+ ST_NBLOCKSIZE, output_block_size));
+ int blocks_width = mbswidth (blocks, MBSWIDTH_FLAGS);
+ int pad = 0;
+ if (0 <= blocks_width && format != with_commas)
+ pad = block_size_width - blocks_width;
+ printf("%*s%s ", pad, "", blocks);
+ }
if (print_scontext)
printf ("%*s ", format == with_commas ? 0 : scontext_width, f->scontext);
--
2.50.1