]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - LinuxGUI/Ventoy2Disk/ventoy_gui.c
Add Linux native GUI program for Ventoy2Disk.
[Ventoy.git] / LinuxGUI / Ventoy2Disk / ventoy_gui.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <string.h>
5 #include <stdarg.h>
6 #include <unistd.h>
7 #include <errno.h>
8 #include <time.h>
9 #include <dirent.h>
10 #include <sys/utsname.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <sys/fcntl.h>
14 #include <sys/mman.h>
15
16 #define LIB_FLAG_GTK2 (1 << 0)
17 #define LIB_FLAG_GTK3 (1 << 1)
18 #define LIB_FLAG_GTK4 (1 << 2)
19 #define LIB_FLAG_QT4 (1 << 3)
20 #define LIB_FLAG_QT5 (1 << 4)
21 #define LIB_FLAG_QT6 (1 << 5)
22 #define LIB_FLAG_GLADE2 (1 << 30)
23
24 #define LIB_FLAG_GTK (LIB_FLAG_GTK2 | LIB_FLAG_GTK3 | LIB_FLAG_GTK4)
25 #define LIB_FLAG_QT (LIB_FLAG_QT4 | LIB_FLAG_QT5 | LIB_FLAG_QT6)
26
27 #define MAX_PARAS 64
28 #define MAX_LOG_BUF (1024 * 1024)
29 #define VTOY_GUI_PATH "_vtoy_gui_path_="
30 #define VTOY_ENV_STR "_vtoy_env_str_="
31 #define LD_CACHE_FILE "/etc/ld.so.cache"
32 #define INT2STR_YN(a) ((a) == 0 ? "NO" : "YES")
33
34 static char *g_log_buf = NULL;
35 extern char ** environ;
36
37 #define CACHEMAGIC "ld.so-1.7.0"
38
39 struct file_entry
40 {
41 int flags; /* This is 1 for an ELF library. */
42 unsigned int key, value; /* String table indices. */
43 };
44
45 struct cache_file
46 {
47 char magic[sizeof CACHEMAGIC - 1];
48 unsigned int nlibs;
49 struct file_entry libs[0];
50 };
51
52 #define CACHEMAGIC_NEW "glibc-ld.so.cache"
53 #define CACHE_VERSION "1.1"
54 #define CACHEMAGIC_VERSION_NEW CACHEMAGIC_NEW CACHE_VERSION
55
56 struct file_entry_new
57 {
58 int32_t flags; /* This is 1 for an ELF library. */
59 uint32_t key, value; /* String table indices. */
60 uint32_t osversion; /* Required OS version. */
61 uint64_t hwcap; /* Hwcap entry. */
62 };
63
64 struct cache_file_new
65 {
66 char magic[sizeof CACHEMAGIC_NEW - 1];
67 char version[sizeof CACHE_VERSION - 1];
68 uint32_t nlibs; /* Number of entries. */
69 uint32_t len_strings; /* Size of string table. */
70 uint32_t unused[5]; /* Leave space for future extensions
71 and align to 8 byte boundary. */
72 struct file_entry_new libs[0]; /* Entries describing libraries. */
73 /* After this the string table of size len_strings is found. */
74 };
75
76 /* Used to align cache_file_new. */
77 #define ALIGN_CACHE(addr) \
78 (((addr) + __alignof__ (struct cache_file_new) -1) \
79 & (~(__alignof__ (struct cache_file_new) - 1)))
80
81 static void vlog(const char *Fmt, ...)
82 {
83 int buflen;
84 char *buf = NULL;
85 char log[512];
86 va_list arg;
87 time_t stamp;
88 struct tm ttm;
89 FILE *fp;
90
91 time(&stamp);
92 localtime_r(&stamp, &ttm);
93
94 if (g_log_buf)
95 {
96 buf = g_log_buf;
97 buflen = MAX_LOG_BUF;
98 }
99 else
100 {
101 buf = log;
102 buflen = sizeof(log);
103 }
104
105 va_start(arg, Fmt);
106 vsnprintf(buf, buflen, Fmt, arg);
107 va_end(arg);
108
109 fp = fopen("log.txt", "a+");
110 if (fp)
111 {
112 fprintf(fp, "[%04u/%02u/%02u %02u:%02u:%02u] %s",
113 ttm.tm_year + 1900, ttm.tm_mon, ttm.tm_mday,
114 ttm.tm_hour, ttm.tm_min, ttm.tm_sec,
115 buf);
116 fclose(fp);
117 }
118
119 printf("[%04u/%02u/%02u %02u:%02u:%02u] %s",
120 ttm.tm_year + 1900, ttm.tm_mon, ttm.tm_mday,
121 ttm.tm_hour, ttm.tm_min, ttm.tm_sec,
122 buf);
123 }
124
125 static int is_gtk_env(void)
126 {
127 const char *env = NULL;
128
129 env = getenv("GNOME_SETUP_DISPLAY");
130 if (env && env[0] == ':')
131 {
132 vlog("GNOME_SETUP_DISPLAY=%s\n", env);
133 return 1;
134 }
135
136 env = getenv("DESKTOP_SESSION");
137 if (env && strcasecmp(env, "xfce") == 0)
138 {
139 vlog("DESKTOP_SESSION=%s\n", env);
140 return 1;
141 }
142
143 return 0;
144 }
145
146 static int is_qt_env(void)
147 {
148 return 0;
149 }
150
151 static int detect_gtk_version(int libflag)
152 {
153 int gtk2;
154 int gtk3;
155 int gtk4;
156 int glade2;
157
158 gtk2 = libflag & LIB_FLAG_GTK2;
159 gtk3 = libflag & LIB_FLAG_GTK3;
160 gtk4 = libflag & LIB_FLAG_GTK4;
161 glade2 = libflag & LIB_FLAG_GLADE2;
162
163 if (gtk2 > 0 && glade2 > 0 && (gtk3 == 0 && gtk4 == 0))
164 {
165 return 2;
166 }
167
168 if (gtk3 > 0 && (gtk2 == 0 && gtk4 == 0))
169 {
170 return 3;
171 }
172
173 if (gtk4 > 0 && (gtk2 == 0 && gtk3 == 0))
174 {
175 return 4;
176 }
177
178 if (gtk3 > 0)
179 {
180 return 3;
181 }
182
183 if (gtk4 > 0)
184 {
185 return 4;
186 }
187
188 if (gtk2 > 0 && glade2 > 0)
189 {
190 return 2;
191 }
192
193 return 0;
194 }
195
196 static int detect_qt_version(int libflag)
197 {
198 int qt4;
199 int qt5;
200 int qt6;
201
202 qt4 = libflag & LIB_FLAG_QT4;
203 qt5 = libflag & LIB_FLAG_QT5;
204 qt6 = libflag & LIB_FLAG_QT6;
205
206 if (qt4 > 0 && (qt5 == 0 && qt6 == 0))
207 {
208 return 4;
209 }
210
211 if (qt5 > 0 && (qt4 == 0 && qt6 == 0))
212 {
213 return 5;
214 }
215
216 if (qt6 > 0 && (qt4 == 0 && qt5 == 0))
217 {
218 return 6;
219 }
220
221 if (qt5 > 0)
222 {
223 return 5;
224 }
225
226 if (qt4 > 0)
227 {
228 return 4;
229 }
230
231 if (qt6 > 0)
232 {
233 return 6;
234 }
235
236 return 0;
237 }
238
239 int bit_from_machine(const char *machine)
240 {
241 if (strstr(machine, "64"))
242 {
243 return 64;
244 }
245 else
246 {
247 return 32;
248 }
249 }
250
251 int get_os_bit(int *bit)
252 {
253 int ret;
254 struct utsname unameData;
255
256 memset(&unameData, 0, sizeof(unameData));
257 ret = uname(&unameData);
258 if (ret != 0)
259 {
260 vlog("uname error, code: %d\n", errno);
261 return 1;
262 }
263
264 *bit = strstr(unameData.machine, "64") ? 64 : 32;
265 vlog("uname -m <%s> %dbit\n", unameData.machine, *bit);
266
267 return 0;
268 }
269
270 int read_file_1st_line(const char *file, char *buffer, int buflen)
271 {
272 FILE *fp = NULL;
273
274 fp = fopen(file, "r");
275 if (fp == NULL)
276 {
277 vlog("Failed to open file %s code:%d", file, errno);
278 return 1;
279 }
280
281 fgets(buffer, buflen, fp);
282 fclose(fp);
283 return 0;
284 }
285
286 static int read_pid_cmdline(long pid, char *Buffer, int BufLen)
287 {
288 char path[256];
289
290 snprintf(path, sizeof(path), "/proc/%ld/cmdline", pid);
291 return read_file_1st_line(path, Buffer, BufLen);
292 }
293
294 static int find_exe_path(const char *exe, char *pathbuf, int buflen)
295 {
296 int i;
297 char path[PATH_MAX];
298 char *tmpptr = NULL;
299 char *saveptr = NULL;
300 char *newenv = NULL;
301 const char *env = getenv("PATH");
302
303 if (NULL == env)
304 {
305 return 0;
306 }
307
308 newenv = strdup(env);
309 if (!newenv)
310 {
311 return 0;
312 }
313
314 tmpptr = newenv;
315 while (NULL != (tmpptr = strtok_r(tmpptr, ":", &saveptr)))
316 {
317 snprintf(path, sizeof(path), "%s/%s", tmpptr, exe);
318 if (access(path, F_OK) != -1)
319 {
320 snprintf(pathbuf, buflen, "%s", path);
321 free(newenv);
322 return 1;
323 }
324 tmpptr = NULL;
325 }
326
327 free(newenv);
328 return 0;
329 }
330
331 void dump_args(const char *prefix, char **argv)
332 {
333 int i = 0;
334
335 vlog("=========%s ARGS BEGIN===========\n", prefix);
336 while (argv[i])
337 {
338 vlog("argv[%d]=<%s>\n", i, argv[i]);
339 i++;
340 }
341 vlog("=========%s ARGS END===========\n", prefix);
342 }
343
344 int pre_check(void)
345 {
346 int ret;
347 int bit;
348 int buildbit;
349 const char *env = NULL;
350
351 env = getenv("DISPLAY");
352 if (NULL == env || env[0] != ':')
353 {
354 vlog("DISPLAY not exist(%p). Not in X environment.\n", env);
355 return 1;
356 }
357
358 ret = get_os_bit(&bit);
359 if (ret)
360 {
361 vlog("Failed to get os bit.\n");
362 return 1;
363 }
364
365 buildbit = strstr(VTOY_GUI_ARCH, "64") ? 64 : 32;
366 vlog("Build bit is %d (%s)\n", buildbit, VTOY_GUI_ARCH);
367
368 if (bit != buildbit)
369 {
370 vlog("Current system is %d bit (%s). Please run the correct VentoyGUI.\n", bit, VTOY_GUI_ARCH);
371 return 1;
372 }
373
374 return 0;
375 }
376
377 static char * find_argv(int argc, char **argv, char *key)
378 {
379 int i;
380 int len;
381
382 len = (int)strlen(key);
383 for (i = 0; i < argc; i++)
384 {
385 if (strncmp(argv[i], key, len) == 0)
386 {
387 return argv[i];
388 }
389 }
390
391 return NULL;
392 }
393
394 static int adjust_cur_dir(char *argv0)
395 {
396 int ret = 2;
397 char c;
398 char *pos = NULL;
399 char *end = NULL;
400
401 if (argv0[0] == '.')
402 {
403 return 1;
404 }
405
406 for (pos = argv0; pos && *pos; pos++)
407 {
408 if (*pos == '/')
409 {
410 end = pos;
411 }
412 }
413
414 if (end)
415 {
416 c = *end;
417 *end = 0;
418 ret = chdir(argv0);
419 *end = c;
420 }
421
422 return ret;
423 }
424
425
426
427 static char **recover_environ_param(char *env)
428 {
429 int i = 0;
430 int j = 0;
431 int k = 0;
432 int cnt = 0;
433 char **newenvs = NULL;
434
435 for (i = 0; env[i]; i++)
436 {
437 if (env[i] == '\n')
438 {
439 cnt++;
440 }
441 }
442
443 newenvs = malloc(sizeof(char *) * (cnt + 1));
444 if (!newenvs)
445 {
446 vlog("malloc new envs fail %d\n", cnt + 1);
447 return NULL;
448 }
449 memset(newenvs, 0, sizeof(char *) * (cnt + 1));
450
451 for (j = i = 0; env[i]; i++)
452 {
453 if (env[i] == '\n')
454 {
455 env[i] = 0;
456 newenvs[k++] = env + j;
457 j = i + 1;
458 }
459 }
460
461 vlog("recover environ %d %d\n", cnt, k);
462 return newenvs;
463 }
464
465 static int restart_main(int argc, char **argv, char *guiexe)
466 {
467 int i = 0;
468 int j = 0;
469 char *para = NULL;
470 char **envs = NULL;
471 char *newargv[MAX_PARAS + 1] = { NULL };
472
473 para = find_argv(argc, argv, VTOY_ENV_STR);
474 if (!para)
475 {
476 vlog("failed to find %s\n", VTOY_ENV_STR);
477 return 1;
478 }
479
480 newargv[j++] = guiexe;
481 for (i = 1; i < argc && j < MAX_PARAS; i++)
482 {
483 if (strncmp(argv[i], "_vtoy_", 6) != 0)
484 {
485 newargv[j++] = argv[i];
486 }
487 }
488
489 envs = recover_environ_param(para + strlen(VTOY_ENV_STR));
490 if (envs)
491 {
492 vlog("recover success, argc=%d evecve <%s>\n", j, guiexe);
493 execve(guiexe, newargv, envs);
494 }
495 else
496 {
497 vlog("recover failed, argc=%d evecv <%s>\n", j, guiexe);
498 execv(guiexe, newargv);
499 }
500
501 return 1;
502 }
503
504 static char *create_environ_param(const char *prefix, char **envs)
505 {
506 int i = 0;
507 int cnt = 0;
508 int envlen = 0;
509 int prelen = 0;
510 char *cur = NULL;
511 char *para = NULL;
512
513 prelen = strlen(prefix);
514 for (i = 0; envs[i]; i++)
515 {
516 cnt++;
517 envlen += strlen(envs[i]) + 1;
518 }
519
520 para = malloc(prelen + envlen);
521 if (!para)
522 {
523 vlog("failed to malloc env str %d\n", prelen + envlen);
524 return NULL;
525 }
526
527 cur = para;
528 memcpy(cur, prefix, prelen);
529 cur += prelen;
530
531 for (i = 0; envs[i]; i++)
532 {
533 envlen = strlen(envs[i]);
534 memcpy(cur, envs[i], envlen);
535
536 cur[envlen] = '\n';
537 cur += envlen + 1;
538 }
539
540 vlog("create environment param %d\n", cnt);
541 return para;
542 }
543
544 static int restart_by_pkexec(int argc, char **argv, const char *curpath, const char *exe)
545 {
546 int i = 0;
547 int j = 0;
548 char envcount[64];
549 char path[PATH_MAX];
550 char pkexec[PATH_MAX];
551 char exepara[PATH_MAX];
552 char *newargv[MAX_PARAS + 1] = { NULL };
553
554 vlog("try restart self by pkexec ...\n");
555
556 if (find_exe_path("pkexec", pkexec, sizeof(pkexec)))
557 {
558 vlog("Find pkexec at <%s>\n", pkexec);
559 }
560 else
561 {
562 vlog("pkexec not found\n");
563 return 1;
564 }
565
566 if (argv[0][0] != '/')
567 {
568 snprintf(path, sizeof(path), "%s/%s", curpath, argv[0]);
569 }
570 else
571 {
572 snprintf(path, sizeof(path), "%s", argv[0]);
573 }
574 snprintf(exepara, sizeof(exepara), "%s%s", VTOY_GUI_PATH, exe);
575
576 newargv[j++] = pkexec;
577 newargv[j++] = path;
578 for (i = 1; i < argc && j < MAX_PARAS - 2; i++)
579 {
580 newargv[j++] = argv[i];
581 }
582 newargv[j++] = create_environ_param(VTOY_ENV_STR, environ);
583 newargv[j++] = exepara;
584
585 dump_args("PKEXEC", newargv);
586 execv(pkexec, newargv);
587
588 return 1;
589 }
590
591 static int ld_cache_lib_check(const char *lib, int *flag)
592 {
593 if (((*flag) & LIB_FLAG_GTK3) == 0)
594 {
595 if (strncmp(lib, "libgtk-3.so", 11) == 0)
596 {
597 vlog("LIB:<%s>\n", lib);
598 *flag |= LIB_FLAG_GTK3;
599 return 0;
600 }
601 }
602
603 if (((*flag) & LIB_FLAG_GTK2) == 0)
604 {
605 if (strncmp(lib, "libgtk-x11-2.0.so", 17) == 0)
606 {
607 vlog("LIB:<%s>\n", lib);
608 *flag |= LIB_FLAG_GTK2;
609 return 0;
610 }
611 }
612
613 if (((*flag) & LIB_FLAG_GTK4) == 0)
614 {
615 if (strncmp(lib, "libgtk-4.so", 11) == 0)
616 {
617 vlog("LIB:<%s>\n", lib);
618 *flag |= LIB_FLAG_GTK4;
619 return 0;
620 }
621 }
622
623 if (((*flag) & LIB_FLAG_QT4) == 0)
624 {
625 if (strncmp(lib, "libqt4", 6) == 0)
626 {
627 vlog("LIB:<%s>\n", lib);
628 *flag |= LIB_FLAG_QT4;
629 return 0;
630 }
631 }
632
633 if (((*flag) & LIB_FLAG_QT5) == 0)
634 {
635 if (strncmp(lib, "libqt5", 6) == 0)
636 {
637 vlog("LIB:<%s>\n", lib);
638 *flag |= LIB_FLAG_QT5;
639 return 0;
640 }
641 }
642
643 if (((*flag) & LIB_FLAG_QT6) == 0)
644 {
645 if (strncmp(lib, "libqt6", 6) == 0)
646 {
647 vlog("LIB:<%s>\n", lib);
648 *flag |= LIB_FLAG_QT6;
649 return 0;
650 }
651 }
652
653 if (((*flag) & LIB_FLAG_GLADE2) == 0)
654 {
655 if (strncmp(lib, "libglade-2", 10) == 0)
656 {
657 vlog("LIB:<%s>\n", lib);
658 *flag |= LIB_FLAG_GLADE2;
659 return 0;
660 }
661 }
662
663 return 0;
664 }
665
666 static int parse_ld_cache(int *flag)
667 {
668 int fd;
669 int format;
670 unsigned int i;
671 struct stat st;
672 size_t offset = 0;
673 size_t cache_size = 0;
674 const char *cache_data = NULL;
675 struct cache_file *cache = NULL;
676 struct cache_file_new *cache_new = NULL;
677
678 *flag = 0;
679
680 fd = open(LD_CACHE_FILE, O_RDONLY);
681 if (fd < 0)
682 {
683 vlog("failed to open %s err:%d\n", LD_CACHE_FILE, errno);
684 return 1;
685 }
686
687 if (fstat(fd, &st) < 0 || st.st_size == 0)
688 {
689 close(fd);
690 return 1;
691 }
692
693 cache = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
694 if (cache == MAP_FAILED)
695 {
696 close(fd);
697 return 1;
698 }
699
700 cache_size = st.st_size;
701 if (cache_size < sizeof (struct cache_file))
702 {
703 vlog("File is not a cache file.\n");
704 munmap (cache, cache_size);
705 close(fd);
706 return 1;
707 }
708
709 if (memcmp(cache->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1))
710 {
711 /* This can only be the new format without the old one. */
712 cache_new = (struct cache_file_new *) cache;
713
714 if (memcmp(cache_new->magic, CACHEMAGIC_NEW, sizeof CACHEMAGIC_NEW - 1) ||
715 memcmp (cache_new->version, CACHE_VERSION, sizeof CACHE_VERSION - 1))
716 {
717 munmap (cache, cache_size);
718 close(fd);
719 return 1;
720 }
721
722 format = 1;
723 /* This is where the strings start. */
724 cache_data = (const char *) cache_new;
725 }
726 else
727 {
728 /* Check for corruption, avoiding overflow. */
729 if ((cache_size - sizeof (struct cache_file)) / sizeof (struct file_entry) < cache->nlibs)
730 {
731 vlog("File is not a cache file.\n");
732 munmap (cache, cache_size);
733 close(fd);
734 return 1;
735 }
736
737 offset = ALIGN_CACHE(sizeof (struct cache_file) + (cache->nlibs * sizeof (struct file_entry)));
738
739 /* This is where the strings start. */
740 cache_data = (const char *) &cache->libs[cache->nlibs];
741
742 /* Check for a new cache embedded in the old format. */
743 if (cache_size > (offset + sizeof (struct cache_file_new)))
744 {
745 cache_new = (struct cache_file_new *) ((void *)cache + offset);
746
747 if (memcmp(cache_new->magic, CACHEMAGIC_NEW, sizeof CACHEMAGIC_NEW - 1) == 0 &&
748 memcmp(cache_new->version, CACHE_VERSION, sizeof CACHE_VERSION - 1) == 0)
749 {
750 cache_data = (const char *) cache_new;
751 format = 1;
752 }
753 }
754 }
755
756 if (format == 0)
757 {
758 vlog("%d libs found in cache format 0\n", cache->nlibs);
759 for (i = 0; i < cache->nlibs; i++)
760 {
761 ld_cache_lib_check(cache_data + cache->libs[i].key, flag);
762 }
763 }
764 else if (format == 1)
765 {
766 vlog("%d libs found in cache format 1\n", cache_new->nlibs);
767
768 for (i = 0; i < cache_new->nlibs; i++)
769 {
770 ld_cache_lib_check(cache_data + cache_new->libs[i].key, flag);
771 }
772 }
773
774 vlog("ldconfig lib flags 0x%x\n", *flag);
775 vlog("lib flags GLADE2:[%s] GTK2:[%s] GTK3:[%s] GTK4:[%s] QT4:[%s] QT5:[%s] QT6:[%s]\n",
776 INT2STR_YN((*flag) & LIB_FLAG_GLADE2), INT2STR_YN((*flag) & LIB_FLAG_GTK2),
777 INT2STR_YN((*flag) & LIB_FLAG_GTK3), INT2STR_YN((*flag) & LIB_FLAG_GTK4),
778 INT2STR_YN((*flag) & LIB_FLAG_QT4), INT2STR_YN((*flag) & LIB_FLAG_QT5),
779 INT2STR_YN((*flag) & LIB_FLAG_QT6));
780
781 munmap (cache, cache_size);
782 close (fd);
783 return 0;
784 }
785
786 static int detect_gui_exe_path(const char *curpath, char *pathbuf, int buflen)
787 {
788 int ret;
789 int ver;
790 int libflag = 0;
791 const char *guitype = NULL;
792 char line[256];
793 mode_t mode;
794 struct stat filestat;
795
796 if (access("./ventoy_gui_type", F_OK) != -1)
797 {
798 vlog("Get GUI type from ventoy_gui_type file.\n");
799
800 line[0] = 0;
801 read_file_1st_line("./ventoy_gui_type", line, sizeof(line));
802 if (strncmp(line, "gtk2", 4) == 0)
803 {
804 guitype = "gtk";
805 ver = 2;
806
807 parse_ld_cache(&libflag);
808 if ((libflag & LIB_FLAG_GLADE2) == 0)
809 {
810 vlog("libglade2 is necessary for GTK2, but not found.\n");
811 return 1;
812 }
813 }
814 else if (strncmp(line, "gtk3", 4) == 0)
815 {
816 guitype = "gtk";
817 ver = 3;
818 }
819 else if (strncmp(line, "gtk4", 4) == 0)
820 {
821 guitype = "gtk";
822 ver = 4;
823 }
824 else if (strncmp(line, "qt4", 3) == 0)
825 {
826 guitype = "qt";
827 ver = 4;
828 }
829 else if (strncmp(line, "qt5", 3) == 0)
830 {
831 guitype = "qt";
832 ver = 5;
833 }
834 else if (strncmp(line, "qt6", 3) == 0)
835 {
836 guitype = "qt";
837 ver = 6;
838 }
839 else
840 {
841 vlog("Current X environment is NOT supported.\n");
842 return 1;
843 }
844 }
845 else
846 {
847 vlog("Now detect the GUI type ...\n");
848
849 parse_ld_cache(&libflag);
850
851 if ((LIB_FLAG_GTK & libflag) > 0 && (LIB_FLAG_QT & libflag) == 0)
852 {
853 guitype = "gtk";
854 ver = detect_gtk_version(libflag);
855 }
856 else if ((LIB_FLAG_GTK & libflag) == 0 && (LIB_FLAG_QT & libflag) > 0)
857 {
858 guitype = "qt";
859 ver = detect_qt_version(libflag);
860 }
861 else if ((LIB_FLAG_GTK & libflag) > 0 && (LIB_FLAG_QT & libflag) > 0)
862 {
863 if (is_gtk_env())
864 {
865 guitype = "gtk";
866 ver = detect_gtk_version(libflag);
867 }
868 else if (is_qt_env())
869 {
870 guitype = "qt";
871 ver = detect_qt_version(libflag);
872 }
873 else
874 {
875 vlog("Current X environment is NOT supported.\n");
876 return 1;
877 }
878 }
879 else
880 {
881 vlog("Current X environment is NOT supported.\n");
882 return 1;
883 }
884 }
885
886 snprintf(pathbuf, buflen, "%s/tool/%s/Ventoy2Disk.%s%d", curpath, VTOY_GUI_ARCH, guitype, ver);
887
888 vlog("This is %s%d X environment.\n", guitype, ver);
889 vlog("exe = %s\n", pathbuf);
890
891 if (access(pathbuf, F_OK) == -1)
892 {
893 vlog("%s is not exist.\n", pathbuf);
894 return 1;
895 }
896
897 if (access(pathbuf, X_OK) == -1)
898 {
899 vlog("execute permission check fail, try chmod.\n", pathbuf);
900 if (stat(pathbuf, &filestat) == 0)
901 {
902 mode = filestat.st_mode | S_IXUSR | S_IXGRP | S_IXOTH;
903 ret = chmod(pathbuf, mode);
904 vlog("old mode=%o new mode=%o ret=%d\n", filestat.st_mode, mode, ret);
905 }
906 }
907 else
908 {
909 vlog("execute permission check success.\n");
910 }
911
912 return 0;
913 }
914
915 int real_main(int argc, char **argv)
916 {
917 int ret;
918 int euid;
919 char *exe = NULL;
920 char path[PATH_MAX];
921 char curpath[PATH_MAX];
922
923 ret = adjust_cur_dir(argv[0]);
924
925 vlog("\n");
926 vlog("=========================================================\n");
927 vlog("=========================================================\n");
928 vlog("=============== VentoyGui %s ===============\n", VTOY_GUI_ARCH);
929 vlog("=========================================================\n");
930 vlog("=========================================================\n");
931
932 euid = geteuid();
933 getcwd(curpath, sizeof(curpath));
934
935 vlog("pid:%ld ppid:%ld uid:%d euid:%d\n", (long)getpid(), (long)getppid(), getuid(), euid);
936 vlog("adjust dir:%d current path:%s\n", ret, curpath);
937 dump_args("RAW", argv);
938
939 if (access("./boot/boot.img", F_OK) == -1)
940 {
941 vlog("Please run under the correct directory!\n");
942 return 1;
943 }
944
945 exe = find_argv(argc, argv, VTOY_GUI_PATH);
946 if (exe)
947 {
948 if (euid != 0)
949 {
950 vlog("Invalid euid %d when restart.\n", euid);
951 return 1;
952 }
953
954 return restart_main(argc, argv, exe + strlen(VTOY_GUI_PATH));
955 }
956 else
957 {
958 if (pre_check())
959 {
960 return 1;
961 }
962
963 if (detect_gui_exe_path(curpath, path, sizeof(path)))
964 {
965 return 1;
966 }
967
968 if (euid == 0)
969 {
970 vlog("We have root privileges, just exec %s\n", path);
971 argv[0] = path;
972 argv[1] = NULL;
973 execv(argv[0], argv);
974 }
975 else
976 {
977 vlog("EUID check failed.\n");
978
979 /* try pkexec */
980 restart_by_pkexec(argc, argv, curpath, path);
981
982 vlog("### Please run with root privileges. ###\n");
983 return 1;
984 }
985 }
986
987 return 1;
988 }
989
990 int main(int argc, char **argv)
991 {
992 int ret;
993
994 g_log_buf = malloc(MAX_LOG_BUF);
995 if (!g_log_buf)
996 {
997 vlog("Failed to malloc log buffer %d\n", MAX_LOG_BUF);
998 return 1;
999 }
1000
1001 ret = real_main(argc, argv);
1002 free(g_log_buf);
1003 return ret;
1004 }
1005