From 16d7786c3002dc334ce285a3f96e10ce537613d9 Mon Sep 17 00:00:00 2001 From: xiaoji <345865759@163.com> Date: Tue, 4 Jun 2024 19:59:14 +0800 Subject: [PATCH] fixed get uuid when in virtual machine --- CONTRIBUTORS | 8 +++ ldevice.c | 138 ++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 117 insertions(+), 29 deletions(-) create mode 100644 CONTRIBUTORS diff --git a/CONTRIBUTORS b/CONTRIBUTORS new file mode 100644 index 0000000..5a59f4c --- /dev/null +++ b/CONTRIBUTORS @@ -0,0 +1,8 @@ +赵振 (jeremiazhao@tencent.com) +陶松桥 (joeytao@tencent.com) +朱延朋 (rockerzhu@tencent.com) +吴涛 (tallwu@tencent.com) +吴德胜 (deshengwu@tencent.com) +练海富 (haifulian@tencent.com) +陈晓杰 (jackxjchen@tencent.com) +夏存舜 (cunshunxia@tencent.com) \ No newline at end of file diff --git a/ldevice.c b/ldevice.c index c6f7772..211a253 100644 --- a/ldevice.c +++ b/ldevice.c @@ -199,48 +199,67 @@ const char* system_get_uuid() { } const char* system_get_cpu() { - static char cpu_model[512]; - char cpu_tmp[512]; - FILE* fp = fopen("/proc/cpuinfo", "r"); - if(fp == NULL) { - printf("Failed to open /proc/cpuinfo\n"); - return NULL; - } + static char cpu_model[1024]; + char cpu_tmp[512]; - while(fgets(cpu_tmp, sizeof(cpu_tmp), fp) != NULL) { - if ( strstr(cpu_tmp, "model name") && strncmp(strstr(cpu_tmp, "model name"), "model name", 10) == 0 ) { + // try phisical machine + FILE* model_name = popen("lscpu | grep 'Model name:' | cut -d: -f2", "r"); + if(model_name == NULL) { + printf("Failed to open /proc/cpuinfo\n"); + return NULL; + } + if(fgets(cpu_tmp, sizeof(cpu_tmp), model_name) != NULL) { + if ( cpu_tmp[0] != '-' && cpu_tmp[0] != '\n' && strlen(cpu_tmp) != 0 ) { // 先获取一个cpu核心的model name,示例Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz // 删除可能出现的换行符 if ( cpu_tmp[strlen(cpu_tmp) - 1] == '\n' ) { cpu_tmp[strlen(cpu_tmp) - 1] = '\0'; } - // 获取第一个token - char* token = strtok(cpu_tmp, "\t:\t"); - // 获取第二个token - token = strtok(NULL, "\t:\t"); - // 删除token开头的空格或制表符 - while(isspace(*token)) { - token++; - } - // 删除token结尾的空格或制表符 - while( strlen(token) > 0 && ( token[strlen(token)-1] == ' ' || token[strlen(token)-1] == '\t' ) ) { - token[strlen(token)-1] = '\0'; - } // 获取cpu核心数,并添加到model中 long cpu_count_long = sysconf(_SC_NPROCESSORS_ONLN); char cpu_count_str[10]; sprintf(cpu_count_str, "%ld", cpu_count_long); - strcat(token, " x "); - strcat(token, cpu_count_str); + strcat(cpu_tmp, " x "); + strcat(cpu_tmp, cpu_count_str); // 最终形式为Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz x 8 - memmove(cpu_model, token, strlen(token)); - fclose(fp); + memmove(cpu_model, cpu_tmp, strlen(cpu_tmp)); + pclose(model_name); + printf("%s\n", cpu_model); + return cpu_model; + } + } + + pclose(model_name); + + + // try virtual machine + FILE* vendor_id = popen("lscpu | grep 'Vendor ID:' | cut -d: -f2", "r"); + if(vendor_id == NULL) { + printf("Failed to open /proc/cpuinfo\n"); + return NULL; + } + if(fgets(cpu_tmp, sizeof(cpu_tmp), vendor_id) != NULL) { + if ( cpu_tmp[0] != '-' && cpu_tmp[0] != '\n' && strlen(cpu_tmp) != 0 ) { + // 先获取一个cpu核心的model name,示例Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz + // 删除可能出现的换行符 + if ( cpu_tmp[strlen(cpu_tmp) - 1] == '\n' ) { + cpu_tmp[strlen(cpu_tmp) - 1] = '\0'; + } + + // 最终为apple之类的形式 + memmove(cpu_model, cpu_tmp, strlen(cpu_tmp)); + pclose(vendor_id); + printf("%s\n", cpu_model); return cpu_model; } } + pclose(vendor_id); + + + perror("Cannot get CPU info\n"); return NULL; } @@ -346,8 +365,64 @@ const char* system_get_mac() { return NULL; } -// 获取/boot所在的文件系统挂载点,再获取该挂载点所属物理硬盘接口名,最后获取硬盘wwid -// 可能不支持虚拟机 +// 虚拟机条件下,获取根分区文件系统uuid +const char* system_get_blkid() { + static char uuid[256]; + FILE *fp; + char line[256]; + char device[64], mount_point[64], fs_type[32]; + + fp = fopen("/proc/mounts", "r"); + if (fp == NULL) { + perror("Failed to open /proc/mounts"); + return NULL; + } + + while (fgets(line, sizeof(line), fp)) { + sscanf(line, "%63s %63s %31s", device, mount_point, fs_type); + if (strcmp(mount_point, "/") == 0) { + break; + } + } + + fclose(fp); + + if (strcmp(mount_point, "/") != 0) { + fprintf(stderr, "Root filesystem not found\n"); + return NULL; + } + + char command[128]; + snprintf(command, sizeof(command), "blkid %s", device); + + fp = popen(command, "r"); + if (fp == NULL) { + perror("Failed to run blkid command"); + return NULL; + } + + while (fgets(line, sizeof(line), fp)) { + char *uuid_pos = strstr(line, " UUID="); + if (uuid_pos) { + uuid_pos += 6; // Move past " UUID=" + char *end = strchr(uuid_pos, ' '); + if (end) { + *end = '\0'; + } + strncpy(uuid, uuid_pos, sizeof(uuid) - 1); + uuid[sizeof(uuid) - 1] = '\0'; // Ensure null-terminated + pclose(fp); + return uuid; + } + } + + pclose(fp); + // todo + return "unkown disk"; +} + +// 物理机条件下,获取/boot所在的文件系统挂载点,再获取该挂载点所属物理硬盘接口名,最后获取硬盘wwid +// 如果获取不到wwid,将采用虚拟机方案 const char* system_get_disk_uuid() { const char *path = "/boot"; struct stat statbuf; @@ -375,7 +450,7 @@ const char* system_get_disk_uuid() { printf("Failed to get device.\n"); return NULL; } - + // 获取这个设备的父设备 dev = udev_device_get_parent_with_subsystem_devtype( dev, @@ -388,8 +463,13 @@ const char* system_get_disk_uuid() { } if (!udev_device_get_sysattr_value(dev, "wwid")) { - fprintf(stderr, "WWID attribute not found\n"); + fprintf(stderr, "WWID attribute not found, maybe a virtual machine\n"); udev_unref(udev); + // 获取不到wwid时,尝试获取blkid + const char * blkid = system_get_blkid(); + if (blkid) { + return blkid; + } return NULL; } -- Gitee