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. */
/* 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;
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. */
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_width (uid_t u)
+format_user_or_group_width (char const *name, unsigned long int id)
{
- char const *name = (numeric_ids ? NULL : getuser (u));
- char buf[INT_BUFSIZE_BOUND (unsigned long int)];
- size_t len;
-
- if (! name)
+ if (name)
+ {
+ int len = mbswidth (name, 0);
+ return MAX (0, len);
+ }
+ else
{
- sprintf (buf, "%lu", (unsigned long int) u);
- name = buf;
+ char buf[INT_BUFSIZE_BOUND (unsigned long int)];
+ sprintf (buf, "%lu", id);
+ return strlen (buf);
}
+}
- len = strlen (name);
- if (INT_MAX < len)
- error (EXIT_FAILURE, 0, _("User name too long"));
- return len;
+/* Return the number of columns that format_user will print. */
+
+static int
+format_user_width (uid_t u)
+{
+ return format_user_or_group_width (numeric_ids ? NULL : getuser (u), u);
}
/* Likewise, for groups. */
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);
}