#include "mrklib_priv.h" static int write_file(Eet_File *ef, const char *key, const char *file) { FILE *f; void *mem; int size; char *s; mem = eet_read(ef, key, &size); if (mem) { s = ecore_file_dir_get(file); if (s) { ecore_file_mkpath(s); free(s); } f = fopen(file, "wb"); if (f) { fwrite(mem, size, 1, f); fclose(f); return 1; } } return 0; } EAPI Eina_Bool mrk_package_src_extract(const char *file, const char *dst) { Eet_File *ef = NULL; char tmp[4096]; ef = eet_open(file, EET_FILE_MODE_READ); if (ef) { int i, num = 0; char **keys = eet_list(ef, "src/*", &num); if (keys) { for (i = 0; i < num; i++) { if (!strncmp(keys[i], "src/", 4)) { if (!_mrk_util_plain_path_check(&(keys[i][4]))) continue; snprintf(tmp, sizeof(tmp), "%s/%s", dst, &(keys[i][4])); if (!write_file(ef, keys[i], tmp)) { free(keys); goto error; } } } free(keys); } snprintf(tmp, sizeof(tmp), "%s/%s", dst, "Marrakesh.mrk"); if (!write_file(ef, "buildinfo", tmp)) goto error; eet_close(ef); return EINA_TRUE; } error: if (ef) eet_close(ef); return EINA_FALSE; } static char * read_string(Eet_File *ef, const char *key) { int size = 0; char *str; char *s = eet_read(ef, key, &size); if (!s) return NULL; str = malloc(size + 1); if (!str) { free(s); return NULL; } memcpy(str, s, size); str[size] = 0; free(s); return str; } static void clean_symlinks(const char *dir) { Eina_List *files; char *s, *ss; char tmp[4096]; files = ecore_file_ls(dir); EINA_LIST_FREE(files, s) { snprintf(tmp, sizeof(tmp), "%s/%s", dir, s); ss = ecore_file_readlink(tmp); if (ss) { free(ss); if (!ecore_file_exists(tmp)) { printf("clean '%s'\n", tmp); ecore_file_unlink(tmp); } } free(s); } } static int field_copy(Eet_File *ef, Eet_File *ef2, const char *key) { int size = 0; char *s = eet_read(ef, key, &size); if (s) { eet_write(ef2, key, s, size, EET_COMPRESSION_VERYFAST); free(s); return 1; } return 0; } static const char * get_home(void) { static char buf[4096] = ""; const char *tmps, *home; if (buf[0]) return buf; tmps = getenv("XDG_DATA_HOME"); home = getenv("HOME"); if (!home) home = "/tmp"; if (tmps) snprintf(buf, sizeof(buf), "%s", tmps); else snprintf(buf, sizeof(buf), "%s", home); return buf; } EAPI Eina_Bool mrk_package_bin_clean(void) { char tmp[4096]; snprintf(tmp, sizeof(tmp), "%s/.local/share/icons", get_home()); clean_symlinks(tmp); snprintf(tmp, sizeof(tmp), "%s/.local/share/applications", get_home()); clean_symlinks(tmp); snprintf(tmp, sizeof(tmp), "%s/Applications/.bin", get_home()); clean_symlinks(tmp); return 1; } EAPI Eina_Bool mrk_package_verify(const char *file, const char *key_cert_file) { Eet_File *ef; Eina_Bool ok = EINA_FALSE; ef = eet_open(file, EET_FILE_MODE_READ); if (!ef) return EINA_FALSE; if (eet_identity_verify(ef, key_cert_file)) ok = EINA_TRUE; eet_close(ef); return ok; } EAPI Eina_Bool mrk_package_bin_install(const char *file, const char *os, const char *arch) { Eet_File *ef, *ef2; #define err(reason) do { fprintf(stderr, "%s\n", reason); goto error; } while (0) ef = eet_open(file, EET_FILE_MODE_READ); if (ef) { int i, num = 0; char **keys = eet_list(ef, "bin/*", &num); char inst[4096]; char dir[4096]; char tmp[4096]; char tmp2[4096]; char *s; Eina_List *files; char *name; char *str; str = read_string(ef, "arch"); if (!str) err("no arch"); snprintf(tmp, sizeof(tmp), "%s-%s", os, arch); if (strcmp(tmp, str)) { free(str); err("arch mismatch\n"); } free(str); name = read_string(ef, "name"); if (!name) err("no name"); if (!_mrk_util_plain_file_check(name)) err("name failed sanity check"); snprintf(tmp, sizeof(tmp), "%s/Applications/.bin", get_home()); ecore_file_mkpath(tmp); snprintf(inst, sizeof(inst), "%s/Applications/%s", get_home(), name); if (ecore_file_exists(inst)) err("destination already exists"); ecore_file_mkpath(inst); if (keys) { for (i = 0; i < num; i++) { if (!strncmp(keys[i], "bin/", 4)) { if (!_mrk_util_plain_path_check(&(keys[i][6]))) continue; snprintf(tmp, sizeof(tmp), "%s/%s", inst, &(keys[i][6])); write_file(ef, keys[i], tmp); if (keys[i][4] == 'X') { printf("+x '%s'\n", &(keys[i][6])); chmod(tmp, 00500); } } } } snprintf(dir, sizeof(dir), "%s/share/icons", inst); files = ecore_file_ls(dir); EINA_LIST_FREE(files, s) { if (!strcmp(s, ".")) continue; else if (!strcmp(s, "..")) continue; snprintf(tmp, sizeof(tmp), "../../../Applications/%s/share/icons/%s", name, s); snprintf(tmp2, sizeof(tmp2), "%s/.local/share/icons/%s", get_home(), s); if (ecore_file_exists(tmp2)) err("icon file symlink already exists"); ecore_file_symlink(tmp, tmp2); free(s); } snprintf(dir, sizeof(dir), "%s/share/applications", inst); files = ecore_file_ls(dir); EINA_LIST_FREE(files, s) { if (!strcmp(s, ".")) continue; else if (!strcmp(s, "..")) continue; snprintf(tmp, sizeof(tmp), "../../../Applications/%s/share/applications/%s", name, s); snprintf(tmp2, sizeof(tmp2), "%s/.local/share/applications/%s", get_home(), s); if (ecore_file_exists(tmp2)) err("desktop file symlink already exists"); ecore_file_symlink(tmp, tmp2); free(s); } snprintf(dir, sizeof(dir), "%s/bin", inst); files = ecore_file_ls(dir); EINA_LIST_FREE(files, s) { if (!strcmp(s, ".")) continue; else if (!strcmp(s, "..")) continue; snprintf(tmp, sizeof(tmp), "../%s/bin/%s", name, s); snprintf(tmp2, sizeof(tmp2), "%s/Applications/.bin/%s", get_home(), s); if (ecore_file_exists(tmp2)) err("bin file symlink already exists"); ecore_file_symlink(tmp, tmp2); free(s); } snprintf(tmp, sizeof(tmp), "%s/Applications/%s/.icon.png", get_home(), name); write_file(ef, "icon", tmp); snprintf(tmp, sizeof(tmp), "%s/Applications/%s/.splash.png", get_home(), name); write_file(ef, "splash", tmp); snprintf(tmp, sizeof(tmp), "%s/Applications/%s/.info.mki", get_home(), name); ef2 = eet_open(tmp, EET_FILE_MODE_WRITE); free(name); if (ef2) { field_copy(ef, ef2, "name"); field_copy(ef, ef2, "brief"); field_copy(ef, ef2, "version"); field_copy(ef, ef2, "license"); field_copy(ef, ef2, "repo"); field_copy(ef, ef2, "devrepo"); field_copy(ef, ef2, "contact"); field_copy(ef, ef2, "needs"); for (i = 0; i < 9999; i++) { snprintf(tmp, sizeof(tmp), "tag/%i", i); if (!field_copy(ef, ef2, tmp)) break; } for (i = 0; i < 9999; i++) { snprintf(tmp, sizeof(tmp), "category/%i", i); if (!field_copy(ef, ef2, tmp)) break; } eet_close(ef2); } eet_close(ef); return EINA_TRUE; } error: if (ef) eet_close(ef); return EINA_FALSE; } EAPI Eina_Bool mrk_package_bin_remove(const char *name) { char tmp[4096]; snprintf(tmp, sizeof(tmp), "%s/Applications/%s", get_home(), name); if (!ecore_file_recursive_rm(tmp)) return EINA_FALSE; return EINA_TRUE; }