#define _XOPEN_SOURCE 500 #include #include #include #include #include #include #include #include "util.h" #include "error.h" #include "uio.h" void util_byte2hex(const uint8_t* bytes, size_t bytes_len, bool uppercase, char* out) { const char* hex = (uppercase) ? "0123456789ABCDEF" : "0123456789abcdef"; for (size_t i = 0; i < bytes_len; i++) { *out++ = hex[bytes[i] >> 4]; *out++ = hex[bytes[i] & 0xF]; } *out = '\0'; } void util_hex2byte(const char *str, uint8_t* out_bytes) { while (*str) { if (*str >= '0' && *str <= '9') *out_bytes = (*str - '0') << 4; if (*str >= 'A' && *str <= 'F') *out_bytes = (*str - ('A' - 10)) << 4; else *out_bytes = (*str - ('a' - 10)) << 4; str++; if (*str >= '0' && *str <= '9') *out_bytes |= (*str - '0'); if (*str >= 'A' && *str <= 'F') *out_bytes |= (*str - ('A' - 10)); else *out_bytes |= (*str - ('a' - 10)); out_bytes++; str++; } } const char *util_get_home() { const char *home_env = getenv("HOME"); return home_env; /* TODO this can be null, use other methods as fallback */ } char *util_basename(const char *fullpath) { char *name_part = strrchr(fullpath, '/'); if (name_part) name_part++; else name_part = (char*)fullpath; return name_part; } uint64_t util_timespec_diff(const struct timespec *past, const struct timespec *future) { int64_t sdiff = future->tv_sec - past->tv_sec; int64_t nsdiff = future->tv_nsec - past->tv_nsec; return sdiff * 1000 + (nsdiff / 1000000); } uint64_t util_iso2unix(const char *isotime) { struct tm tm = {0}; char *ms = strptime(isotime, "%Y-%m-%d", &tm); if (!ms || (*ms != '\0' && *ms != ' ' && *ms != 'T')) return 0; if (*ms == '\0') ms = "T00:00:00"; ms = strptime(ms + 1, "%H:%M", &tm); if (!ms || (*ms != '\0' && *ms != ':')) return 0; if (*ms == '\0') ms = ":00"; ms = strptime(ms + 1, "%S", &tm); if (!ms) return 0; return mktime(&tm); } /* nftw doesn't support passing in user data to the callback function :/ */ static util_itercb global_iterpath_cb = NULL; static void *global_iterpath_data = NULL; static int util_iterpath_walk(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { if (typeflag == FTW_DNR) { uio_error("Cannot read directory '%s'. Skipping", fpath); return NOERR; } if (typeflag == FTW_D) return NOERR; if (typeflag != FTW_F) { uio_error("Unhandled error '%d'", typeflag); return ERR_ITERPATH; } return global_iterpath_cb(fpath, sb, global_iterpath_data); } enum error util_iterpath(const char *path, util_itercb cb, void *data) { assert(global_iterpath_cb == NULL); enum error ret = ERR_ITERPATH; struct stat ts; if (stat(path, &ts) != 0) { uio_error("Stat failed for path: '%s' (%s)", path, strerror(errno)); goto error; } if (S_ISREG(ts.st_mode)) { /* If the path is a regular file, call the cb once */ ret = cb(path, &ts, data); goto end; } else if (S_ISDIR(ts.st_mode)) { global_iterpath_cb = cb; global_iterpath_data = data; /* If a directory, walk over it */ ret = nftw(path, util_iterpath_walk, 20, 0); if (ret == -1) { uio_error("nftw failure"); goto error; } goto end; } uio_error("Unsupported file type: %d", ts.st_mode & S_IFMT); end: global_iterpath_cb = global_iterpath_data = NULL; return ret; error: ret = ERR_ITERPATH; goto end; }