fix ls segfault

This commit is contained in:
Freya 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 += $(INCFLAGS)
LDFLAGS = -s
LDFLAGS += $(INCFLAGS)
BIN = bin

View file

@ -5,6 +5,7 @@
#include <dirent.h>
#include <ftw.h>
#include <limits.h>
#include <string.h>
#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);
}

View file

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

View file

@ -1,6 +1,7 @@
#include "shared.h"
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@ -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';
}

View file

@ -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);