]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - LinuxGUI/Ventoy2Disk/Web/ventoy_http.c
update languages.ini and license
[Ventoy.git] / LinuxGUI / Ventoy2Disk / Web / ventoy_http.c
1 /******************************************************************************
2 * ventoy_http.c ---- ventoy http
3 * Copyright (c) 2021, longpanda <admin@ventoy.net>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include <stdarg.h>
24 #include <errno.h>
25 #include <time.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <sys/types.h>
29 #include <sys/ioctl.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 #include <sys/mount.h>
33 #include <linux/fs.h>
34 #include <dirent.h>
35 #include <pthread.h>
36 #include <ventoy_define.h>
37 #include <ventoy_json.h>
38 #include <ventoy_util.h>
39 #include <ventoy_disk.h>
40 #include <ventoy_http.h>
41 #include "fat_filelib.h"
42
43 static pthread_mutex_t g_api_mutex;
44 static char g_cur_language[128];
45 static int g_cur_part_style = 0;
46 static char g_cur_server_token[64];
47 static struct mg_context *g_ventoy_http_ctx = NULL;
48
49 static uint32_t g_efi_part_offset = 0;
50 static uint8_t *g_efi_part_raw_img = NULL;
51 static uint8_t *g_grub_stg1_raw_img = NULL;
52
53 static char g_cur_process_diskname[64];
54 static char g_cur_process_type[64];
55 static int g_cur_process_result = 0;
56 static PROGRESS_POINT g_current_progress = PT_FINISH;
57
58 static int ventoy_load_mbr_template(void)
59 {
60 FILE *fp = NULL;
61
62 fp = fopen("boot/boot.img", "rb");
63 if (fp == NULL)
64 {
65 vlog("Failed to open file boot/boot.img\n");
66 return 1;
67 }
68
69 fread(g_mbr_template, 1, 512, fp);
70 fclose(fp);
71
72 ventoy_gen_preudo_uuid(g_mbr_template + 0x180);
73 return 0;
74 }
75
76 static int ventoy_disk_xz_flush(void *src, unsigned int size)
77 {
78 memcpy(g_efi_part_raw_img + g_efi_part_offset, src, size);
79 g_efi_part_offset += size;
80
81 g_current_progress = PT_LOAD_DISK_IMG + (g_efi_part_offset / SIZE_1MB);
82 return (int)size;
83 }
84
85 static int ventoy_unxz_efipart_img(void)
86 {
87 int rc;
88 int inlen;
89 int xzlen;
90 void *xzbuf = NULL;
91 uint8_t *buf = NULL;
92
93 rc = ventoy_read_file_to_buf(VENTOY_FILE_DISK_IMG, 0, &xzbuf, &xzlen);
94 vdebug("read disk.img.xz rc:%d len:%d\n", rc, xzlen);
95
96 if (g_efi_part_raw_img)
97 {
98 buf = g_efi_part_raw_img;
99 }
100 else
101 {
102 buf = malloc(VTOYEFI_PART_BYTES);
103 if (!buf)
104 {
105 check_free(xzbuf);
106 return 1;
107 }
108 }
109
110 g_efi_part_offset = 0;
111 g_efi_part_raw_img = buf;
112
113 rc = unxz(xzbuf, xzlen, NULL, ventoy_disk_xz_flush, buf, &inlen, NULL);
114 vdebug("ventoy_unxz_efipart_img len:%d rc:%d unxzlen:%u\n", inlen, rc, g_efi_part_offset);
115
116 check_free(xzbuf);
117 return 0;
118 }
119
120 static int ventoy_unxz_stg1_img(void)
121 {
122 int rc;
123 int inlen;
124 int xzlen;
125 void *xzbuf = NULL;
126 uint8_t *buf = NULL;
127
128 rc = ventoy_read_file_to_buf(VENTOY_FILE_STG1_IMG, 0, &xzbuf, &xzlen);
129 vdebug("read core.img.xz rc:%d len:%d\n", rc, xzlen);
130
131 if (g_grub_stg1_raw_img)
132 {
133 buf = g_grub_stg1_raw_img;
134 }
135 else
136 {
137 buf = zalloc(SIZE_1MB);
138 if (!buf)
139 {
140 check_free(xzbuf);
141 return 1;
142 }
143 }
144
145 rc = unxz(xzbuf, xzlen, NULL, NULL, buf, &inlen, NULL);
146 vdebug("ventoy_unxz_stg1_img len:%d rc:%d\n", inlen, rc);
147
148 g_grub_stg1_raw_img = buf;
149
150 check_free(xzbuf);
151 return 0;
152 }
153
154
155 static int ventoy_http_save_cfg(void)
156 {
157 FILE *fp;
158
159 fp = fopen("./Ventoy2Disk.ini", "w");
160 if (!fp)
161 {
162 return 0;
163 }
164
165 fprintf(fp, "[Ventoy]\nLanguage=%s\nPartStyle=%d\n", g_cur_language, g_cur_part_style);
166
167 fclose(fp);
168 return 0;
169 }
170
171 static int ventoy_http_load_cfg(void)
172 {
173 int i;
174 int len;
175 char line[256];
176 FILE *fp;
177
178 fp = fopen("./Ventoy2Disk.ini", "r");
179 if (!fp)
180 {
181 return 0;
182 }
183
184 while (fgets(line, sizeof(line), fp))
185 {
186 len = (int)strlen(line);
187 for (i = len - 1; i >= 0; i--)
188 {
189 if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r' || line[i] == '\n')
190 {
191 line[i] = 0;
192 }
193 else
194 {
195 break;
196 }
197 }
198
199 len = (int)strlen("Language=");
200 if (strncmp(line, "Language=", len) == 0)
201 {
202 scnprintf(g_cur_language, "%s", line + len);
203 }
204 else if (strncmp(line, "PartStyle=", strlen("PartStyle=")) == 0)
205 {
206 g_cur_part_style = (int)strtol(line + strlen("PartStyle="), NULL, 10);
207 }
208 }
209
210 fclose(fp);
211 return 0;
212 }
213
214
215 static int ventoy_json_result(struct mg_connection *conn, const char *err)
216 {
217 mg_printf(conn,
218 "HTTP/1.1 200 OK \r\n"
219 "Content-Type: application/json\r\n"
220 "Content-Length: %d\r\n"
221 "\r\n%s",
222 (int)strlen(err), err);
223 return 0;
224 }
225
226 static int ventoy_json_buffer(struct mg_connection *conn, const char *json_buf, int json_len)
227 {
228 mg_printf(conn,
229 "HTTP/1.1 200 OK \r\n"
230 "Content-Type: application/json\r\n"
231 "Content-Length: %d\r\n"
232 "\r\n%s",
233 json_len, json_buf);
234 return 0;
235 }
236
237 static int ventoy_api_sysinfo(struct mg_connection *conn, VTOY_JSON *json)
238 {
239 int busy = 0;
240 int pos = 0;
241 int buflen = 0;
242 char buf[512];
243
244 (void)json;
245
246 busy = (g_current_progress == PT_FINISH) ? 0 : 1;
247
248 buflen = sizeof(buf) - 1;
249 VTOY_JSON_FMT_BEGIN(pos, buf, buflen);
250 VTOY_JSON_FMT_OBJ_BEGIN();
251 VTOY_JSON_FMT_STRN("token", g_cur_server_token);
252 VTOY_JSON_FMT_STRN("language", g_cur_language);
253 VTOY_JSON_FMT_STRN("ventoy_ver", ventoy_get_local_version());
254 VTOY_JSON_FMT_UINT("partstyle", g_cur_part_style);
255 VTOY_JSON_FMT_BOOL("busy", busy);
256 VTOY_JSON_FMT_STRN("process_disk", g_cur_process_diskname);
257 VTOY_JSON_FMT_STRN("process_type", g_cur_process_type);
258 VTOY_JSON_FMT_OBJ_END();
259 VTOY_JSON_FMT_END(pos);
260
261 ventoy_json_buffer(conn, buf, pos);
262 return 0;
263 }
264
265 static int ventoy_api_get_percent(struct mg_connection *conn, VTOY_JSON *json)
266 {
267 int pos = 0;
268 int buflen = 0;
269 int percent = 0;
270 char buf[128];
271
272 (void)json;
273
274 percent = g_current_progress * 100 / PT_FINISH;
275
276 buflen = sizeof(buf) - 1;
277 VTOY_JSON_FMT_BEGIN(pos, buf, buflen);
278 VTOY_JSON_FMT_OBJ_BEGIN();
279 VTOY_JSON_FMT_STRN("result", g_cur_process_result ? "failed" : "success");
280 VTOY_JSON_FMT_STRN("process_disk", g_cur_process_diskname);
281 VTOY_JSON_FMT_STRN("process_type", g_cur_process_type);
282 VTOY_JSON_FMT_UINT("percent", percent);
283 VTOY_JSON_FMT_OBJ_END();
284 VTOY_JSON_FMT_END(pos);
285
286 ventoy_json_buffer(conn, buf, pos);
287 return 0;
288 }
289
290 static int ventoy_api_set_language(struct mg_connection *conn, VTOY_JSON *json)
291 {
292 const char *lang = NULL;
293
294 lang = vtoy_json_get_string_ex(json, "language");
295 if (lang)
296 {
297 scnprintf(g_cur_language, "%s", lang);
298 ventoy_http_save_cfg();
299 }
300
301 ventoy_json_result(conn, VTOY_JSON_SUCCESS_RET);
302 return 0;
303 }
304
305 static int ventoy_api_set_partstyle(struct mg_connection *conn, VTOY_JSON *json)
306 {
307 int ret;
308 int style = 0;
309
310 ret = vtoy_json_get_int(json, "partstyle", &style);
311 if (JSON_SUCCESS == ret)
312 {
313 if ((style == 0) || (style == 1))
314 {
315 g_cur_part_style = style;
316 ventoy_http_save_cfg();
317 }
318 }
319
320 ventoy_json_result(conn, VTOY_JSON_SUCCESS_RET);
321 return 0;
322 }
323
324 static int ventoy_clean_disk(int fd, uint64_t size)
325 {
326 int zerolen;
327 ssize_t len;
328 off_t offset;
329 void *buf = NULL;
330
331 vdebug("ventoy_clean_disk fd:%d size:%llu\n", fd, (_ull)size);
332
333 zerolen = 64 * 1024;
334 buf = zalloc(zerolen);
335 if (!buf)
336 {
337 vlog("failed to alloc clean buffer\n");
338 return 1;
339 }
340
341 offset = lseek(fd, 0, SEEK_SET);
342 len = write(fd, buf, zerolen);
343 vdebug("write disk at off:%llu writelen:%lld datalen:%d\n", (_ull)offset, (_ll)len, zerolen);
344
345 offset = lseek(fd, size - zerolen, SEEK_SET);
346 len = write(fd, buf, zerolen);
347 vdebug("write disk at off:%llu writelen:%lld datalen:%d\n", (_ull)offset, (_ll)len, zerolen);
348
349 free(buf);
350 return 0;
351 }
352
353 static int ventoy_write_legacy_grub(int fd, int partstyle)
354 {
355 ssize_t len;
356 off_t offset;
357
358 if (partstyle)
359 {
360 vlog("Write GPT stage1 ...\n");
361
362 offset = lseek(fd, 512 * 34, SEEK_SET);
363
364 g_grub_stg1_raw_img[500] = 35;//update blocklist
365 len = write(fd, g_grub_stg1_raw_img, SIZE_1MB - 512 * 34);
366
367 vlog("lseek offset:%llu(%u) writelen:%llu(%u)\n", (_ull)offset, 512 * 34, (_ull)len, SIZE_1MB - 512 * 34);
368 if (SIZE_1MB - 512 * 34 != len)
369 {
370 vlog("write length error\n");
371 return 1;
372 }
373 }
374 else
375 {
376 vlog("Write MBR stage1 ...\n");
377 offset = lseek(fd, 512, SEEK_SET);
378 len = write(fd, g_grub_stg1_raw_img, SIZE_1MB - 512);
379
380 vlog("lseek offset:%llu(%u) writelen:%llu(%u)\n", (_ull)offset, 512, (_ull)len, SIZE_1MB - 512);
381 if (SIZE_1MB - 512 != len)
382 {
383 vlog("write length error\n");
384 return 1;
385 }
386 }
387
388 return 0;
389 }
390
391 static int VentoyFatMemRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
392 {
393 uint32 i;
394 uint32 offset;
395
396 for (i = 0; i < SectorCount; i++)
397 {
398 offset = (Sector + i) * 512;
399 memcpy(Buffer + i * 512, g_efi_part_raw_img + offset, 512);
400 }
401
402 return 1;
403 }
404
405 static int VentoyFatMemWrite(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
406 {
407 uint32 i;
408 uint32 offset;
409
410 for (i = 0; i < SectorCount; i++)
411 {
412 offset = (Sector + i) * 512;
413 memcpy(g_efi_part_raw_img + offset, Buffer + i * 512, 512);
414 }
415
416 return 1;
417 }
418
419 static int VentoyProcSecureBoot(int SecureBoot)
420 {
421 int rc = 0;
422 int size;
423 char *filebuf = NULL;
424 void *file = NULL;
425
426 vlog("VentoyProcSecureBoot %d ...\n", SecureBoot);
427
428 if (SecureBoot)
429 {
430 vlog("Secure boot is enabled ...\n");
431 return 0;
432 }
433
434 fl_init();
435
436 if (0 == fl_attach_media(VentoyFatMemRead, VentoyFatMemWrite))
437 {
438 file = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
439 vlog("Open ventoy efi file %p \n", file);
440 if (file)
441 {
442 fl_fseek(file, 0, SEEK_END);
443 size = (int)fl_ftell(file);
444 fl_fseek(file, 0, SEEK_SET);
445
446 vlog("ventoy efi file size %d ...\n", size);
447
448 filebuf = (char *)malloc(size);
449 if (filebuf)
450 {
451 fl_fread(filebuf, 1, size, file);
452 }
453
454 fl_fclose(file);
455
456 vlog("Now delete all efi files ...\n");
457 fl_remove("/EFI/BOOT/BOOTX64.EFI");
458 fl_remove("/EFI/BOOT/grubx64.efi");
459 fl_remove("/EFI/BOOT/grubx64_real.efi");
460 fl_remove("/EFI/BOOT/MokManager.efi");
461 fl_remove("/ENROLL_THIS_KEY_IN_MOKMANAGER.cer");
462
463 file = fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb");
464 vlog("Open bootx64 efi file %p \n", file);
465 if (file)
466 {
467 if (filebuf)
468 {
469 fl_fwrite(filebuf, 1, size, file);
470 }
471
472 fl_fflush(file);
473 fl_fclose(file);
474 }
475
476 if (filebuf)
477 {
478 free(filebuf);
479 }
480 }
481
482 file = fl_fopen("/EFI/BOOT/grubia32_real.efi", "rb");
483 vlog("Open ventoy efi file %p\n", file);
484 if (file)
485 {
486 fl_fseek(file, 0, SEEK_END);
487 size = (int)fl_ftell(file);
488 fl_fseek(file, 0, SEEK_SET);
489
490 vlog("ventoy efi file size %d ...\n", size);
491
492 filebuf = (char *)malloc(size);
493 if (filebuf)
494 {
495 fl_fread(filebuf, 1, size, file);
496 }
497
498 fl_fclose(file);
499
500 vlog("Now delete all efi files ...\n");
501 fl_remove("/EFI/BOOT/BOOTIA32.EFI");
502 fl_remove("/EFI/BOOT/grubia32.efi");
503 fl_remove("/EFI/BOOT/grubia32_real.efi");
504 fl_remove("/EFI/BOOT/mmia32.efi");
505
506 file = fl_fopen("/EFI/BOOT/BOOTIA32.EFI", "wb");
507 vlog("Open bootia32 efi file %p\n", file);
508 if (file)
509 {
510 if (filebuf)
511 {
512 fl_fwrite(filebuf, 1, size, file);
513 }
514
515 fl_fflush(file);
516 fl_fclose(file);
517 }
518
519 if (filebuf)
520 {
521 free(filebuf);
522 }
523 }
524
525 }
526 else
527 {
528 rc = 1;
529 }
530
531 fl_shutdown();
532
533 return rc;
534 }
535
536 static int ventoy_check_efi_part_data(int fd, uint64_t offset)
537 {
538 int i;
539 ssize_t len;
540 char *buf;
541
542 buf = malloc(SIZE_1MB);
543 if (!buf)
544 {
545 return 0;
546 }
547
548 lseek(fd, offset, SEEK_SET);
549 for (i = 0; i < 32; i++)
550 {
551 len = read(fd, buf, SIZE_1MB);
552 if (len != SIZE_1MB || memcmp(buf, g_efi_part_raw_img + i * SIZE_1MB, SIZE_1MB))
553 {
554 vlog("part2 data check failed i=%d len:%llu\n", i, (_ull)len);
555 return 1;
556 }
557
558 g_current_progress = PT_CHECK_PART2 + (i / 4);
559 }
560
561 return 0;
562 }
563
564 static int ventoy_write_efipart(int fd, uint64_t offset, uint32_t secureboot)
565 {
566 int i;
567 ssize_t len;
568
569 vlog("Formatting part2 EFI offset:%llu ...\n", (_ull)offset);
570 lseek(fd, offset, SEEK_SET);
571
572 VentoyProcSecureBoot((int)secureboot);
573
574 g_current_progress = PT_WRITE_VENTOY_START;
575 for (i = 0; i < 32; i++)
576 {
577 len = write(fd, g_efi_part_raw_img + i * SIZE_1MB, SIZE_1MB);
578 vlog("write disk writelen:%lld datalen:%d [ %s ]\n",
579 (_ll)len, SIZE_1MB, (len == SIZE_1MB) ? "success" : "failed");
580
581 if (len != SIZE_1MB)
582 {
583 vlog("failed to format part2 EFI\n");
584 return 1;
585 }
586
587 g_current_progress = PT_WRITE_VENTOY_START + i / 4;
588 }
589
590 return 0;
591 }
592
593 static int VentoyFillBackupGptHead(VTOY_GPT_INFO *pInfo, VTOY_GPT_HDR *pHead)
594 {
595 uint64_t LBA;
596 uint64_t BackupLBA;
597
598 memcpy(pHead, &pInfo->Head, sizeof(VTOY_GPT_HDR));
599
600 LBA = pHead->EfiStartLBA;
601 BackupLBA = pHead->EfiBackupLBA;
602
603 pHead->EfiStartLBA = BackupLBA;
604 pHead->EfiBackupLBA = LBA;
605 pHead->PartTblStartLBA = BackupLBA + 1 - 33;
606
607 pHead->Crc = 0;
608 pHead->Crc = ventoy_crc32(pHead, pHead->Length);
609
610 return 0;
611 }
612
613 static int ventoy_write_gpt_part_table(int fd, uint64_t disksize, VTOY_GPT_INFO *gpt)
614 {
615 ssize_t len;
616 off_t offset;
617 VTOY_GPT_HDR BackupHead;
618
619 VentoyFillBackupGptHead(gpt, &BackupHead);
620
621 offset = lseek(fd, disksize - 512, SEEK_SET);
622 len = write(fd, &BackupHead, sizeof(VTOY_GPT_HDR));
623 vlog("write backup gpt part table off:%llu len:%llu\n", (_ull)offset, (_ull)len);
624 if (offset != disksize - 512 || len != sizeof(VTOY_GPT_HDR))
625 {
626 return 1;
627 }
628
629 offset = lseek(fd, disksize - 512 * 33, SEEK_SET);
630 len = write(fd, gpt->PartTbl, sizeof(gpt->PartTbl));
631 vlog("write main gpt part table off:%llu len:%llu\n", (_ull)offset, (_ull)len);
632 if (offset != disksize - 512 * 33 || len != sizeof(gpt->PartTbl))
633 {
634 return 1;
635 }
636
637 offset = lseek(fd, 0, SEEK_SET);
638 len = write(fd, gpt, sizeof(VTOY_GPT_INFO));
639 vlog("write gpt part head off:%llu len:%llu\n", (_ull)offset, (_ull)len);
640 if (offset != 0 || len != sizeof(VTOY_GPT_INFO))
641 {
642 return 1;
643 }
644
645 return 0;
646 }
647
648 static void * ventoy_update_thread(void *data)
649 {
650 int fd;
651 ssize_t len;
652 off_t offset;
653 MBR_HEAD MBR;
654 ventoy_disk *disk = NULL;
655 ventoy_thread_data *thread = (ventoy_thread_data *)data;
656
657 vdebug("ventoy_update_thread run ...\n");
658
659 fd = thread->diskfd;
660 disk = thread->disk;
661
662 g_current_progress = PT_PRAPARE_FOR_CLEAN;
663 vdebug("check disk %s\n", disk->disk_name);
664 if (ventoy_is_disk_mounted(disk->disk_path))
665 {
666 vlog("disk is mounted, now try to unmount it ...\n");
667 ventoy_try_umount_disk(disk->disk_path);
668 }
669
670 if (ventoy_is_disk_mounted(disk->disk_path))
671 {
672 vlog("%s is mounted and can't umount!\n", disk->disk_path);
673 goto err;
674 }
675 else
676 {
677 vlog("disk is not mounted now, we can do continue ...\n");
678 }
679
680 g_current_progress = PT_LOAD_CORE_IMG;
681 ventoy_unxz_stg1_img();
682
683 g_current_progress = PT_LOAD_DISK_IMG;
684 ventoy_unxz_efipart_img();
685
686 g_current_progress = PT_FORMAT_PART2;
687
688 vlog("Formatting part2 EFI ...\n");
689 if (0 != ventoy_write_efipart(fd, disk->vtoydata.part2_start_sector * 512, thread->secure_boot))
690 {
691 vlog("Failed to format part2 efi ...\n");
692 goto err;
693 }
694
695 g_current_progress = PT_WRITE_STG1_IMG;
696
697 vlog("Writing legacy grub ...\n");
698 if (0 != ventoy_write_legacy_grub(fd, disk->vtoydata.partition_style))
699 {
700 vlog("ventoy_write_legacy_grub failed ...\n");
701 goto err;
702 }
703
704 offset = lseek(fd, 512 * 2040, SEEK_SET);
705 len = write(fd, disk->vtoydata.rsvdata, sizeof(disk->vtoydata.rsvdata));
706 vlog("Writing reserve data offset:%llu len:%llu ...\n", (_ull)offset, (_ull)len);
707
708 memcpy(&MBR, &(disk->vtoydata.gptinfo.MBR), 512);
709 if (disk->vtoydata.partition_style == 0 && MBR.PartTbl[0].Active == 0)
710 {
711 MBR.PartTbl[0].Active = 0x80;
712 MBR.PartTbl[1].Active = 0;
713 MBR.PartTbl[2].Active = 0;
714 MBR.PartTbl[3].Active = 0;
715
716 offset = lseek(fd, 0, SEEK_SET);
717 len = write(fd, &MBR, 512);
718 vlog("set MBR partition 1 active flag enabled offset:%llu len:%llu\n", (_ull)offset, (_ull)len);
719 }
720
721 g_current_progress = PT_SYNC_DATA1;
722
723 vlog("fsync data1...\n");
724 fsync(fd);
725 vtoy_safe_close_fd(fd);
726
727 g_current_progress = PT_SYNC_DATA2;
728
729 vlog("====================================\n");
730 vlog("====== ventoy update success ======\n");
731 vlog("====================================\n");
732 goto end;
733
734 err:
735 g_cur_process_result = 1;
736 vtoy_safe_close_fd(fd);
737
738 end:
739 g_current_progress = PT_FINISH;
740
741 check_free(thread);
742
743 return NULL;
744 }
745
746 static void * ventoy_install_thread(void *data)
747 {
748 int fd;
749 ssize_t len;
750 off_t offset;
751 MBR_HEAD MBR;
752 ventoy_disk *disk = NULL;
753 VTOY_GPT_INFO *gpt = NULL;
754 ventoy_thread_data *thread = (ventoy_thread_data *)data;
755 uint64_t Part1StartSector = 0;
756 uint64_t Part1SectorCount = 0;
757 uint64_t Part2StartSector = 0;
758
759 vdebug("ventoy_install_thread run ...\n");
760
761 fd = thread->diskfd;
762 disk = thread->disk;
763
764 g_current_progress = PT_PRAPARE_FOR_CLEAN;
765 vdebug("check disk %s\n", disk->disk_name);
766 if (ventoy_is_disk_mounted(disk->disk_path))
767 {
768 vlog("disk is mounted, now try to unmount it ...\n");
769 ventoy_try_umount_disk(disk->disk_path);
770 }
771
772 if (ventoy_is_disk_mounted(disk->disk_path))
773 {
774 vlog("%s is mounted and can't umount!\n", disk->disk_path);
775 goto err;
776 }
777 else
778 {
779 vlog("disk is not mounted now, we can do continue ...\n");
780 }
781
782 g_current_progress = PT_DEL_ALL_PART;
783 ventoy_clean_disk(fd, disk->size_in_byte);
784
785 g_current_progress = PT_LOAD_CORE_IMG;
786 ventoy_unxz_stg1_img();
787
788 g_current_progress = PT_LOAD_DISK_IMG;
789 ventoy_unxz_efipart_img();
790
791 if (thread->partstyle)
792 {
793 vdebug("Fill GPT part table\n");
794 gpt = zalloc(sizeof(VTOY_GPT_INFO));
795 ventoy_fill_gpt(disk->size_in_byte, thread->reserveBytes, thread->align4kb, gpt);
796 Part1StartSector = gpt->PartTbl[0].StartLBA;
797 Part1SectorCount = gpt->PartTbl[0].LastLBA - Part1StartSector + 1;
798 Part2StartSector = gpt->PartTbl[1].StartLBA;
799 }
800 else
801 {
802 vdebug("Fill MBR part table\n");
803 ventoy_fill_mbr(disk->size_in_byte, thread->reserveBytes, thread->align4kb, 0, &MBR);
804 Part1StartSector = MBR.PartTbl[0].StartSectorId;
805 Part1SectorCount = MBR.PartTbl[0].SectorCount;
806 Part2StartSector = MBR.PartTbl[1].StartSectorId;
807 }
808
809 vlog("Part1StartSector:%llu Part1SectorCount:%llu Part2StartSector:%llu\n",
810 (_ull)Part1StartSector, (_ull)Part1SectorCount, (_ull)Part2StartSector);
811
812 if (thread->partstyle != disk->partstyle)
813 {
814 vlog("Wait for format part1 (partstyle changed) ...\n");
815 sleep(1);
816 }
817
818 g_current_progress = PT_FORMAT_PART1;
819 vlog("Formatting part1 exFAT %s ...\n", disk->disk_path);
820 if (0 != mkexfat_main(disk->disk_path, fd, Part1SectorCount))
821 {
822 vlog("Failed to format exfat ...\n");
823 goto err;
824 }
825
826 g_current_progress = PT_FORMAT_PART2;
827 vlog("Formatting part2 EFI ...\n");
828 if (0 != ventoy_write_efipart(fd, Part2StartSector * 512, thread->secure_boot))
829 {
830 vlog("Failed to format part2 efi ...\n");
831 goto err;
832 }
833
834 g_current_progress = PT_WRITE_STG1_IMG;
835 vlog("Writing legacy grub ...\n");
836 if (0 != ventoy_write_legacy_grub(fd, thread->partstyle))
837 {
838 vlog("ventoy_write_legacy_grub failed ...\n");
839 goto err;
840 }
841
842 g_current_progress = PT_SYNC_DATA1;
843 vlog("fsync data1...\n");
844 fsync(fd);
845 vtoy_safe_close_fd(fd);
846
847 /* reopen for check part2 data */
848 vlog("Checking part2 efi data %s ...\n", disk->disk_path);
849 g_current_progress = PT_CHECK_PART2;
850 fd = open(disk->disk_path, O_RDONLY | O_BINARY);
851 if (fd < 0)
852 {
853 vlog("failed to open %s for check fd:%d err:%d\n", disk->disk_path, fd, errno);
854 goto err;
855 }
856
857 if (0 == ventoy_check_efi_part_data(fd, Part2StartSector * 512))
858 {
859 vlog("efi part data check success\n");
860 }
861 else
862 {
863 vlog("efi part data check failed\n");
864 goto err;
865 }
866
867 vtoy_safe_close_fd(fd);
868
869 /* reopen for write part table */
870 g_current_progress = PT_WRITE_PART_TABLE;
871 vlog("Writting Partition Table style:%d...\n", thread->partstyle);
872
873 fd = open(disk->disk_path, O_RDWR | O_BINARY);
874 if (fd < 0)
875 {
876 vlog("failed to open %s for part table fd:%d err:%d\n", disk->disk_path, fd, errno);
877 goto err;
878 }
879
880 if (thread->partstyle)
881 {
882 ventoy_write_gpt_part_table(fd, disk->size_in_byte, gpt);
883 }
884 else
885 {
886 offset = lseek(fd, 0, SEEK_SET);
887 len = write(fd, &MBR, 512);
888 vlog("Writting MBR Partition Table %llu %llu\n", (_ull)offset, (_ull)len);
889 if (offset != 0 || len != 512)
890 {
891 goto err;
892 }
893 }
894
895 g_current_progress = PT_SYNC_DATA2;
896 vlog("fsync data2...\n");
897 fsync(fd);
898 vtoy_safe_close_fd(fd);
899
900
901 vlog("====================================\n");
902 vlog("====== ventoy install success ======\n");
903 vlog("====================================\n");
904 goto end;
905
906 err:
907 g_cur_process_result = 1;
908 vtoy_safe_close_fd(fd);
909
910 end:
911 g_current_progress = PT_FINISH;
912
913 check_free(gpt);
914 check_free(thread);
915
916 return NULL;
917 }
918
919 static int ventoy_api_clean(struct mg_connection *conn, VTOY_JSON *json)
920 {
921 int i = 0;
922 int fd = 0;
923 ventoy_disk *disk = NULL;
924 const char *diskname = NULL;
925 char path[128];
926
927 if (g_current_progress != PT_FINISH)
928 {
929 ventoy_json_result(conn, VTOY_JSON_BUSY_RET);
930 return 0;
931 }
932
933 diskname = vtoy_json_get_string_ex(json, "disk");
934 if (diskname == NULL)
935 {
936 ventoy_json_result(conn, VTOY_JSON_INVALID_RET);
937 return 0;
938 }
939
940 for (i = 0; i < g_disk_num; i++)
941 {
942 if (strcmp(g_disk_list[i].disk_name, diskname) == 0)
943 {
944 disk = g_disk_list + i;
945 break;
946 }
947 }
948
949 if (disk == NULL)
950 {
951 vlog("disk %s not found\n", diskname);
952 ventoy_json_result(conn, VTOY_JSON_NOTFOUND_RET);
953 return 0;
954 }
955
956 scnprintf(path, "/sys/block/%s", diskname);
957 if (access(path, F_OK) < 0)
958 {
959 vlog("File %s not exist anymore\n", path);
960 ventoy_json_result(conn, VTOY_JSON_NOTFOUND_RET);
961 return 0;
962 }
963
964 vlog("==================================\n");
965 vlog("===== ventoy clean %s =====\n", disk->disk_path);
966 vlog("==================================\n");
967
968 if (ventoy_is_disk_mounted(disk->disk_path))
969 {
970 vlog("disk is mounted, now try to unmount it ...\n");
971 ventoy_try_umount_disk(disk->disk_path);
972 }
973
974 if (ventoy_is_disk_mounted(disk->disk_path))
975 {
976 vlog("%s is mounted and can't umount!\n", disk->disk_path);
977 ventoy_json_result(conn, VTOY_JSON_FAILED_RET);
978 return 0;
979 }
980 else
981 {
982 vlog("disk is not mounted now, we can do the clean ...\n");
983 }
984
985 fd = open(disk->disk_path, O_RDWR | O_BINARY);
986 if (fd < 0)
987 {
988 vlog("failed to open %s fd:%d err:%d\n", disk->disk_path, fd, errno);
989 ventoy_json_result(conn, VTOY_JSON_FAILED_RET);
990 return 0;
991 }
992
993 vdebug("start clean %s ...\n", disk->disk_model);
994 ventoy_clean_disk(fd, disk->size_in_byte);
995
996 vtoy_safe_close_fd(fd);
997
998 ventoy_json_result(conn, VTOY_JSON_SUCCESS_RET);
999 return 0;
1000 }
1001
1002 static int ventoy_api_install(struct mg_connection *conn, VTOY_JSON *json)
1003 {
1004 int i = 0;
1005 int ret = 0;
1006 int fd = 0;
1007 uint32_t align4kb = 0;
1008 uint32_t style = 0;
1009 uint32_t secure_boot = 0;
1010 uint64_t reserveBytes = 0;
1011 ventoy_disk *disk = NULL;
1012 const char *diskname = NULL;
1013 const char *reserve_space = NULL;
1014 ventoy_thread_data *thread = NULL;
1015 char path[128];
1016
1017 if (g_current_progress != PT_FINISH)
1018 {
1019 ventoy_json_result(conn, VTOY_JSON_BUSY_RET);
1020 return 0;
1021 }
1022
1023 diskname = vtoy_json_get_string_ex(json, "disk");
1024 reserve_space = vtoy_json_get_string_ex(json, "reserve_space");
1025 ret += vtoy_json_get_uint(json, "partstyle", &style);
1026 ret += vtoy_json_get_uint(json, "secure_boot", &secure_boot);
1027 ret += vtoy_json_get_uint(json, "align_4kb", &align4kb);
1028
1029 if (diskname == NULL || reserve_space == NULL || ret != JSON_SUCCESS)
1030 {
1031 ventoy_json_result(conn, VTOY_JSON_INVALID_RET);
1032 return 0;
1033 }
1034
1035 reserveBytes = (uint64_t)strtoull(reserve_space, NULL, 10);
1036
1037 for (i = 0; i < g_disk_num; i++)
1038 {
1039 if (strcmp(g_disk_list[i].disk_name, diskname) == 0)
1040 {
1041 disk = g_disk_list + i;
1042 break;
1043 }
1044 }
1045
1046 if (disk == NULL)
1047 {
1048 vlog("disk %s not found\n", diskname);
1049 ventoy_json_result(conn, VTOY_JSON_NOTFOUND_RET);
1050 return 0;
1051 }
1052
1053 scnprintf(path, "/sys/block/%s", diskname);
1054 if (access(path, F_OK) < 0)
1055 {
1056 vlog("File %s not exist anymore\n", path);
1057 ventoy_json_result(conn, VTOY_JSON_NOTFOUND_RET);
1058 return 0;
1059 }
1060
1061 if (disk->size_in_byte > 2199023255552ULL && style == 0)
1062 {
1063 vlog("disk %s is more than 2TB and GPT is needed\n", path);
1064 ventoy_json_result(conn, VTOY_JSON_MBR_2TB_RET);
1065 return 0;
1066 }
1067
1068 if ((reserveBytes + VTOYEFI_PART_BYTES * 2) > disk->size_in_byte)
1069 {
1070 vlog("reserve space %llu is too big for disk %s %llu\n", (_ull)reserveBytes, path, (_ull)disk->size_in_byte);
1071 ventoy_json_result(conn, VTOY_JSON_INVALID_RSV_RET);
1072 return 0;
1073 }
1074
1075 vlog("==================================================================================\n");
1076 vlog("===== ventoy install %s style:%s secureboot:%u align4K:%u reserve:%llu =========\n",
1077 disk->disk_path, (style ? "GPT" : "MBR"), secure_boot, align4kb, (_ull)reserveBytes);
1078 vlog("==================================================================================\n");
1079
1080 if (ventoy_is_disk_mounted(disk->disk_path))
1081 {
1082 vlog("disk is mounted, now try to unmount it ...\n");
1083 ventoy_try_umount_disk(disk->disk_path);
1084 }
1085
1086 if (ventoy_is_disk_mounted(disk->disk_path))
1087 {
1088 vlog("%s is mounted and can't umount!\n", disk->disk_path);
1089 ventoy_json_result(conn, VTOY_JSON_FAILED_RET);
1090 return 0;
1091 }
1092 else
1093 {
1094 vlog("disk is not mounted now, we can do the install ...\n");
1095 }
1096
1097 fd = open(disk->disk_path, O_RDWR | O_BINARY);
1098 if (fd < 0)
1099 {
1100 vlog("failed to open %s fd:%d err:%d\n", disk->disk_path, fd, errno);
1101 ventoy_json_result(conn, VTOY_JSON_FAILED_RET);
1102 return 0;
1103 }
1104
1105 vdebug("start install thread %s ...\n", disk->disk_model);
1106 thread = zalloc(sizeof(ventoy_thread_data));
1107 if (!thread)
1108 {
1109 vtoy_safe_close_fd(fd);
1110 vlog("failed to alloc thread data err:%d\n", errno);
1111 ventoy_json_result(conn, VTOY_JSON_FAILED_RET);
1112 return 0;
1113 }
1114
1115 g_current_progress = PT_START;
1116 g_cur_process_result = 0;
1117 scnprintf(g_cur_process_type, "%s", "install");
1118 scnprintf(g_cur_process_diskname, "%s", disk->disk_name);
1119
1120 thread->disk = disk;
1121 thread->diskfd = fd;
1122 thread->align4kb = align4kb;
1123 thread->partstyle = style;
1124 thread->secure_boot = secure_boot;
1125 thread->reserveBytes = reserveBytes;
1126
1127 mg_start_thread(ventoy_install_thread, thread);
1128
1129 ventoy_json_result(conn, VTOY_JSON_SUCCESS_RET);
1130 return 0;
1131 }
1132
1133 static int ventoy_api_update(struct mg_connection *conn, VTOY_JSON *json)
1134 {
1135 int i = 0;
1136 int ret = 0;
1137 int fd = 0;
1138 uint32_t secure_boot = 0;
1139 ventoy_disk *disk = NULL;
1140 const char *diskname = NULL;
1141 ventoy_thread_data *thread = NULL;
1142 char path[128];
1143
1144 if (g_current_progress != PT_FINISH)
1145 {
1146 ventoy_json_result(conn, VTOY_JSON_BUSY_RET);
1147 return 0;
1148 }
1149
1150 diskname = vtoy_json_get_string_ex(json, "disk");
1151 ret += vtoy_json_get_uint(json, "secure_boot", &secure_boot);
1152 if (diskname == NULL || ret != JSON_SUCCESS)
1153 {
1154 ventoy_json_result(conn, VTOY_JSON_INVALID_RET);
1155 return 0;
1156 }
1157
1158 for (i = 0; i < g_disk_num; i++)
1159 {
1160 if (strcmp(g_disk_list[i].disk_name, diskname) == 0)
1161 {
1162 disk = g_disk_list + i;
1163 break;
1164 }
1165 }
1166
1167 if (disk == NULL)
1168 {
1169 vlog("disk %s not found\n", diskname);
1170 ventoy_json_result(conn, VTOY_JSON_NOTFOUND_RET);
1171 return 0;
1172 }
1173
1174 if (disk->vtoydata.ventoy_valid == 0)
1175 {
1176 vlog("disk %s is not ventoy disk\n", diskname);
1177 ventoy_json_result(conn, VTOY_JSON_FAILED_RET);
1178 return 0;
1179 }
1180
1181 scnprintf(path, "/sys/block/%s", diskname);
1182 if (access(path, F_OK) < 0)
1183 {
1184 vlog("File %s not exist anymore\n", path);
1185 ventoy_json_result(conn, VTOY_JSON_NOTFOUND_RET);
1186 return 0;
1187 }
1188
1189 vlog("==========================================================\n");
1190 vlog("===== ventoy update %s new_secureboot:%u =========\n", disk->disk_path, secure_boot);
1191 vlog("==========================================================\n");
1192
1193 vlog("%s version:%s partstyle:%u oldsecureboot:%u reserve:%llu\n",
1194 disk->disk_path, disk->vtoydata.ventoy_ver,
1195 disk->vtoydata.partition_style,
1196 disk->vtoydata.secure_boot_flag,
1197 (_ull)(disk->vtoydata.preserved_space)
1198 );
1199
1200 if (ventoy_is_disk_mounted(disk->disk_path))
1201 {
1202 vlog("disk is mounted, now try to unmount it ...\n");
1203 ventoy_try_umount_disk(disk->disk_path);
1204 }
1205
1206 if (ventoy_is_disk_mounted(disk->disk_path))
1207 {
1208 vlog("%s is mounted and can't umount!\n", disk->disk_path);
1209 ventoy_json_result(conn, VTOY_JSON_FAILED_RET);
1210 return 0;
1211 }
1212 else
1213 {
1214 vlog("disk is not mounted now, we can do the update ...\n");
1215 }
1216
1217 fd = open(disk->disk_path, O_RDWR | O_BINARY);
1218 if (fd < 0)
1219 {
1220 vlog("failed to open %s fd:%d err:%d\n", disk->disk_path, fd, errno);
1221 ventoy_json_result(conn, VTOY_JSON_FAILED_RET);
1222 return 0;
1223 }
1224
1225 vdebug("start update thread %s ...\n", disk->disk_model);
1226 thread = zalloc(sizeof(ventoy_thread_data));
1227 if (!thread)
1228 {
1229 vtoy_safe_close_fd(fd);
1230 vlog("failed to alloc thread data err:%d\n", errno);
1231 ventoy_json_result(conn, VTOY_JSON_FAILED_RET);
1232 return 0;
1233 }
1234
1235 g_current_progress = PT_START;
1236 g_cur_process_result = 0;
1237 scnprintf(g_cur_process_type, "%s", "update");
1238 scnprintf(g_cur_process_diskname, "%s", disk->disk_name);
1239
1240 thread->disk = disk;
1241 thread->diskfd = fd;
1242 thread->secure_boot = secure_boot;
1243
1244 mg_start_thread(ventoy_update_thread, thread);
1245
1246 ventoy_json_result(conn, VTOY_JSON_SUCCESS_RET);
1247 return 0;
1248 }
1249
1250
1251 static int ventoy_api_refresh_device(struct mg_connection *conn, VTOY_JSON *json)
1252 {
1253 (void)json;
1254
1255 if (g_current_progress == PT_FINISH)
1256 {
1257 g_disk_num = 0;
1258 ventoy_disk_enumerate_all();
1259 }
1260
1261 ventoy_json_result(conn, VTOY_JSON_SUCCESS_RET);
1262 return 0;
1263 }
1264
1265 static int ventoy_api_get_dev_list(struct mg_connection *conn, VTOY_JSON *json)
1266 {
1267 int i = 0;
1268 int rc = 0;
1269 int pos = 0;
1270 int buflen = 0;
1271 uint32_t alldev = 0;
1272 char *buf = NULL;
1273 ventoy_disk *cur = NULL;
1274
1275 rc = vtoy_json_get_uint(json, "alldev", &alldev);
1276 if (JSON_SUCCESS != rc)
1277 {
1278 alldev = 0;
1279 }
1280
1281 buflen = g_disk_num * 1024;
1282 buf = (char *)malloc(buflen + 1024);
1283 if (!buf)
1284 {
1285 ventoy_json_result(conn, VTOY_JSON_FAILED_RET);
1286 return 0;
1287 }
1288
1289 VTOY_JSON_FMT_BEGIN(pos, buf, buflen);
1290 VTOY_JSON_FMT_OBJ_BEGIN();
1291 VTOY_JSON_FMT_KEY("list");
1292 VTOY_JSON_FMT_ARY_BEGIN();
1293
1294 for (i = 0; i < g_disk_num; i++)
1295 {
1296 cur = g_disk_list + i;
1297
1298 if (alldev == 0 && cur->type != VTOY_DEVICE_USB)
1299 {
1300 continue;
1301 }
1302
1303 VTOY_JSON_FMT_OBJ_BEGIN();
1304 VTOY_JSON_FMT_STRN("name", cur->disk_name);
1305 VTOY_JSON_FMT_STRN("model", cur->disk_model);
1306 VTOY_JSON_FMT_STRN("size", cur->human_readable_size);
1307 VTOY_JSON_FMT_UINT("vtoy_valid", cur->vtoydata.ventoy_valid);
1308 VTOY_JSON_FMT_STRN("vtoy_ver", cur->vtoydata.ventoy_ver);
1309 VTOY_JSON_FMT_UINT("vtoy_secure_boot", cur->vtoydata.secure_boot_flag);
1310 VTOY_JSON_FMT_UINT("vtoy_partstyle", cur->vtoydata.partition_style);
1311 VTOY_JSON_FMT_OBJ_ENDEX();
1312 }
1313
1314 VTOY_JSON_FMT_ARY_END();
1315 VTOY_JSON_FMT_OBJ_END();
1316 VTOY_JSON_FMT_END(pos);
1317
1318 ventoy_json_buffer(conn, buf, pos);
1319 return 0;
1320 }
1321
1322 static JSON_CB g_ventoy_json_cb[] =
1323 {
1324 { "sysinfo", ventoy_api_sysinfo },
1325 { "sel_language", ventoy_api_set_language },
1326 { "sel_partstyle", ventoy_api_set_partstyle },
1327 { "refresh_device", ventoy_api_refresh_device },
1328 { "get_dev_list", ventoy_api_get_dev_list },
1329 { "install", ventoy_api_install },
1330 { "update", ventoy_api_update },
1331 { "clean", ventoy_api_clean },
1332 { "get_percent", ventoy_api_get_percent },
1333 };
1334
1335 static int ventoy_json_handler(struct mg_connection *conn, VTOY_JSON *json)
1336 {
1337 int i;
1338 const char *token = NULL;
1339 const char *method = NULL;
1340
1341 method = vtoy_json_get_string_ex(json, "method");
1342 if (!method)
1343 {
1344 ventoy_json_result(conn, VTOY_JSON_SUCCESS_RET);
1345 return 0;
1346 }
1347
1348 if (strcmp(method, "sysinfo"))
1349 {
1350 token = vtoy_json_get_string_ex(json, "token");
1351 if (token == NULL || strcmp(token, g_cur_server_token))
1352 {
1353 ventoy_json_result(conn, VTOY_JSON_TOKEN_ERR_RET);
1354 return 0;
1355 }
1356 }
1357
1358 for (i = 0; i < (int)(sizeof(g_ventoy_json_cb) / sizeof(g_ventoy_json_cb[0])); i++)
1359 {
1360 if (strcmp(method, g_ventoy_json_cb[i].method) == 0)
1361 {
1362 g_ventoy_json_cb[i].callback(conn, json);
1363 break;
1364 }
1365 }
1366
1367 return 0;
1368 }
1369
1370 static int ventoy_request_handler(struct mg_connection *conn)
1371 {
1372 int post_data_len;
1373 int post_buf_len;
1374 VTOY_JSON *json = NULL;
1375 char *post_data_buf = NULL;
1376 const struct mg_request_info *ri = NULL;
1377 char stack_buf[512];
1378
1379 ri = mg_get_request_info(conn);
1380
1381 if (strcmp(ri->uri, "/vtoy/json") == 0)
1382 {
1383 if (ri->content_length > 500)
1384 {
1385 post_data_buf = malloc(ri->content_length + 4);
1386 post_buf_len = ri->content_length + 1;
1387 }
1388 else
1389 {
1390 post_data_buf = stack_buf;
1391 post_buf_len = sizeof(stack_buf);
1392 }
1393
1394 post_data_len = mg_read(conn, post_data_buf, post_buf_len);
1395 post_data_buf[post_data_len] = 0;
1396
1397 json = vtoy_json_create();
1398 if (JSON_SUCCESS == vtoy_json_parse(json, post_data_buf))
1399 {
1400 pthread_mutex_lock(&g_api_mutex);
1401 ventoy_json_handler(conn, json->pstChild);
1402 pthread_mutex_unlock(&g_api_mutex);
1403 }
1404 else
1405 {
1406 ventoy_json_result(conn, VTOY_JSON_INVALID_RET);
1407 }
1408
1409 vtoy_json_destroy(json);
1410
1411 if (post_data_buf != stack_buf)
1412 {
1413 free(post_data_buf);
1414 }
1415 return 1;
1416 }
1417 else
1418 {
1419 return 0;
1420 }
1421 }
1422
1423 int ventoy_http_start(const char *ip, const char *port)
1424 {
1425 uint8_t uuid[16];
1426 char addr[128];
1427 struct mg_callbacks callbacks;
1428 const char *options[] =
1429 {
1430 "listening_ports", "24680",
1431 "document_root", "WebUI",
1432 "error_log_file", VTOY_LOG_FILE,
1433 "request_timeout_ms", "10000",
1434 NULL
1435 };
1436
1437 /* unique token */
1438 ventoy_gen_preudo_uuid(uuid);
1439 scnprintf(g_cur_server_token, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
1440 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
1441 uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
1442
1443 /* option */
1444 scnprintf(addr, "%s:%s", ip, port);
1445 options[1] = addr;
1446
1447 memset(&callbacks, 0, sizeof(callbacks));
1448 callbacks.begin_request = ventoy_request_handler;
1449 g_ventoy_http_ctx = mg_start(&callbacks, NULL, options);
1450
1451 return g_ventoy_http_ctx ? 0 : 1;
1452 }
1453
1454 int ventoy_http_stop(void)
1455 {
1456 if (g_ventoy_http_ctx)
1457 {
1458 mg_stop(g_ventoy_http_ctx);
1459 }
1460 return 0;
1461 }
1462
1463 int ventoy_http_init(void)
1464 {
1465 pthread_mutex_init(&g_api_mutex, NULL);
1466
1467 ventoy_http_load_cfg();
1468
1469 ventoy_load_mbr_template();
1470
1471 return 0;
1472 }
1473
1474 void ventoy_http_exit(void)
1475 {
1476 pthread_mutex_destroy(&g_api_mutex);
1477
1478 check_free(g_efi_part_raw_img);
1479 g_efi_part_raw_img = NULL;
1480 }
1481