ls: make readlink error to not disrupt output (try ls -l /proc/self/fd).

libbb: make xmalloc_readlink_or_warn warning more specific.

function                                             old     new   delta
xmalloc_readlink_or_warn                              33      61     +28
showfiles                                           1495    1460     -35
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 28/-35)             Total: -7 bytes
This commit is contained in:
Denis Vlasenko 2009-03-21 19:11:23 +00:00
parent 05af832097
commit 3a014b85dc
2 changed files with 106 additions and 106 deletions

View File

@ -76,7 +76,7 @@ LIST_ID_NAME = 1 << 4,
LIST_ID_NUMERIC = 1 << 5,
LIST_CONTEXT = 1 << 6,
LIST_SIZE = 1 << 7,
LIST_DEV = 1 << 8,
//LIST_DEV = 1 << 8, - unused, synonym to LIST_SIZE
LIST_DATE_TIME = 1 << 9,
LIST_FULLTIME = 1 << 10,
LIST_FILENAME = 1 << 11,
@ -741,8 +741,8 @@ static int print_name(const char *name)
static int list_single(const struct dnode *dn)
{
int i, column = 0;
int column = 0;
char *lpath;
#if ENABLE_FEATURE_LS_TIMESTAMPS
char *filetime;
time_t ttime, age;
@ -767,41 +767,44 @@ static int list_single(const struct dnode *dn)
append = append_char(dn->dstat.st_mode);
#endif
for (i = 0; i <= 31; i++) {
switch (all_fmt & (1 << i)) {
case LIST_INO:
/* Do readlink early, so that if it fails, error message
* does not appear *inside* of the "ls -l" line */
if (all_fmt & LIST_SYMLINK)
if (S_ISLNK(dn->dstat.st_mode))
lpath = xmalloc_readlink_or_warn(dn->fullname);
if (all_fmt & LIST_INO)
column += printf("%7lu ", (long) dn->dstat.st_ino);
break;
case LIST_BLOCKS:
if (all_fmt & LIST_BLOCKS)
column += printf("%4"OFF_FMT"u ", (off_t) dn->dstat.st_blocks >> 1);
break;
case LIST_MODEBITS:
if (all_fmt & LIST_MODEBITS)
column += printf("%-10s ", (char *) bb_mode_string(dn->dstat.st_mode));
break;
case LIST_NLINKS:
if (all_fmt & LIST_NLINKS)
column += printf("%4lu ", (long) dn->dstat.st_nlink);
break;
case LIST_ID_NAME:
#if ENABLE_FEATURE_LS_USERNAME
if (all_fmt & LIST_ID_NAME) {
if (option_mask32 & OPT_g) {
printf("%-8.8s",
column += printf("%-8.8s",
get_cached_username(dn->dstat.st_uid));
column += 9;
break;
}
printf("%-8.8s %-8.8s",
} else {
column += printf("%-8.8s %-8.8s",
get_cached_username(dn->dstat.st_uid),
get_cached_groupname(dn->dstat.st_gid));
column += 17;
break;
}
}
#endif
case LIST_ID_NUMERIC:
column += printf("%-8u %-8u", dn->dstat.st_uid, dn->dstat.st_gid);
break;
case LIST_SIZE:
case LIST_DEV:
if (all_fmt & LIST_ID_NUMERIC) {
if (option_mask32 & OPT_g)
column += printf("%-8u", (int) dn->dstat.st_uid);
else
column += printf("%-8u %-8u",
(int) dn->dstat.st_uid,
(int) dn->dstat.st_gid);
}
if (all_fmt & (LIST_SIZE /*|LIST_DEV*/ )) {
if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) {
column += printf("%4u, %3u ", (int) major(dn->dstat.st_rdev),
column += printf("%4u, %3u ",
(int) major(dn->dstat.st_rdev),
(int) minor(dn->dstat.st_rdev));
} else {
if (all_fmt & LS_DISP_HR) {
@ -811,13 +814,11 @@ static int list_single(const struct dnode *dn)
column += printf("%9"OFF_FMT"u ", (off_t) dn->dstat.st_size);
}
}
break;
}
#if ENABLE_FEATURE_LS_TIMESTAMPS
case LIST_FULLTIME:
printf("%24.24s ", filetime);
column += 25;
break;
case LIST_DATE_TIME:
if (all_fmt & LIST_FULLTIME)
column += printf("%24.24s ", filetime);
if (all_fmt & LIST_DATE_TIME)
if ((all_fmt & LIST_FULLTIME) == 0) {
/* current_time_t ~== time(NULL) */
age = current_time_t - ttime;
@ -830,15 +831,14 @@ static int list_single(const struct dnode *dn)
}
column += 13;
}
break;
#endif
#if ENABLE_SELINUX
case LIST_CONTEXT:
if (all_fmt & LIST_CONTEXT) {
column += printf("%-32s ", dn->sid ? dn->sid : "unknown");
freecon(dn->sid);
break;
}
#endif
case LIST_FILENAME:
if (all_fmt & LIST_FILENAME) {
#if ENABLE_FEATURE_LS_COLOR
if (show_color) {
info.st_mode = 0; /* for fgcolor() */
@ -851,11 +851,9 @@ static int list_single(const struct dnode *dn)
if (show_color) {
printf("\033[0m");
}
break;
case LIST_SYMLINK:
if (S_ISLNK(dn->dstat.st_mode)) {
char *lpath = xmalloc_readlink_or_warn(dn->fullname);
if (!lpath) break;
}
if (all_fmt & LIST_SYMLINK) {
if (S_ISLNK(dn->dstat.st_mode) && lpath) {
printf(" -> ");
#if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR
#if ENABLE_FEATURE_LS_COLOR
@ -877,17 +875,15 @@ static int list_single(const struct dnode *dn)
}
free(lpath);
}
break;
}
#if ENABLE_FEATURE_LS_FILETYPES
case LIST_FILETYPE:
if (all_fmt & LIST_FILETYPE) {
if (append) {
putchar(append);
column++;
}
break;
}
#endif
}
}
return column;
}

View File

@ -91,7 +91,11 @@ char* FAST_FUNC xmalloc_readlink_or_warn(const char *path)
char *buf = xmalloc_readlink(path);
if (!buf) {
/* EINVAL => "file: Invalid argument" => puzzled user */
bb_error_msg("%s: cannot read link (not a symlink?)", path);
const char *errmsg = "not a symlink";
int err = errno;
if (err != EINVAL)
errmsg = strerror(err);
bb_error_msg("%s: cannot read link: %s", path, errmsg);
}
return buf;
}