From 1a590a5859207d5adb4f7a72d6b9ed1ab301e8c4 Mon Sep 17 00:00:00 2001 From: "@syxhe" Date: Sun, 26 Jan 2025 23:24:58 -0600 Subject: Reimplement dirname() as xdirname() --- src/shared.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 108 insertions(+), 7 deletions(-) (limited to 'src/shared.c') diff --git a/src/shared.c b/src/shared.c index 40240d5..c46b001 100644 --- a/src/shared.c +++ b/src/shared.c @@ -13,7 +13,11 @@ void* xcalloc(size_t nmemb, size_t size) { if(!mem) { #if defined ___VXGG___XALLOC_EXIT_ON_ERROR___ && ___VXGG___XALLOC_EXIT_ON_ERROR___ > 0 - error(1, errno, " Could not allocate memory"); + #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 + error(1, errno, " Could not allocate memory"); + #else + exit(EXIT_FAILURE); + #endif #endif abort(); @@ -27,8 +31,11 @@ void* xreallocarray(void *ptr, size_t nmemb, size_t size) { void *mem = reallocarray(ptr, nmemb, size); if(mem == NULL) { #if defined ___VXGG___XALLOC_EXIT_ON_ERROR___ && ___VXGG___XALLOC_EXIT_ON_ERROR___ > 0 - error(1, errno, " Could not allocate memory"); - + #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 + error(1, errno, " Could not allocate memory"); + #else + exit(EXIT_FAILURE); + #endif #endif abort(); @@ -56,7 +63,9 @@ int readwholebuffer(char **str, unsigned long int initsize, int fd) { tmp = realloc(lstr, csize * sizeof(char)); if(!tmp) { - error(0, errno, "Could not reallocate enough space for lstr"); + #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 + error(0, errno, "Could not reallocate enough space for lstr"); + #endif free(lstr); lstr = NULL; // Need to set this because of the break bytesread = -100; @@ -66,7 +75,9 @@ int readwholebuffer(char **str, unsigned long int initsize, int fd) { } } if(bytesread < 0 && bytesread != -100) { - error(0, errno, "Ran into a read() error"); + #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 + error(0, errno, "Ran into a read() error"); + #endif free(lstr); lstr = NULL; } @@ -74,7 +85,9 @@ int readwholebuffer(char **str, unsigned long int initsize, int fd) { if(lstr) { tmp = realloc(lstr, csize - ccap + 1); if(!tmp) { - error(0, errno, "Could not shrink lstr after reading buffer"); + #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 + error(0, errno, "Could not shrink lstr after reading buffer"); + #endif free(lstr); bytesread = -100; } @@ -107,4 +120,92 @@ int writewholebuffer(int fd, const unsigned char *buf, int len) { } // Adapted from Beej's `sendall()` function // https://beej.us/guide/bgnet/html/split/slightly-advanced-techniques.html#sendall - // Thanks Beej! \ No newline at end of file + // Thanks Beej! + +// dirname but less retarded hopefully +char *xdirname(const char * const path) { + char *tmp = NULL; + if(!path) { // Path being null is a special case which should return super early, before anything else + tmp = strdup("."); + if(!tmp) + abort(); + + return tmp; + } + + unsigned char flag = 0; + if(strcmp(path, ".") == 0) {tmp = strdup("."); flag++;} + if(strcmp(path, "/") == 0 && !flag) {tmp = strdup("/"); flag++;} + if(strcmp(path, "..") == 0 && !flag) {tmp = strdup("."); flag++;} + + if(flag) { + if(!tmp) + abort(); + + return tmp; + } + + + /* From the manpages: (man 3 dirname) + // +=======================================+ + // | path dirname basename | + // +=======================================+ + // | /usr/lib /usr lib | + // | /usr/ / usr | + // | usr . usr | + // +=======================================+ + */ + + // Get a temp copy of the path for manipulation purposes + tmp = strdup(path); + if(!tmp) + abort(); + + // If there's a trailing '/', delete it + size_t pathlen = strlen(path); + if(tmp[pathlen - 1] == '/') { + tmp[pathlen - 1] = '\0'; + pathlen--; + } + + // Ok, I think the easiest way to do this (if maybe a bit slow) is to count the number of '/'s in the string + // If there's only one, return '/' + // If there are 2 or more, find the last one in the list and set it to '\0' + + size_t count = 0; + for(size_t i = 0; i < pathlen; i++) { + if(tmp[i] == '/') + count++; + } + + if(count == 0) { + free(tmp); + tmp = strdup("."); + if(!tmp) + abort(); + + return tmp; + } + if(count == 1) { + free(tmp); + tmp = strdup("/"); + if(!tmp) + abort(); + + return tmp; + } + + for(size_t i = 0, c2 = 0; i < pathlen; i++) { + if(tmp[i] == '/') + c2++; + if(c2 == count) + tmp[i] = '\0'; + } + + char * const actual = strdup(tmp); + if(!actual) + abort(); + free(tmp); + + return actual; +} \ No newline at end of file -- cgit v1.2.3