// SPDX-License-Identifier: GPL-2.0 /* * lass.c - list files and directories in Kebab style */ #include #include #include #include #include #include #include #include #include #include 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; char time_buffer[64]; 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 : "?"); timeinfo = localtime(&st.st_mtime); 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("."); }