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/minils.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 201 insertions(+), 1 deletions(-)
create mode 100644 usr/utils/minils.c
diff --git a/usr/utils/Kbuild b/usr/utils/Kbuild
index 5b6dc28..e4f90f0 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 minils
progs += uname halt kill readlink cpio sync dmesg
static-y := $(addprefix static/, $(progs))
@@ -40,6 +40,8 @@ static/nuke-y := nuke.o
shared/nuke-y := nuke.o
static/minips-y := minips.o
shared/minips-y := minips.o
+static/minils-y := minils.o
+shared/minils-y := minils.o
static/cat-y := cat.o
shared/cat-y := cat.o
static/uname-y := uname.o
diff --git a/usr/utils/minils.c b/usr/utils/minils.c
new file mode 100644
index 0000000..71a3261
--- /dev/null
+++ b/usr/utils/minils.c
@@ -0,0 +1,198 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <sys/types.h>
+
+#define STAT_ISSET(mode, mask) (((mode) & mask) == mask)
+
+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)
+{
+ size_t max_siz = 128;
+ size_t sz;
+ char *fmt, *link_name;
+
+ switch (st->st_mode & S_IFMT) {
+ case S_IFBLK: printf("b"); break;
+ case S_IFCHR: printf("c"); break;
+ case S_IFDIR: printf("d"); break;
+ case S_IFIFO: printf("p"); break;
+ case S_IFLNK: printf("l"); break;
+ case S_IFSOCK: printf("s"); break;
+ case S_IFREG: printf("-"); break;
+ default: printf("?"); break;
+ }
+ printf ("%s%s",
+ STAT_ISSET(st->st_mode, S_IRUSR) ? "r" : "-",
+ STAT_ISSET(st->st_mode, S_IWUSR) ? "w" : "-");
+
+ !STAT_ISSET(st->st_mode, S_ISUID) ?
+ printf ("%s", STAT_ISSET(st->st_mode, S_IXUSR) ? "x" :
"-") :
+ printf ("S");
+
+ printf ("%s%s",
+ STAT_ISSET(st->st_mode, S_IRGRP) ? "r" : "-",
+ STAT_ISSET(st->st_mode, S_IWGRP) ? "w" : "-");
+
+ !STAT_ISSET(st->st_mode, S_ISGID) ?
+ printf ("%s", STAT_ISSET(st->st_mode, S_IXGRP) ? "x" :
"-") :
+ printf ("S");
+
+ printf ("%s%s",
+ STAT_ISSET(st->st_mode, S_IROTH) ? "r" : "-",
+ STAT_ISSET(st->st_mode, S_IWOTH) ? "w" : "-");
+
+ !STAT_ISSET(st->st_mode, S_ISVTX) ?
+ printf ("%s", STAT_ISSET(st->st_mode, S_IXOTH) ? "x" :
"-") :
+ printf ("%s", S_ISDIR(st->st_mode) ? "t" :
"T");
+
+ sz = snprintf(NULL, 0, " %%%dju %%%dju %%%dju", max_nlinks, max_uid,
max_gid);
+ if ((fmt = malloc(max_size + sz + 1)) == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+
+ if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
+ sprintf(fmt, " %%%dju %%%dju %%%dju %%%du,%%%du",
+ max_nlinks, max_uid, max_gid, max_maj, max_min);
+ printf (fmt,
+ (uintmax_t) st->st_nlink,
+ (uintmax_t) st->st_uid,
+ (uintmax_t) st->st_gid,
+ major(st->st_rdev),
+ minor(st->st_rdev));
+ }
+ else {
+ sprintf(fmt, " %%%dju %%%dju %%%dju %%%dju",
+ max_nlinks, max_uid, max_gid, max_size);
+ printf (fmt,
+ (uintmax_t) st->st_nlink,
+ (uintmax_t) st->st_uid,
+ (uintmax_t) st->st_gid,
+ (uintmax_t) st->st_size);
+ }
+ free(fmt);
+
+ printf (" %s", path);
+
+ if (S_ISLNK(st->st_mode)) {
+ if ((link_name = malloc(max_siz)) == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+
+ if (readlink(path, link_name, max_siz) == -1) {
+ perror("readlink");
+ free(link_name);
+ exit(1);
+ }
+ printf(" -> %s", link_name);
+ free(link_name);
+ }
+
+ printf ("\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 (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;
+}
--
Rgrds, legion