From 889b35ebd1659d7e14deee8b3c6cf63d2237ff9e Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Tue, 2 May 2023 18:02:47 -0400 Subject: [PATCH] fix ls segfault --- Makefile | 1 - src/commands/ls.c | 138 ++++++++++++++++++++---------------------- src/commands/printf.c | 2 - src/util/shared.c | 23 +++++++ src/util/shared.h | 5 ++ 5 files changed, 95 insertions(+), 74 deletions(-) diff --git a/Makefile b/Makefile index 708443e..ba4984d 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,6 @@ CCFLAGS = -std=c99 -Wall -Wextra -pedantic -O2 CCFLAGS += -D_DEFAULT_SOURCE -DMAJOR=$(MAJOR) -DMINOR=$(MINOR) -DPATCH=$(PATCH) -DCHECK_LINK CCFLAGS += $(INCFLAGS) -LDFLAGS = -s LDFLAGS += $(INCFLAGS) BIN = bin diff --git a/src/commands/ls.c b/src/commands/ls.c index 3aad1a1..fec8cdd 100644 --- a/src/commands/ls.c +++ b/src/commands/ls.c @@ -5,6 +5,7 @@ #include #include #include +#include #define FILE_COLOR ANSCII BLACK COLOR #define DIR_COLOR ANSCII BOLD NEXT NORMAL BLUE COLOR @@ -28,7 +29,7 @@ static struct { struct FileInfo { struct passwd* usr; struct group* grp; - char name[PATH_MAX]; + char* name; char date[13]; char mode[11]; char size[5]; @@ -62,41 +63,27 @@ static DIR* get_directory(char* path) { return d; } -static void append_path(char buf[PATH_MAX], const char* dir_path, const char* file_path) { - size_t dir_len = strlen(dir_path); - size_t file_len = strlen(file_path); - - memcpy(buf, dir_path, dir_len); - if (buf[dir_len-1] != '/') { - buf[dir_len] = '/'; - dir_len++; - } - memcpy(buf + dir_len, file_path, file_len); - buf[dir_len + file_len] = '\0'; -} - -static bool get_file_info(const char* file_path, const char* dir_path, struct FileInfo* info) { +static bool get_file_info(const char* file_name, struct FileInfo* info) { uid_t uid = getuid(); gid_t gid = getgid(); - char buf[PATH_MAX]; - append_path(buf, dir_path, file_path); - struct stat s; memset(&s, 0, sizeof(struct stat)); - if (lstat(buf, &s) < 0) { - printf("\x1b[0merror: failed to read file '%s': %s\n", buf, strerror(errno)); + int save = push_path_buffer(file_name); + + if (lstat(get_path_buffer(), &s) < 0) { + printf("\x1b[0merror: failed to read file '%s': %s\n", get_path_buffer(), strerror(errno)); + pop_path_buffer(save); return false; } - + int ty = (s.st_mode & S_IFMT) >> 12; info->set_uid = false; info->set_gid = false; info->exec = false; - info->name[0] = '\0'; switch (ty) { case DT_BLK: @@ -168,17 +155,32 @@ static bool get_file_info(const char* file_path, const char* dir_path, struct Fi info->mode[10] = '\0'; info->usr = getpwuid(s.st_uid); + if (info->usr == NULL) { + fprintf(stderr, "error: 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) { + fprintf(stderr, "error: failed to get user from %s\n", get_path_buffer()); + pop_path_buffer(save); + return false; + } + info->links = s.st_nlink; info->type = ty; - strcpy(info->name, file_path); + size_t 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 * s.st_blksize; + info->bytes = (s.st_size + s.st_blksize - 1) / s.st_blksize; + pop_path_buffer(save); return true; } @@ -213,7 +215,7 @@ static char* get_file_color(struct FileInfo* info) { return color; } -static void list_files(struct FileInfo* files, int file_len, struct FileListInfo info, const char* dir_path) { +static void list_files(struct FileInfo* files, int file_len, struct FileListInfo info) { if (flags.more_info) { char total[13]; @@ -254,17 +256,17 @@ static void list_files(struct FileInfo* files, int file_len, struct FileListInfo flags.colored != NO ? "\x1b[0m" : "" ); if (finfo.type == DT_LNK) { - char path[PATH_MAX]; - append_path(path, dir_path, finfo.name); + int save = push_path_buffer(finfo.name); char lnk[PATH_MAX]; ssize_t n; - if ((n = readlink(path, lnk, PATH_MAX)) != -1) { + 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'); } @@ -280,6 +282,7 @@ static void list_files(struct FileInfo* files, int file_len, struct FileListInfo flags.colored != NO ? "\x1b[0m" : ""); } } + free(finfo.name); } if (!flags.more_info) printf("\n"); @@ -303,12 +306,10 @@ static void push_file( struct FileInfo** files, struct FileListInfo* info, int* size, int* capacity, - const char* file_path, - const char* dir_path + const char* file_path ) { - struct FileInfo finfo; - if (!get_file_info(file_path, dir_path, &finfo)) return; + if (!get_file_info(file_path, &finfo)) return; if (*size == *capacity) { *capacity *= 2; @@ -336,13 +337,15 @@ static void push_file( (*size)++; } -static bool recurse_directory(char* path) { +static void recurse_directory(char* dir_name) { DIR* d; struct dirent* file; - bool first = true; + int save = push_path_buffer(dir_name); - d = get_directory(path); - if (d == NULL) return false; + d = get_directory(get_path_buffer()); + if (d == NULL) { + return; + } int capacity = 8; int size = 0; @@ -351,50 +354,42 @@ static bool recurse_directory(char* path) { memset(&info, 0, sizeof(struct FileListInfo)); while((file = readdir(d)) != NULL) { - if (file->d_type == DT_DIR && !is_dot_dir(file->d_name)) continue; if (!flags.hidden && prefix(".", file->d_name)) continue; if (flags.hide_dot && is_dot_dir(file->d_name)) continue; - if (first) { - if (flags.colored == NO) - printf("\n%s:\n", path); - else - printf("\n%s%s:%s\n", DIR_COLOR, path, FILE_COLOR); - first = false; + 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); } - push_file(&files, &info, &size, &capacity, file->d_name, path); } - - list_files(files, size, info, path); + + + 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); - d = get_directory(path); - if (d == NULL) return false; - - while((file = readdir(d)) != NULL) { - if (file->d_type != DT_DIR) continue; - if (!flags.hidden && prefix(".", file->d_name)) continue; - if (is_dot_dir(file->d_name)) continue; - char buf[PATH_MAX]; - append_path(buf, path, file->d_name); - recurse_directory(buf); - } - - closedir(d); - - return true; + pop_path_buffer(save); } -static bool list_directory(char* path) { +static void list_directory(char* path) { if (flags.recurse) { - return recurse_directory(path); + recurse_directory(path); + return; } DIR* d = get_directory(path); - if (d == NULL) return false; + if (d == NULL) return; + + int save = push_path_buffer(path); int capacity = 8; int size = 0; @@ -406,14 +401,15 @@ static bool list_directory(char* path) { 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, path); + push_file(&files, &info, &size, &capacity, file->d_name); } - if (size > 0) list_files(files, size, info, path); + if (size > 0) list_files(files, size, info); free(files); - + + pop_path_buffer(save); + closedir(d); - return true; } static bool is_dir(const char* path) { @@ -431,10 +427,10 @@ static void list_file_args(int start, int argc, char** argv) { for (int i = start; i < argc; i++) { if (is_dir(argv[i])) continue; - push_file((struct FileInfo**) &files, &info, &size, &capacity, argv[i], argv[i][0] == '/' ? "" : "."); + push_file((struct FileInfo**) &files, &info, &size, &capacity, argv[i]); } - if (size > 0) list_files(files, size, info, "."); + if (size > 0) list_files(files, size, info); free(files); } diff --git a/src/commands/printf.c b/src/commands/printf.c index 4663a86..f9f3931 100644 --- a/src/commands/printf.c +++ b/src/commands/printf.c @@ -75,8 +75,6 @@ static void handle_slash(char n) { case 'f': putchar('\f'); break; - case 'e': - putchar('\e'); case 'a': putchar('\a'); break; diff --git a/src/util/shared.c b/src/util/shared.c index 3e6fca3..600a967 100644 --- a/src/util/shared.c +++ b/src/util/shared.c @@ -1,6 +1,7 @@ #include "shared.h" #include +#include #include #include #include @@ -232,3 +233,25 @@ FILE* get_tty_stream(char* type) { return file; } +static char path_buffer[PATH_MAX + 1]; +static int path_buffer_index = 0; + +char* get_path_buffer() { + return path_buffer; +} + +int push_path_buffer(const char* string) { + int save = path_buffer_index; + if (path_buffer_index > 1 || (path_buffer_index == 1 && path_buffer[0] != '/')) { + path_buffer[path_buffer_index++] = '/'; + } + int string_len = strlen(string); + memcpy(path_buffer + path_buffer_index, string, string_len + 1); + path_buffer_index += string_len; + return save; +} + +void pop_path_buffer(int i) { + path_buffer_index = i; + path_buffer[path_buffer_index] = '\0'; +} diff --git a/src/util/shared.h b/src/util/shared.h index c0945c1..9bade52 100644 --- a/src/util/shared.h +++ b/src/util/shared.h @@ -57,3 +57,8 @@ int parse_args (int argc, char** argv, void (*help)(void), int (*short_arg)(char int get_tty(); FILE* get_tty_stream(char* type); + +char* get_path_buffer(); +int push_path_buffer(const char* string); +void pop_path_buffer(int i); +