diff options
author | pankunull <panku_null@proton.me> | 2025-09-01 06:01:28 +0200 |
---|---|---|
committer | pankunull <panku_null@proton.me> | 2025-09-01 06:01:28 +0200 |
commit | bd2ad840f4f92930710b05a91b32b6038d62ea63 (patch) | |
tree | 1f3a3590519fda5b76358f513dc2e854a313bdad /src |
lass init
Diffstat (limited to 'src')
-rw-r--r-- | src/lass.c | 177 |
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("."); +} + |