[klibc] [klibc:master] ls: Handle relative directory names correctly

klibc-bot for Ben Hutchings ben at decadent.org.uk
Fri Jan 13 14:15:07 PST 2023


Commit-ID:  3d63cd68496a1c8aeccbdac6488bc1f002700bc8
Gitweb:     http://git.kernel.org/?p=libs/klibc/klibc.git;a=commit;h=3d63cd68496a1c8aeccbdac6488bc1f002700bc8
Author:     Ben Hutchings <ben at decadent.org.uk>
AuthorDate: Sat, 31 Dec 2022 16:00:28 +0100
Committer:  Ben Hutchings <ben at decadent.org.uk>
CommitDate: Sat, 31 Dec 2022 16:04:19 +0100

[klibc] ls: Handle relative directory names correctly

ls currently starts to list a directory with chdir(path) and
opendir(path).  This obviously fails for relative names.  That could
be fixed by using opendir(".") instead.  However, if multiple relative
directory names are given, this would still fail after the first such
directory.

Instead, leave the current directory unchanged and use the fstatat()
and readlinkat() functions to get information about files in each
directory.

Signed-off-by: Ben Hutchings <ben at decadent.org.uk>

---
 usr/utils/ls.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/usr/utils/ls.c b/usr/utils/ls.c
index 9677bc0f..50af4349 100644
--- a/usr/utils/ls.c
+++ b/usr/utils/ls.c
@@ -50,7 +50,7 @@ static void do_preformat(const struct stat *st)
 	return;
 }
 
-static void do_stat(const struct stat *st, const char *path)
+static void do_stat(const struct stat *st, int dir_fd, const char *path)
 {
 	char *fmt, *link_name;
 	int rc;
@@ -138,7 +138,7 @@ static void do_stat(const struct stat *st, const char *path)
 			perror("malloc");
 			exit(1);
 		}
-		rc = readlink(path, link_name, max_linksiz);
+		rc = readlinkat(dir_fd, path, link_name, max_linksiz);
 		if (rc == -1) {
 			free(link_name);
 			perror("readlink");
@@ -156,28 +156,26 @@ static void do_stat(const struct stat *st, const char *path)
 static void do_dir(const char *path, int preformat)
 {
 	DIR *dir;
+	int dir_fd;
 	struct dirent *dent;
 	struct stat st;
 
-	if (chdir(path) == -1) {
-		perror(path);
-		exit(1);
-	}
-
 	dir = opendir(path);
 	if (dir == NULL) {
 		perror(path);
 		exit(1);
 	}
+	dir_fd = dirfd(dir);
 
 	while ((dent = readdir(dir)) != NULL) {
-		if (lstat(dent->d_name, &st)) {
+		if (fstatat(dir_fd, dent->d_name, &st,
+			    AT_SYMLINK_NOFOLLOW)) {
 			perror(dent->d_name);
 			exit(1);
 		}
 		(preformat) ?
 			do_preformat(&st) :
-			do_stat(&st, dent->d_name);
+			do_stat(&st, dir_fd, dent->d_name);
 	}
 
 	closedir(dir);
@@ -218,7 +216,7 @@ int main(int argc, char *argv[])
 
 		S_ISDIR(st.st_mode) ?
 			do_dir(argv[i], 0) :
-			do_stat(&st, argv[i]);
+			do_stat(&st, AT_FDCWD, argv[i]);
 	}
 
 	return 0;


More information about the klibc mailing list