fix seg faults by strcat of paths and filenames

This commit is contained in:
Night Kaly 2024-04-01 20:53:19 +00:00
commit 3969ddc7dc
Signed by: night0721
GPG key ID: 957D67B8DB7A119B
4 changed files with 113 additions and 99 deletions

124
ccc.c
View file

@ -26,7 +26,7 @@ void change_dir(const char *buf, int selection, int ftype);
void mkdir_p(const char *destdir); void mkdir_p(const char *destdir);
void populate_files(const char *path, int ftype); void populate_files(const char *path, int ftype);
int get_directory_size(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf); int get_directory_size(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf);
void add_file_stat(char *filepath, int ftype); void add_file_stat(char *filename, char *path, int ftype);
char *get_file_mode(mode_t mode); char *get_file_mode(mode_t mode);
void highlight_current_line(); void highlight_current_line();
void show_file_content(); void show_file_content();
@ -75,6 +75,7 @@ int main(int argc, char** argv)
die("Error from chdir"); die("Error from chdir");
} }
if (S_ISREG(st.st_mode)) { if (S_ISREG(st.st_mode)) {
// char *rm_f_name = strrchr(argv[1], '/');
to_open_file = true; to_open_file = true;
} }
} }
@ -135,7 +136,6 @@ int main(int argc, char** argv)
die("ccc: Terminal size needs to be at least 80x24\n"); die("ccc: Terminal size needs to be at least 80x24\n");
} }
ch = getch(); ch = getch();
/* printf("%d ",ch); */
switch (ch) { switch (ch) {
/* quit */ /* quit */
case 'q': case 'q':
@ -152,8 +152,8 @@ int main(int argc, char** argv)
break; break;
/* go back by backspace or h or left arrow */ /* go back by backspace or h or left arrow */
case BACKSPACE: case BACKSPACE: /* PASSTHROUGH */
case LEFT: case LEFT: /* PASSTHROUGH */
case 'h':; case 'h':;
/* get parent directory */ /* get parent directory */
strcpy(p_cwd, cwd); strcpy(p_cwd, cwd);
@ -169,9 +169,9 @@ int main(int argc, char** argv)
break; break;
/* enter directory/open a file using enter or l or right arrow */ /* enter directory/open a file using enter or l or right arrow */
case ENTER: case ENTER: /* PASSTHROUGH */
case RIGHT: case RIGHT: /* PASSTHROUGH */
case 'l':; case 'l':
strcpy(p_cwd, cwd); strcpy(p_cwd, cwd);
file c_file = files->items[current_selection]; file c_file = files->items[current_selection];
/* check if it is directory or a regular file */ /* check if it is directory or a regular file */
@ -194,7 +194,7 @@ int main(int argc, char** argv)
break; break;
/* go up by k or up arrow */ /* go up by k or up arrow */
case UP: case UP: /* PASSTHROUGH */
case 'k': case 'k':
if (current_selection > 0) if (current_selection > 0)
current_selection--; current_selection--;
@ -213,7 +213,7 @@ int main(int argc, char** argv)
break; break;
/* go down by j or down arrow */ /* go down by j or down arrow */
case DOWN: case DOWN: /* PASSTHROUGH */
case 'j': case 'j':
if (current_selection < (files->length - 1)) if (current_selection < (files->length - 1))
current_selection++; current_selection++;
@ -291,7 +291,7 @@ int main(int argc, char** argv)
/* mark one file */ /* mark one file */
case SPACE: case SPACE:
add_file_stat(files->items[current_selection].path, 1); add_file_stat(files->items[current_selection].name, files->items[current_selection].path, 1);
highlight_current_line(); highlight_current_line();
break; break;
@ -302,39 +302,51 @@ int main(int argc, char** argv)
/* mark actions: */ /* mark actions: */
/* delete */ /* delete */
case 'd':; case 'd':
if (marked->length) { if (marked->length) {
char *trash_dir = check_trash_dir(); char *trash_dir = check_trash_dir();
if (trash_dir != NULL) { if (trash_dir != NULL) {
; // int i = 0;
/* do your magic here */ /*
while (i < marked->length) {
printf("deleted %s ", marked->items->path);
if (rename(marked->items->path, trash_dir) == 0) {
printf("file deleted");
} else {
perror("error moving file");
}
i++;
}
*/
} else {
wpprintw("implement hard delete");
} }
} }
break; break;
/* move */ /* move */
case 'm':; case 'm':
if (marked->length) { if (marked->length) {
; ;
} }
break; break;
/* copy */ /* copy */
case 'c':; case 'c':
if (marked->length) { if (marked->length) {
; ;
} }
break; break;
/* symbolic link */ /* symbolic link */
case 's':; case 's':
if (marked->length) { if (marked->length) {
; ;
} }
break; break;
/* bulk rename */ /* bulk rename */
case 'b':; case 'b':
if (marked->length) { if (marked->length) {
; ;
} }
@ -380,7 +392,9 @@ void start_ccc()
init_windows(); init_windows();
} }
/* Checks if trash directory is set and returns it */ /*
* Checks if the trash directory is set and returns it
*/
char *check_trash_dir() char *check_trash_dir()
{ {
char *path = memalloc(PATH_MAX * sizeof(char)); char *path = memalloc(PATH_MAX * sizeof(char));
@ -411,7 +425,7 @@ char *check_trash_dir()
/* if has access to trash_dir */ /* if has access to trash_dir */
if (access(path, F_OK) != 0) { if (access(path, F_OK) != 0) {
/* create the directory with 755 perm if it doesn't exit */ /* create the directory with 755 permissions if it doesn't exist */
mkdir_p(path); mkdir_p(path);
} }
} }
@ -491,7 +505,6 @@ void mkdir_p(const char *destdir)
/* /*
* Read the provided directory and add all files in directory to linked list * Read the provided directory and add all files in directory to linked list
* ftype: normal files = 0, marked = 1, marking ALL = 2 * ftype: normal files = 0, marked = 1, marking ALL = 2
* ep->d_name -> filename
*/ */
void populate_files(const char *path, int ftype) void populate_files(const char *path, int ftype)
{ {
@ -503,22 +516,22 @@ void populate_files(const char *path, int ftype)
wclear(directory_content); wclear(directory_content);
while ((ep = readdir(dp)) != NULL) { while ((ep = readdir(dp)) != NULL) {
char *path = memalloc(PATH_MAX * sizeof(char));
char *filename = memalloc(PATH_MAX * sizeof(char)); char *filename = memalloc(PATH_MAX * sizeof(char));
/* make filename be basename of selected item just to pass check */ /* copy filename */
filename[0] = '\0'; strcpy(filename, ep->d_name);
strcat(filename, ep->d_name);
/* use strncmp to filter out dotfiles */ /* use strncmp to filter out dotfiles */
if ((!show_hidden && strncmp(filename, ".", 1) && strncmp(filename, "..", 2)) || (show_hidden && strcmp(filename, ".") && strcmp(filename, ".."))) { if ((!show_hidden && strncmp(filename, ".", 1) && strncmp(filename, "..", 2)) || (show_hidden && strcmp(filename, ".") && strcmp(filename, ".."))) {
/* construct full file path */ /* construct full file path */
filename[0] = '\0'; strcpy(path, cwd);
strcat(filename, cwd); strcat(path, "/");
strcat(filename, "/"); strcat(path, filename); /* add filename */
strcat(filename, ep->d_name); /* add filename */
add_file_stat(filename, ftype); add_file_stat(filename, path, ftype);
} }
free(filename); free(filename);
free(path);
} }
closedir(dp); closedir(dp);
wrefresh(directory_content); wrefresh(directory_content);
@ -539,13 +552,13 @@ int get_directory_size(const char *fpath, const struct stat *sb, int typeflag, s
* Add that file into list * Add that file into list
* ftype: normal file = 0, normal marked = 1, marked ALL = 2 * ftype: normal file = 0, normal marked = 1, marked ALL = 2
*/ */
void add_file_stat(char *filepath, int ftype) void add_file_stat(char *filename, char *path, int ftype)
{ {
struct stat file_stat; struct stat file_stat;
if (stat(filepath, &file_stat) == -1) { if (stat(path, &file_stat) == -1) {
/* can't be triggered? */ /* can't be triggered? */
if (errno == EACCES) if (errno == EACCES)
arraylist_add(files, filepath, NULL, NULL, NULL, 8, false, false); arraylist_add(files, filename, path, NULL, NULL, NULL, 8, false, false);
} }
/* get file type and color, 4 chars for the type and icon */ /* get file type and color, 4 chars for the type and icon */
@ -555,36 +568,27 @@ void add_file_stat(char *filepath, int ftype)
char *type = memalloc(type_size); char *type = memalloc(type_size);
wchar_t *icon_str = memalloc(icon_size); wchar_t *icon_str = memalloc(icon_size);
filepath[strlen(filepath)] = '\0'; filename[strlen(filename)] = '\0';
/* find last / in path by finding basename */ /* handle file without extension
char *f_bname = strrchr(filepath, '/'); * ext is the extension if . exist in filename
char *ext = NULL; * otherwise is nothing and handled through tenery operator */
if (f_bname != NULL) { char *ext = strrchr(filename, '.');
/* shift 1 to get basename */
f_bname += 1;
/* handle file without extension */
ext = strrchr(f_bname, '.');
if (ext != NULL) {
ext += 1;
} else {
ext = f_bname;
}
}
if (ext != NULL) { if (ext != NULL) {
icon *ext_icon = hashtable_search(ext); ext += 1;
if (ext_icon == NULL)
wcsncpy(icon_str, L"", 2);
else
wcsncpy(icon_str, ext_icon->icon, 2);
} else {
wcsncpy(icon_str, L"", 2);
} }
/* add file extension */
icon *ext_icon = hashtable_search(ext != NULL ? ext : filename);
if (ext_icon == NULL)
wcsncpy(icon_str, L"", 2);
else
wcsncpy(icon_str, ext_icon->icon, 2);
int color; int color;
if (S_ISDIR(file_stat.st_mode)) { if (S_ISDIR(file_stat.st_mode)) {
strncpy(type, "DIR", 4); /* directory type */ strncpy(type, "DIR", 4); /* directory type */
color = 5; /* blue color */ color = 5; /* blue color */
wcsncpy(icon_str, L"󰉋", 2);
} else if (S_ISREG(file_stat.st_mode)) { } else if (S_ISREG(file_stat.st_mode)) {
strncpy(type, "REG", 4); /* regular file */ strncpy(type, "REG", 4); /* regular file */
color = 8; /* white color */ color = 8; /* white color */
@ -611,7 +615,7 @@ void add_file_stat(char *filepath, int ftype)
if (ftype == 1 || ftype == 2) { if (ftype == 1 || ftype == 2) {
/* force if user is marking all files */ /* force if user is marking all files */
bool force = ftype == 2 ? true : false; bool force = ftype == 2 ? true : false;
arraylist_add(marked, filepath, NULL, type, icon_str, 8, true, force); arraylist_add(marked, filename, path, NULL, type, icon_str, 8, true, force);
/* free type and return without allocating more stuff */ /* free type and return without allocating more stuff */
free(type); free(type);
return; return;
@ -631,11 +635,12 @@ void add_file_stat(char *filepath, int ftype)
if (S_ISDIR(file_stat.st_mode)) { if (S_ISDIR(file_stat.st_mode)) {
/* at most 15 fd opened */ /* at most 15 fd opened */
total_dir_size = 0; total_dir_size = 0;
nftw(filepath, &get_directory_size, 15, FTW_PHYS); nftw(path, &get_directory_size, 15, FTW_PHYS);
bytes = total_dir_size; bytes = total_dir_size;
} }
} }
/* 4 before decimal + 1 dot + DECIMAL_PLACES (after decimal) + unit length(1 for K, 3 for KiB, taking units[1] as B never changes)+ 1 space + 1 null */ /* 4 before decimal + 1 dot + DECIMAL_PLACES (after decimal) +
unit length (1 for K, 3 for KiB, taking units[1] as B never changes) + 1 space + 1 null */
int size_size = 4 + 1 + DECIMAL_PLACES + strlen(units[1]) + 1 + 1; int size_size = 4 + 1 + DECIMAL_PLACES + strlen(units[1]) + 1 + 1;
char *size = memalloc(size_size * sizeof(char)); char *size = memalloc(size_size * sizeof(char));
int unit = 0; int unit = 0;
@ -657,7 +662,7 @@ void add_file_stat(char *filepath, int ftype)
char *total_stat = memalloc(stat_size); char *total_stat = memalloc(stat_size);
snprintf(total_stat, stat_size, "%s %s %-*s", mode_str, time, size_size, size); snprintf(total_stat, stat_size, "%s %s %-*s", mode_str, time, size_size, size);
arraylist_add(files, filepath, total_stat, type, icon_str, color, false, false); arraylist_add(files, filename, path, total_stat, type, icon_str, color, false, false);
free(time); free(time);
free(size); free(size);
@ -786,15 +791,16 @@ void highlight_current_line()
*/ */
void show_file_content() void show_file_content()
{ {
wclear(preview_content);
file current_file = files->items[current_selection]; file current_file = files->items[current_selection];
if (strncmp(current_file.type, "DIR", 3) == 0) if (strncmp(current_file.type, "DIR", 3) == 0)
return; return;
wclear(preview_content);
FILE *file = fopen(current_file.path, "r"); FILE *file = fopen(current_file.path, "r");
if (file == NULL) { if (file == NULL) {
mvwprintw(preview_content, 0, 0, "Unable to read %s", current_file.path); mvwprintw(preview_content, 0, 0, "Unable to read %s", current_file.name);
return; return;
} }

View file

@ -5,7 +5,7 @@
#define DECIMAL_PLACES 1 /* how many decimal places show size with */ #define DECIMAL_PLACES 1 /* how many decimal places show size with */
/* Size units */ /* Size units */
const char* units[] = {"B", "K", "M", "G", "T", "P"}; static const char* units[] = {"B", "K", "M", "G", "T", "P"};
/* Set width offset for windows: /* Set width offset for windows:
+-------------%-------------+ +-------------%-------------+

77
file.c
View file

@ -20,10 +20,12 @@ ArrayList *arraylist_init(size_t capacity)
void arraylist_free(ArrayList *list) void arraylist_free(ArrayList *list)
{ {
for (size_t i = 0; i < list->length; i++) { for (size_t i = 0; i < list->length; i++) {
if (list->items[i].type != NULL) if (list->items[i].name != NULL)
free(list->items[i].type); free(list->items[i].name);
if (list->items[i].path != NULL) if (list->items[i].path != NULL)
free(list->items[i].path); free(list->items[i].path);
if (list->items[i].type != NULL)
free(list->items[i].type);
if (list->items[i].stats != NULL) if (list->items[i].stats != NULL)
free(list->items[i].stats); free(list->items[i].stats);
if (list->items[i].icon != NULL) if (list->items[i].icon != NULL)
@ -34,20 +36,22 @@ void arraylist_free(ArrayList *list)
list->length = 0; list->length = 0;
} }
long arraylist_search(ArrayList *list, char *path, bool bname) /*
* Check if the file is in the arraylist
* Treat filepath as base name if bname is true
*/
long arraylist_search(ArrayList *list, char *filepath, bool bname)
{ {
for (long i = 0; i < list->length; i++) { for (long i = 0; i < list->length; i++) {
if (!bname && strcmp(list->items[i].path, path) == 0) { if (!bname && strcmp(list->items[i].path, filepath) == 0) {
return i; return i;
} }
if (bname) { if (bname) {
char *fbname = basename(list->items[i].path); if (strcmp(list->items[i].name, filepath) == 0) {
if (fbname != NULL && strcmp(fbname, path) == 0) {
return i; return i;
} }
} }
} }
return -1; return -1;
} }
@ -56,9 +60,10 @@ void arraylist_remove(ArrayList *list, long index)
if (index >= list->length) if (index >= list->length)
return; return;
free(list->items[index].name);
free(list->items[index].path); free(list->items[index].path);
free(list->items[index].stats);
free(list->items[index].type); free(list->items[index].type);
free(list->items[index].stats);
free(list->items[index].icon); free(list->items[index].icon);
for (long i = index; i < list->length - 1; i++) for (long i = index; i < list->length - 1; i++)
@ -70,36 +75,42 @@ void arraylist_remove(ArrayList *list, long index)
/* /*
* Force will not remove duplicate marked files, instead it just skip adding * Force will not remove duplicate marked files, instead it just skip adding
*/ */
void arraylist_add(ArrayList *list, char *filepath, char *stats, char *type, wchar_t *icon, int color, bool marked, bool force) void arraylist_add(ArrayList *list, char *name, char *path, char *stats, char *type, wchar_t *icon, int color, bool marked, bool force)
{ {
char *filepath_cp = NULL; char *name_cp = NULL;
char *stats_cp = NULL; char *path_cp = NULL;
char *type_cp = NULL; char *type_cp = NULL;
char *stats_cp = NULL;
wchar_t *icon_cp = NULL; wchar_t *icon_cp = NULL;
if (filepath != NULL) { if (name != NULL) {
filepath_cp = strdup(filepath); name_cp = strdup(name);
if (filepath_cp == NULL) if (name_cp == NULL)
perror("ccc"); perror("can't add name to arraylist");
} }
if (stats != NULL) { if (path != NULL) {
stats_cp = strdup(stats); path_cp = strdup(path);
if (stats_cp == NULL) if (path_cp == NULL)
perror("ccc"); perror("can't add path to arraylist");
} }
if (type != NULL) { if (type != NULL) {
type_cp = strdup(type); type_cp = strdup(type);
if (type_cp == NULL) if (type_cp == NULL)
perror("ccc"); perror("can't add type to arraylist");
}
if (stats != NULL) {
stats_cp = strdup(stats);
if (stats_cp == NULL)
perror("can't add stats to arraylist");
} }
if (icon != NULL) { if (icon != NULL) {
icon_cp = wcsdup(icon); icon_cp = wcsdup(icon);
if (icon_cp == NULL) if (icon_cp == NULL)
perror("ccc"); perror("can't add icon to arraylist");
} }
/* path, stats, type, icon, color */ /* name, path, stats, type, icon, color */
file new_file = { filepath_cp, stats_cp, type_cp, icon_cp, color }; file new_file = { name_cp, path_cp, type_cp, stats_cp, icon_cp, color };
if (list->capacity != list->length) { if (list->capacity != list->length) {
if (marked) { if (marked) {
@ -134,28 +145,24 @@ void arraylist_add(ArrayList *list, char *filepath, char *stats, char *type, wch
char *get_line(ArrayList *list, long index, bool detail) char *get_line(ArrayList *list, long index, bool detail)
{ {
file file = list->items[index]; file file = list->items[index];
char *name = strdup(file.path); char *name = strdup(file.name);
name = basename(name); wchar_t *icon = wcsdup(file.icon);
if (name == NULL) if (name == NULL || icon == NULL)
perror("ccc"); perror("ccc");
wchar_t *icon = wcsdup(file.icon); size_t name_len = strlen(name);
char *stats = NULL; char *stats = NULL;
size_t length; size_t length;
if (detail) { if (detail) {
stats = strdup(file.stats); stats = strdup(file.stats);
length = strlen(name) + strlen(stats) + 7; /* 4 for icon, 2 for space and 1 for null */ if (stats == NULL)
if (stats == NULL) {
perror("ccc"); perror("ccc");
} length = name_len + strlen(stats) + 7; /* 4 for icon, 2 for space and 1 for null */
} else { } else {
length = strlen(name) + 6; /* 4 for icon, 1 for space and 1 for null */ length = name_len + 6; /* 4 for icon, 1 for space and 1 for null */
} }
char *line = memalloc(length * sizeof(char)); char *line = memalloc(length * sizeof(char));
if (detail) { if (detail) {
snprintf(line, length, "%s %ls %s", stats, icon, name); snprintf(line, length, "%s %ls %s", stats, icon, name);
} else { } else {

9
file.h
View file

@ -4,9 +4,10 @@
#include <stdio.h> #include <stdio.h>
typedef struct file { typedef struct file {
char *path; char *name; /* basename */
char *stats; char *path; /* absolute path */
char *type; char *type;
char *stats;
wchar_t *icon; wchar_t *icon;
int color; int color;
} file; } file;
@ -19,9 +20,9 @@ typedef struct ArrayList {
ArrayList *arraylist_init(size_t capacity); ArrayList *arraylist_init(size_t capacity);
void arraylist_free(ArrayList *list); void arraylist_free(ArrayList *list);
long arraylist_search(ArrayList *list, char *path, bool bname); long arraylist_search(ArrayList *list, char *filepath, bool bname);
void arraylist_remove(ArrayList *list, long index); void arraylist_remove(ArrayList *list, long index);
void arraylist_add(ArrayList *list, char *filepath, char *stats, char *type, wchar_t *icon, int color, bool marked, bool force); void arraylist_add(ArrayList *list, char *filename, char *path, char *stats, char *type, wchar_t *icon, int color, bool marked, bool force);
char *get_line(ArrayList *list, long index, bool detail); char *get_line(ArrayList *list, long index, bool detail);
#endif #endif