Files
linuxSmartie/src/utils.c
2026-06-07 17:54:38 +02:00

126 lines
4.0 KiB
C

#include <errno.h>
#include <fcntl.h>
#include <glob.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
#include <time.h>
#include <unistd.h>
#include "log.h"
#include "utils.h"
int get_instance_lock(void) {
const char *xdg_runtime_dir = getenv("XDG_RUNTIME_DIR");
char tmp_dir[256];
snprintf(tmp_dir, sizeof(tmp_dir), "%s/linuxSmartie.lock", xdg_runtime_dir);
const int file = open(tmp_dir, O_CREAT | O_RDWR | O_CLOEXEC, 0600);
if (file < 0) {
applog(LOG_ERR, "Couldn't create a lock file at %s", tmp_dir);
return -1;
}
if (flock(file, LOCK_EX | LOCK_NB) < 0) {
if (errno == EWOULDBLOCK)
applog(LOG_ERR, "another instance already running, this one will exit.");
else
applog(LOG_ERR, "flock failed: %s", strerror(errno));
close(file);
return -1;
}
return 0;
}
inline void timespec_add_ms(struct timespec *ts, const uint16_t ms) {
ts->tv_nsec += ms * 1000000L;
if (ts->tv_nsec >= 1000000000L) {
ts->tv_sec++;
ts->tv_nsec -= 1000000000L;
}
}
inline uint64_t timespec_diff_us(const struct timespec *a, const struct timespec *b) {
const int64_t sec = a->tv_sec - b->tv_sec;
const int64_t nsec = a->tv_nsec - b->tv_nsec;
return sec * 1000000LL + nsec / 1000LL;
}
inline char *pretty_num(const double num, char *buf, const size_t bufsz) {
const uint8_t decimals = (num <= 10) ? 2 : (num <= 100) ? 1 : 0;
snprintf(buf, bufsz, "%.*f", decimals, num);
return buf;
}
inline char *pretty_bytes(const uint64_t bytes, int8_t start_suffix, char *buf, const size_t bufsz) {
const char suffix_list[] = {'K', 'M', 'G', 'T', 'P', 'E', 'Z'};
start_suffix *= -1;
double bytes_d = (double)bytes;
while (bytes_d >= 1024.0) {
bytes_d /= 1024.0;
start_suffix++;
}
snprintf(buf, bufsz, "%s%c", P_NUM(bytes_d), suffix_list[MAX(0, start_suffix)]);
return buf;
}
/* path has to have at least 8 free chars at the end for glob */
int get_hwmon_dir(char *path, const size_t bufsz) {
glob_t g;
strncat(path, "/hwmon*", 10);
if (glob(path, 0, NULL, &g) == 0) {
strncpy(path, g.gl_pathv[0], bufsz); // same size as hwmon length, careful
globfree(&g);
return 0;
}
return -1;
}
/* instead of building the path here we could build it once in *_detect funcs for each sensor, but thats a lot of paths damn
* actual slowdown is in the syscalls anyway, open(), read(), close () */
/* read n bytes from path into buffer */
inline size_t read_file(const char *dir, const char *file, char *buffer, const size_t n) {
char path[160]; // bug alert
char *nt = stpcpy(path, dir); // nt is a pointer to the null terminator of the copied string
stpcpy(nt, file); // write at the null terminator address, aka append to the end
const int fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
if (buffer != NULL) // if its null means we're just checking if it exists at all, so dont log it
applog(LOG_ERR, "Error reading %s", path);
return 0;
}
const ssize_t len = read(fd, buffer, n);
if (len >= 0 && buffer)
buffer[len] = '\0';
close(fd);
return len;
}
inline void fast_read_num_u64(const char *dir, const char *file, char *buf, uint64_t *result, const uint32_t divider) {
read_file(dir, file, buf, 32);
*result = strtoull(buf, NULL, 10) / divider;
}
inline void fast_read_num_u16(const char *dir, const char *file, char *buf, uint16_t *result, const uint32_t divider) {
read_file(dir, file, buf, 32);
*result = strtol(buf, NULL, 10) / divider;
}
inline void fast_read_num_u8(const char *dir, const char *file, char *buf, uint8_t *result, const uint32_t divider) {
read_file(dir, file, buf, 32);
*result = strtol(buf, NULL, 10) / divider;
}
inline void fast_read_num_i16(const char *dir, const char *file, char *buf, int16_t *result, const uint32_t divider) {
read_file(dir, file, buf, 32);
*result = (int16_t)(strtol(buf, NULL, 10) / divider);
}
inline void fast_read_num_f(const char *dir, const char *file, char *buf, float *result, const uint32_t divider) {
read_file(dir, file, buf, 32);
*result = (float)strtoull(buf, NULL, 10) / (float)divider;
}