Skip to content

Commit 09b0b43

Browse files
authored
runtime.c: Backport appimage-updateinformation and appimage-signature (probonopd#37)
Closes probonopd#35
1 parent 6f0dcea commit 09b0b43

File tree

1 file changed

+101
-10
lines changed

1 file changed

+101
-10
lines changed

src/runtime/runtime.c

Lines changed: 101 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ extern int sqfs_opt_proc(void* data, const char* arg, int key, struct fuse_args*
6060
#include <sys/wait.h>
6161
#include <fnmatch.h>
6262
#include <sys/mman.h>
63-
6463
#include <stdint.h>
6564

6665
typedef struct {
@@ -313,6 +312,57 @@ ssize_t appimage_get_elf_size(const char* fname) {
313312
return size;
314313
}
315314

315+
/* Return the offset, and the length of an ELF section with a given name in a given ELF file */
316+
bool appimage_get_elf_section_offset_and_length(const char* fname, const char* section_name, unsigned long* offset, unsigned long* length) {
317+
uint8_t* data;
318+
int i;
319+
int fd = open(fname, O_RDONLY);
320+
size_t map_size = (size_t) lseek(fd, 0, SEEK_END);
321+
322+
data = mmap(NULL, map_size, PROT_READ, MAP_SHARED, fd, 0);
323+
close(fd);
324+
325+
// this trick works as both 32 and 64 bit ELF files start with the e_ident[EI_NINDENT] section
326+
unsigned char class = data[EI_CLASS];
327+
328+
if (class == ELFCLASS32) {
329+
Elf32_Ehdr* elf;
330+
Elf32_Shdr* shdr;
331+
332+
elf = (Elf32_Ehdr*) data;
333+
shdr = (Elf32_Shdr*) (data + ((Elf32_Ehdr*) elf)->e_shoff);
334+
335+
char* strTab = (char*) (data + shdr[elf->e_shstrndx].sh_offset);
336+
for (i = 0; i < elf->e_shnum; i++) {
337+
if (strcmp(&strTab[shdr[i].sh_name], section_name) == 0) {
338+
*offset = shdr[i].sh_offset;
339+
*length = shdr[i].sh_size;
340+
}
341+
}
342+
} else if (class == ELFCLASS64) {
343+
Elf64_Ehdr* elf;
344+
Elf64_Shdr* shdr;
345+
346+
elf = (Elf64_Ehdr*) data;
347+
shdr = (Elf64_Shdr*) (data + elf->e_shoff);
348+
349+
char* strTab = (char*) (data + shdr[elf->e_shstrndx].sh_offset);
350+
for (i = 0; i < elf->e_shnum; i++) {
351+
if (strcmp(&strTab[shdr[i].sh_name], section_name) == 0) {
352+
*offset = shdr[i].sh_offset;
353+
*length = shdr[i].sh_size;
354+
}
355+
}
356+
} else {
357+
fprintf(stderr, "Platforms other than 32-bit/64-bit are currently not supported!");
358+
munmap(data, map_size);
359+
return false;
360+
}
361+
362+
munmap(data, map_size);
363+
return true;
364+
}
365+
316366
/* Return the offset, and the length of an ELF section with a given name in a given ELF file */
317367
char* read_file_offset_length(const char* fname, unsigned long offset, unsigned long length) {
318368
FILE* f;
@@ -330,6 +380,35 @@ char* read_file_offset_length(const char* fname, unsigned long offset, unsigned
330380
return buffer;
331381
}
332382

383+
int appimage_print_hex(char* fname, unsigned long offset, unsigned long length) {
384+
char* data;
385+
if ((data = read_file_offset_length(fname, offset, length)) == NULL) {
386+
return 1;
387+
}
388+
389+
for (long long k = 0; k < length && data[k] != '\0'; k++) {
390+
printf("%x", data[k]);
391+
}
392+
393+
free(data);
394+
395+
printf("\n");
396+
397+
return 0;
398+
}
399+
400+
int appimage_print_binary(char* fname, unsigned long offset, unsigned long length) {
401+
char* data;
402+
if ((data = read_file_offset_length(fname, offset, length)) == NULL) {
403+
return 1;
404+
}
405+
406+
printf("%s\n", data);
407+
408+
free(data);
409+
410+
return 0;
411+
}
333412

334413
/* Exit status to use when launching an AppImage fails.
335414
* For applications that assign meanings to exit status codes (e.g. rsync),
@@ -523,6 +602,8 @@ void print_help(const char* appimage_path) {
523602
" https://github.com/vasi/squashfuse/blob/master/LICENSE\n"
524603
" * libzstd, licensed under the terms of\n"
525604
" https://github.com/facebook/zstd/blob/dev/LICENSE\n"
605+
" * zlib, licensed under the terms of\n"
606+
" https://zlib.net/zlib_license.html\n"
526607
"Please see https://github.com/probonopd/static-tools/\n"
527608
"for information on how to obtain and build the source code\n", appimage_path);
528609
}
@@ -1441,18 +1522,28 @@ int main(int argc, char* argv[]) {
14411522
exit(status);
14421523
}
14431524

1444-
if (arg && (strcmp(arg, "appimage-updateinformation") == 0 || strcmp(arg, "appimage-updateinfo") == 0)) {
1445-
fprintf(stderr, "--%s is not yet implemented in version %s\n", arg, GIT_COMMIT);
1446-
// NOTE: Must be implemented in this .c file with no additional dependencies
1447-
exit(1);
1525+
if(arg && (strcmp(arg,"appimage-updateinformation")==0 || strcmp(arg,"appimage-updateinfo")==0)) {
1526+
unsigned long offset = 0;
1527+
unsigned long length = 0;
1528+
appimage_get_elf_section_offset_and_length(appimage_path, ".upd_info", &offset, &length);
1529+
// fprintf(stderr, "offset: %lu\n", offset);
1530+
// fprintf(stderr, "length: %lu\n", length);
1531+
// print_hex(appimage_path, offset, length);
1532+
appimage_print_binary(appimage_path, offset, length);
1533+
exit(0);
14481534
}
14491535

1450-
if (arg && strcmp(arg, "appimage-signature") == 0) {
1451-
fprintf(stderr, "--%s is not yet implemented in version %s\n", arg, GIT_COMMIT);
1452-
// NOTE: Must be implemented in this .c file with no additional dependencies
1453-
exit(1);
1536+
if(arg && strcmp(arg,"appimage-signature")==0) {
1537+
unsigned long offset = 0;
1538+
unsigned long length = 0;
1539+
appimage_get_elf_section_offset_and_length(appimage_path, ".sha256_sig", &offset, &length);
1540+
// fprintf(stderr, "offset: %lu\n", offset);
1541+
// fprintf(stderr, "length: %lu\n", length);
1542+
// print_hex(appimage_path, offset, length);
1543+
appimage_print_binary(appimage_path, offset, length);
1544+
exit(0);
14541545
}
1455-
1546+
14561547
portable_option(arg, appimage_path, "home");
14571548
portable_option(arg, appimage_path, "config");
14581549

0 commit comments

Comments
 (0)