I recently finished a high school project of mine for a class revolving around creating my own multithreaded implementation of the "cp" terminal command in UNIX systems.
I am seeking for help by experienced people in C to help me make my code better, offering constructive criticism all while improving myself at the same time.
Specifically:
- Can my code become faster than it currently is?
- Are there any potential runtime errors in my code? ( I have tested it with multiple examples and all would work fine, I'm just trying to find the ones I didn't think of)
- Does my code have a good overall structure?
Points of interest:
src/crawler.c
#include "../headers/crawler.h"
int dircrawler(char* path, char* dest, int pathsize)
{
// dirent variables and structures
DIR* dp;
struct dirent* entry;
// buffers
size_t bufsize;
char *buf1, *buf2;
buf1 = buf2 = NULL;
struct cp_thr_args* args = NULL;
if ((dp = opendir(path)) != NULL) {
while ((entry = readdir(dp)) != NULL) {
// skip over . and ..
if (!(strcmp(entry->d_name, ".")) || !(strcmp(entry->d_name, "..")))
continue;
if (buf1 != NULL)
free(buf1);
if (buf2 != NULL)
free(buf2);
// printf("%s\n",entry->d_name);
// buf1: absolute new path, buf2: relative destination path
bufsize = snprintf(NULL, 0, "%s/%s", path, entry->d_name) + 1;
mmalloc(&buf1, bufsize); // buf1
snprintf(buf1, bufsize, "%s/%s", path, entry->d_name);
bufsize = snprintf(NULL, 0, "%s%s/%s", dest, (path + pathsize - 1), entry->d_name) + 1;
mmalloc(&buf2, bufsize); // buf2
snprintf(buf2, bufsize, "%s%s/%s", dest, (path + pathsize), entry->d_name);
if (entry->d_type == DT_DIR) {
// make new directory in dest
mkdir(buf2, 0755);
if (dircrawler(buf1, dest, pathsize))
closedir(dp);
} else {
// thread copying section
int found = 1;
while (1) { // ((Point of interest))
// trying to find a non occupied thread
// using status[]
for (int i = 0; i < THREADCOUNT; ++i) {
if (status[i] == 1) {
cp_thr_init(&args, buf1, buf2, &status[i]);
pthread_create(&cpthr[i], NULL, cp_thr, (void*)args);
pthread_barrier_wait(&can_free);
cp_thr_free(args);
found = 0;
break;
}
}
if (!found)
break;
}
}
}
if (buf1 != NULL)
free(buf1);
if (buf2 != NULL)
free(buf2);
closedir(dp);
return 0;
}
}
src/threads.c
#include "../headers/threads.h"
int status[THREADCOUNT] = { 1, 1, 1, 1 };
pthread_mutex_t cp_lock = PTHREAD_MUTEX_INITIALIZER;
void* cp_thr(void* args)
{
// extract args data before it gets rewritten
struct cp_thr_args* temp = args;
char* from;
mmalloc(&from, return_size(temp->from) + 1);
char* dest;
mmalloc(&dest, return_size(temp->dest) + 1);
int* status = temp->status;
strcpy(from, temp->from);
strcpy(dest, temp->dest);
// send signal to release barrier and free args from crawl
pthread_barrier_wait(&can_free); // ((Point of interest))
// assign status to 0 to mark thread as occupied
pthread_mutex_lock(&cp_lock);
*status = 0;
pthread_mutex_unlock(&cp_lock);
copy_file(from, dest);
free(from);
free(dest);
// assign status to 1 to mark thread as free to use
pthread_mutex_lock(&cp_lock);
*status = 1;
pthread_mutex_unlock(&cp_lock);
return (void*)0;
}