1758 lines
53 KiB
C
1758 lines
53 KiB
C
/*
|
|
gcc mrk.c -o mrk `pkg-config --cflags --libs eina ecore-file eet`
|
|
*/
|
|
// note that this code is far from clean or nice at all. it's not very robust
|
|
// but it works for the purposes of a proof of concept and getting things off
|
|
// the ground - so please judge it by that for now
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/stat.h>
|
|
#include <Eina.h>
|
|
#include <Ecore.h>
|
|
#include <Ecore_File.h>
|
|
#include <Ecore_Ipc.h>
|
|
#include <Eet.h>
|
|
|
|
#include "mrk-proto.h"
|
|
|
|
typedef enum
|
|
{
|
|
TMODE_EOL,
|
|
TMODE_PATH,
|
|
TMODE_TEXT,
|
|
TMODE_PATH_CP,
|
|
TMODE_PATH_CP_LIST,
|
|
TMODE_PATH_LIST,
|
|
} Tag_Mode;
|
|
|
|
typedef struct
|
|
{
|
|
const char *tag;
|
|
Tag_Mode mode;
|
|
} Tag_Type;
|
|
|
|
typedef struct
|
|
{
|
|
char *bin;
|
|
Eina_List *srcs;
|
|
Eina_List *deps;
|
|
Eina_List *incs;
|
|
} Build_Bin;
|
|
|
|
typedef struct
|
|
{
|
|
char *src;
|
|
char *dest;
|
|
} Build_Data;
|
|
|
|
typedef struct
|
|
{
|
|
char *name;
|
|
char *icon;
|
|
char *brief;
|
|
char *version;
|
|
char *license;
|
|
char *domain;
|
|
char *repo;
|
|
char *devrepo;
|
|
char *contact;
|
|
Eina_List *tags;
|
|
Eina_List *categories;
|
|
Eina_List *copying;
|
|
char *needs;
|
|
Eina_List *bins;
|
|
Eina_List *data;
|
|
Eina_List *desktops;
|
|
Eina_List *icons;
|
|
Eina_List *po;
|
|
} Build;
|
|
|
|
|
|
static const Tag_Type tags[] =
|
|
{
|
|
{"PROJ:", TMODE_EOL},
|
|
{"PROJICON:", TMODE_PATH},
|
|
{"BRIEF:", TMODE_TEXT},
|
|
{"VERSION:", TMODE_EOL},
|
|
{"LICENSE:", TMODE_EOL},
|
|
{"COPYING:", TMODE_PATH_LIST},
|
|
{"NEEDS:", TMODE_EOL},
|
|
{"DOMAIN:", TMODE_PATH},
|
|
{"REPO:", TMODE_EOL},
|
|
{"DEVREPO:", TMODE_EOL},
|
|
{"CONTACT:", TMODE_TEXT},
|
|
{"CATEGORY:", TMODE_PATH_LIST},
|
|
{"TAGS:", TMODE_PATH_LIST},
|
|
{"BIN:", TMODE_PATH},
|
|
{"SRC:", TMODE_PATH_LIST},
|
|
{"DEPS:", TMODE_PATH_LIST},
|
|
{"INC:", TMODE_PATH_LIST},
|
|
{"DATA:", TMODE_PATH_CP_LIST},
|
|
{"DESKTOP:", TMODE_PATH_LIST},
|
|
{"ICON:", TMODE_PATH_LIST},
|
|
{"PODOMAIN:", TMODE_PATH},
|
|
{"PO:", TMODE_PATH_LIST},
|
|
{NULL, 0} // END OF LIST
|
|
};
|
|
|
|
static Build build = { 0 };
|
|
static char *tmpd = "Marrakesh";
|
|
static const char *sane_name_veto[] = {"../", "./", "/", NULL};
|
|
static const char *sane_name_ok = "01234567890-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ. ";
|
|
static const char *sane_path_veto[] = {"../", "./", NULL};
|
|
static const char *sane_path_ok = "01234567890-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ. ";
|
|
static char *server = "devs.enlightenment.org";
|
|
static int server_port = 10077;
|
|
static char *arch = ARCH;
|
|
static char *os = OS;
|
|
|
|
static void
|
|
err(char *msg)
|
|
{
|
|
fprintf(stderr, "ERROR: %s\n", msg);
|
|
exit(1);
|
|
}
|
|
|
|
static int
|
|
sane_forbidden_path(const char *file, const char **forbidden)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; forbidden[i]; i++)
|
|
{
|
|
if (strstr(forbidden[i], file)) return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
sane_allowed_path(const char *file, const char *allowed)
|
|
{
|
|
int i, j;
|
|
|
|
for (i = 0; file[i]; i++)
|
|
{
|
|
int ok;
|
|
|
|
ok = 0;
|
|
for (j = 0; allowed[j]; j++)
|
|
{
|
|
if (file[i] == allowed[j])
|
|
{
|
|
ok = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (!ok) return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static char *
|
|
parse_token(char **p, char *end)
|
|
{
|
|
char *tok, *seg;
|
|
|
|
while ((*p < end) && (isspace(**p))) (*p)++;
|
|
if (*p >= end) return NULL;
|
|
tok = *p;
|
|
|
|
while (*p < end)
|
|
{
|
|
if (isspace(**p)) goto token;
|
|
(*p)++;
|
|
}
|
|
token:
|
|
seg = malloc(*p - tok + 1);
|
|
if (!seg) return NULL;
|
|
memcpy(seg, tok, *p - tok);
|
|
seg[*p - tok] = 0;
|
|
return seg;
|
|
}
|
|
|
|
static char *
|
|
parse_eol(char **p, char *end)
|
|
{
|
|
char *tok, *seg;
|
|
|
|
while ((*p < end) && (isspace(**p))) (*p)++;
|
|
if (*p >= end) return NULL;
|
|
tok = *p;
|
|
|
|
while (*p < end)
|
|
{
|
|
if (**p == '\n') goto token;
|
|
(*p)++;
|
|
}
|
|
token:
|
|
seg = malloc(*p - tok + 1);
|
|
if (!seg) return NULL;
|
|
memcpy(seg, tok, *p - tok);
|
|
seg[*p - tok] = 0;
|
|
return seg;
|
|
}
|
|
|
|
static char *
|
|
path_check(char *tok)
|
|
{
|
|
// XXX: check me
|
|
return strdup(tok);
|
|
}
|
|
|
|
static int
|
|
parse_content(char *mem, size_t size)
|
|
{
|
|
char prevc = '\n';
|
|
char *end = mem + size;
|
|
char *p = mem;
|
|
int skipline = 0;
|
|
int startline = 0;
|
|
char *seg = NULL, *s;
|
|
char *data1 = NULL, *data2 = NULL;
|
|
int i;
|
|
Tag_Mode mode = TMODE_TEXT;
|
|
|
|
while (p < end)
|
|
{
|
|
if (prevc == '\n')
|
|
{
|
|
if (*p == '#') skipline = 1;
|
|
else skipline = 0;
|
|
startline = 1;
|
|
}
|
|
if (!skipline)
|
|
{
|
|
char *tok;
|
|
char *prevp;
|
|
|
|
prevp = p;
|
|
tok = parse_token(&p, end);
|
|
if (!tok) return 1;
|
|
if (startline)
|
|
{
|
|
for (i = 0; tags[i].tag; i++)
|
|
{
|
|
if (!strcmp(tok, tags[i].tag))
|
|
{
|
|
// printf("#: %s\n", tok);
|
|
free(seg);
|
|
seg = strdup(tok);
|
|
mode = tags[i].mode;
|
|
break;
|
|
}
|
|
}
|
|
if (!tags[i].tag) goto not_tag;
|
|
}
|
|
else
|
|
{
|
|
not_tag:
|
|
switch (mode)
|
|
{
|
|
case TMODE_EOL:
|
|
case TMODE_TEXT:
|
|
// prse eol of prevp
|
|
p = prevp;
|
|
data1 = parse_eol(&p, end);
|
|
if (!data1) err("no content");
|
|
break;
|
|
case TMODE_PATH:
|
|
case TMODE_PATH_LIST:
|
|
// sanitize (check) path tok put into data1
|
|
data1 = path_check(tok);
|
|
if (!data1) err("path invalid");
|
|
break;
|
|
case TMODE_PATH_CP:
|
|
case TMODE_PATH_CP_LIST:
|
|
// sanitize path, then next token > then path 2 -> data1, data2
|
|
data1 = path_check(tok);
|
|
if (!data1) err("path invalid");
|
|
s = parse_token(&p, end);
|
|
if (!s) err("missing > in path copy");
|
|
if (!(!strcmp(s, ">"))) err("copy token is not >");
|
|
free(s);
|
|
s = parse_token(&p, end);
|
|
if (!s) err("missing destination path in path copy");
|
|
data2 = path_check(s);
|
|
if (!data2) err("destination path not valid");
|
|
free(s);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
// if (data2)
|
|
// printf(" %i> %s '%s' '%s'\n",
|
|
// mode, seg, data1, data2);
|
|
// else
|
|
// printf(" %i> %s '%s'\n",
|
|
// mode, seg, data1);
|
|
if (seg)
|
|
{
|
|
if (!strcmp(seg, "PROJ:"))
|
|
{
|
|
if (!(sane_forbidden_path(data1, sane_name_veto) &&
|
|
sane_allowed_path(data1, sane_name_ok)))
|
|
err("name failed sanity check");
|
|
free(build.name);
|
|
build.name = strdup(data1);
|
|
}
|
|
else if (!strcmp(seg, "PROJICON:"))
|
|
{
|
|
free(build.icon);
|
|
build.icon = strdup(data1);
|
|
}
|
|
else if (!strcmp(seg, "BRIEF:"))
|
|
{
|
|
if (!build.brief) build.brief = strdup(data1);
|
|
else
|
|
{
|
|
s = malloc(strlen(build.brief) + 1 + strlen(data1) + 1);
|
|
if (s)
|
|
{
|
|
strcpy(s, build.brief);
|
|
strcat(s, " ");
|
|
strcat(s, data1);
|
|
free(build.brief);
|
|
build.brief = s;
|
|
}
|
|
}
|
|
}
|
|
else if (!strcmp(seg, "VERSION:"))
|
|
{
|
|
free(build.version);
|
|
build.version = strdup(data1);
|
|
}
|
|
else if (!strcmp(seg, "LICENSE:"))
|
|
{
|
|
free(build.license);
|
|
build.license = strdup(data1);
|
|
}
|
|
else if (!strcmp(seg, "COPYING:"))
|
|
{
|
|
build.copying = eina_list_append(build.copying,
|
|
strdup(data1));
|
|
}
|
|
else if (!strcmp(seg, "NEEDS:"))
|
|
{
|
|
free(build.needs);
|
|
build.license = strdup(data1);
|
|
}
|
|
else if (!strcmp(seg, "DOMAIN:"))
|
|
{
|
|
free(build.domain);
|
|
build.domain = strdup(data1);
|
|
}
|
|
else if (!strcmp(seg, "REPO:"))
|
|
{
|
|
free(build.repo);
|
|
build.repo = strdup(data1);
|
|
}
|
|
else if (!strcmp(seg, "DEVREPO:"))
|
|
{
|
|
free(build.devrepo);
|
|
build.devrepo = strdup(data1);
|
|
}
|
|
else if (!strcmp(seg, "CATEGORY:"))
|
|
{
|
|
build.categories = eina_list_append(build.categories,
|
|
strdup(data1));
|
|
}
|
|
else if (!strcmp(seg, "TAGS:"))
|
|
{
|
|
build.tags = eina_list_append(build.tags,
|
|
strdup(data1));
|
|
}
|
|
else if (!strcmp(seg, "CONTACT:"))
|
|
{
|
|
if (!build.contact) build.contact = strdup(data1);
|
|
else
|
|
{
|
|
s = malloc(strlen(build.contact) + 1 + strlen(data1) + 1);
|
|
if (s)
|
|
{
|
|
strcpy(s, build.contact);
|
|
strcat(s, " ");
|
|
strcat(s, data1);
|
|
free(build.contact);
|
|
build.contact = s;
|
|
}
|
|
}
|
|
}
|
|
else if (!strcmp(seg, "BIN:"))
|
|
{
|
|
Build_Bin *build_bin = calloc(1, sizeof(Build_Bin));
|
|
if (build_bin)
|
|
{
|
|
build_bin->bin = strdup(data1);
|
|
build.bins = eina_list_append(build.bins,
|
|
build_bin);
|
|
}
|
|
}
|
|
else if (!strcmp(seg, "SRC:"))
|
|
{
|
|
Build_Bin *build_bin = eina_list_data_get(eina_list_last(build.bins));
|
|
if (build_bin)
|
|
{
|
|
build_bin->srcs = eina_list_append(build_bin->srcs,
|
|
strdup(data1));
|
|
}
|
|
}
|
|
else if (!strcmp(seg, "DEPS:"))
|
|
{
|
|
Build_Bin *build_bin = eina_list_data_get(eina_list_last(build.bins));
|
|
if (build_bin)
|
|
{
|
|
build_bin->deps = eina_list_append(build_bin->deps,
|
|
strdup(data1));
|
|
}
|
|
}
|
|
else if (!strcmp(seg, "INC:"))
|
|
{
|
|
Build_Bin *build_bin = eina_list_data_get(eina_list_last(build.bins));
|
|
if (build_bin)
|
|
{
|
|
build_bin->incs = eina_list_append(build_bin->incs,
|
|
strdup(data1));
|
|
}
|
|
}
|
|
else if (!strcmp(seg, "DATA:"))
|
|
{
|
|
Build_Data *build_data = calloc(1, sizeof(Build_Data));
|
|
if (build_data)
|
|
{
|
|
build_data->src = strdup(data1);
|
|
build_data->dest = strdup(data2);
|
|
build.data = eina_list_append(build.data,
|
|
build_data);
|
|
}
|
|
}
|
|
else if (!strcmp(seg, "DESKTOP:"))
|
|
{
|
|
build.desktops = eina_list_append(build.desktops,
|
|
strdup(data1));
|
|
}
|
|
else if (!strcmp(seg, "ICON:"))
|
|
{
|
|
build.icons = eina_list_append(build.icons,
|
|
strdup(data1));
|
|
}
|
|
else if (!strcmp(seg, "PO:"))
|
|
{
|
|
build.po = eina_list_append(build.po,
|
|
strdup(data1));
|
|
}
|
|
}
|
|
free(data1);
|
|
free(data2);
|
|
data1 = NULL;
|
|
data2 = NULL;
|
|
}
|
|
free(tok);
|
|
prevc = *p;
|
|
}
|
|
else
|
|
{
|
|
prevc = *p;
|
|
p++;
|
|
}
|
|
startline = 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
parse_bld(const char *file)
|
|
{
|
|
Eina_File *ef;
|
|
char *mem;
|
|
size_t size;
|
|
int ret;
|
|
|
|
ef = eina_file_open(file, EINA_FALSE);
|
|
if (!ef) return 0;
|
|
|
|
size = eina_file_size_get(ef);
|
|
mem = eina_file_map_all(ef, EINA_FILE_SEQUENTIAL);
|
|
if ((size == 0) || (!mem)) return 0;
|
|
|
|
ret = parse_content(mem, size);
|
|
|
|
eina_file_close(ef);
|
|
return ret;
|
|
}
|
|
|
|
static int
|
|
build_proj(void)
|
|
{
|
|
Eina_List *l, *ll;
|
|
Build_Bin *bin;
|
|
Build_Data *data;
|
|
Eina_Strbuf *buf;
|
|
char *s, *extn, *s2;
|
|
char tmp[4096];
|
|
char tmp2[4096];
|
|
const char *ss, *cc;
|
|
|
|
EINA_LIST_FOREACH(build.po, l, s)
|
|
{
|
|
snprintf(tmp, sizeof(tmp), "%s/share/locale/%s/LC_MESSAGES/", tmpd, s);
|
|
ecore_file_mkpath(tmp);
|
|
snprintf(tmp2, sizeof(tmp2), "po/%s.gmo", s);
|
|
snprintf(tmp, sizeof(tmp), "%s/share/locale/%s/LC_MESSAGES/%s.mo", tmpd, s, build.domain);
|
|
ecore_file_cp(tmp2, tmp);
|
|
}
|
|
EINA_LIST_FOREACH(build.data, l, data)
|
|
{
|
|
s = ecore_file_dir_get(data->dest);
|
|
if (s)
|
|
{
|
|
snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, s);
|
|
ecore_file_mkpath(tmp);
|
|
free(s);
|
|
}
|
|
snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, data->dest);
|
|
ecore_file_cp(data->src, tmp);
|
|
}
|
|
snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, "share/applications");
|
|
ecore_file_mkpath(tmp);
|
|
EINA_LIST_FOREACH(build.desktops, l, s)
|
|
{
|
|
ss = ecore_file_file_get(s);
|
|
if (!(!strncmp(ss, build.domain, strlen(build.domain))))
|
|
err("destkop file wrong domain");
|
|
snprintf(tmp, sizeof(tmp), "%s/share/applications/%s", tmpd, ss);
|
|
ecore_file_cp(s, tmp);
|
|
}
|
|
snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, "share/icons");
|
|
ecore_file_mkpath(tmp);
|
|
EINA_LIST_FOREACH(build.icons, l, s)
|
|
{
|
|
ss = ecore_file_file_get(s);
|
|
if (!(!strncmp(ss, build.domain, strlen(build.domain))))
|
|
err("icon file wrong domain");
|
|
snprintf(tmp, sizeof(tmp), "%s/share/icons/%s", tmpd, ss);
|
|
ecore_file_cp(s, tmp);
|
|
}
|
|
EINA_LIST_FOREACH(build.copying, l, s)
|
|
{
|
|
if (strchr(s, '/'))
|
|
{
|
|
s2 = ecore_file_dir_get(s);
|
|
snprintf(tmp, sizeof(tmp), "%s/share/licenses/%s", tmpd, s2);
|
|
free(s2);
|
|
}
|
|
else
|
|
snprintf(tmp, sizeof(tmp), "%s/share/licenses", tmpd);
|
|
ecore_file_mkpath(tmp);
|
|
snprintf(tmp, sizeof(tmp), "%s/share/licenses/%s", tmpd, s);
|
|
ecore_file_cp(s, tmp);
|
|
}
|
|
EINA_LIST_FOREACH(build.bins, l, bin)
|
|
{
|
|
if ((buf = eina_strbuf_new()))
|
|
{
|
|
s = ecore_file_dir_get(bin->bin);
|
|
if (s)
|
|
{
|
|
snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, s);
|
|
ecore_file_mkpath(tmp);
|
|
free(s);
|
|
}
|
|
cc = getenv("CC");
|
|
if (!cc) cc = "gcc";
|
|
eina_strbuf_append(buf, cc);
|
|
eina_strbuf_append(buf, " -I. -lm -o ");
|
|
eina_strbuf_append(buf, tmpd);
|
|
eina_strbuf_append(buf, "/");
|
|
eina_strbuf_append(buf, bin->bin);
|
|
|
|
eina_strbuf_append(buf, " -DLOCALEDIR=\\\"/tmp/X/share/locale\\\"");
|
|
eina_strbuf_append(buf, " -DPACKAGE_BIN_DIR=\\\"/tmp/X/bin\\\"");
|
|
eina_strbuf_append(buf, " -DPACKAGE_LIB_DIR=\\\"/tmp/X/lib\\\"");
|
|
eina_strbuf_append(buf, " -DPACKAGE_DATA_DIR=\\\"/tmp/X/share/");
|
|
eina_strbuf_append(buf, build.domain);
|
|
eina_strbuf_append(buf, "\\\"");
|
|
|
|
eina_strbuf_append(buf, " -DPACKAGE_NAME=\\\"");
|
|
eina_strbuf_append(buf, build.domain);
|
|
eina_strbuf_append(buf, "\\\"");
|
|
|
|
eina_strbuf_append(buf, " -DPACKAGE_VERSION=\\\"");
|
|
eina_strbuf_append(buf, build.version);
|
|
eina_strbuf_append(buf, "\\\"");
|
|
|
|
eina_strbuf_append(buf, " -D_REENTRANT -DHAVE_CONFIG_H -pthread ");
|
|
eina_strbuf_append(buf, " $CFLAGS ");
|
|
|
|
EINA_LIST_FOREACH(bin->srcs, ll, s)
|
|
{
|
|
extn = strrchr(s, '.');
|
|
if ((extn) && (!strcasecmp(extn, ".c")))
|
|
{
|
|
eina_strbuf_append(buf, s);
|
|
eina_strbuf_append(buf, " ");
|
|
}
|
|
}
|
|
EINA_LIST_FOREACH(bin->deps, ll, s)
|
|
{
|
|
eina_strbuf_append(buf, " `pkg-config --cflags --libs ");
|
|
eina_strbuf_append(buf, s);
|
|
eina_strbuf_append(buf, "` ");
|
|
}
|
|
EINA_LIST_FOREACH(bin->incs, ll, s)
|
|
{
|
|
eina_strbuf_append(buf, " -I");
|
|
eina_strbuf_append(buf, s);
|
|
eina_strbuf_append(buf, " ");
|
|
}
|
|
s = (char *)eina_strbuf_string_get(buf);
|
|
if (s) system(s);
|
|
eina_strbuf_free(buf);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static void
|
|
package_file(Eet_File *ef, const char *file, const char *key)
|
|
{
|
|
Eina_File *enf = eina_file_open(file, EINA_FALSE);
|
|
if (enf)
|
|
{
|
|
void *mem = eina_file_map_all(enf, EINA_FILE_SEQUENTIAL);
|
|
if (mem)
|
|
{
|
|
size_t size = eina_file_size_get(enf);
|
|
eet_write(ef, key, mem, size, EET_COMPRESSION_VERYFAST);
|
|
}
|
|
eina_file_close(enf);
|
|
}
|
|
}
|
|
|
|
static void
|
|
package_bin_iter(Eet_File *ef, const char *dir, const char *key)
|
|
{
|
|
Eina_List *files;
|
|
Eina_File *enf;
|
|
char *s;
|
|
char tmp[4096];
|
|
char tmp2[4096];
|
|
|
|
files = ecore_file_ls(dir);
|
|
EINA_LIST_FREE(files, s)
|
|
{
|
|
if (!strcmp(s, ".")) continue;
|
|
else if (!strcmp(s, "..")) continue;
|
|
snprintf(tmp, sizeof(tmp), "%s/%s", dir, s);
|
|
snprintf(tmp2, sizeof(tmp2), "%s/%s", key, s);
|
|
if (ecore_file_is_dir(tmp))
|
|
{
|
|
if (ecore_file_can_exec(tmp)) tmp2[4] = 'D';
|
|
package_bin_iter(ef, tmp, tmp2);
|
|
}
|
|
else
|
|
{
|
|
if (ecore_file_can_exec(tmp)) tmp2[4] = 'X';
|
|
else tmp2[4] = 'f';
|
|
package_file(ef, tmp, tmp2);
|
|
}
|
|
free(s);
|
|
}
|
|
}
|
|
|
|
static int
|
|
pakage_bin(void)
|
|
{
|
|
Eet_File *ef;
|
|
char tmp[4096];
|
|
Eina_List *l;
|
|
char *s;
|
|
int i;
|
|
|
|
snprintf(tmp, sizeof(tmp), "%s-%s.mkb", build.name, build.version);
|
|
ef = eet_open(tmp, EET_FILE_MODE_WRITE);
|
|
if (ef)
|
|
{
|
|
#define WRTS(key, var) \
|
|
if (var) eet_write(ef, key, var, strlen(var), EET_COMPRESSION_VERYFAST)
|
|
WRTS("name", build.name);
|
|
if (build.icon) package_file(ef, build.icon, "icon");
|
|
WRTS("brief", build.brief);
|
|
WRTS("version", build.version);
|
|
WRTS("license", build.license);
|
|
WRTS("repo", build.repo);
|
|
WRTS("devrepo", build.devrepo);
|
|
WRTS("contact", build.contact);
|
|
WRTS("needs", build.needs);
|
|
snprintf(tmp, sizeof(tmp), "%s-%s", os, arch);
|
|
WRTS("arch", tmp);
|
|
i = 0;
|
|
EINA_LIST_FOREACH(build.tags, l, s)
|
|
{
|
|
snprintf(tmp, sizeof(tmp), "tag/%i", i++);
|
|
WRTS(tmp, s);
|
|
}
|
|
i = 0;
|
|
EINA_LIST_FOREACH(build.categories, l, s)
|
|
{
|
|
snprintf(tmp, sizeof(tmp), "category/%i", i++);
|
|
WRTS(tmp, s);
|
|
}
|
|
package_bin_iter(ef, tmpd, "bin/f");
|
|
eet_close(ef);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
pakage_src(const char *file)
|
|
{
|
|
Eet_File *ef;
|
|
char tmp[4096];
|
|
char tmp2[4096];
|
|
|
|
snprintf(tmp, sizeof(tmp), "%s-%s.mks", build.name, build.version);
|
|
ef = eet_open(tmp, EET_FILE_MODE_WRITE);
|
|
if (ef)
|
|
{
|
|
Eina_File *enf;
|
|
Eina_List *l, *ll;
|
|
void *mem;
|
|
size_t size;
|
|
char *s;
|
|
Build_Bin *bin;
|
|
Build_Data *data;
|
|
|
|
enf = eina_file_open(file, EINA_FALSE);
|
|
if (!enf) err("can't open build file");
|
|
mem = eina_file_map_all(enf, EINA_FILE_SEQUENTIAL);
|
|
if (!mem) err("can't map build file");
|
|
size = eina_file_size_get(enf);
|
|
eet_write(ef, "buildinfo", mem, size, EET_COMPRESSION_VERYFAST);
|
|
eina_file_close(enf);
|
|
|
|
EINA_LIST_FOREACH(build.copying, l, s)
|
|
{
|
|
snprintf(tmp, sizeof(tmp), "src/%s", s);
|
|
package_file(ef, s, tmp);
|
|
}
|
|
EINA_LIST_FOREACH(build.desktops, l, s)
|
|
{
|
|
snprintf(tmp, sizeof(tmp), "src/%s", s);
|
|
package_file(ef, s, tmp);
|
|
}
|
|
EINA_LIST_FOREACH(build.icons, l, s)
|
|
{
|
|
snprintf(tmp, sizeof(tmp), "src/%s", s);
|
|
package_file(ef, s, tmp);
|
|
}
|
|
EINA_LIST_FOREACH(build.po, l, s)
|
|
{
|
|
snprintf(tmp2, sizeof(tmp2), "po/%s.gmo", s);
|
|
snprintf(tmp, sizeof(tmp), "src/po/%s.gmo", s);
|
|
package_file(ef, tmp2, tmp);
|
|
}
|
|
EINA_LIST_FOREACH(build.bins, l, bin)
|
|
{
|
|
EINA_LIST_FOREACH(bin->srcs, ll, s)
|
|
{
|
|
snprintf(tmp, sizeof(tmp), "src/%s", s);
|
|
package_file(ef, s, tmp);
|
|
}
|
|
}
|
|
EINA_LIST_FOREACH(build.data, l, data)
|
|
{
|
|
snprintf(tmp, sizeof(tmp), "src/%s", data->src);
|
|
package_file(ef, data->src, tmp);
|
|
}
|
|
eet_close(ef);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
err("file write failed");
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
package_extract(const char *file)
|
|
{
|
|
Eet_File *ef;
|
|
|
|
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 (!sane_forbidden_path(keys[i], sane_path_veto)) continue;
|
|
write_file(ef, keys[i], &(keys[i][4]));
|
|
}
|
|
}
|
|
}
|
|
write_file(ef, "buildinfo", "Marrakesh.mrk");
|
|
eet_close(ef);
|
|
return 1;
|
|
}
|
|
err("file does not open");
|
|
return 0;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
static int
|
|
package_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;
|
|
}
|
|
|
|
static int
|
|
package_install(const char *file)
|
|
{
|
|
Eet_File *ef, *ef2;
|
|
|
|
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;
|
|
|
|
name = read_string(ef, "name");
|
|
if (!name) err("no name");
|
|
if (!(sane_forbidden_path(name, sane_name_veto) &&
|
|
sane_allowed_path(name, sane_name_ok)))
|
|
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 (!sane_forbidden_path(keys[i], sane_path_veto)) 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/.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 1;
|
|
}
|
|
err("file does not open");
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
package_remove(const char *name)
|
|
{
|
|
char tmp[4096];
|
|
|
|
snprintf(tmp, sizeof(tmp), "%s/Applications/%s", get_home(), name);
|
|
if (!ecore_file_recursive_rm(tmp)) return 0;
|
|
return 1;
|
|
}
|
|
|
|
static Ecore_Ipc_Server *ipc = NULL;
|
|
static char *up_file = NULL;
|
|
static char *up_path = NULL;
|
|
|
|
static Eina_Bool
|
|
_ipc_cb_add(void *data, int type, void *event)
|
|
{
|
|
Ecore_Ipc_Event_Server_Add *e = event;
|
|
FILE *f;
|
|
|
|
char tmp[4096];
|
|
|
|
snprintf(tmp, sizeof(tmp), "%s-%s", os, arch);
|
|
ecore_ipc_server_send(ipc, 10, M_ID_ARCH, 0, 0, 0,
|
|
tmp, strlen(tmp));
|
|
snprintf(tmp, sizeof(tmp), "%i.%i.%i",
|
|
eina_version->major, eina_version->minor, eina_version->micro);
|
|
ecore_ipc_server_send(ipc, 10, M_ID_VERSION, 0, 0, 0,
|
|
tmp, strlen(tmp));
|
|
f = fopen(up_path, "rb");
|
|
if (f)
|
|
{
|
|
char buf[10000];
|
|
size_t size;
|
|
|
|
ecore_ipc_server_send(ipc, 10, M_UP_START, 0, 0, 0,
|
|
up_file, strlen(up_file));
|
|
for (;;)
|
|
{
|
|
size = fread(buf, 1, 10000, f);
|
|
if (size > 0)
|
|
ecore_ipc_server_send(ipc, 10, M_UP_DATA, 0, 0, 0,
|
|
buf, size);
|
|
else break;
|
|
}
|
|
ecore_ipc_server_send(ipc, 10, M_UP_END, 0, 0, 0,
|
|
NULL, 0);
|
|
fclose(f);
|
|
}
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_ipc_cb_del(void *data, int type, void *event)
|
|
{
|
|
Ecore_Ipc_Event_Server_Del *e = event;
|
|
err("disconnect...");
|
|
ecore_main_loop_quit();
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_ipc_cb_dat(void *data, int type, void *event)
|
|
{
|
|
Ecore_Ipc_Event_Server_Data *e = event;
|
|
if (e->major == 10)
|
|
{
|
|
if (e->minor == M_UP_OK)
|
|
{
|
|
printf("OK\n");
|
|
ecore_main_loop_quit();
|
|
}
|
|
else if (e->minor == M_UP_FAIL)
|
|
{
|
|
printf("FAIL\n");
|
|
err("upload rejected");
|
|
}
|
|
}
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static int
|
|
package_up(const char *file)
|
|
{
|
|
ipc = ecore_ipc_server_connect(ECORE_IPC_REMOTE_SYSTEM, server, server_port, NULL);
|
|
if (!ipc) return 0;
|
|
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_ADD, _ipc_cb_add, NULL);
|
|
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DEL, _ipc_cb_del, NULL);
|
|
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DATA, _ipc_cb_dat, NULL);
|
|
up_path = strdup(file);
|
|
up_file = strdup(ecore_file_file_get(file));
|
|
ecore_main_loop_begin();
|
|
return 1;
|
|
}
|
|
|
|
static char *down_name = NULL;
|
|
static char *down_file = NULL;
|
|
static FILE *down_f = NULL;
|
|
|
|
static Eina_Bool
|
|
_ipc2_cb_add(void *data, int type, void *event)
|
|
{
|
|
Ecore_Ipc_Event_Server_Add *e = event;
|
|
char tmp[4096];
|
|
|
|
snprintf(tmp, sizeof(tmp), "%s-%s", os, arch);
|
|
ecore_ipc_server_send(ipc, 10, M_ID_ARCH, 0, 0, 0,
|
|
tmp, strlen(tmp));
|
|
snprintf(tmp, sizeof(tmp), "%i.%i.%i",
|
|
eina_version->major, eina_version->minor, eina_version->micro);
|
|
ecore_ipc_server_send(ipc, 10, M_ID_VERSION, 0, 0, 0,
|
|
tmp, strlen(tmp));
|
|
ecore_ipc_server_send(ipc, 10, M_QRY_GET, 0, 0, 0,
|
|
down_name, strlen(down_name));
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_ipc2_cb_del(void *data, int type, void *event)
|
|
{
|
|
Ecore_Ipc_Event_Server_Del *e = event;
|
|
err("disconnect...");
|
|
ecore_main_loop_quit();
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_ipc2_cb_dat(void *data, int type, void *event)
|
|
{
|
|
Ecore_Ipc_Event_Server_Data *e = event;
|
|
if (e->major == 10)
|
|
{
|
|
switch (e->minor)
|
|
{
|
|
case M_DOWN_START:
|
|
if ((e->size > 0) && (e->size <= 1000) && (e->data))
|
|
{
|
|
char *file = malloc(e->size + 1);
|
|
if (file)
|
|
{
|
|
memcpy(file, e->data, e->size);
|
|
file[e->size] = 0;
|
|
if ((sane_forbidden_path(file, sane_name_veto) &&
|
|
sane_allowed_path(file, sane_name_ok)))
|
|
{
|
|
if (!down_f)
|
|
{
|
|
char tmp[4096];
|
|
|
|
down_file = file;
|
|
snprintf(tmp, sizeof(tmp),
|
|
"%s/Applications/.tmp",
|
|
getenv("HOME"));
|
|
ecore_file_mkpath(tmp);
|
|
snprintf(tmp, sizeof(tmp),
|
|
"%s/Applications/.tmp/%s",
|
|
getenv("HOME"), down_file);
|
|
if (ecore_file_exists(tmp))
|
|
err("file already exists");
|
|
down_f = fopen(file, "wb");
|
|
printf("%s\n", file);
|
|
}
|
|
else err("already have download");
|
|
}
|
|
else err("mangled filename");
|
|
}
|
|
else err("download file not sane");
|
|
}
|
|
else err("no such package");
|
|
break;
|
|
case M_DOWN_DATA:
|
|
if ((down_f) && (e->data) && (e->size > 0) && (e->size <= 10000))
|
|
{
|
|
fwrite(e->data, e->size, 1, down_f);
|
|
}
|
|
break;
|
|
case M_DOWN_END:
|
|
if (down_f)
|
|
{
|
|
fclose(down_f);
|
|
down_f = NULL;
|
|
ecore_main_loop_quit();
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static int
|
|
package_down(const char *name)
|
|
{
|
|
ipc = ecore_ipc_server_connect(ECORE_IPC_REMOTE_SYSTEM, server, server_port, NULL);
|
|
if (!ipc) return 0;
|
|
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_ADD, _ipc2_cb_add, NULL);
|
|
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DEL, _ipc2_cb_del, NULL);
|
|
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DATA, _ipc2_cb_dat, NULL);
|
|
down_name = strdup(name);
|
|
ecore_main_loop_begin();
|
|
return 1;
|
|
}
|
|
|
|
static char *downsrc_name = NULL;
|
|
static char *downsrc_file = NULL;
|
|
static FILE *downsrc_f = NULL;
|
|
|
|
static Eina_Bool
|
|
_ipc3_cb_add(void *data, int type, void *event)
|
|
{
|
|
Ecore_Ipc_Event_Server_Add *e = event;
|
|
char tmp[4096];
|
|
|
|
snprintf(tmp, sizeof(tmp), "%s-%s", os, arch);
|
|
ecore_ipc_server_send(ipc, 10, M_ID_ARCH, 0, 0, 0,
|
|
tmp, strlen(tmp));
|
|
snprintf(tmp, sizeof(tmp), "%i.%i.%i",
|
|
eina_version->major, eina_version->minor, eina_version->micro);
|
|
ecore_ipc_server_send(ipc, 10, M_ID_VERSION, 0, 0, 0,
|
|
tmp, strlen(tmp));
|
|
ecore_ipc_server_send(ipc, 10, M_QRY_GETSRC, 0, 0, 0,
|
|
downsrc_name, strlen(downsrc_name));
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_ipc3_cb_del(void *data, int type, void *event)
|
|
{
|
|
Ecore_Ipc_Event_Server_Del *e = event;
|
|
err("disconnect...");
|
|
ecore_main_loop_quit();
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_ipc3_cb_dat(void *data, int type, void *event)
|
|
{
|
|
Ecore_Ipc_Event_Server_Data *e = event;
|
|
if (e->major == 10)
|
|
{
|
|
switch (e->minor)
|
|
{
|
|
case M_SRC_START:
|
|
if ((e->size > 0) && (e->size <= 1000) && (e->data))
|
|
{
|
|
char *file = malloc(e->size + 1);
|
|
if (file)
|
|
{
|
|
memcpy(file, e->data, e->size);
|
|
file[e->size] = 0;
|
|
if ((sane_forbidden_path(file, sane_name_veto) &&
|
|
sane_allowed_path(file, sane_name_ok)))
|
|
{
|
|
if (!downsrc_f)
|
|
{
|
|
char tmp[4096];
|
|
|
|
downsrc_file = file;
|
|
snprintf(tmp, sizeof(tmp),
|
|
"%s/Applications/.tmp",
|
|
getenv("HOME"));
|
|
ecore_file_mkpath(tmp);
|
|
snprintf(tmp, sizeof(tmp),
|
|
"%s/Applications/.tmp/%s",
|
|
getenv("HOME"), downsrc_file);
|
|
if (ecore_file_exists(tmp))
|
|
err("file already exists");
|
|
downsrc_f = fopen(file, "wb");
|
|
printf("%s\n", file);
|
|
}
|
|
else err("already have download");
|
|
}
|
|
else err("mangled filename");
|
|
}
|
|
else err("download file not sane");
|
|
}
|
|
else err("no such package");
|
|
break;
|
|
case M_SRC_DATA:
|
|
if ((downsrc_f) && (e->data) && (e->size > 0) && (e->size <= 10000))
|
|
{
|
|
fwrite(e->data, e->size, 1, downsrc_f);
|
|
}
|
|
break;
|
|
case M_SRC_END:
|
|
if (downsrc_f)
|
|
{
|
|
fclose(downsrc_f);
|
|
downsrc_f = NULL;
|
|
ecore_main_loop_quit();
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static int
|
|
package_downsrc(const char *name)
|
|
{
|
|
ipc = ecore_ipc_server_connect(ECORE_IPC_REMOTE_SYSTEM, server, server_port, NULL);
|
|
if (!ipc) return 0;
|
|
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_ADD, _ipc3_cb_add, NULL);
|
|
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DEL, _ipc3_cb_del, NULL);
|
|
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DATA, _ipc3_cb_dat, NULL);
|
|
downsrc_name = strdup(name);
|
|
ecore_main_loop_begin();
|
|
return 1;
|
|
}
|
|
|
|
static int qry_op = 0;
|
|
static char *qry_data;
|
|
|
|
static Eina_Bool
|
|
_ipc4_cb_add(void *data, int type, void *event)
|
|
{
|
|
Ecore_Ipc_Event_Server_Add *e = event;
|
|
char tmp[4096];
|
|
|
|
snprintf(tmp, sizeof(tmp), "%s-%s", os, arch);
|
|
ecore_ipc_server_send(ipc, 10, M_ID_ARCH, 0, 0, 0,
|
|
tmp, strlen(tmp));
|
|
snprintf(tmp, sizeof(tmp), "%i.%i.%i",
|
|
eina_version->major, eina_version->minor, eina_version->micro);
|
|
ecore_ipc_server_send(ipc, 10, M_ID_VERSION, 0, 0, 0,
|
|
tmp, strlen(tmp));
|
|
ecore_ipc_server_send(ipc, 10, qry_op, 0, 0, 0,
|
|
qry_data, qry_data ? strlen(qry_data) : 0);
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_ipc4_cb_del(void *data, int type, void *event)
|
|
{
|
|
Ecore_Ipc_Event_Server_Del *e = event;
|
|
err("disconnect...");
|
|
ecore_main_loop_quit();
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_ipc4_cb_dat(void *data, int type, void *event)
|
|
{
|
|
Ecore_Ipc_Event_Server_Data *e = event;
|
|
if (e->major == 10)
|
|
{
|
|
switch (e->minor)
|
|
{
|
|
case M_ANS_START:
|
|
break;
|
|
case M_ANS_DATA:
|
|
if ((e->data) && (e->size > 0) && (e->size <= 10000))
|
|
{
|
|
fwrite(e->data, e->size, 1, stdout);
|
|
fwrite("\n", 1, 1, stdout);
|
|
}
|
|
break;
|
|
case M_ANS_END:
|
|
if (qry_data) free(qry_data);
|
|
qry_data = NULL;
|
|
ecore_main_loop_quit();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static int
|
|
package_qry(int op, const char *opdat)
|
|
{
|
|
ipc = ecore_ipc_server_connect(ECORE_IPC_REMOTE_SYSTEM, server, server_port, NULL);
|
|
if (!ipc) return 0;
|
|
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_ADD, _ipc4_cb_add, NULL);
|
|
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DEL, _ipc4_cb_del, NULL);
|
|
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DATA, _ipc4_cb_dat, NULL);
|
|
qry_op = op;
|
|
if (opdat) qry_data = strdup(opdat);
|
|
ecore_main_loop_begin();
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
package_file_isbin(const char *file)
|
|
{
|
|
const char *p;
|
|
|
|
p = strchr(file, '.');
|
|
if (p)
|
|
{
|
|
if (!strcasecmp(p, ".png")) return 1;
|
|
if (!strcasecmp(p, ".jpg")) return 1;
|
|
if (!strcasecmp(p, ".edj")) return 1;
|
|
if (!strcasecmp(p, ".gif")) return 1;
|
|
if (!strcasecmp(p, ".bmp")) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static Eina_Bool
|
|
string_rep(const Eina_Hash *hash, const void *key, void *data, void *fdata)
|
|
{
|
|
eina_strbuf_replace_all(fdata, key, data);
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static int
|
|
package_dir_dup(const char *src, const char *dst, Eina_Hash *vars)
|
|
{
|
|
char tmp[4096];
|
|
char tmp2[4096];
|
|
Eina_Strbuf *dstsbuf;
|
|
|
|
dstsbuf = eina_strbuf_new();
|
|
if (!dstsbuf) return 0;
|
|
eina_strbuf_append(dstsbuf, dst);
|
|
eina_hash_foreach(vars, string_rep, dstsbuf);
|
|
if (ecore_file_is_dir(src))
|
|
{
|
|
Eina_List *files;
|
|
char *s;
|
|
|
|
ecore_file_mkdir(eina_strbuf_string_get(dstsbuf));
|
|
files = ecore_file_ls(src);
|
|
EINA_LIST_FREE(files, s)
|
|
{
|
|
if (s[0] != '.')
|
|
{
|
|
snprintf(tmp, sizeof(tmp), "%s/%s", src, s);
|
|
snprintf(tmp2, sizeof(tmp2), "%s/%s", eina_strbuf_string_get(dstsbuf), s);
|
|
package_dir_dup(tmp, tmp2, vars);
|
|
}
|
|
free(s);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (package_file_isbin(src))
|
|
ecore_file_cp(src, eina_strbuf_string_get(dstsbuf));
|
|
else
|
|
{
|
|
FILE *fsrc, *fdst;
|
|
|
|
fsrc = fopen(src, "rb");
|
|
fdst = fopen(eina_strbuf_string_get(dstsbuf), "wb");
|
|
if ((fsrc) && (fdst))
|
|
{
|
|
long size;
|
|
|
|
fseek(fsrc, 0, SEEK_END);
|
|
size = ftell(fsrc);
|
|
fseek(fsrc, 0, SEEK_SET);
|
|
if (size > 0)
|
|
{
|
|
char *buf = malloc(size + 1);
|
|
|
|
if (buf)
|
|
{
|
|
Eina_Strbuf *tmpsbuf;
|
|
|
|
tmpsbuf = eina_strbuf_new();
|
|
if (tmpsbuf)
|
|
{
|
|
fread(buf, size, 1, fsrc);
|
|
buf[size] = 0;
|
|
eina_strbuf_append(tmpsbuf, buf);
|
|
eina_hash_foreach(vars, string_rep, tmpsbuf);
|
|
fwrite(eina_strbuf_string_get(tmpsbuf),
|
|
eina_strbuf_length_get(tmpsbuf),
|
|
1, fdst);
|
|
eina_strbuf_free(tmpsbuf);
|
|
}
|
|
free(buf);
|
|
}
|
|
}
|
|
}
|
|
if (fsrc) fclose(fsrc);
|
|
if (fdst) fclose(fdst);
|
|
}
|
|
}
|
|
eina_strbuf_free(dstsbuf);
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
package_gen(const char *tmpldir, const char *tmpl, Eina_Hash *vars)
|
|
{
|
|
char tmp[4096];
|
|
char tmp2[4096];
|
|
const char *domain;
|
|
|
|
domain = eina_hash_find(vars, "@APPDOM@");
|
|
ecore_file_mkdir(domain);
|
|
snprintf(tmp, sizeof(tmp), "%s/apps/%s", tmpldir, tmpl);
|
|
package_dir_dup(tmp, domain, vars);
|
|
snprintf(tmp, sizeof(tmp), "%s/licenses/%s",
|
|
tmpldir, eina_hash_find(vars, "@APPCOPY@"));
|
|
snprintf(tmp2, sizeof(tmp2), "%s/COPYING", domain);
|
|
ecore_file_cp(tmp, tmp2);
|
|
}
|
|
|
|
static int
|
|
package_new(void)
|
|
{
|
|
Eina_Hash *vars = eina_hash_string_superfast_new(NULL);
|
|
char tmp[4096];
|
|
|
|
if (!vars) return 0;
|
|
printf("App Name: (e.g. Hello)\n");
|
|
if (scanf("%500s", tmp) <= 0) return 0;
|
|
eina_hash_add(vars, "@APPNAME@", eina_stringshare_add(tmp));
|
|
printf("App Domain: (e.g. hello)\n");
|
|
if (scanf("%500s", tmp) <= 0) return 0;
|
|
eina_hash_add(vars, "@APPDOM@", eina_stringshare_add(tmp));
|
|
printf("App Version: (e.g. 1.0.0)\n");
|
|
if (scanf("%150s", tmp) <= 0) return 0;
|
|
eina_hash_add(vars, "@APPVER@", eina_stringshare_add(tmp));
|
|
printf("App License: (e.g. BSD-2 | GPL2 | APACHE | GPL3)\n");
|
|
if (scanf("%20s", tmp) <= 0) return 0;
|
|
eina_hash_add(vars, "@APPCOPY@", eina_stringshare_add(tmp));
|
|
printf("App Brief Description: (1 line)\n");
|
|
if (scanf("%400s", tmp) <= 0) return 0;
|
|
eina_hash_add(vars, "@APPDESC@", eina_stringshare_add(tmp));
|
|
printf("App Categories: (e.g. media)\n");
|
|
if (scanf("%1000s", tmp) <= 0) return 0;
|
|
eina_hash_add(vars, "@APPCATEGORIES@", eina_stringshare_add(tmp));
|
|
printf("App Tags: (e.g. video audio media film movies music player)\n");
|
|
if (scanf("%4000s", tmp) <= 0) return 0;
|
|
eina_hash_add(vars, "@APPTAGS@", eina_stringshare_add(tmp));
|
|
printf("Developer Name + E-Mail: Bob Jones <bob@bob.com>\n");
|
|
if (scanf("%1000s", tmp) <= 0) return 0;
|
|
eina_hash_add(vars, "@DEVMAIL@", eina_stringshare_add(tmp));
|
|
printf("App EFL Minimum Version: (e.g. 1.11)\n");
|
|
if (scanf("%50s", tmp) <= 0) return 0;
|
|
eina_hash_add(vars, "@EFLVER@", eina_stringshare_add(tmp));
|
|
package_gen("/home/raster/C/marrakesh/tmpl", "default", vars);
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
char *s;
|
|
|
|
eina_init();
|
|
eet_init();
|
|
ecore_ipc_init();
|
|
ecore_file_init();
|
|
if (argc < 2)
|
|
{
|
|
printf("sub commands:\n"
|
|
" new\n"
|
|
" build\n"
|
|
" bin\n"
|
|
" check\n"
|
|
" src\n"
|
|
" extract FILE\n"
|
|
" inst FILE\n"
|
|
" rm PKGNAME\n"
|
|
" rel [FILE]\n"
|
|
" down PKGNAME\n"
|
|
" get PKGNAME\n"
|
|
" getsrc PKGNAME\n"
|
|
" clean\n"
|
|
" list [CATEGORY]\n"
|
|
" search KEY1 [KEY2] [KEY3] [...]\n"
|
|
"\n");
|
|
return -1;
|
|
}
|
|
|
|
s = getenv("DESTDIR");
|
|
if (s) tmpd = s;
|
|
|
|
if (getenv("MRKHOST")) server = getenv("MRKHOST");
|
|
if (getenv("MRKPORT")) server_port = atoi(getenv("MRKPORT"));
|
|
if (getenv("MRKARCH")) arch = getenv("MRKARCH");
|
|
if (getenv("MRKOS")) os = getenv("MRKOS");
|
|
|
|
if (!strcmp(argv[1], "build"))
|
|
{
|
|
if (!parse_bld("Marrakesh.mrk")) return 1;
|
|
if (!build_proj()) return 1;
|
|
}
|
|
else if (!strcmp(argv[1], "src"))
|
|
{
|
|
if (!parse_bld("Marrakesh.mrk")) return 1;
|
|
if (!pakage_src("Marrakesh.mrk")) return 1;
|
|
}
|
|
else if (!strcmp(argv[1], "bin"))
|
|
{
|
|
if (!parse_bld("Marrakesh.mrk")) return 1;
|
|
if (!pakage_bin()) return 1;
|
|
}
|
|
else if (!strcmp(argv[1], "extract"))
|
|
{
|
|
if (argc < 3) err("need file to extract");
|
|
if (!package_extract(argv[2])) return 1;
|
|
}
|
|
else if (!strcmp(argv[1], "inst"))
|
|
{
|
|
if (argc < 3) err("need file to install");
|
|
package_clean();
|
|
if (!package_install(argv[2])) return 1;
|
|
}
|
|
else if (!strcmp(argv[1], "clean"))
|
|
{
|
|
package_clean();
|
|
}
|
|
else if (!strcmp(argv[1], "rm"))
|
|
{
|
|
if (argc < 3) err("need package to remove");
|
|
if (!package_remove(argv[2])) return 1;
|
|
package_clean();
|
|
}
|
|
else if (!strcmp(argv[1], "rel"))
|
|
{
|
|
char tmp[4096];
|
|
char *pk;
|
|
|
|
if (argc < 3)
|
|
{
|
|
printf("making src...\n");
|
|
if (!parse_bld("Marrakesh.mrk")) return 1;
|
|
if (!pakage_src("Marrakesh.mrk")) return 1;
|
|
snprintf(tmp, sizeof(tmp), "%s-%s.mks", build.name, build.version);
|
|
pk = tmp;
|
|
}
|
|
else pk = argv[2];
|
|
printf("upload + build...\n");
|
|
if (!package_up(pk)) return 1;
|
|
}
|
|
else if (!strcmp(argv[1], "down"))
|
|
{
|
|
if (argc < 3) err("need package to download");
|
|
if (!package_down(argv[2])) return 1;
|
|
}
|
|
else if (!strcmp(argv[1], "get"))
|
|
{
|
|
if (argc < 3) err("need package to get");
|
|
if (!package_down(argv[2])) return 1;
|
|
if (!down_file) err("no download");
|
|
package_remove(argv[2]);
|
|
package_clean();
|
|
if (!package_install(down_file)) return 1;
|
|
ecore_file_unlink(down_file);
|
|
}
|
|
else if (!strcmp(argv[1], "list"))
|
|
{
|
|
if (argc < 3) package_qry(M_QRY_LIST, NULL);
|
|
else package_qry(M_QRY_LIST, argv[2]);
|
|
}
|
|
else if (!strcmp(argv[1], "search"))
|
|
{
|
|
if (argc < 3) err("need search strings");
|
|
else
|
|
{
|
|
int i;
|
|
int len = 0;
|
|
char *ts;
|
|
|
|
for (i = 2; i < argc; i++)
|
|
{
|
|
len += strlen(argv[i]);
|
|
len++;
|
|
}
|
|
ts = malloc(len);
|
|
if (ts)
|
|
{
|
|
ts[0] = 0;
|
|
for (i = 2; i < argc; i++)
|
|
{
|
|
strcat(ts, argv[i]);
|
|
if (i < (argc - 1)) strcat(ts, " ");
|
|
}
|
|
package_qry(M_QRY_SEARCH, ts);
|
|
free(ts);
|
|
}
|
|
}
|
|
}
|
|
else if (!strcmp(argv[1], "new"))
|
|
{
|
|
package_new();
|
|
}
|
|
else if (!strcmp(argv[1], "getsrc"))
|
|
{
|
|
if (argc < 3) err("need package to download");
|
|
if (!package_downsrc(argv[2])) return 1;
|
|
}
|
|
else if (!strcmp(argv[1], "check"))
|
|
{
|
|
char tmp[4096];
|
|
ecore_file_recursive_rm("Marrakesh-Check");
|
|
ecore_file_mkdir("Marrakesh-Check");
|
|
if (!parse_bld("Marrakesh.mrk")) err("Parse build failed");
|
|
if (!pakage_src("Marrakesh.mrk")) err("Source packaging failed");
|
|
chdir("Marrakesh-Check");
|
|
snprintf(tmp, sizeof(tmp), "../%s-%s.mks", build.name, build.version);
|
|
if (!package_extract(tmp)) err("Source extract failed");
|
|
memset(&build, 0, sizeof(Build));
|
|
if (!parse_bld("Marrakesh.mrk")) err("Parse build 2 from source failed");
|
|
if (!build_proj()) err("Build project failed");
|
|
memset(&build, 0, sizeof(Build));
|
|
if (!parse_bld("Marrakesh.mrk")) err("Parse build 3 failed");
|
|
if (!pakage_bin()) err("Package binary failed");
|
|
printf("OK\n");
|
|
}
|
|
else
|
|
{
|
|
err("unknown subcommand!");
|
|
return 1;
|
|
}
|
|
ecore_file_shutdown();
|
|
ecore_ipc_shutdown();
|
|
eet_shutdown();
|
|
eina_shutdown();
|
|
return 0;
|
|
}
|