#include "util.h" #include "config.h" #include "log.h" #include #include #include #include #include #include #include /** * \brief Backtrace buffer size */ #define BT_BUF_SIZE 100 /** * \brief The length of a MD5SUM string */ #define MD5_HASH_LEN 32 /** * \brief The length of the salt * \details This is basically the length of a UUID */ #define SALT_LEN 36 char *path_append(const char *path, const char *filename) { int needs_separator = 0; if ((path[strnlen(path, MAX_PATH_LEN) - 1] != '/') && (filename[0] != '/')) { needs_separator = 1; } char *str; size_t ul = strnlen(path, MAX_PATH_LEN); size_t sl = strnlen(filename, MAX_FILENAME_LEN); str = CALLOC(ul + sl + needs_separator + 1, sizeof(char)); strncpy(str, path, ul); if (needs_separator) { str[ul] = '/'; } strncat(str, filename, sl); return str; } char *escape_char(const char *url, const ESCAPE_CHAR c) { char escape_me; /* A space, for example, becomes thrice bigger as '%20' after escaping */ int how_bigger = 3; switch (c) { case ESCAPED_CHAR_SPACE: escape_me = ' '; break; default: lprintf(error, "unknown character to escape: %d\n", c); return NULL; } if (!strchr(url, escape_me)) { return NULL; } int len = strnlen(url, MAX_PATH_LEN); /* Best case scenario of only one character to escape */ if (len + 3 > MAX_PATH_LEN) { lprintf(fatal, "URL too long: %s\n", url); } char *escaped = CALLOC(MAX_PATH_LEN, sizeof(char)); int j = 0, k = 0; for (int i = 0; i < len; i++) { /* Precaution against writing beyond the buffer, since we do not count * all spaces beforehand to know the exact amount of memory to calloc * for the escaped URL. */ if (k > MAX_PATH_LEN) { lprintf(fatal, "URL too long: %s\n", url); } if (url[i] == escape_me) { switch (c) { case ESCAPED_CHAR_SPACE: strncpy(escaped + j, "%20", how_bigger); break; } k = j + how_bigger; j = k; } else { escaped[j++] = url[i]; } } return escaped; } int64_t round_div(int64_t a, int64_t b) { return (a + (b / 2)) / b; } void PTHREAD_MUTEX_UNLOCK(pthread_mutex_t *x) { int i; i = pthread_mutex_unlock(x); if (i) { lprintf(fatal, "thread %x: %d, %s\n", pthread_self(), i, strerror(i)); } } void PTHREAD_MUTEX_LOCK(pthread_mutex_t *x) { int i; i = pthread_mutex_lock(x); if (i) { lprintf(fatal, "thread %x: %d, %s\n", pthread_self(), i, strerror(i)); } } void exit_failure(void) { int nptrs; void *buffer[BT_BUF_SIZE]; nptrs = backtrace(buffer, BT_BUF_SIZE); fprintf(stderr, "\nOops! HTTPDirFS crashed! :(\n"); fprintf(stderr, "backtrace() returned the following %d addresses:\n", nptrs); backtrace_symbols_fd(buffer, nptrs, STDERR_FILENO); exit(EXIT_FAILURE); } void erase_string(FILE *file, size_t max_len, char *s) { size_t l = strnlen(s, max_len); for (size_t k = 0; k < l; k++) { fprintf(file, "\b"); } for (size_t k = 0; k < l; k++) { fprintf(file, " "); } for (size_t k = 0; k < l; k++) { fprintf(file, "\b"); } } char *generate_salt(void) { char *out; out = CALLOC(SALT_LEN + 1, sizeof(char)); uuid_t uu; uuid_generate(uu); uuid_unparse(uu, out); return out; } char *generate_md5sum(const char *str) { MD5_CTX c; unsigned char md5[MD5_DIGEST_LENGTH]; size_t len = strnlen(str, MAX_PATH_LEN); char *out = CALLOC(MD5_HASH_LEN + 1, sizeof(char)); MD5_Init(&c); MD5_Update(&c, str, len); MD5_Final(md5, &c); for (int i = 0; i < MD5_DIGEST_LENGTH; i++) { sprintf(out + 2 * i, "%02x", md5[i]); } return out; } void *CALLOC(size_t nmemb, size_t size) { void *ptr = calloc(nmemb, size); if (!ptr) { lprintf(fatal, "%s!\n", strerror(errno)); } return ptr; } void FREE(void *ptr) { if (ptr) { free(ptr); } else { lprintf(fatal, "attempted to free NULL ptr!\n"); } } char *str_to_hex(char *s) { char *hex = CALLOC(strnlen(s, MAX_PATH_LEN) * 2 + 1, sizeof(char)); for (char *c = s, *h = hex; *c; c++, h += 2) { sprintf(h, "%x", *c); } return hex; }