foxygit / ytmdl Log in
commits tags

/c/src/util.c · 2.06 KB

raw
#include "util.h"

#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

void safe_strcpy(char *dst, size_t dst_size, const char *src) {
    if (dst_size == 0) return;
    size_t n = strlen(src);
    if (n >= dst_size) n = dst_size - 1;
    memcpy(dst, src, n);
    dst[n] = '\0';
}

static int is_illegal_dirname_char(unsigned char c) {
    if (c < 0x20) return 1;
    switch (c) {
        case '<': case '>': case ':': case '"':
        case '/': case '\\': case '|': case '?': case '*':
            return 1;
        default:
            return 0;
    }
}

void sanitize_dirname(const char *name, char *dst, size_t dst_size) {
    if (dst_size == 0) return;

    char tmp[1024];
    size_t out = 0;
    int last_was_space = 0;

    for (const unsigned char *p = (const unsigned char *)name; *p && out + 1 < sizeof(tmp); p++) {
        unsigned char c = *p;
        if (is_illegal_dirname_char(c)) c = '_';
        if (isspace(c)) {
            if (last_was_space) continue;
            last_was_space = 1;
            tmp[out++] = ' ';
        } else {
            last_was_space = 0;
            tmp[out++] = (char)c;
        }
    }
    tmp[out] = '\0';

    /* strip leading/trailing spaces and dots */
    char *start = tmp;
    while (*start == ' ' || *start == '.') start++;
    char *end = start + strlen(start);
    while (end > start && (end[-1] == ' ' || end[-1] == '.')) end--;
    *end = '\0';

    if (*start == '\0') {
        safe_strcpy(dst, dst_size, "playlist");
    } else {
        safe_strcpy(dst, dst_size, start);
    }
}

int mkdir_p(const char *path) {
    char tmp[1024];
    safe_strcpy(tmp, sizeof(tmp), path);
    size_t len = strlen(tmp);
    if (len == 0) {
        errno = EINVAL;
        return -1;
    }
    if (tmp[len - 1] == '/') tmp[len - 1] = '\0';

    for (char *p = tmp + 1; *p; p++) {
        if (*p == '/') {
            *p = '\0';
            if (mkdir(tmp, 0755) != 0 && errno != EEXIST) return -1;
            *p = '/';
        }
    }
    if (mkdir(tmp, 0755) != 0 && errno != EEXIST) return -1;
    return 0;
}