mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-07-28 11:29:09 +02:00
Fix bug: GNU 'ls' didn't count columns correctly if user or group
names contained multibyte characters where the column count differed from the byte count. This patch also corrects some comments. (format_user_or_group): New function, which counts columns correctly. (format_user, format_group): Use it. (format_user_or_group_width): New function, which counts columns correctly. (format_user_width, format_group_width): Use it.
This commit is contained in:
@@ -330,7 +330,7 @@ static struct pending *pending_dirs;
|
||||
static time_t current_time = TYPE_MINIMUM (time_t);
|
||||
static int current_time_ns = -1;
|
||||
|
||||
/* The number of bytes to use for columns containing inode numbers,
|
||||
/* The number of columns to use for columns containing inode numbers,
|
||||
block sizes, link counts, owners, groups, authors, major device
|
||||
numbers, minor device numbers, and file sizes, respectively. */
|
||||
|
||||
@@ -804,14 +804,14 @@ static struct column_info *column_info;
|
||||
/* Maximum number of columns ever possible for this display. */
|
||||
static size_t max_idx;
|
||||
|
||||
/* The minimum width of a colum is 3: 1 character for the name and 2
|
||||
/* The minimum width of a column is 3: 1 character for the name and 2
|
||||
for the separating white space. */
|
||||
#define MIN_COLUMN_WIDTH 3
|
||||
|
||||
|
||||
/* This zero-based index is used solely with the --dired option.
|
||||
When that option is in effect, this counter is incremented for each
|
||||
character of output generated by this program so that the beginning
|
||||
byte of output generated by this program so that the beginning
|
||||
and ending indices (in that output) of every file name can be recorded
|
||||
and later output themselves. */
|
||||
static size_t dired_pos;
|
||||
@@ -3055,19 +3055,44 @@ get_current_time (void)
|
||||
current_time_ns = 999999999;
|
||||
}
|
||||
|
||||
/* Print the user or group name NAME, with numeric id ID, using a
|
||||
print width of WIDTH columns. */
|
||||
|
||||
static void
|
||||
format_user_or_group (char const *name, unsigned long int id, int width)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (name)
|
||||
{
|
||||
/* The output column count may differ from the byte count.
|
||||
Adjust for this, but don't output garbage if integer overflow
|
||||
occurs during adjustment. */
|
||||
len = strlen (name);
|
||||
width -= mbswidth (name, 0);
|
||||
width += len;
|
||||
if (width < 0)
|
||||
width = 0;
|
||||
printf ("%-*s ", width, name);
|
||||
if (len < width)
|
||||
len = width;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("%*lu ", width, id);
|
||||
len = width;
|
||||
}
|
||||
|
||||
dired_pos += len + 1;
|
||||
}
|
||||
|
||||
/* Print the name or id of the user with id U, using a print width of
|
||||
WIDTH. */
|
||||
|
||||
static void
|
||||
format_user (uid_t u, int width)
|
||||
{
|
||||
char const *name = (numeric_ids ? NULL : getuser (u));
|
||||
if (name)
|
||||
printf ("%-*s ", width, name);
|
||||
else
|
||||
printf ("%*lu ", width, (unsigned long int) u);
|
||||
dired_pos += width;
|
||||
dired_pos++;
|
||||
format_user_or_group (numeric_ids ? NULL : getuser (u), u, width);
|
||||
}
|
||||
|
||||
/* Likewise, for groups. */
|
||||
@@ -3075,34 +3100,33 @@ format_user (uid_t u, int width)
|
||||
static void
|
||||
format_group (gid_t g, int width)
|
||||
{
|
||||
char const *name = (numeric_ids ? NULL : getgroup (g));
|
||||
if (name)
|
||||
printf ("%-*s ", width, name);
|
||||
else
|
||||
printf ("%*lu ", width, (unsigned long int) g);
|
||||
dired_pos += width;
|
||||
dired_pos++;
|
||||
format_user_or_group (numeric_ids ? NULL : getgroup (g), g, width);
|
||||
}
|
||||
|
||||
/* Return the number of bytes that format_user will print. */
|
||||
/* Return the number of columns that format_user_or_group will print. */
|
||||
|
||||
static int
|
||||
format_user_or_group_width (char const *name, unsigned long int id)
|
||||
{
|
||||
if (name)
|
||||
{
|
||||
int len = mbswidth (name, 0);
|
||||
return MAX (0, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[INT_BUFSIZE_BOUND (unsigned long int)];
|
||||
sprintf (buf, "%lu", id);
|
||||
return strlen (buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the number of columns that format_user will print. */
|
||||
|
||||
static int
|
||||
format_user_width (uid_t u)
|
||||
{
|
||||
char const *name = (numeric_ids ? NULL : getuser (u));
|
||||
char buf[INT_BUFSIZE_BOUND (unsigned long int)];
|
||||
size_t len;
|
||||
|
||||
if (! name)
|
||||
{
|
||||
sprintf (buf, "%lu", (unsigned long int) u);
|
||||
name = buf;
|
||||
}
|
||||
|
||||
len = strlen (name);
|
||||
if (INT_MAX < len)
|
||||
error (EXIT_FAILURE, 0, _("User name too long"));
|
||||
return len;
|
||||
return format_user_or_group_width (numeric_ids ? NULL : getuser (u), u);
|
||||
}
|
||||
|
||||
/* Likewise, for groups. */
|
||||
@@ -3110,20 +3134,7 @@ format_user_width (uid_t u)
|
||||
static int
|
||||
format_group_width (gid_t g)
|
||||
{
|
||||
char const *name = (numeric_ids ? NULL : getgroup (g));
|
||||
char buf[INT_BUFSIZE_BOUND (unsigned long int)];
|
||||
size_t len;
|
||||
|
||||
if (! name)
|
||||
{
|
||||
sprintf (buf, "%lu", (unsigned long int) g);
|
||||
name = buf;
|
||||
}
|
||||
|
||||
len = strlen (name);
|
||||
if (INT_MAX < len)
|
||||
error (EXIT_FAILURE, 0, _("Group name too long"));
|
||||
return len;
|
||||
return format_user_or_group_width (numeric_ids ? NULL : getgroup (g), g);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user