diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-02-28 14:19:04 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-02-28 14:19:04 +0100 |
| commit | e753c19da1b621b1e667de85ce5ef60d186f0684 (patch) | |
| tree | 9bc80378efbe42ec72678230de2905ab121a4d8f /src/tools | |
| parent | 7b50468b61b7bdd9a15753c0a28711c1654a8c12 (diff) | |
| download | box64-e753c19da1b621b1e667de85ce5ef60d186f0684.tar.gz box64-e753c19da1b621b1e667de85ce5ef60d186f0684.zip | |
Added some minimal set of source (now box64 compile and say hello at least)
Diffstat (limited to 'src/tools')
| -rwxr-xr-x | src/tools/fileutils.c | 129 | ||||
| -rwxr-xr-x | src/tools/pathcoll.c | 182 | ||||
| -rwxr-xr-x | src/tools/wine_tools.c | 107 |
3 files changed, 418 insertions, 0 deletions
diff --git a/src/tools/fileutils.c b/src/tools/fileutils.c new file mode 100755 index 00000000..6a964553 --- /dev/null +++ b/src/tools/fileutils.c @@ -0,0 +1,129 @@ +#define _FILE_OFFSET_BITS 64 +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <limits.h> +#include <stdint.h> + +#ifndef MAX_PATH +#define MAX_PATH 4096 +#endif + +#include "debug.h" +#include "fileutils.h" + +static const char* x64sign = "\x7f" "ELF" "\x02" "\x01" "\x01" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x02" "\x00" "\x3e" "\x00"; + +int FileExist(const char* filename, int flags) +{ + struct stat sb; + if (stat(filename, &sb) == -1) + return 0; + if(flags==-1) + return 1; + // check type of file? should be executable, or folder + if(flags&IS_FILE) { + if(!S_ISREG(sb.st_mode)) + return 0; + } else if(!S_ISDIR(sb.st_mode)) + return 0; + + if(flags&IS_EXECUTABLE) { + if((sb.st_mode&S_IXUSR)!=S_IXUSR) + return 0; // nope + } + return 1; +} + +char* ResolveFile(const char* filename, path_collection_t* paths) +{ + char p[MAX_PATH]; + if(filename[0]=='/') + return strdup(filename); + for (int i=0; i<paths->size; ++i) { + if(paths->paths[i][0]!='/') { + // not an absolute path... + getcwd(p, sizeof(p)); + if(p[strlen(p)-1]!='/') + strcat(p, "/"); + strcat(p, paths->paths[i]); + } else + strcpy(p, paths->paths[i]); + strcat(p, filename); + if(FileExist(p, IS_FILE)) + return realpath(p, NULL); + } + + return NULL; +} + +int FileIsX64ELF(const char* filename) +{ + FILE *f = fopen(filename, "rb"); + if(!f) + return 0; + char head[sizeof(*x64sign)] = {0}; + int sz = fread(head, sizeof(*x64sign), 1, f); + if(sz!=1) { + fclose(f); + return 0; + } + fclose(f); + if(memcmp(head, x64sign, sizeof(*x64sign))==0) + return 1; + return 0; +} + +#if defined(RPI) || defined(RK3399) +void sanitize_mojosetup_gtk_background() +{ + // get GTK2_RC_FILES folder + const char* gtk2_rc = getenv("GTK2_RC_FILES"); + // check if $GTK2_RC_FILES/pixmaps/background.png exist + char background[1000] = {0}; + strcpy(background, gtk2_rc); + char* p = strrchr(background, '/'); // remove "/gtkrc" + // every error will just silently abort + if(!p) + return; + *p = 0; + strcat(background, "/pixmaps/background.png"); + if(!FileExist(background, IS_FILE)) + return; + // now open are read the header of the PNG to grab the width and height + //very crude reading here! + FILE* f = fopen(background, "rb"); + if(!f) + return; + char sign[8]; + if(fread(sign, 8, 1, f)!=1) { + fclose(f); return; + } + const char ref[8] = {'\211', 'P', 'N', 'G', '\r', '\n', '\032', '\n' }; + if (memcmp(sign, ref, 8)) { + fclose(f); return; + } + int32_t width, height; + fseek(f, 16, SEEK_SET); + if(fread(&width, sizeof(width), 1, f)!=1) { + fclose(f); return; + } + if(fread(&height, sizeof(height), 1, f)!=1) { + fclose(f); return; + } + fclose(f); + // need to swap bitness! + width = __builtin_bswap32(width); + height = __builtin_bswap32(height); + printf_log(LOG_INFO, "Mojosetup detected, size of background picture is %dx%d\n", width, height); + if(width!=5000 || height!=3000) + return; // not a background that will cause any issue + // delete the file! + f = fopen(background, "r+b"); + remove(background); + printf_log(LOG_INFO, "background deleted!\n"); +} +#endif diff --git a/src/tools/pathcoll.c b/src/tools/pathcoll.c new file mode 100755 index 00000000..d7e423bb --- /dev/null +++ b/src/tools/pathcoll.c @@ -0,0 +1,182 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <stdint.h> + +#ifndef MAX_PATH +#define MAX_PATH 4096 +#endif + +#include "debug.h" +#include "pathcoll.h" + +void FreeCollection(path_collection_t* collection) +{ + if(!collection) + return; + if(collection->cap) { + for(int i=0; i<collection->size; ++i) + free(collection->paths[i]); + free(collection->paths); + } + collection->paths = NULL; + collection->size = 0; + collection->cap = 0; + return; +} + +void ParseList(const char* List, path_collection_t* collection, int folder) +{ + if(collection->cap) + FreeCollection(collection); + // count the stings (basically count(':') + 1) to define cap + int cnt = 1; + { + const char* p = List; + while(p) { + p = strchr(p, ':'); + ++cnt; + if(p) ++p; + } + } + // alloc empty strings + collection->cap = cnt; + collection->paths = (char**)calloc(cnt, sizeof(char*)); + // and now split the paths... + char tmp[MAX_PATH]; + const char *p = List; + int idx = 0; + while(p) { + const char *p2 = strchr(p, ':'); + if(!p2) { + strncpy(tmp, p, MAX_PATH - 1); + p=NULL; + } else { + int l = (uintptr_t)p2 - (uintptr_t)p; + strncpy(tmp, p, l); + tmp[l]='\0'; + p=p2+1; + } + // check if there is terminal '/', add it if not + int l = strlen(tmp); + // skip empty strings + if(l) { + if(folder && tmp[l-1]!='/') + strcat(tmp, "/"); + collection->paths[idx] =strdup(tmp); + collection->size=++idx; + } + } +} + +void CopyCollection(path_collection_t* to, path_collection_t* from) +{ + to->cap = from->cap; + to->paths = (char**)calloc(to->cap, sizeof(char*)); + to->size = from->size; + for (int i=0; i<to->size; ++i) + to->paths[i] = strdup(from->paths[i]); +} + +void AddPath(const char* path, path_collection_t* collection, int folder) +{ + char tmp[MAX_PATH]; + strcpy(tmp, path); + int l = strlen(tmp); + // skip empty strings + if(l) { + if(folder && tmp[l-1]!='/') + strcat(tmp, "/"); + if(collection->size==collection->cap) { + collection->cap += 4; + collection->paths = (char**)realloc(collection->paths, collection->cap*sizeof(char*)); + } + collection->paths[collection->size++]=strdup(tmp); + } +} +void PrependPath(const char* path, path_collection_t* collection, int folder) +{ + char tmp[MAX_PATH]; + strcpy(tmp, path); + int l = strlen(tmp); + // skip empty strings + if(l) { + if(folder && tmp[l-1]!='/') + strcat(tmp, "/"); + if(collection->size==collection->cap) { + collection->cap += 4; + collection->paths = (char**)realloc(collection->paths, collection->cap*sizeof(char*)); + } + memmove(collection->paths+1, collection->paths, sizeof(char*)*collection->size); + collection->paths[0]=strdup(tmp); + ++collection->size; + } +} + +void AppendList(path_collection_t* collection, const char* List, int folder) +{ + if(!List) + return; + // and now split the paths... + char tmp[MAX_PATH]; + const char *p = List; + while(p) { + const char *p2 = strchr(p, ':'); + if(!p2) { + strncpy(tmp, p, MAX_PATH - 1); + p=NULL; + } else { + int l = (uintptr_t)p2 - (uintptr_t)p; + strncpy(tmp, p, l); + tmp[l]='\0'; + p=p2+1; + } + // check if there is terminal '/', add it if not + int l = strlen(tmp); + // skip empty strings + if(l) { + if(folder && tmp[l-1]!='/') + strcat(tmp, "/"); + AddPath(tmp, collection, folder); + } + } + +} +void PrependList(path_collection_t* collection, const char* List, int folder) +{ + if(!List) + return; + // and now split the paths... + char tmp[MAX_PATH]; + char *p = strdup(List); + while(p) { + char *p2 = strrchr(p, ':'); + if(!p2) { + strncpy(tmp, p, MAX_PATH - 1); + free(p); + p=NULL; + } else { + strncpy(tmp, p2+1, MAX_PATH - 1); + tmp[MAX_PATH - 1]='\0'; + *p2 = '\0'; + } + // check if there is terminal '/', add it if not + int l = strlen(tmp); + // skip empty strings + if(l) { + if(folder && tmp[l-1]!='/') + strcat(tmp, "/"); + PrependPath(tmp, collection, folder); + } + } + +} + +int FindInCollection(const char* path, path_collection_t* collection) +{ + for (int i=0; i<collection->size; ++i) + if(strcmp(path, collection->paths[i])==0) + return 1; + return 0; +} diff --git a/src/tools/wine_tools.c b/src/tools/wine_tools.c new file mode 100755 index 00000000..6fa7a47d --- /dev/null +++ b/src/tools/wine_tools.c @@ -0,0 +1,107 @@ +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <sys/mman.h> +#include <errno.h> + +#include "wine_tools.h" +#include "debug.h" +#include "box64context.h" + +typedef struct wine_prereserve_s +{ + void* addr; + size_t size; +} wine_prereserve_t; + +// only the prereseve argument is reserved, not the other zone that wine-preloader reserve +static wine_prereserve_t my_wine_reserve[] = {{(void*)0x00010000, 0x00008000}, {(void*)0x00110000, 0x30000000}, {(void*)0x7f000000, 0x03000000}, {0, 0}, {0, 0}}; + +int wine_preloaded = 0; + +static int get_prereserve(const char* reserve, void** addr, size_t* size) +{ + if(!reserve) + return 0; + uintptr_t r = 0; + int first = 1; + while(*reserve) { + // numbers reading + if(*reserve>='0' && *reserve<='9') r=r*16+(*reserve)-'0'; + else if(*reserve>='A' && *reserve<='F') r=r*16+(*reserve)-'A'+10; + else if(*reserve>='a' && *reserve<='f') r=r*16+(*reserve)-'a'+10; + else if(*reserve=='-') {if(first) {*addr=(void*)(r&~(box64_pagesize-1)); r=0; first=0;} else {printf_log(LOG_NONE, "Warning, Wine prereserve badly formated\n"); return 0;}} + else {printf_log(LOG_NONE, "Warning, Wine prereserve badly formated\n"); return 0;} + ++reserve; + } + *size = r; + return 1; +} + +static void add_no_overlap(void* addr, size_t size) +{ + int idx = 0; + while(my_wine_reserve[idx].addr && my_wine_reserve[idx].size) { + if(addr>=my_wine_reserve[idx].addr && addr<my_wine_reserve[idx].addr+my_wine_reserve[idx].size) { + // overlap + if (addr+size > my_wine_reserve[idx].addr+my_wine_reserve[idx].size) + // need adjust size + my_wine_reserve[idx].size = (intptr_t)addr-(intptr_t)my_wine_reserve[idx].addr+size; + return; + } + ++idx; + } + my_wine_reserve[idx].addr = addr; + my_wine_reserve[idx].size = size; +} + +void wine_prereserve(const char* reserve) +{ + void* addr = NULL; + size_t size = 0; + + if(get_prereserve(reserve, &addr, &size)) { + add_no_overlap(addr, size); + } + + int idx = 0; + while(my_wine_reserve[idx].addr && my_wine_reserve[idx].size) { + void* p = mmap(my_wine_reserve[idx].addr, my_wine_reserve[idx].size, + PROT_NONE, /*MAP_FIXED |*/ MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0); + if(p==(void*)-1 || p!=my_wine_reserve[idx].addr) { + printf_log(LOG_NONE, "Warning, prereserve of %p:0x%x failed (%s)\n", my_wine_reserve[idx].addr, my_wine_reserve[idx].size, strerror(errno)); + if(p!=(void*)-1) + munmap(p, my_wine_reserve[idx].size); + my_wine_reserve[idx].addr = NULL; + my_wine_reserve[idx].size = 0; + } else { + printf_log(LOG_DEBUG, "WINE prereserve of %p:0x%x done\n", my_wine_reserve[idx].addr, my_wine_reserve[idx].size); + ++idx; + } + } + + wine_preloaded = 1; +} + +void* get_wine_prereserve() +{ + if(!wine_preloaded) + wine_prereserve(NULL); + return (void*)my_wine_reserve; +} + +#ifdef DYNAREC +void dynarec_wine_prereserve() +{ + #if 0 + // disable for now, as it break some installer + if(!wine_preloaded) + wine_prereserve(NULL); + // don't reserve the initial arbritrary block as "with linker", it's not true + for(int i=1; i<sizeof(my_wine_reserve)/sizeof(my_wine_reserve[0]); ++i) + if(my_wine_reserve[i].addr && my_wine_reserve[i].size) + addDBFromAddressRange(my_context, (uintptr_t)my_wine_reserve[i].addr, my_wine_reserve[i].size, 0); // prepare the prereserved area for exec, with linker + #endif +} +#endif |