diff options
author | David Johnson <davijoh3@cisco.com> | 2011-10-04 15:03:49 -0700 |
---|---|---|
committer | Stephen Hemminger <shemminger@vyatta.com> | 2011-10-04 15:03:49 -0700 |
commit | 4decdea3afe1f90f8335ce8156d678aee4582141 (patch) | |
tree | 012cb76bc908e8daf619c700c881db02479ec967 | |
parent | 7fc99b7f0f3a5e022a09b6525ef18c58ec25f66d (diff) | |
download | android_external_brctl-4decdea3afe1f90f8335ce8156d678aee4582141.tar.gz android_external_brctl-4decdea3afe1f90f8335ce8156d678aee4582141.tar.bz2 android_external_brctl-4decdea3afe1f90f8335ce8156d678aee4582141.zip |
bug with older glibc: "brctl show" shows nothing
Older glibc has a bug in scandir() where if the last call to filter
is a failure and filter sets errno, scandir() will fail and return that
errno to the caller.
If running "brctl show" on a system where the last (sorted) directory
in /sys/class/net is not a bridge, isbridge() will leave errno set to
ENOENT and trigger this bug in glibc.
Attached patch against bridge-utils v1.5 saves/restores errno in
isbridge() to workaround this bug in older glibc.
-rw-r--r-- | libbridge/libbridge_init.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/libbridge/libbridge_init.c b/libbridge/libbridge_init.c index 177a391..f3a551e 100644 --- a/libbridge/libbridge_init.c +++ b/libbridge/libbridge_init.c @@ -48,6 +48,7 @@ static int isbridge(const struct dirent *entry) { char path[SYSFS_PATH_MAX]; struct stat st; + int ret, saved_errno; if (entry->d_name[0] == '.' && (entry->d_name[1] == '\0' @@ -57,7 +58,14 @@ static int isbridge(const struct dirent *entry) snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/bridge", entry->d_name); - return stat(path, &st) == 0 && S_ISDIR(st.st_mode); + + /* Workaround old glibc breakage. + If errno is set, then it fails scandir! */ + saved_errno = errno; + ret = (stat(path, &st) == 0 && S_ISDIR(st.st_mode)); + errno = saved_errno; + + return ret; } /* |