summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorpankunull <panku_null@proton.me>2025-09-01 06:01:28 +0200
committerpankunull <panku_null@proton.me>2025-09-01 06:01:28 +0200
commitbd2ad840f4f92930710b05a91b32b6038d62ea63 (patch)
tree1f3a3590519fda5b76358f513dc2e854a313bdad /src
lass init
Diffstat (limited to 'src')
-rw-r--r--src/lass.c177
1 files changed, 177 insertions, 0 deletions
diff --git a/src/lass.c b/src/lass.c
new file mode 100644
index 0000000..ddbced0
--- /dev/null
+++ b/src/lass.c
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * lass.c - list files and directories in kernel style
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <grp.h>
+#include <time.h>
+#include <math.h>
+#include <limits.h>
+
+static int cmp_entries(const void *a, const void *b)
+{
+ const char *fa = *(const char **)a;
+ const char *fb = *(const char **)b;
+
+ return strcmp(fa, fb);
+}
+
+static void print_file_info(const char *path, const char *name, int width_uid,
+ int width_gid, int width_size)
+{
+ struct stat st;
+ struct passwd *pw;
+ struct group *gr;
+ struct tm *timeinfo;
+ time_t rawtime;
+ char time_buffer[20];
+
+ if (stat(path, &st))
+ return;
+
+ printf(S_ISDIR(st.st_mode) ? "d" :
+ S_ISSOCK(st.st_mode) ? "s" :
+ S_ISREG(st.st_mode) ? "-" :
+ S_ISLNK(st.st_mode) ? "l" :
+ S_ISCHR(st.st_mode) ? "c" :
+ S_ISBLK(st.st_mode) ? "b" :
+ S_ISFIFO(st.st_mode) ? "p" : "?");
+
+ printf((st.st_mode & 0400) ? "r" : "-");
+ printf((st.st_mode & 0200) ? "w" : "-");
+ printf((st.st_mode & 0100) ? "x" : "-");
+ printf((st.st_mode & 0040) ? "r" : "-");
+ printf((st.st_mode & 0020) ? "w" : "-");
+ printf((st.st_mode & 0010) ? "x" : "-");
+ printf((st.st_mode & 0004) ? "r" : "-");
+ printf((st.st_mode & 0002) ? "w" : "-");
+ printf((st.st_mode & 0001) ? "x" : "-");
+
+ pw = getpwuid(st.st_uid);
+ gr = getgrgid(st.st_gid);
+
+ printf(" %*s %*s ", width_uid, pw ? pw->pw_name : "?",
+ width_gid, gr ? gr->gr_name : "?");
+
+ time(&rawtime);
+ timeinfo = localtime(&rawtime);
+
+ strftime(time_buffer, sizeof(time_buffer),
+ "%a %b %d %H:%M:%S %Y", timeinfo);
+
+ printf("%s ", time_buffer);
+
+ if (S_ISSOCK(st.st_mode) || S_ISFIFO(st.st_mode))
+ printf("%*d ", width_size, 0);
+ else
+ printf("%*zu ", width_size, st.st_size);
+
+ printf("%s\n", name);
+}
+
+static int list_files(const char *path)
+{
+ DIR *dir;
+ struct dirent *entry;
+ char **entries;
+ size_t file_count;
+ size_t capacity;
+ int width_uid;
+ int width_gid;
+ int width_size;
+ int size_digits;
+ struct stat st;
+ struct passwd *pw;
+ struct group *gr;
+ char fullpath[PATH_MAX];
+
+ file_count = 0;
+ capacity = 2;
+ width_uid = 0;
+ width_gid = 0;
+ width_size = 0;
+
+ if (stat(path, &st))
+ return 1;
+
+ if (!S_ISDIR(st.st_mode)) {
+ pw = getpwuid(st.st_uid);
+ gr = getgrgid(st.st_gid);
+ width_uid = pw ? strlen(pw->pw_name) : 1;
+ width_gid = gr ? strlen(gr->gr_name) : 1;
+ width_size = (st.st_size == 0) ? 1 : (int)log10(st.st_size) + 1;
+ print_file_info(path, path, width_uid, width_gid, width_size);
+ return 0;
+ }
+
+ dir = opendir(path);
+ if (!dir)
+ return 1;
+
+ entries = malloc(capacity * sizeof(char *));
+ if (!entries) {
+ closedir(dir);
+ return 1;
+ }
+
+ while ((entry = readdir(dir)) != NULL) {
+ if (file_count == capacity) {
+ capacity *= 2;
+ entries = realloc(entries, capacity * sizeof(char *));
+ if (!entries) {
+ closedir(dir);
+ return 1;
+ }
+ }
+ entries[file_count] = strdup(entry->d_name);
+ if (!entries[file_count])
+ continue;
+
+ snprintf(fullpath, sizeof(fullpath), "%s/%s", path,
+ entry->d_name);
+ if (stat(fullpath, &st))
+ continue;
+
+ pw = getpwuid(st.st_uid);
+ gr = getgrgid(st.st_gid);
+
+ size_digits = (st.st_size == 0) ? 1 : (int)log10(st.st_size)+1;
+
+ if (size_digits > width_size)
+ width_size = size_digits;
+ if (pw && (int)strlen(pw->pw_name) > width_uid)
+ width_uid = strlen(pw->pw_name);
+ if (gr && (int)strlen(gr->gr_name) > width_gid)
+ width_gid = strlen(gr->gr_name);
+
+ file_count++;
+ }
+
+ closedir(dir);
+
+ qsort(entries, file_count, sizeof(char *), cmp_entries);
+
+ for (size_t i = 0; i < file_count; i++) {
+ snprintf(fullpath, sizeof(fullpath), "%s/%s", path, entries[i]);
+ print_file_info(fullpath, entries[i], width_uid, width_gid,
+ width_size);
+ free(entries[i]);
+ }
+
+ free(entries);
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc > 1)
+ return list_files(argv[1]);
+ return list_files(".");
+}
+