|
5 | 5 | * as possible (one .c file) and use as few external dependencies |
6 | 6 | * as possible |
7 | 7 | * |
8 | | - * Copyright (c) 2004-22 Simon Peter |
| 8 | + * Copyright (c) 2004-24 Simon Peter |
9 | 9 | * Portions Copyright (c) 2007 Alexander Larsson |
10 | 10 | * Portions from WjCryptLib_Md5 originally written by Alexander Peslyak, |
11 | 11 | modified by WaterJuice retaining Public Domain license |
@@ -62,6 +62,10 @@ extern int sqfs_opt_proc(void* data, const char* arg, int key, struct fuse_args* |
62 | 62 | #include <sys/mman.h> |
63 | 63 | #include <stdint.h> |
64 | 64 | #include <libgen.h> |
| 65 | +#include <dirent.h> |
| 66 | +#include <ctype.h> |
| 67 | + |
| 68 | +const char* fusermountPath = NULL; |
65 | 69 |
|
66 | 70 | typedef struct { |
67 | 71 | uint32_t lo; |
@@ -405,6 +409,93 @@ int appimage_print_binary(char* fname, unsigned long offset, unsigned long lengt |
405 | 409 | return 0; |
406 | 410 | } |
407 | 411 |
|
| 412 | +char* find_fusermount() { |
| 413 | + char* fusermount_base = "fusermount"; |
| 414 | + |
| 415 | + char* fusermount_path = getenv("PATH"); |
| 416 | + if (fusermount_path == NULL) { |
| 417 | + return NULL; |
| 418 | + } |
| 419 | + |
| 420 | + char* path_copy = strdup(fusermount_path); |
| 421 | + char* dir = strtok(path_copy, ":"); |
| 422 | + |
| 423 | + while (dir != NULL) { |
| 424 | + DIR* dir_ptr = opendir(dir); |
| 425 | + if (dir_ptr == NULL) { |
| 426 | + dir = strtok(NULL, ":"); |
| 427 | + continue; |
| 428 | + } |
| 429 | + |
| 430 | + struct dirent* entry; |
| 431 | + while ((entry = readdir(dir_ptr)) != NULL) { |
| 432 | + // Check if the entry starts with "fusermount" |
| 433 | + if (strncmp(entry->d_name, fusermount_base, 10) == 0) { |
| 434 | + // Check if the rest of the entry is a digit |
| 435 | + char* suffix = entry->d_name + 10; |
| 436 | + int j = 0; |
| 437 | + while (suffix[j] != '\0' && isdigit(suffix[j])) { |
| 438 | + j++; |
| 439 | + } |
| 440 | + |
| 441 | + if (suffix[j] == '\0') { |
| 442 | + // Construct the full path of the entry |
| 443 | + char* fusermount_full_path = malloc(strlen(dir) + strlen(entry->d_name) + 2); |
| 444 | + sprintf(fusermount_full_path, "%s/%s", dir, entry->d_name); |
| 445 | + |
| 446 | + // Check if the binary is setuid root |
| 447 | + struct stat sb; |
| 448 | + if (stat(fusermount_full_path, &sb) == -1) { |
| 449 | + perror("stat"); |
| 450 | + free(fusermount_full_path); |
| 451 | + continue; |
| 452 | + } |
| 453 | + |
| 454 | + if (sb.st_uid != 0 || (sb.st_mode & S_ISUID) == 0) { |
| 455 | + // Not setuid root, skip this binary |
| 456 | + free(fusermount_full_path); |
| 457 | + continue; |
| 458 | + } |
| 459 | + |
| 460 | + pid_t pid = fork(); |
| 461 | + if (pid == -1) { |
| 462 | + perror("fork"); |
| 463 | + free(fusermount_full_path); |
| 464 | + continue; |
| 465 | + } |
| 466 | + |
| 467 | + if (pid == 0) { |
| 468 | + // Child process |
| 469 | + char* args[] = {fusermount_full_path, "--version", NULL}; |
| 470 | + execvp(fusermount_full_path, args); |
| 471 | + // If execvp returns, it means the executable was not found |
| 472 | + exit(1); |
| 473 | + } else { |
| 474 | + // Parent process |
| 475 | + int status; |
| 476 | + waitpid(pid, &status, 0); |
| 477 | + |
| 478 | + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { |
| 479 | + // The executable was found and executed successfully |
| 480 | + closedir(dir_ptr); |
| 481 | + free(path_copy); |
| 482 | + return fusermount_full_path; |
| 483 | + } |
| 484 | + |
| 485 | + free(fusermount_full_path); |
| 486 | + } |
| 487 | + } |
| 488 | + } |
| 489 | + } |
| 490 | + |
| 491 | + closedir(dir_ptr); |
| 492 | + dir = strtok(NULL, ":"); |
| 493 | + } |
| 494 | + |
| 495 | + free(path_copy); |
| 496 | + return NULL; |
| 497 | +} |
| 498 | + |
408 | 499 | /* Exit status to use when launching an AppImage fails. |
409 | 500 | * For applications that assign meanings to exit status codes (e.g. rsync), |
410 | 501 | * we avoid "cluttering" pre-defined exit status codes by using 127 which |
@@ -1600,6 +1691,18 @@ int main(int argc, char* argv[]) { |
1600 | 1691 | if (pid == 0) { |
1601 | 1692 | /* in child */ |
1602 | 1693 |
|
| 1694 | + fusermountPath = getenv("FUSERMOUNT_PROG"); |
| 1695 | + if (fusermountPath == NULL) { |
| 1696 | + char* new_prog = find_fusermount(); |
| 1697 | + if (new_prog != NULL) { |
| 1698 | + setenv("FUSERMOUNT_PROG", new_prog, 1); |
| 1699 | + // printf("FUSERMOUNT_PROG set to %s\n", new_prog); |
| 1700 | + free(new_prog); |
| 1701 | + } else { |
| 1702 | + printf("Error: No suitable fusermount binary found on the $PATH\n"); |
| 1703 | + } |
| 1704 | + } |
| 1705 | + |
1603 | 1706 | char* child_argv[5]; |
1604 | 1707 |
|
1605 | 1708 | /* close read pipe */ |
|
0 commit comments