diff --git a/e2fsprogs/chattr.c b/e2fsprogs/chattr.c index e599abae7..f436cd91e 100644 --- a/e2fsprogs/chattr.c +++ b/e2fsprogs/chattr.c @@ -162,8 +162,6 @@ static void change_attributes(const char *name, struct globals *gp) bb_perror_msg("can't stat '%s'", name); return; } - if (S_ISLNK(st.st_mode) && gp->recursive) - return; /* Don't try to open device files, fifos etc. We probably * ought to display an error if the file was explicitly given @@ -172,7 +170,12 @@ static void change_attributes(const char *name, struct globals *gp) if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode)) return; - fd = open_or_warn(name, O_RDONLY | O_NONBLOCK); /* neither read nor write asked for */ + /* There is no way to run needed ioctls on a symlink. + * open(O_PATH | O_NOFOLLOW) _can_ be used to get a fd referring to the symlink, + * but ioctls fail on such a fd (tried on 4.12.0 kernel). + * e2fsprogs-1.46.2 uses open(O_NOFOLLOW), it fails on symlinks. + */ + fd = open_or_warn(name, O_RDONLY | O_NONBLOCK | O_NOCTTY | O_NOFOLLOW); if (fd >= 0) { int r; diff --git a/e2fsprogs/lsattr.c b/e2fsprogs/lsattr.c index b4ed12d50..545afa7f5 100644 --- a/e2fsprogs/lsattr.c +++ b/e2fsprogs/lsattr.c @@ -49,8 +49,13 @@ static void list_attributes(const char *name) unsigned fsflags; int fd, r; - fd = open_or_warn(name, O_RDONLY | O_NONBLOCK); /* neither read nor write asked for */ - if (fd < 0) /* for example, dangling links */ + /* There is no way to run needed ioctls on a symlink. + * open(O_PATH | O_NOFOLLOW) _can_ be used to get a fd referring to the symlink, + * but ioctls fail on such a fd (tried on 4.12.0 kernel). + * e2fsprogs-1.46.2 uses open(O_NOFOLLOW), it fails on symlinks. + */ + fd = open_or_warn(name, O_RDONLY | O_NONBLOCK | O_NOCTTY | O_NOFOLLOW); + if (fd < 0) return; if (option_mask32 & OPT_PROJID) { @@ -102,8 +107,12 @@ static int FAST_FUNC lsattr_dir_proc(const char *dir_name, if (lstat(path, &st) != 0) bb_perror_msg("can't stat '%s'", path); + else if (de->d_name[0] != '.' || (option_mask32 & OPT_ALL)) { - list_attributes(path); + /* Don't try to open device files, fifos etc */ + if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode) || S_ISDIR(st.st_mode)) + list_attributes(path); + if (S_ISDIR(st.st_mode) && (option_mask32 & OPT_RECUR) && !DOT_OR_DOTDOT(de->d_name) ) {