|
@@ -0,0 +1,140 @@
|
|
|
|
|
+#include "common.h"
|
|
|
|
|
+#include <ctype.h>
|
|
|
|
|
+#include <sys/time.h>
|
|
|
|
|
+#include <sys/stat.h>
|
|
|
|
|
+#include <sys/types.h>
|
|
|
|
|
+
|
|
|
|
|
+/* 全局日志回调 */
|
|
|
|
|
+LogCallback g_log_callback = NULL;
|
|
|
|
|
+
|
|
|
|
|
+void set_log_callback(LogCallback cb) {
|
|
|
|
|
+ g_log_callback = cb;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+char* get_timestamp(char* buf, size_t bufsize, const char* fmt) {
|
|
|
|
|
+ time_t now = time(NULL);
|
|
|
|
|
+ struct tm* tm_info = localtime(&now);
|
|
|
|
|
+
|
|
|
|
|
+ if (fmt == NULL) {
|
|
|
|
|
+ fmt = "%Y-%m-%d %H:%M:%S";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ strftime(buf, bufsize, fmt, tm_info);
|
|
|
|
|
+ return buf;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+char* str_tolower(char* str) {
|
|
|
|
|
+ char* p = str;
|
|
|
|
|
+ while (*p) {
|
|
|
|
|
+ *p = tolower((unsigned char)*p);
|
|
|
|
|
+ p++;
|
|
|
|
|
+ }
|
|
|
|
|
+ return str;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+size_t safe_strcpy(char* dest, const char* src, size_t size) {
|
|
|
|
|
+ if (size == 0 || src == NULL) return 0;
|
|
|
|
|
+
|
|
|
|
|
+ size_t len = strlen(src);
|
|
|
|
|
+ if (len >= size) {
|
|
|
|
|
+ len = size - 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ memcpy(dest, src, len);
|
|
|
|
|
+ dest[len] = '\0';
|
|
|
|
|
+ return len;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 简单的文件写入工具 */
|
|
|
|
|
+int write_file(const char* path, const char* content) {
|
|
|
|
|
+ FILE* fp = fopen(path, "w");
|
|
|
|
|
+ if (fp == NULL) {
|
|
|
|
|
+ LOG_ERROR("Failed to open file: %s, error: %s", path, strerror(errno));
|
|
|
|
|
+ return FAILURE;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ fprintf(fp, "%s", content);
|
|
|
|
|
+ fclose(fp);
|
|
|
|
|
+ return SUCCESS;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 读取配置文件(简单键值对格式) */
|
|
|
|
|
+char* read_config_value(const char* file, const char* key) {
|
|
|
|
|
+ static char value[256];
|
|
|
|
|
+ FILE* fp = fopen(file, "r");
|
|
|
|
|
+ if (fp == NULL) {
|
|
|
|
|
+ LOG_ERROR("Failed to open config file: %s", file);
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ char line[512];
|
|
|
|
|
+ while (fgets(line, sizeof(line), fp)) {
|
|
|
|
|
+ /* 跳过注释和空行 */
|
|
|
|
|
+ if (line[0] == '#' || line[0] == ';' || line[0] == '\n') continue;
|
|
|
|
|
+
|
|
|
|
|
+ /* 移除换行符 */
|
|
|
|
|
+ line[strcspn(line, "\n")] = '\0';
|
|
|
|
|
+
|
|
|
|
|
+ char* eq = strchr(line, '=');
|
|
|
|
|
+ if (eq != NULL) {
|
|
|
|
|
+ *eq = '\0';
|
|
|
|
|
+ if (strcmp(line, key) == 0) {
|
|
|
|
|
+ safe_strcpy(value, eq + 1, sizeof(value));
|
|
|
|
|
+ fclose(fp);
|
|
|
|
|
+ return value;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ fclose(fp);
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 确保目录存在 */
|
|
|
|
|
+int ensure_directory(const char* path) {
|
|
|
|
|
+ struct stat st;
|
|
|
|
|
+ if (stat(path, &st) == 0) {
|
|
|
|
|
+ return S_ISDIR(st.st_mode) ? SUCCESS : FAILURE;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* 递归创建目录 */
|
|
|
|
|
+ char tmp[MAX_PATH_SIZE];
|
|
|
|
|
+ safe_strcpy(tmp, path, sizeof(tmp));
|
|
|
|
|
+
|
|
|
|
|
+ char* p = tmp;
|
|
|
|
|
+ while (*p) {
|
|
|
|
|
+ if (*p == '/') {
|
|
|
|
|
+ *p = '\0';
|
|
|
|
|
+ mkdir(tmp, 0755);
|
|
|
|
|
+ *p = '/';
|
|
|
|
|
+ }
|
|
|
|
|
+ p++;
|
|
|
|
|
+ }
|
|
|
|
|
+ mkdir(tmp, 0755);
|
|
|
|
|
+ return SUCCESS;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 生成唯一ID */
|
|
|
|
|
+static int g_id_counter = 0;
|
|
|
|
|
+int generate_id(void) {
|
|
|
|
|
+ return ++g_id_counter;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 睡眠(可中断) */
|
|
|
|
|
+int sleep_milliseconds(int ms) {
|
|
|
|
|
+ struct timespec ts;
|
|
|
|
|
+ ts.tv_sec = ms / 1000;
|
|
|
|
|
+ ts.tv_nsec = (ms % 1000) * 1000000L;
|
|
|
|
|
+ return nanosleep(&ts, NULL);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 获取当前毫秒时间戳 */
|
|
|
|
|
+long long get_current_ms(void) {
|
|
|
|
|
+ struct timeval tv;
|
|
|
|
|
+ gettimeofday(&tv, NULL);
|
|
|
|
|
+ return (long long)tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 获取当前秒时间戳 */
|
|
|
|
|
+long long get_current_s(void) {
|
|
|
|
|
+ return (long long)time(NULL);
|
|
|
|
|
+}
|