fix ls segfault

This commit is contained in:
Murphy 2023-05-02 18:02:47 -04:00
parent f6e64afaee
commit 889b35ebd1
5 changed files with 95 additions and 74 deletions

View file

@ -12,7 +12,6 @@ CCFLAGS = -std=c99 -Wall -Wextra -pedantic -O2
CCFLAGS += -D_DEFAULT_SOURCE -DMAJOR=$(MAJOR) -DMINOR=$(MINOR) -DPATCH=$(PATCH) -DCHECK_LINK CCFLAGS += -D_DEFAULT_SOURCE -DMAJOR=$(MAJOR) -DMINOR=$(MINOR) -DPATCH=$(PATCH) -DCHECK_LINK
CCFLAGS += $(INCFLAGS) CCFLAGS += $(INCFLAGS)
LDFLAGS = -s
LDFLAGS += $(INCFLAGS) LDFLAGS += $(INCFLAGS)
BIN = bin BIN = bin

View file

@ -5,6 +5,7 @@
#include <dirent.h> #include <dirent.h>
#include <ftw.h> #include <ftw.h>
#include <limits.h> #include <limits.h>
#include <string.h>
#define FILE_COLOR ANSCII BLACK COLOR #define FILE_COLOR ANSCII BLACK COLOR
#define DIR_COLOR ANSCII BOLD NEXT NORMAL BLUE COLOR #define DIR_COLOR ANSCII BOLD NEXT NORMAL BLUE COLOR
@ -28,7 +29,7 @@ static struct {
struct FileInfo { struct FileInfo {
struct passwd* usr; struct passwd* usr;
struct group* grp; struct group* grp;
char name[PATH_MAX]; char* name;
char date[13]; char date[13];
char mode[11]; char mode[11];
char size[5]; char size[5];
@ -62,32 +63,19 @@ static DIR* get_directory(char* path) {
return d; return d;
} }
static void append_path(char buf[PATH_MAX], const char* dir_path, const char* file_path) { static bool get_file_info(const char* file_name, struct FileInfo* info) {
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) {
uid_t uid = getuid(); uid_t uid = getuid();
gid_t gid = getgid(); gid_t gid = getgid();
char buf[PATH_MAX];
append_path(buf, dir_path, file_path);
struct stat s; struct stat s;
memset(&s, 0, sizeof(struct stat)); memset(&s, 0, sizeof(struct stat));
if (lstat(buf, &s) < 0) { int save = push_path_buffer(file_name);
printf("\x1b[0merror: failed to read file '%s': %s\n", buf, strerror(errno));
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; return false;
} }
@ -96,7 +84,6 @@ static bool get_file_info(const char* file_path, const char* dir_path, struct Fi
info->set_uid = false; info->set_uid = false;
info->set_gid = false; info->set_gid = false;
info->exec = false; info->exec = false;
info->name[0] = '\0';
switch (ty) { switch (ty) {
case DT_BLK: 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->mode[10] = '\0';
info->usr = getpwuid(s.st_uid); 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); 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->links = s.st_nlink;
info->type = ty; 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_file_size(s.st_size, info->size);
print_date_time(s.st_mtim.tv_sec + s.st_mtim.tv_nsec / 1000000000, info->date); 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; return true;
} }
@ -213,7 +215,7 @@ static char* get_file_color(struct FileInfo* info) {
return color; 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) { if (flags.more_info) {
char total[13]; char total[13];
@ -254,17 +256,17 @@ static void list_files(struct FileInfo* files, int file_len, struct FileListInfo
flags.colored != NO ? "\x1b[0m" : "" flags.colored != NO ? "\x1b[0m" : ""
); );
if (finfo.type == DT_LNK) { if (finfo.type == DT_LNK) {
char path[PATH_MAX]; int save = push_path_buffer(finfo.name);
append_path(path, dir_path, finfo.name);
char lnk[PATH_MAX]; char lnk[PATH_MAX];
ssize_t n; 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); printf(" -> %.*s\n", (int)n, lnk);
} else { } else {
putchar('\n'); putchar('\n');
} }
pop_path_buffer(save);
} else { } else {
putchar('\n'); putchar('\n');
} }
@ -280,6 +282,7 @@ static void list_files(struct FileInfo* files, int file_len, struct FileListInfo
flags.colored != NO ? "\x1b[0m" : ""); flags.colored != NO ? "\x1b[0m" : "");
} }
} }
free(finfo.name);
} }
if (!flags.more_info) printf("\n"); if (!flags.more_info) printf("\n");
@ -303,12 +306,10 @@ static void push_file(
struct FileInfo** files, struct FileInfo** files,
struct FileListInfo* info, struct FileListInfo* info,
int* size, int* capacity, int* size, int* capacity,
const char* file_path, const char* file_path
const char* dir_path
) { ) {
struct FileInfo finfo; struct FileInfo finfo;
if (!get_file_info(file_path, dir_path, &finfo)) return; if (!get_file_info(file_path, &finfo)) return;
if (*size == *capacity) { if (*size == *capacity) {
*capacity *= 2; *capacity *= 2;
@ -336,13 +337,15 @@ static void push_file(
(*size)++; (*size)++;
} }
static bool recurse_directory(char* path) { static void recurse_directory(char* dir_name) {
DIR* d; DIR* d;
struct dirent* file; struct dirent* file;
bool first = true; int save = push_path_buffer(dir_name);
d = get_directory(path); d = get_directory(get_path_buffer());
if (d == NULL) return false; if (d == NULL) {
return;
}
int capacity = 8; int capacity = 8;
int size = 0; int size = 0;
@ -351,50 +354,42 @@ static bool recurse_directory(char* path) {
memset(&info, 0, sizeof(struct FileListInfo)); memset(&info, 0, sizeof(struct FileListInfo));
while((file = readdir(d)) != NULL) { 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.hidden && prefix(".", file->d_name)) continue;
if (flags.hide_dot && is_dot_dir(file->d_name)) continue; if (flags.hide_dot && is_dot_dir(file->d_name)) continue;
if (first) { if (file->d_type == DT_DIR && !is_dot_dir(file->d_name)) {
if (flags.colored == NO) recurse_directory(file->d_name);
printf("\n%s:\n", path); } else {
else push_file(&files, &info, &size, &capacity, file->d_name);
printf("\n%s%s:%s\n", DIR_COLOR, path, FILE_COLOR);
first = false;
} }
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); free(files);
if (!flags.more_info) printf("\n"); if (!flags.more_info) printf("\n");
closedir(d); closedir(d);
d = get_directory(path); pop_path_buffer(save);
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;
} }
static bool list_directory(char* path) { static void list_directory(char* path) {
if (flags.recurse) { if (flags.recurse) {
return recurse_directory(path); recurse_directory(path);
return;
} }
DIR* d = get_directory(path); DIR* d = get_directory(path);
if (d == NULL) return false; if (d == NULL) return;
int save = push_path_buffer(path);
int capacity = 8; int capacity = 8;
int size = 0; int size = 0;
@ -406,14 +401,15 @@ static bool list_directory(char* path) {
while ((file = readdir(d)) != NULL) { while ((file = readdir(d)) != NULL) {
if (!flags.hidden && prefix(".", file->d_name)) continue; if (!flags.hidden && prefix(".", file->d_name)) continue;
if (flags.hide_dot && is_dot_dir(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); free(files);
pop_path_buffer(save);
closedir(d); closedir(d);
return true;
} }
static bool is_dir(const char* path) { 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++) { for (int i = start; i < argc; i++) {
if (is_dir(argv[i])) continue; 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); free(files);
} }

View file

@ -75,8 +75,6 @@ static void handle_slash(char n) {
case 'f': case 'f':
putchar('\f'); putchar('\f');
break; break;
case 'e':
putchar('\e');
case 'a': case 'a':
putchar('\a'); putchar('\a');
break; break;

View file

@ -1,6 +1,7 @@
#include "shared.h" #include "shared.h"
#include <errno.h> #include <errno.h>
#include <limits.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -232,3 +233,25 @@ FILE* get_tty_stream(char* type) {
return file; 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';
}

View file

@ -57,3 +57,8 @@ int parse_args (int argc, char** argv, void (*help)(void), int (*short_arg)(char
int get_tty(); int get_tty();
FILE* get_tty_stream(char* type); FILE* get_tty_stream(char* type);
char* get_path_buffer();
int push_path_buffer(const char* string);
void pop_path_buffer(int i);