]>
glassweightruler.freedombox.rocks Git - Ventoy.git/blob - VtoyTool/vtoyexpand.c
1 /******************************************************************************
2 * vtoyexpand.c ---- ventoy auto install script variable expansion
4 * Copyright (c) 2022, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
28 #include <sys/types.h>
30 #include <sys/ioctl.h>
32 #include <sys/types.h>
41 #define TMP_FILE "/ventoy/tmp_var_expansion"
43 #define SIZE_1MB (1024 * 1024)
44 #define ulong unsigned long
45 #define ulonglong unsigned long long
47 typedef struct disk_info
55 static disk_info
*g_disk_list
= NULL
;
56 static int g_disk_num
= 0;
57 static const char *g_vtoy_disk_name
= NULL
;
59 static void vlog(const char *fmt
, ...)
66 fp
= fopen("/ventoy/autoinstall.log", "a+");
70 n
+= vsnprintf(log
, sizeof(log
) - 1, fmt
, arg
);
73 fwrite(log
, 1, n
, fp
);
78 static int copy_file(const char *file1
, const char *file2
)
87 fp1
= fopen(file1
, "rb");
90 vlog("Failed to read file <%s>\n", file1
);
94 fp2
= fopen(file2
, "wb+");
97 vlog("Failed to create file <%s>\n", file2
);
101 fseek(fp1
, 0, SEEK_END
);
102 size
= (int)ftell(fp1
);
103 fseek(fp1
, 0, SEEK_SET
);
108 vlog("Failed to malloc buf\n");
112 n
= fread(buf
, 1, size
, fp1
);
115 vlog("Failed to read <%s> %d %d\n", file1
, n
, size
);
119 n
= fwrite(buf
, 1, size
, fp2
);
122 vlog("Failed to write <%s> %d %d\n", file2
, n
, size
);
140 static int vtoy_is_possible_blkdev(const char *name
)
148 if (name
[0] == 'r' && name
[1] == 'a' && name
[2] == 'm')
154 if (name
[0] == 'l' && name
[1] == 'o' && name
[2] == 'o' && name
[3] == 'p')
160 if (name
[0] == 'd' && name
[1] == 'm' && name
[2] == '-' && IS_DIGIT(name
[3]))
166 if (name
[0] == 's' && name
[1] == 'r' && (name
[2] >= '0' && name
[2] <= '9'))
174 static ulonglong
vtoy_get_disk_size_in_byte(const char *disk
)
178 unsigned long long size
= 0;
179 char diskpath
[256] = {0};
180 char sizebuf
[64] = {0};
182 // Try 1: get size from sysfs
183 snprintf(diskpath
, sizeof(diskpath
) - 1, "/sys/block/%s/size", disk
);
184 if (access(diskpath
, F_OK
) >= 0)
186 vlog("get disk size from sysfs for %s\n", disk
);
188 fd
= open(diskpath
, O_RDONLY
| O_BINARY
);
191 read(fd
, sizebuf
, sizeof(sizebuf
));
192 size
= strtoull(sizebuf
, NULL
, 10);
199 vlog("%s not exist \n", diskpath
);
202 // Try 2: get size from ioctl
203 snprintf(diskpath
, sizeof(diskpath
) - 1, "/dev/%s", disk
);
204 fd
= open(diskpath
, O_RDONLY
);
207 vlog("get disk size from ioctl for %s\n", disk
);
208 rc
= ioctl(fd
, BLKGETSIZE64
, &size
);
212 vlog("failed to ioctl %d\n", rc
);
218 vlog("failed to open %s %d\n", diskpath
, errno
);
221 vlog("disk %s size %llu bytes\n", disk
, (ulonglong
)size
);
225 static int get_disk_num(void)
229 struct dirent
* p
= NULL
;
231 dir
= opendir("/sys/block");
237 while ((p
= readdir(dir
)) != NULL
)
246 static int is_usb_disk(const char *diskname
)
249 char dstpath
[1024] = { 0 };
250 char syspath
[1024] = { 0 };
252 snprintf(syspath
, sizeof(syspath
), "/sys/block/%s", diskname
);
253 rc
= readlink(syspath
, dstpath
, sizeof(dstpath
) - 1);
254 if (rc
> 0 && strstr(dstpath
, "/usb"))
262 static int get_all_disk(void)
267 ulonglong cursize
= 0;
269 struct dirent
* p
= NULL
;
270 disk_info
*node
= NULL
;
273 num
= get_disk_num();
279 g_disk_list
= malloc(num
* sizeof(disk_info
));
284 memset(g_disk_list
, 0, num
* sizeof(disk_info
));
286 dir
= opendir("/sys/block");
292 while (((p
= readdir(dir
)) != NULL
) && g_disk_num
< num
)
294 if (!vtoy_is_possible_blkdev(p
->d_name
))
296 vlog("disk %s is filted by name\n", p
->d_name
);
300 cursize
= vtoy_get_disk_size_in_byte(p
->d_name
);
302 node
= g_disk_list
+ g_disk_num
;
306 snprintf(node
->name
, sizeof(node
->name
), p
->d_name
);
307 node
->size
= cursize
;
308 node
->isUSB
= is_usb_disk(p
->d_name
);
309 if (strncmp(node
->name
, "sd", 2) == 0)
317 for (i
= 0; i
< g_disk_num
; i
++)
319 for (j
= i
+ 1; j
< g_disk_num
; j
++)
321 if (g_disk_list
[i
].isSDX
&& g_disk_list
[j
].isSDX
)
323 if (strcmp(g_disk_list
[i
].name
, g_disk_list
[j
].name
) > 0)
325 memcpy(&tmpnode
, g_disk_list
+ i
, sizeof(tmpnode
));
326 memcpy(g_disk_list
+ i
, g_disk_list
+ j
, sizeof(tmpnode
));
327 memcpy(g_disk_list
+ j
, &tmpnode
, sizeof(tmpnode
));
333 vlog("============ DISK DUMP BEGIN ===========\n");
334 for (i
= 0; i
< g_disk_num
; i
++)
336 node
= g_disk_list
+ i
;
337 vlog("[%d] %s %dGB(%llu) USB:%d\n", i
, node
->name
,
338 node
->size
/ 1024 / 1024 / 1024, node
->size
, node
->isUSB
);
340 vlog("============ DISK DUMP END ===========\n");
345 static int expand_var(const char *var
, char *value
, int len
)
351 ulonglong maxsize
= 0;
352 ulonglong maxdelta
= 0xFFFFFFFFFFFFFFFFULL
;
353 disk_info
*node
= NULL
;
356 if (strcmp(var
, "VT_LINUX_DISK_SDX_1ST_NONVTOY") == 0)
358 for (i
= 0; i
< g_disk_num
; i
++)
360 node
= g_disk_list
+ i
;
361 if (node
->size
> 0 && node
->isSDX
&& strcmp(node
->name
, g_vtoy_disk_name
) != 0)
363 vlog("%s=<%s>\n", var
, node
->name
);
364 snprintf(value
, len
, "%s", node
->name
);
369 vlog("[Error] %s not found\n", var
);
371 else if (strcmp(var
, "VT_LINUX_DISK_SDX_1ST_NONUSB") == 0)
373 for (i
= 0; i
< g_disk_num
; i
++)
375 node
= g_disk_list
+ i
;
376 if (node
->size
> 0 && node
->isSDX
&& node
->isUSB
== 0)
378 vlog("%s=<%s>\n", var
, node
->name
);
379 snprintf(value
, len
, "%s", node
->name
);
384 vlog("[Error] %s not found\n", var
);
386 else if (strcmp(var
, "VT_LINUX_DISK_MAX_SIZE") == 0)
388 for (i
= 0; i
< g_disk_num
; i
++)
390 node
= g_disk_list
+ i
;
391 if (node
->size
> 0 && node
->size
> maxsize
)
394 maxsize
= node
->size
;
400 vlog("%s=<%s>\n", var
, g_disk_list
[index
].name
);
401 snprintf(value
, len
, "%s", g_disk_list
[index
].name
);
406 vlog("[Error] %s not found\n", var
);
409 else if (strncmp(var
, "VT_LINUX_DISK_CLOSEST_", 22) == 0)
411 uiDst
= strtoul(var
+ 22, NULL
, 10);
412 uiDst
= uiDst
* (1024ULL * 1024ULL * 1024ULL);
414 for (i
= 0; i
< g_disk_num
; i
++)
416 node
= g_disk_list
+ i
;
422 if (node
->size
> uiDst
)
424 delta
= node
->size
- uiDst
;
428 delta
= uiDst
- node
->size
;
431 if (delta
< maxdelta
)
440 vlog("%s=<%s>\n", var
, g_disk_list
[index
].name
);
441 snprintf(value
, len
, "%s", g_disk_list
[index
].name
);
446 vlog("[Error] %s not found\n", var
);
451 vlog("Invalid var name <%s>\n", var
);
452 snprintf(value
, len
, "$$%s$$", var
);
457 snprintf(value
, len
, "$$%s$$", var
);
463 int vtoyexpand_main(int argc
, char **argv
)
472 vlog("========= vtoyexpand_main %d ========\n", argc
);
479 g_vtoy_disk_name
= argv
[2];
480 if (strncmp(g_vtoy_disk_name
, "/dev/", 5) == 0)
482 g_vtoy_disk_name
+= 5;
484 vlog("<%s> <%s> <%s>\n", argv
[1], argv
[2], g_vtoy_disk_name
);
488 fp
= fopen(argv
[1], "r");
491 vlog("Failed to open file <%s>\n", argv
[1]);
495 fout
= fopen(TMP_FILE
, "w+");
498 vlog("Failed to create file <%s>\n", TMP_FILE
);
503 memset(line
, 0, sizeof(line
));
504 memset(value
, 0, sizeof(value
));
506 while (fgets(line
, sizeof(line
), fp
))
508 start
= strstr(line
, "$$VT_");
511 end
= strstr(start
+ 5, "$$");
517 fprintf(fout
, "%s", line
);
520 expand_var(start
+ 2, value
, sizeof(value
));
521 fprintf(fout
, "%s", value
);
523 fprintf(fout
, "%s", end
+ 2);
525 memset(value
, 0, sizeof(value
));
529 fprintf(fout
, "%s", line
);
532 line
[0] = line
[4095] = 0;
538 vlog("delete file <%s>\n", argv
[1]);
541 vlog("Copy file <%s> --> <%s>\n", TMP_FILE
, argv
[1]);
542 copy_file(TMP_FILE
, argv
[1]);
548 #ifndef BUILD_VTOY_TOOL
549 int main(int argc
, char **argv
)
551 return vtoyexpand_main(argc
, argv
);