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, Padraig
From 673ffd38184cd21e04e56f4b0ead2b6ef74c9f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?= <p...@draigbrady.com> 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