/* * revdep - reverse dependency checker for rawnix * util.c - string, path, and logging utilities * * Copyright (c) 2025 zorz@gmx.com * Licensed under the BSD 2-Clause License. See revdep.h. */ #define _POSIX_C_SOURCE 200809L #define _DEFAULT_SOURCE #include "revdep.h" #include #include #include #include #include #include int verbosity = V_QUIET; /* --- logging --------------------------------------------------------- */ void msg(int level, const char *fmt, ...) { va_list ap; if (level > verbosity) return; va_start(ap, fmt); vfprintf(stdout, fmt, ap); va_end(ap); fflush(stdout); } /* --- string utilities ------------------------------------------------ */ char * xstrdup(const char *s) { char *d; size_t n; if (!s) return NULL; n = strlen(s); d = malloc(n + 1); if (!d) { fprintf(stderr, "revdep: out of memory\n"); exit(1); } memcpy(d, s, n + 1); return d; } char * xpathjoin(const char *dir, const char *file) { size_t dlen, flen; char *buf; if (!dir || !file) return NULL; dlen = strlen(dir); flen = strlen(file); buf = malloc(dlen + 1 + flen + 1); if (!buf) { fprintf(stderr, "revdep: out of memory\n"); exit(1); } memcpy(buf, dir, dlen); buf[dlen] = '/'; memcpy(buf + dlen + 1, file, flen + 1); return buf; } void strsplit(const char *s, char delim, strvec_t *v) { const char *p, *end; char *tok; size_t len; if (!s || !v) return; p = s; while ((end = strchr(p, delim)) != NULL) { len = (size_t)(end - p); if (len > 0) { tok = malloc(len + 1); if (tok) { memcpy(tok, p, len); tok[len] = '\0'; strvec_push(v, tok); free(tok); } } p = end + 1; } if (*p) strvec_push(v, p); } /* --- path utilities -------------------------------------------------- */ bool is_regfile(const char *path) { struct stat st; if (!path) return false; if (lstat(path, &st) == -1) return false; return S_ISREG(st.st_mode); } char * realpath_safe(const char *path) { char *resolved; if (!path) return NULL; resolved = realpath(path, NULL); return resolved; } /* --- strvec ---------------------------------------------------------- */ void strvec_init(strvec_t *v) { v->items = NULL; v->count = 0; v->capacity = 0; } void strvec_free(strvec_t *v) { size_t i; if (!v) return; for (i = 0; i < v->count; i++) free(v->items[i]); free(v->items); v->items = NULL; v->count = 0; v->capacity = 0; } bool strvec_push(strvec_t *v, const char *s) { size_t newcap; char **tmp; if (!v || !s) return false; if (v->count >= v->capacity) { newcap = v->capacity == 0 ? 8 : v->capacity * 2; tmp = realloc(v->items, newcap * sizeof(char *)); if (!tmp) return false; v->items = tmp; v->capacity = newcap; } v->items[v->count] = xstrdup(s); v->count++; return true; } bool strvec_contains(const strvec_t *v, const char *s) { size_t i; if (!v || !s) return false; for (i = 0; i < v->count; i++) { if (strcmp(v->items[i], s) == 0) return true; } return false; }