fix ls segfault
This commit is contained in:
parent
f6e64afaee
commit
889b35ebd1
5 changed files with 95 additions and 74 deletions
1
Makefile
1
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
|
||||
|
|
|
@ -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,32 +63,19 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -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_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);
|
||||
pop_path_buffer(save);
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -75,8 +75,6 @@ static void handle_slash(char n) {
|
|||
case 'f':
|
||||
putchar('\f');
|
||||
break;
|
||||
case 'e':
|
||||
putchar('\e');
|
||||
case 'a':
|
||||
putchar('\a');
|
||||
break;
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue