marrakesh/mrklib_package.c

307 lines
8.6 KiB
C

#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;
}