[klibc] [PATCH v2] klibc-utils: add simple ls

Alexey Gladkov gladkov.alexey at gmail.com
Fri May 29 14:24:05 PDT 2009


Simple utility to list information about a files. The utility which
does the same thing as "ls -la". This is a useful test program.

Signed-off-by: Alexey Gladkov <gladkov.alexey at gmail.com>
---
 usr/utils/Kbuild |    4 +-
 usr/utils/ls.c   |  202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 205 insertions(+), 1 deletions(-)
 create mode 100644 usr/utils/ls.c

diff --git a/usr/utils/Kbuild b/usr/utils/Kbuild
index 5b6dc28..354a364 100644
--- a/usr/utils/Kbuild
+++ b/usr/utils/Kbuild
@@ -3,7 +3,7 @@
 #
 
 progs := chroot dd mkdir mkfifo mknod mount pivot_root umount
-progs += true false sleep ln nuke minips cat
+progs += true false sleep ln nuke minips cat ls
 progs += uname halt kill readlink cpio sync dmesg
 
 static-y := $(addprefix static/, $(progs))
@@ -36,6 +36,8 @@ static/sleep-y      := sleep.o
 shared/sleep-y      := sleep.o
 static/ln-y         := ln.o
 shared/ln-y         := ln.o
+static/ls-y         := ls.o
+shared/ls-y         := ls.o
 static/nuke-y       := nuke.o
 shared/nuke-y       := nuke.o
 static/minips-y     := minips.o
