1
0
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:
Jim Meyering
2004-06-22 12:50:01 +00:00
parent c18f06d7b0
commit e1de0b295e
+57 -46
View File
@@ -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);
}