[PATCH v4] lsof: correct check for symbolic link

Thomas De Schampheleire patrickdepinguin+busybox at gmail.com
Fri Jun 21 19:27:56 UTC 2013


Busybox lsof used the d_type field of a 'struct dirent' to verify whether the
entry is a symbolic link. This field, however, is not portable. On at least
one board [1] I have seen, that field is 0, and the check fails even though
the entry is a link.

The explicit check for a symbolic link is really only needed to skip the
default directory entries '.' and '..'. The directory /proc/<pid>/fd/
should not contain anything else but these two and symbolic links.
With these assumptions, this patch replaces the explicit link check with a
basic check for '.' and '..' (and any hidden file). In the unlikely case that
there are other file types, xmalloc_readlink() will return NULL, and we can
skip the entry.

[1] A MIPS-based board with glibc 2.9, Linux 2.6.32.27.

Signed-off-by: Thomas De Schampheleire <thomas.de.schampheleire at gmail.com>

---
v2: avoid lstat overhead when possible
v3: avoid strncpy overhead when possible
v4: replace explicit link checking with check on ./.. and readlink return code

 procps/lsof.c |  9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)

Size impact (x86, based on allnoconfig):
original lsof:
   text    data     bss     dec     hex filename
   5633     414      20    6067    17b3 busybox
    234       0       0     234      ea procps/lsof.o

patch-v2:
   text    data     bss     dec     hex filename
   5828     418      20    6266    187a busybox
    290       0       0     290     122 procps/lsof.o

patch-v3:
   text    data     bss     dec     hex filename
   5837     418      20    6275    1883 busybox
    299       0       0     299     12b procps/lsof.o

patch-v4:
   text    data     bss     dec     hex filename
   5637     414      20    6071    17b7 busybox
    238       0       0     238      ee procps/lsof.o

diff --git a/procps/lsof.c b/procps/lsof.c
--- a/procps/lsof.c
+++ b/procps/lsof.c
@@ -61,9 +61,12 @@ int lsof_main(int argc UNUSED_PARAM, cha
 		d_fd = opendir(name);
 		if (d_fd) {
 			while ((entry = readdir(d_fd)) != NULL) {
-				if (entry->d_type == DT_LNK) {
-					safe_strncpy(name + baseofs, entry->d_name, 10);
-					fdlink = xmalloc_readlink(name);
+				/* Skip entries '.' and '..' (and any hidden file) */
+				if (entry->d_name[0] == '.')
+					continue;
+
+				safe_strncpy(name + baseofs, entry->d_name, 10);
+				if ((fdlink = xmalloc_readlink(name)) != NULL) {
 					printf("%d\t%s\t%s\n", proc->pid, proc->exe, fdlink);
 					free(fdlink);
 				}


More information about the busybox mailing list