diff --git a/usr/utils/ls.c b/usr/utils/ls.c
new file mode 100644
index 0000000..859142a
--- /dev/null
+++ b/usr/utils/ls.c
@@ -0,0 +1,202 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+
+#define STAT_ISSET(mode, mask) (((mode) & mask) == mask)
+
+static size_t max_linksiz = 128;
+static int max_nlinks = 1;
+static int max_size = 1;
+static int max_uid = 1;
+static int max_gid = 1;
+static int max_min = 1;
+static int max_maj = 1;
+
+static void do_preformat(const struct stat *st)
+{
+	int bytes;
+
+	if ((bytes = snprintf(NULL, 0, "%ju", (uintmax_t) st->st_nlink)) > max_nlinks)
+		max_nlinks = bytes;
+
+	if ((bytes = snprintf(NULL, 0, "%ju", (uintmax_t) st->st_uid)) > max_uid)
+		max_uid = bytes;
+
+	if ((bytes = snprintf(NULL, 0, "%ju", (uintmax_t) st->st_gid)) > max_gid)
+		max_gid = bytes;
+
+	if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
+		if ((bytes = snprintf(NULL, 0, "%u", major(st->st_rdev))) > max_maj)
+			max_maj = bytes;
+
+		if ((bytes = snprintf(NULL, 0, "%u", minor(st->st_rdev))) > max_min)
+			max_min = bytes;
+
+		max_size = max_maj + max_min + 1;
+	}
+	else {
+		if ((bytes = snprintf(NULL, 0, "%ju", (uintmax_t) st->st_size)) > max_size)
+			max_size = bytes;
+	}
+	return;
+}
+
+static void do_stat(const struct stat *st, const char *path)
+{
+	char *fmt, *link_name;
+	int rc;
+
+	switch (st->st_mode & S_IFMT) {
+		case S_IFBLK:  putchar('b'); break;
+		case S_IFCHR:  putchar('c'); break;
+		case S_IFDIR:  putchar('d'); break;
+		case S_IFIFO:  putchar('p'); break;
+		case S_IFLNK:  putchar('l'); break;
+		case S_IFSOCK: putchar('s'); break;
+		case S_IFREG:  putchar('-'); break;
+		default:       putchar('?'); break;
+	}
+	putchar(STAT_ISSET(st->st_mode, S_IRUSR) ? 'r' : '-');
+	putchar(STAT_ISSET(st->st_mode, S_IWUSR) ? 'w' : '-');
+
+	!STAT_ISSET(st->st_mode, S_ISUID) ?
+		putchar(STAT_ISSET(st->st_mode, S_IXUSR) ? 'x' : '-') :
+		putchar('S');
+
+	putchar(STAT_ISSET(st->st_mode, S_IRGRP) ? 'r' : '-');
+	putchar(STAT_ISSET(st->st_mode, S_IWGRP) ? 'w' : '-');
+
+	!STAT_ISSET(st->st_mode, S_ISGID) ?
+		putchar(STAT_ISSET(st->st_mode, S_IXGRP) ? 'x' : '-') :
+		putchar('S');
+
+	putchar(STAT_ISSET(st->st_mode, S_IROTH) ? 'r' : '-');
+	putchar(STAT_ISSET(st->st_mode, S_IWOTH) ? 'w' : '-');
+
+	!STAT_ISSET(st->st_mode, S_ISVTX) ?
+		putchar(STAT_ISSET(st->st_mode, S_IXOTH) ? 'x' : '-') :
+		putchar(S_ISDIR(st->st_mode) ? 't' : 'T');
+
+	if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
+		rc = asprintf(&fmt," %%%dju %%%dju %%%dju %%%du,%%%du %%s",
+		              max_nlinks, max_uid, max_gid, max_maj, max_min);
+		if (rc == -1) {
+			perror("asprintf");
+			exit(1);
+		}
+		fprintf(stdout, fmt,
+			(uintmax_t) st->st_nlink,
+			(uintmax_t) st->st_uid,
+			(uintmax_t) st->st_gid,
+			major(st->st_rdev),
+			minor(st->st_rdev),
+			path);
+	}
+	else {
+		rc = asprintf(&fmt," %%%dju %%%dju %%%dju %%%dju %%s",
+		              max_nlinks, max_uid, max_gid, max_size);
+		if (rc == -1) {
+			perror("asprintf");
+			exit(1);
+		}
+		fprintf(stdout, fmt,
+			(uintmax_t) st->st_nlink,
+			(uintmax_t) st->st_uid,
+			(uintmax_t) st->st_gid,
+			(uintmax_t) st->st_size,
+			path);
+	}
+	free(fmt);
+
+	if (S_ISLNK(st->st_mode)) {
+		if ((link_name = malloc(max_linksiz)) == NULL) {
+			perror("malloc");
+			exit(1);
+		}
+		if ((rc = readlink(path, link_name, max_linksiz)) == -1) {
+			free(link_name);
+			perror("readlink");
+			exit(1);
+		}
+		link_name[rc] = '\0';
+		fprintf(stdout, " -> %s", link_name);
+		free(link_name);
+	}
+
+	putchar('\n');
+	return;
+}
+
+static void do_dir(const char *path, int preformat)
+{
+	DIR *dir;
+	struct dirent *dent;
+	struct stat st;
+
+	if (chdir(path) == -1) {
+		perror(path);
+		exit(1);
+	}
+
+	if ((dir = opendir(path)) == NULL) {
+		perror(path);
+		exit(1);
+	}
+
+	while ((dent = readdir(dir)) != NULL) {
+		if (lstat(dent->d_name, &st)) {
+			perror(dent->d_name);
+			exit(1);
+		}
+		(preformat) ?
+			do_preformat(&st) :
+			do_stat(&st, dent->d_name);
+	}
+
+	closedir(dir);
+}
+
+int main(int argc, char *argv[])
+{
+	int i;
+	struct stat st;
+
+	if (argc == 1) {
+		do_dir(".", 1);
+		do_dir(".", 0);
+		return 0;
+	}
+
+	for (i = 1; i < argc; i++) {
+		if (argv[i][0] == '-' && argv[i][1] == 'h') {
+			fprintf(stdout, "Usage: ls [-h] [FILE ...]\n");
+			return 0;
+		}
+
+		if (lstat(argv[i], &st)) {
+			perror(argv[i]);
+			exit(1);
+		}
+
+		S_ISDIR(st.st_mode) ?
+			do_dir(argv[i], 1) :
+			do_preformat(&st);
+	}
+
+	for (i = 1; i < argc; i++) {
+		if (lstat(argv[i], &st)) {
+			perror(argv[i]);
+			exit(1);
+		}
+
+		S_ISDIR(st.st_mode) ?
+			do_dir(argv[i], 0) :
+			do_stat(&st, argv[i]);
+	}
+
+	return 0;
+}
-- 
1.6.3.1



More information about the klibc mailing list