From d8f2c10b7108fff6b7e437291093a1cadc15ab9f Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Sat, 6 May 2023 00:39:44 -0400 Subject: refactor --- src/commands/ls.c | 552 ------------------------------------------------------ 1 file changed, 552 deletions(-) delete mode 100644 src/commands/ls.c (limited to 'src/commands/ls.c') diff --git a/src/commands/ls.c b/src/commands/ls.c deleted file mode 100644 index e8d58d0..0000000 --- a/src/commands/ls.c +++ /dev/null @@ -1,552 +0,0 @@ -#include "../command.h" - -#include -#include -#include -#include -#include -#include - -#define FILE_COLOR ANSCII BLACK COLOR -#define DIR_COLOR ANSCII BOLD NEXT NORMAL BLUE COLOR -#define DIR_COLOR_EXEC ANSCII BACKGROUND GREEN NEXT NORMAL BLACK COLOR -#define LINK_COLOR ANSCII BOLD NEXT NORMAL TURQUOISE COLOR -#define SET_UID_COLOR ANSCII BACKGROUND RED NEXT NORMAL WHITE COLOR -#define SET_GID_COLOR ANSCII BACKGROUND YELLOW NEXT NORMAL BLACK COLOR -#define EXEC_COLOR ANSCII BOLD NEXT NORMAL GREEN COLOR -#define BLK_COLOR ANSCII BOLD NEXT NORMAL YELLOW COLOR -#define SOCK_COLOR ANSCII BOLD NEXT NORMAL MAGENTA COLOR - -static struct { - bool hidden; - bool hide_dot; - bool more_info; - bool one_column; - bool recurse; - enum When colored; -} flags; - -struct FileInfo { - struct passwd* usr; - struct group* grp; - char* name; - char date[13]; - char mode[11]; - char size[5]; - int links; - int bytes; - bool set_uid; - bool set_gid; - bool exec; - unsigned char type; -}; - -struct FileListInfo { - int max_link; - int max_usr; - int max_grp; - int max_size; - int max_name; - int total_len; - int total_size; -}; - -static DIR* get_directory(char* path) { - DIR* d = opendir(path); - if (d == NULL) { - if (errno == ENOTDIR) { - error_s("`%s` is a a file\n", path); - } else { - error_s("failed to open directory '%s': %s\n", path, strerror(errno)); - } - } - return d; -} - -static bool get_file_info(const char* file_name, struct FileInfo* info) { - - uid_t uid; - gid_t gid; - int save, ty; - struct stat s; - size_t file_len; - - uid = getuid(); - gid = getgid(); - - memset(&s, 0, sizeof(struct stat)); - - save = push_path_buffer(file_name); - - if (lstat(get_path_buffer(), &s) < 0) { - error_s("failed to read file '%s': %s\n", get_path_buffer(), strerror(errno)); - pop_path_buffer(save); - return false; - } - - ty = (s.st_mode & S_IFMT) >> 12; - - info->set_uid = false; - info->set_gid = false; - info->exec = false; - - switch (ty) { - case DT_BLK: - info->mode[0] = 'b'; - break; - case DT_CHR: - info->mode[0] = 'c'; - break; - case DT_DIR: - info->mode[0] = 'd'; - break; - case DT_FIFO: - info->mode[0] = 'f'; - break; - case DT_LNK: - info->mode[0] = 'l'; - break; - case DT_SOCK: - info->mode[0] = 's'; - break; - case DT_UNKNOWN: - info->mode[0] = 'u'; - break; - case DT_WHT: - info->mode[0] = 'w'; - break; - default: - info->mode[0] = '-'; - break; - } - - info->mode[1] = (s.st_mode & S_IRUSR) ? 'r' : '-'; - info->mode[2] = (s.st_mode & S_IWUSR) ? 'w' : '-'; - if (s.st_mode & S_IXUSR) { - if (s.st_mode & S_ISUID) { - info->mode[3] = 's'; - info->set_uid = true; - } else { - info->mode[3] = 'x'; - } - if (!info->exec) info->exec = s.st_uid == uid; - } else { - info->mode[3] = '-'; - } - - info->mode[4] = (s.st_mode & S_IRGRP) ? 'r' : '-'; - info->mode[5] = (s.st_mode & S_IWGRP) ? 'w' : '-'; - if (s.st_mode & S_IXGRP) { - if (s.st_mode & S_ISGID) { - info->mode[6] = 's'; - info->set_gid = true; - } else { - info->mode[6] = 'x'; - } - if (!info->exec) info->exec = s.st_gid == gid; - } else { - info->mode[6] = '-'; - } - - info->mode[7] = (s.st_mode & S_IROTH) ? 'r' : '-'; - info->mode[8] = (s.st_mode & S_IWOTH) ? 'w' : '-'; - if (s.st_mode & S_IXOTH) { - info->mode[9] = 'x'; - info->exec = true; - } else { - info->mode[9] = '-'; - } - - info->mode[10] = '\0'; - - info->usr = getpwuid(s.st_uid); - if (info->usr == NULL) { - error_s("failed to get user from `%s`\n", get_path_buffer()); - pop_path_buffer(save); - return false; - } - - info->grp = getgrgid(s.st_gid); - if (info->grp == NULL) { - error_s("failed to get user from `%s`\n", get_path_buffer()); - pop_path_buffer(save); - return false; - } - - info->links = s.st_nlink; - info->type = ty; - - file_len = strlen(file_name) + 1; - info->name = malloc(file_len); - memcpy(info->name, file_name, file_len); - - print_file_size(s.st_size, info->size); - print_date_time(s.st_mtim.tv_sec + s.st_mtim.tv_nsec / 1000000000, info->date); - - info->bytes = (s.st_size + s.st_blksize - 1) / s.st_blksize; - - pop_path_buffer(save); - return true; -} - -static char* get_file_color(struct FileInfo* info) { - char* color; - if (info->type == DT_DIR) { - if (info->mode[8] == 'w') { - color = DIR_COLOR_EXEC; - } else { - color = DIR_COLOR; - } - } else if (info->type == DT_LNK) { - color = LINK_COLOR; - } else if (info->type == DT_SOCK) { - color = SOCK_COLOR; - } else if ( - info->type == DT_CHR || - info->type == DT_BLK - ) { - color = BLK_COLOR; - } else { - if (info->set_uid) { - color = SET_UID_COLOR; - } else if (info->set_gid) { - color = SET_GID_COLOR; - } else if (info->exec) { - color = EXEC_COLOR; - } else { - color = FILE_COLOR; - } - } - return color; -} - -static void list_files(struct FileInfo* files, int file_len, struct FileListInfo info) { - - struct winsize w; - char* color; - int column_width, row_count, i; - - if (flags.more_info) { - char total[13]; - print_file_size(info.total_size, total); - printf("total %s\n", total); - } - - ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); - - if (!isatty(1)) { - flags.one_column = true; - if (flags.colored == AUTO) - flags.colored = NO; - } - - column_width = info.max_name + 1; - row_count = w.ws_col / column_width; - - for (i = 0; i < file_len; i++) { - struct FileInfo finfo = files[i]; - color = get_file_color(&finfo); - if (flags.more_info) { - printf("%s %*d %*s %*s %*s %s %s%s%s", - finfo.mode, - info.max_link, - finfo.links, - info.max_usr, - finfo.usr->pw_name, - info.max_grp, - finfo.grp->gr_name, - info.max_size, - finfo.size, - finfo.date, - flags.colored != NO ? color : "", - finfo.name, - flags.colored != NO ? "\x1b[0m" : "" - ); - if (finfo.type == DT_LNK) { - int save = push_path_buffer(finfo.name); - - char lnk[PATH_MAX]; - ssize_t n; - if ((n = readlink(get_path_buffer(), lnk, PATH_MAX)) != -1) { - printf(" -> %.*s\n", (int)n, lnk); - } else { - putchar('\n'); - } - - pop_path_buffer(save); - } else { - putchar('\n'); - } - } else if (flags.one_column) { - printf("%s%s%s\n", flags.colored != NO ? color : "", finfo.name, flags.colored != NO ? "\x1b[0m" : ""); - } else { - if (info.total_len > w.ws_col) { - if (i != 0 && i % row_count == 0) putchar('\n'); - printf("%s%*s%s", flags.colored != NO ? color : "", -column_width, - finfo.name, flags.colored != NO ? "\x1b[0m" : ""); - } else { - printf("%s%s%s ", flags.colored != NO ? color : "", finfo.name, - flags.colored != NO ? "\x1b[0m" : ""); - } - } - free(finfo.name); - } - - if (!flags.more_info) printf("\n"); -} - -static int num_places (int n) { - int r = 1; - if (n < 0) n = (n == INT_MIN) ? INT_MAX: -n; - while (n > 9) { - n /= 10; - r++; - } - return r; -} - -static void push_file( - struct FileInfo** files, - struct FileListInfo* info, - int* size, int* capacity, - const char* file_path -) { - struct FileInfo finfo; - int user_len, group_len, name_len, size_len, link_len; - - if (!get_file_info(file_path, &finfo)) return; - - if (*size == *capacity) { - *capacity *= 2; - *files = realloc(*files, sizeof(struct FileInfo) * *capacity); - } - - user_len = strlen(finfo.usr->pw_name); - if (user_len > info->max_usr) info->max_usr = user_len; - - group_len = strlen(finfo.grp->gr_name); - if (group_len > info->max_grp) info->max_grp = group_len; - - name_len = strlen(file_path); - if (name_len > info->max_name) info->max_name = name_len; - - size_len = strlen(finfo.size); - if (size_len > info->max_size) info->max_size = size_len; - - link_len = num_places(finfo.links); - if (link_len > info->max_link) info->max_link = link_len; - - info->total_len += name_len + 2; - info->total_size += finfo.bytes; - - (*files)[*size] = finfo; - (*size)++; -} - -static void recurse_directory(char* dir_name) { - DIR* d; - int capacity, size, save; - struct dirent* file; - struct FileInfo* files; - struct FileListInfo info; - - save = push_path_buffer(dir_name); - - d = get_directory(get_path_buffer()); - if (d == NULL) { - return; - } - - capacity = 8; - size = 0; - - files = malloc(sizeof(struct FileInfo) * capacity); - memset(&info, 0, sizeof(struct FileListInfo)); - - while((file = readdir(d)) != NULL) { - if (!flags.hidden && prefix(".", file->d_name)) continue; - if (flags.hide_dot && is_dot_dir(file->d_name)) continue; - if (file->d_type == DT_DIR && !is_dot_dir(file->d_name)) { - recurse_directory(file->d_name); - } else { - push_file(&files, &info, &size, &capacity, file->d_name); - } - } - - - if (flags.colored == NO) { - printf("\n%s:\n", get_path_buffer()); - } else { - printf("\n%s%s:%s\n", DIR_COLOR, get_path_buffer(), FILE_COLOR); - } - - list_files(files, size, info); - - free(files); - - if (!flags.more_info) printf("\n"); - - closedir(d); - - pop_path_buffer(save); -} - -static void list_directory(char* path) { - - DIR* d; - int capacity, size, save; - struct FileInfo* files; - struct FileListInfo info; - struct dirent* file; - - if (flags.recurse) { - recurse_directory(path); - return; - } - - d = get_directory(path); - if (d == NULL) return; - - save = push_path_buffer(path); - - capacity = 8; - size = 0; - - files = malloc(sizeof(struct FileInfo) * capacity); - memset(&info, 0, sizeof(struct FileListInfo)); - - while ((file = readdir(d)) != NULL) { - if (!flags.hidden && prefix(".", file->d_name)) continue; - if (flags.hide_dot && is_dot_dir(file->d_name)) continue; - push_file(&files, &info, &size, &capacity, file->d_name); - } - - if (size > 0) list_files(files, size, info); - free(files); - - pop_path_buffer(save); - - closedir(d); -} - -static bool is_dir(const char* path) { - struct stat s; - if (stat(path, &s) < 0) return false; - return S_ISDIR(s.st_mode); -} - -static void list_file_args(int start, int argc, char** argv) { - - int capacity, size, i; - struct FileInfo* files; - struct FileListInfo info; - - capacity = 8; - size = 0; - - files = malloc(sizeof(struct FileInfo) * capacity); - memset(&info, 0, sizeof(struct FileListInfo)); - - for (i = start; i < argc; i++) { - if (is_dir(argv[i])) continue; - push_file(&files, &info, &size, &capacity, argv[i]); - } - - if (size > 0) list_files(files, size, info); - - free(files); -} - -static void help(void) { - printf("Usage: ls [FILE]...\n\n"); - printf("List directory contents\n\n"); - printf("\t-1\tOne column output\n"); - printf("\t-l\tLong format\n"); - printf("\t-a\tInclude names starting with .\n"); - printf("\t-A\tLike -a but without . and ..\n"); - printf("\t-R\tRecurse\n"); -} - -static int short_arg(char c, char* next) { - UNUSED(next); - switch (c) { - case 'R': - flags.recurse = true; - break; - case '1': - flags.one_column = true; - break; - case 'A': - flags.hide_dot = true; - flags.hidden = true; - break; - case 'a': - flags.hidden = true; - break; - case 'l': - flags.more_info = true; - break; - default: - return ARG_INVALID; - } - return ARG_UNUSED; -} - -static int long_arg(char* cur, char* next) { - UNUSED(next); - if (prefix("--color=", cur)) { - char* arg = cur + 8; - if (streql("yes", arg) || streql("always", arg)) { - flags.colored = YES; - } else if (streql("auto", arg)) { - flags.colored = AUTO; - } else if (streql("no", arg) || streql("never", arg)) { - flags.colored = NO; - } else { - error("invalid color options: %s", arg); - } - } else { - return ARG_IGNORE; - } - return ARG_UNUSED; -} - -COMMAND(ls) { - - int start, i; - bool titled; - - flags.hidden = false; - flags.more_info = false; - flags.hide_dot = false; - flags.one_column = false; - flags.recurse = false; - flags.colored = NO; - - start = parse_args(argc, argv, help, short_arg, long_arg); - - if (argc - start == 0) { - list_directory("."); - return EXIT_SUCCESS; - } - - list_file_args(start, argc, argv); - - titled = argc - start > 1; - for (i = start; i < argc; i++) { - - if (!is_dir(argv[i])) continue; - - if (titled && !flags.recurse) { - if (flags.colored != NO) { - printf("\n%s%s:%s\n", DIR_COLOR, argv[i], FILE_COLOR); - } else { - printf("\n%s:\n", argv[i]); - } - } - - list_directory(argv[i]); - } - - return EXIT_SUCCESS; -} -- cgit v1.2.3-freya