marrakesh - first stage code cleanup into something resembling an api

this makes a single binary for server, build, indexing etc. and an
abstracted lib-like core. needs work but its a first step.
This commit is contained in:
Carsten Haitzler 2014-10-25 18:34:14 +09:00
parent 01af8bc9c0
commit 9c3cb5a9f5
17 changed files with 5057 additions and 1644 deletions

View File

@ -1,4 +1,2 @@
#!/bin/sh
gcc mrk.c -o mrk `pkg-config --cflags --libs eina ecore ecore-file ecore-ipc eet`
gcc mrk-srv.c -o mrk-srv `pkg-config --cflags --libs eina ecore ecore-ipc ecore-file eet`
gcc mrk-index.c -o mrk-index `pkg-config --cflags --libs eina ecore ecore-ipc ecore-file eet`
gcc mrklib*.c mrk.c -o mrk `pkg-config --cflags --libs eina ecore ecore-file ecore-ipc eet`

1895
mrk.c

File diff suppressed because it is too large Load Diff

162
mrklib.c Normal file
View File

@ -0,0 +1,162 @@
#include "mrklib_priv.h"
const char *_mrk_server_host = MRK_SERVER_HOST;
int _mrk_server_port = MRK_SERVER_PORT;
const char *_mrk_appdir = NULL;
const char *_mrk_appdir_tmp = NULL;
const char *_mrk_appdir_bin = NULL;
unsigned char *_mrk_uuid = NULL;
int _mrk_uuid_len = 0;
static int _mrk_init = 0;
static void
_entropy_get(unsigned char *dat, int len)
{
int fd;
Eina_Bool ok = EINA_FALSE;
fd = open("/dev/random", O_RDONLY);
if (fd >= 0)
{
if (read(fd, dat, len) == len) ok = EINA_TRUE;
close(fd);
}
if (!ok)
{
struct timeval tv;
unsigned int seed = 0x12345678;
int i;
if (gettimeofday(&tv, NULL) == 0)
seed = ((tv.tv_sec << 16) | (tv.tv_sec >> 16)) ^ tv.tv_usec;
else
seed = (unsigned int)time(NULL);
srand(seed);
for (i = 0; i < len; i++) dat[i] = rand() & 0xff;
}
}
static void
_mrk_config_new(const char *file)
{
Eet_File *ef;
unsigned char uuid[32];
int uuid_len = sizeof(uuid);
ef = eet_open(file, EET_FILE_MODE_WRITE);
if (!ef) return;
_entropy_get(uuid, uuid_len);
eet_write(ef, "uuid", uuid, uuid_len, EET_COMPRESSION_VERYFAST);
eet_close(ef);
}
static void
_mrk_config_init(const char *file)
{
Eet_File *ef;
int len;
ef = eet_open(file, EET_FILE_MODE_READ);
if (!ef)
{
_mrk_config_new(file);
ef = eet_open(file, EET_FILE_MODE_READ);
}
if (!ef) return;
_mrk_uuid = eet_read(ef, "uuid", &len);
if ((!_mrk_uuid) || (len != 32))
{
free(_mrk_uuid);
_mrk_uuid = NULL;
eet_close(ef);
_mrk_config_new(file);
ef = eet_open(file, EET_FILE_MODE_READ);
if (!ef) return;
_mrk_uuid = eet_read(ef, "uuid", &len);
if ((!_mrk_uuid) || (len != 32))
{
free(_mrk_uuid);
_mrk_uuid = NULL;
eet_close(ef);
return;
}
}
_mrk_uuid_len = len;
eet_close(ef);
}
static void
_mrk_appdir_init(void)
{
char tmp[4096];
const char *home;
home = getenv("XDG_DATA_HOME");
if (!home) home = getenv("HOME");
if (!home) home = "/tmp";
snprintf(tmp, sizeof(tmp), "%s/Applications", home);
if (!ecore_file_exists(tmp)) ecore_file_mkdir(tmp);
_mrk_appdir = eina_stringshare_add(tmp);
snprintf(tmp, sizeof(tmp), "%s/Applications/.bin", home);
if (!ecore_file_exists(tmp)) ecore_file_mkdir(tmp);
_mrk_appdir_bin = eina_stringshare_add(tmp);
snprintf(tmp, sizeof(tmp), "%s/Applications/.tmp", home);
if (!ecore_file_exists(tmp)) ecore_file_mkdir(tmp);
_mrk_appdir_tmp = eina_stringshare_add(tmp);
snprintf(tmp, sizeof(tmp), "%s/Applications/.marrakesh.cfg", home);
_mrk_config_init(tmp);
}
EAPI Eina_Bool
mrk_init(void)
{
_mrk_init++;
if (_mrk_init == 1)
{
eina_init();
eet_init();
ecore_init();
ecore_ipc_init();
ecore_file_init();
_mrk_appdir_init();
}
return EINA_TRUE;
}
EAPI void
mrk_shutdown(void)
{
_mrk_init--;
if (_mrk_init == 0)
{
eina_stringshare_del(_mrk_appdir);
_mrk_appdir = NULL;
eina_stringshare_del(_mrk_appdir_bin);
_mrk_appdir_bin = NULL;
eina_stringshare_del(_mrk_appdir_tmp);
_mrk_appdir_tmp = NULL;
ecore_file_shutdown();
ecore_ipc_shutdown();
eet_shutdown();
ecore_shutdown();
eina_shutdown();
}
}
EAPI const char *
mrk_arch_get(void)
{
return ARCH;
}
EAPI const char *
mrk_os_get(void)
{
return OS;
}

143
mrklib.h Normal file
View File

@ -0,0 +1,143 @@
#ifndef MRKLIB_H
#define MRKLIB_H
#include <Eina.h>
EAPI Eina_Bool mrk_init(void);
EAPI void mrk_shutdown(void);
EAPI const char *mrk_arch_get(void);
EAPI const char *mrk_os_get(void);
// yes - this should become an eo object - later. right now... cleaning up
// the mess that was putting the pipeline together
// mrk client api - for clients that conne3ct to an mrk server to upload,
// download, query etc. etc. the server - so the "main" set of api for a
// client-server api. in future protocol should be extendable in api
// below with sending extended requests and handling return data
typedef struct _Mrk Mrk;
EAPI Mrk *mrk_connect(const char *host, int port);
EAPI void mrk_disconnect(Mrk *server);
EAPI Eina_Bool mrk_upload(Mrk *server, const char *file);
EAPI Eina_Bool mrk_download(Mrk *server, const char *package);
EAPI Eina_Bool mrk_download_source(Mrk *server, const char *package);
EAPI Eina_Bool mrk_list(Mrk *server, const char *category);
EAPI Eina_Bool mrk_search(Mrk *server, const char *keys);
EAPI void mrk_callback_connect_set(Mrk *server,
void (*connect) (void *data, Mrk *server),
void *connect_data,
void (*disconnect) (void *data, Mrk *server),
void *disconnect_data);
EAPI void mrk_callback_upload_set(Mrk *server,
void (*upload_begin) (void *data, Mrk *server),
void *upload_begin_data,
void (*upload_progress) (void *data, Mrk *server, double pos),
void *upload_progress_data,
void (*upload_end) (void *data, Mrk *server),
void *upload_end_data,
void (*upload_success) (void *data, Mrk *server, Eina_Bool sucess),
void *upload_success_data);
EAPI void mrk_callback_download_set(Mrk *server,
void (*download_begin) (void *data, Mrk *server),
void *download_begin_data,
void (*download_progress) (void *data, Mrk *server, double pos),
void *download_progress_data,
void (*download_end) (void *data, Mrk *server),
void *download_end_data,
void (*download_success) (void *data, Mrk *server, const char *file),
void *download_success_data);
EAPI void mrk_callback_answer_set(Mrk *server,
void (*answer_begin) (void *data, Mrk *server),
void *answer_begin_data,
void (*answer_progress) (void *data, Mrk *server, const char *result),
void *answer_progress_data,
void (*answer_end) (void *data, Mrk *server),
void *answer_end_data);
// api to run a mrk server - right now you have very little choice here
// as everything is just magically handled internally - in future some way
// to access the repodb that a serve loads (and auto-updates) as well as
// get callbacks when things happen and also to extend protocol
typedef struct _Mrk_Serve Mrk_Serve;
EAPI Mrk_Serve *mrk_serve(const char *listen, int port, const char *repodir, const char *bldsh);
EAPI void mrk_unserve(Mrk_Serve *server);
// this is the api to deal with a repository database of files and to
// request and update of them, auto-reload when update done and tell you
// when it's done
typedef struct _Mrk_Repodb Mrk_Repodb;
EAPI Mrk_Repodb *mrk_repodb_load(const char *repodir);
EAPI void mrk_repodb_free(Mrk_Repodb *rdb);
EAPI void mrk_repodb_callback_update_set(Mrk_Repodb *rdb,
void (*update) (void *data, Mrk_Repodb *rdb),
void *update_data);
EAPI void mrk_repodb_update(Mrk_Repodb *rdb);
EAPI const Eina_List *mrk_repodb_category_list(Mrk_Repodb *rdb,
const char *arch,
const char *category);
EAPI Eina_List *mrk_repodb_search(Mrk_Repodb *rdb,
const char *arch,
const char *search);
// this iapi si very simple - it scans the dir of mrk binary packages and
// updates the database files inside
EAPI Eina_Bool mrk_index(const char *dir);
typedef struct _Mrk_Build Mrk_Build;
typedef struct _Mrk_Build_Bin Mrk_Build_Bin;
typedef struct _Mrk_Build_Data Mrk_Build_Data;
struct _Mrk_Build_Bin
{
const char *bin;
Eina_List *srcs;
Eina_List *deps;
Eina_List *incs;
};
struct _Mrk_Build_Data
{
const char *src;
const char *dest;
};
struct _Mrk_Build
{
const char *name;
const char *icon;
const char *brief;
const char *version;
const char *license;
const char *domain;
const char *repo;
const char *devrepo;
const char *contact;
Eina_List *tags;
Eina_List *categories;
Eina_List *copying;
const char *needs;
Eina_List *bins;
Eina_List *data;
Eina_List *desktops;
Eina_List *icons;
Eina_List *po;
};
EAPI Mrk_Build *mrk_build_load(const char *file);
EAPI void mrk_build_free(Mrk_Build *bld);
EAPI Eina_Bool mrk_build_do(Mrk_Build *bld, const char *tmpd);
EAPI Eina_Bool mrk_build_pakage_bin(Mrk_Build *bld, const char *file, const char *tmpd, const char *os, const char *arch);
EAPI Eina_Bool mrk_build_package_src(Mrk_Build *bld, const char *buildfile, const char *file);
EAPI Eina_Bool mrk_package_src_extract(const char *file, const char *dst);
EAPI Eina_Bool mrk_package_bin_clean(void);
EAPI Eina_Bool mrk_package_bin_install(const char *file);
EAPI Eina_Bool mrk_package_bin_remove(const char *name);
// XXX: .mrk parsing api handled/exposed and other related functions
// XXX: installation/uninstallation handling apis
// XXX: cleanup apis
#endif

711
mrklib_buildfile.c Normal file
View File

@ -0,0 +1,711 @@
#include "mrklib_priv.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;
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 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 Mrk_Build *
parse_content(char *mem, size_t size)
{
Mrk_Build *bld = NULL;
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;
#define err(reason) do { fprintf(stderr, "%s\n", reason); goto error; } while (0)
bld = calloc(1, sizeof(Mrk_Build));
if (!bld) return NULL;
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) err("token parse error");
if (startline)
{
for (i = 0; tags[i].tag; i++)
{
if (!strcmp(tok, tags[i].tag))
{
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:
p = prevp;
data1 = parse_eol(&p, end);
if (!data1) err("no content");
break;
case TMODE_PATH:
case TMODE_PATH_LIST:
data1 = path_check(tok);
if (!data1) err("path invalid");
break;
case TMODE_PATH_CP:
case TMODE_PATH_CP_LIST:
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 (seg)
{
if (!strcmp(seg, "PROJ:"))
{
if (!_mrk_util_plain_file_check(data1))
err("name failed sanity check");
eina_stringshare_del(bld->name);
bld->name = eina_stringshare_add(data1);
}
else if (!strcmp(seg, "PROJICON:"))
{
eina_stringshare_del(bld->icon);
bld->icon = eina_stringshare_add(data1);
}
else if (!strcmp(seg, "BRIEF:"))
{
if (!bld->brief) bld->brief = eina_stringshare_add(data1);
else
{
s = malloc(strlen(bld->brief) + 1 + strlen(data1) + 1);
if (s)
{
strcpy(s, bld->brief);
strcat(s, " ");
strcat(s, data1);
eina_stringshare_del(bld->brief);
bld->brief = s;
}
}
}
else if (!strcmp(seg, "VERSION:"))
{
eina_stringshare_del(bld->version);
bld->version = eina_stringshare_add(data1);
}
else if (!strcmp(seg, "LICENSE:"))
{
eina_stringshare_del(bld->license);
bld->license = eina_stringshare_add(data1);
}
else if (!strcmp(seg, "COPYING:"))
{
bld->copying = eina_list_append(bld->copying,
eina_stringshare_add(data1));
}
else if (!strcmp(seg, "NEEDS:"))
{
eina_stringshare_del(bld->needs);
bld->license = eina_stringshare_add(data1);
}
else if (!strcmp(seg, "DOMAIN:"))
{
eina_stringshare_del(bld->domain);
bld->domain = eina_stringshare_add(data1);
}
else if (!strcmp(seg, "REPO:"))
{
eina_stringshare_del(bld->repo);
bld->repo = eina_stringshare_add(data1);
}
else if (!strcmp(seg, "DEVREPO:"))
{
eina_stringshare_del(bld->devrepo);
bld->devrepo = eina_stringshare_add(data1);
}
else if (!strcmp(seg, "CATEGORY:"))
{
bld->categories = eina_list_append(bld->categories,
eina_stringshare_add(data1));
}
else if (!strcmp(seg, "TAGS:"))
{
bld->tags = eina_list_append(bld->tags,
eina_stringshare_add(data1));
}
else if (!strcmp(seg, "CONTACT:"))
{
if (!bld->contact) bld->contact = eina_stringshare_add(data1);
else
{
s = malloc(strlen(bld->contact) + 1 + strlen(data1) + 1);
if (s)
{
strcpy(s, bld->contact);
strcat(s, " ");
strcat(s, data1);
eina_stringshare_del(bld->contact);
bld->contact = s;
}
}
}
else if (!strcmp(seg, "BIN:"))
{
Mrk_Build_Bin *build_bin = calloc(1, sizeof(Mrk_Build_Bin));
if (build_bin)
{
build_bin->bin = eina_stringshare_add(data1);
bld->bins = eina_list_append(bld->bins,
build_bin);
}
}
else if (!strcmp(seg, "SRC:"))
{
Mrk_Build_Bin *build_bin = eina_list_data_get(eina_list_last(bld->bins));
if (build_bin)
{
build_bin->srcs = eina_list_append(build_bin->srcs,
eina_stringshare_add(data1));
}
}
else if (!strcmp(seg, "DEPS:"))
{
Mrk_Build_Bin *build_bin = eina_list_data_get(eina_list_last(bld->bins));
if (build_bin)
{
build_bin->deps = eina_list_append(build_bin->deps,
eina_stringshare_add(data1));
}
}
else if (!strcmp(seg, "INC:"))
{
Mrk_Build_Bin *build_bin = eina_list_data_get(eina_list_last(bld->bins));
if (build_bin)
{
build_bin->incs = eina_list_append(build_bin->incs,
eina_stringshare_add(data1));
}
}
else if (!strcmp(seg, "DATA:"))
{
Mrk_Build_Data *build_data = calloc(1, sizeof(Mrk_Build_Data));
if (build_data)
{
build_data->src = eina_stringshare_add(data1);
build_data->dest = eina_stringshare_add(data2);
bld->data = eina_list_append(bld->data,
build_data);
}
}
else if (!strcmp(seg, "DESKTOP:"))
{
bld->desktops = eina_list_append(bld->desktops,
eina_stringshare_add(data1));
}
else if (!strcmp(seg, "ICON:"))
{
bld->icons = eina_list_append(bld->icons,
eina_stringshare_add(data1));
}
else if (!strcmp(seg, "PO:"))
{
bld->po = eina_list_append(bld->po,
eina_stringshare_add(data1));
}
}
free(data1);
free(data2);
data1 = NULL;
data2 = NULL;
}
free(tok);
prevc = *p;
}
else
{
prevc = *p;
p++;
}
startline = 0;
}
return bld;
error:
mrk_build_free(bld);
return NULL;
#undef err
}
EAPI Mrk_Build *
mrk_build_load(const char *file)
{
Mrk_Build *bld;
Eina_File *ef;
char *mem;
size_t size;
int ret;
ef = eina_file_open(file, EINA_FALSE);
if (!ef) return NULL;
size = eina_file_size_get(ef);
mem = eina_file_map_all(ef, EINA_FILE_SEQUENTIAL);
if ((size == 0) || (!mem)) return NULL;
bld = parse_content(mem, size);
eina_file_close(ef);
return bld;
}
EAPI void
mrk_build_free(Mrk_Build *bld)
{
const char *s;
Mrk_Build_Bin *build_bin;
Mrk_Build_Data *build_data;
if (!bld) return;
eina_stringshare_del(bld->name);
eina_stringshare_del(bld->icon);
eina_stringshare_del(bld->brief);
eina_stringshare_del(bld->version);
eina_stringshare_del(bld->license);
eina_stringshare_del(bld->domain);
eina_stringshare_del(bld->repo);
eina_stringshare_del(bld->devrepo);
eina_stringshare_del(bld->contact);
EINA_LIST_FREE(bld->tags, s) eina_stringshare_del(s);
EINA_LIST_FREE(bld->categories, s) eina_stringshare_del(s);
EINA_LIST_FREE(bld->copying, s) eina_stringshare_del(s);
eina_stringshare_del(bld->needs);
EINA_LIST_FREE(bld->desktops, s) eina_stringshare_del(s);
EINA_LIST_FREE(bld->bins, build_bin)
{
eina_stringshare_del(build_bin->bin);
EINA_LIST_FREE(build_bin->srcs, s) eina_stringshare_del(s);
EINA_LIST_FREE(build_bin->deps, s) eina_stringshare_del(s);
EINA_LIST_FREE(build_bin->incs, s) eina_stringshare_del(s);
free(build_bin);
}
EINA_LIST_FREE(bld->data, build_data)
{
eina_stringshare_del(build_data->src);
eina_stringshare_del(build_data->dest);
free(build_data);
}
EINA_LIST_FREE(bld->icons, s) eina_stringshare_del(s);
EINA_LIST_FREE(bld->po, s) eina_stringshare_del(s);
free(bld);
}
EAPI Eina_Bool
mrk_build_do(Mrk_Build *bld, const char *tmpd)
{
Eina_List *l, *ll;
Mrk_Build_Bin *bin;
Mrk_Build_Data *data;
Eina_Strbuf *buf;
char *s, *extn, *s2;
char tmp[4096];
char tmp2[4096];
const char *ss, *cc;
#define err(reason) do { fprintf(stderr, "%s\n", reason); goto error; } while (0)
EINA_LIST_FOREACH(bld->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, bld->domain);
ecore_file_cp(tmp2, tmp);
}
EINA_LIST_FOREACH(bld->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(bld->desktops, l, s)
{
ss = ecore_file_file_get(s);
if (!(!strncmp(ss, bld->domain, strlen(bld->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(bld->icons, l, s)
{
ss = ecore_file_file_get(s);
if (!(!strncmp(ss, bld->domain, strlen(bld->domain))))
err("icon file wrong domain");
snprintf(tmp, sizeof(tmp), "%s/share/icons/%s", tmpd, ss);
ecore_file_cp(s, tmp);
}
EINA_LIST_FOREACH(bld->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(bld->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, bld->domain);
eina_strbuf_append(buf, "\\\"");
eina_strbuf_append(buf, " -DPACKAGE_NAME=\\\"");
eina_strbuf_append(buf, bld->domain);
eina_strbuf_append(buf, "\\\"");
eina_strbuf_append(buf, " -DPACKAGE_VERSION=\\\"");
eina_strbuf_append(buf, bld->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 EINA_TRUE;
error:
return EINA_FALSE;
#undef err
}
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);
}
}
EAPI Eina_Bool
mrk_build_package_bin(Mrk_Build *bld, const char *file, const char *tmpd, const char *os, const char *arch)
{
Eet_File *ef;
char tmp[4096];
Eina_List *l;
char *s;
int i;
// snprintf(tmp, sizeof(tmp), "%s-%s.mkb", bld->name, bld->version);
ef = eet_open(file, EET_FILE_MODE_WRITE);
if (ef)
{
#define WRTS(key, var) \
if (var) eet_write(ef, key, var, strlen(var), EET_COMPRESSION_VERYFAST)
WRTS("name", bld->name);
if (bld->icon) package_file(ef, bld->icon, "icon");
WRTS("brief", bld->brief);
WRTS("version", bld->version);
WRTS("license", bld->license);
WRTS("repo", bld->repo);
WRTS("devrepo", bld->devrepo);
WRTS("contact", bld->contact);
WRTS("needs", bld->needs);
snprintf(tmp, sizeof(tmp), "%s-%s", os, arch);
WRTS("arch", tmp);
i = 0;
EINA_LIST_FOREACH(bld->tags, l, s)
{
snprintf(tmp, sizeof(tmp), "tag/%i", i++);
WRTS(tmp, s);
}
i = 0;
EINA_LIST_FOREACH(bld->categories, l, s)
{
snprintf(tmp, sizeof(tmp), "category/%i", i++);
WRTS(tmp, s);
}
package_bin_iter(ef, tmpd, "bin/f");
eet_close(ef);
return EINA_TRUE;
}
return EINA_FALSE;
}
EAPI Eina_Bool
mrk_build_package_src(Mrk_Build *bld, const char *buildfile, const char *file)
{
Eet_File *ef;
char tmp[4096];
char tmp2[4096];
// snprintf(tmp, sizeof(tmp), "%s-%s.mks", bld->name, bld->version);
ef = eet_open(file, EET_FILE_MODE_WRITE);
if (ef)
{
Eina_File *enf;
Eina_List *l, *ll;
void *mem;
size_t size;
char *s;
Mrk_Build_Bin *bin;
Mrk_Build_Data *data;
enf = eina_file_open(buildfile, 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(bld->copying, l, s)
{
snprintf(tmp, sizeof(tmp), "src/%s", s);
package_file(ef, s, tmp);
}
EINA_LIST_FOREACH(bld->desktops, l, s)
{
snprintf(tmp, sizeof(tmp), "src/%s", s);
package_file(ef, s, tmp);
}
EINA_LIST_FOREACH(bld->icons, l, s)
{
snprintf(tmp, sizeof(tmp), "src/%s", s);
package_file(ef, s, tmp);
}
EINA_LIST_FOREACH(bld->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(bld->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(bld->data, l, data)
{
snprintf(tmp, sizeof(tmp), "src/%s", data->src);
package_file(ef, data->src, tmp);
}
eet_close(ef);
return EINA_TRUE;
}
return EINA_FALSE;
}

302
mrklib_index.c Normal file
View File

@ -0,0 +1,302 @@
#include "mrklib_priv.h"
typedef struct
{
Eina_Hash *name_hash;
Eina_Hash *category_hash;
Eina_Hash *tag_hash;
Eina_Hash *key_hash;
} Mdb;
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
key_register(Eina_Hash *hash, const char *key, const char *entry)
{
const char *ss;
Eina_List *entries;
ss = eina_stringshare_add(entry);
entries = eina_hash_find(hash, key);
entries = eina_list_sorted_insert(entries, EINA_COMPARE_CB(strcasecmp), ss);
eina_hash_set(hash, key, entries);
}
typedef struct
{
Eina_Hash *master;
const char *entry;
} Inf;
static Eina_Bool
key_enter_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
{
Inf *inf = fdata;
key_register(inf->master, key, inf->entry);
return EINA_TRUE;
}
static void
key_enter(Eina_Hash *master, Eina_Hash *keys, const char *entry)
{
Inf inf = { master, entry };
eina_hash_foreach(keys, key_enter_cb, &inf);
}
static Eina_Hash *
key_new(void)
{
return eina_hash_string_superfast_new(NULL);
}
static void
key_free(Eina_Hash *hash)
{
eina_hash_free(hash);
}
static void
key_add(Eina_Hash *hash, const char *key)
{
if (eina_hash_find(hash, key)) return;
eina_hash_add(hash, key, hash);
}
static void
key_str_add(Eina_Hash *hash, const char *str)
{
char *ts = strdup(str);
char *p, *pe;
if (!ts) return;
for (p = ts; *p; p++)
{
if (!(((*p >= 'a') && (*p <= 'z')) ||
((*p >= 'A') && (*p <= 'Z')) ||
((*p >= '0') && (*p <= '9')))) *p = 0;
else *p = tolower(*p);
pe = p;
}
for (p = ts; p < pe; p++)
{
if (*p)
{
key_add(hash, p);
p += strlen(p);
}
}
free(ts);
}
static Eina_Bool
key_merge_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
{
key_add(fdata, key);
return EINA_TRUE;
}
static void
key_merge(Eina_Hash *master, Eina_Hash *keys)
{
eina_hash_foreach(keys, key_merge_cb, master);
}
static Eina_Bool
index_file(Mdb *db, const char *file, const char *fname)
{
Eet_File *ef;
char *s;
int i;
char tmp[4096];
Eina_Hash *ky;
Eina_Hash *tk;
ef = eet_open(file, EET_FILE_MODE_READ);
if (!ef) return EINA_FALSE;
ky = key_new();
s = read_string(ef, "name");
if (s)
{
tk = key_new();
key_add(tk, s);
key_str_add(ky, s);
key_enter(db->name_hash, tk, fname);
key_free(tk);
tk = key_new();
key_str_add(tk, s);
key_merge(ky, tk);
key_free(tk);
free(s);
}
for (i = 0; i < 9999; i++)
{
tk = key_new();
snprintf(tmp, sizeof(tmp), "tag/%i", i);
s = read_string(ef, tmp);
if (s)
{
key_str_add(tk, s);
free(s);
}
key_enter(db->tag_hash, tk, fname);
key_merge(ky, tk);
key_free(tk);
}
key_register(db->category_hash, "@", fname);
for (i = 0; i < 9999; i++)
{
tk = key_new();
snprintf(tmp, sizeof(tmp), "category/%i", i);
s = read_string(ef, tmp);
if (s)
{
key_str_add(tk, s);
free(s);
}
key_enter(db->category_hash, tk, fname);
key_merge(ky, tk);
key_free(tk);
}
s = read_string(ef, "brief");
if (s)
{
tk = key_new();
key_str_add(tk, s);
key_merge(ky, tk);
key_free(tk);
free(s);
}
key_enter(db->key_hash, ky, fname);
key_free(ky);
eet_close(ef);
return EINA_TRUE;
}
static Eina_Bool
index_out_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
{
FILE *f = fdata;
const char *s;
fprintf(f, "%s\n", (const char *)key);
EINA_LIST_FREE(data, s)
{
fprintf(f, "\t%s\n", s);
eina_stringshare_del(s);
}
return EINA_TRUE;
}
static Eina_Bool
index_dir(const char *dir)
{
Eina_List *files;
char *s;
char tmp[4096];
FILE *f;
Mdb *db;
db = calloc(1, sizeof(Mdb));
if (!db) return 0;
db->name_hash = eina_hash_string_superfast_new(NULL);
db->category_hash = eina_hash_string_superfast_new(NULL);
db->tag_hash = eina_hash_string_superfast_new(NULL);
db->key_hash = eina_hash_string_superfast_new(NULL);
files = ecore_file_ls(dir);
EINA_LIST_FREE(files, s)
{
char *lnk;
if (s[0] == '.')
{
free(s);
continue;
}
snprintf(tmp, sizeof(tmp), "%s/%s", dir, s);
lnk = ecore_file_readlink(tmp);
if (!lnk)
{
free(s);
continue;
}
index_file(db, tmp, s);
free(lnk);
free(s);
}
snprintf(tmp, sizeof(tmp), "%s/.mrkdb-name.txt", dir);
f = fopen(tmp, "wb");
if (f)
{
eina_hash_foreach(db->name_hash, index_out_cb, f);
eina_hash_free(db->name_hash);
fclose(f);
}
snprintf(tmp, sizeof(tmp), "%s/.mrkdb-tag.txt", dir);
f = fopen(tmp, "wb");
if (f)
{
eina_hash_foreach(db->tag_hash, index_out_cb, f);
eina_hash_free(db->tag_hash);
fclose(f);
}
snprintf(tmp, sizeof(tmp), "%s/.mrkdb-category.txt", dir);
f = fopen(tmp, "wb");
if (f)
{
eina_hash_foreach(db->category_hash, index_out_cb, f);
eina_hash_free(db->category_hash);
fclose(f);
}
snprintf(tmp, sizeof(tmp), "%s/.mrkdb-key.txt", dir);
f = fopen(tmp, "wb");
if (f)
{
eina_hash_foreach(db->key_hash, index_out_cb, f);
eina_hash_free(db->key_hash);
fclose(f);
}
free(db);
return 1;
}
EAPI Eina_Bool
mrk_index(const char *dir)
{
Eina_Bool ok = EINA_FALSE;
char *repodir;
const char *file;
file = ecore_file_file_get(dir);
if (!file) return ok;
if (!_mrk_util_arch_ok(file)) return ok;
repodir = ecore_file_realpath(dir);
if (repodir)
{
ok = index_dir(repodir);
free(repodir);
}
return ok;
}

281
mrklib_package.c Normal file
View File

@ -0,0 +1,281 @@
#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_bin_install(const char *file)
{
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;
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/.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;
}

99
mrklib_priv.h Normal file
View File

@ -0,0 +1,99 @@
#include "mrklib.h"
#include <Ecore.h>
#include <Ecore_File.h>
#include <Ecore_Ipc.h>
#include <Eet.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define MRK_SERVER_HOST "devs.enlightenment.org"
#define MRK_SERVER_PORT 10077
extern const char *_mrk_server_host;
extern int _mrk_server_port;
extern const char *_mrk_appdir;
extern const char *_mrk_appdir_tmp;
extern const char *_mrk_appdir_bin;
extern unsigned char *_mrk_uuid;
extern int _mrk_uuid_len;
#define M_OP 10
#define M_UP_B 0
#define M_UP_E 10
#define M_UP_START 1
#define M_UP_DATA 2
#define M_UP_END 3
#define M_UP_OK 4
#define M_UP_FAIL 5
#define M_DOWN_B 10
#define M_DOWN_E 20
#define M_DOWN_START 11
#define M_DOWN_DATA 12
#define M_DOWN_END 13
#define M_QRY_B 20
#define M_QRY_E 30
#define M_QRY_LIST 21
#define M_QRY_SEARCH 22
#define M_QRY_GET 23
#define M_QRY_GETSRC 24
#define M_ANS_B 30
#define M_ANS_E 40
#define M_ANS_START 31
#define M_ANS_DATA 32
#define M_ANS_END 33
#define M_SRC_B 40
#define M_SRC_E 50
#define M_SRC_START 41
#define M_SRC_DATA 42
#define M_SRC_END 43
#define M_ID_B 50
#define M_ID_E 60
#define M_ID_UUID 51
#define M_ID_VERSION 52
#define M_ID_ARCH 53
#if defined(__x86_64__)
# define ARCH "x86_64"
#elif defined(__i386__)
# define ARCH "ix86"
#elif defined(__arm__)
# ifdef __ARM_V7__
# define ARCH "armv7"
# else
# define ARCH "armv6"
# endif
#elif defined(__ppc64__) || defined(__powerpc64__)
# define ARCH "ppc64"
#elif defined(__ppc__) || defined(__powerpc__)
# define ARCH "ppc"
#endif
#if defined(__linux__)
# define OS "linux"
#elif defined(__MACH__)
# define OS "osx"
#elif defined(__FreeBSD__)
# define OS "freebsd"
#elif defined(_WIN32) || defined(_WIN64)
# define OS "win"
#endif
Eina_Bool _mrk_util_plain_file_check(const char *file);
Eina_Bool _mrk_util_plain_path_check(const char *file);
char *_mrk_util_proto_string(Ecore_Ipc_Event_Server_Data *e);
char *_mrk_util_proto_cli_string(Ecore_Ipc_Event_Client_Data *e);
Eina_Bool _mrk_util_arch_ok(const char *arch);

338
mrklib_repodb.c Normal file
View File

@ -0,0 +1,338 @@
#include "mrklib_priv.h"
typedef struct
{
const char *arch;
Eina_Hash *name_hash;
Eina_Hash *category_hash;
Eina_Hash *tag_hash;
Eina_Hash *key_hash;
} Db;
struct _Mrk_Repodb
{
const char *repodir;
Eina_List *dbs;
Ecore_Exe *exe;
Eina_Bool update;
Eina_List *handlers;
struct {
void (*update) (void *data, Mrk_Repodb *repodb);
} func;
struct {
void *update;
} data;
};
static void
db_load_hash(Eina_Hash *hash, FILE *f)
{
char line[16384], *s;
int len;
Eina_List *list = NULL;
const char *key = NULL;
for (;;)
{
s = fgets(line, sizeof(line), f);
if (!s) break;;
len = strlen(s);
if (len < 1) continue;
s[len - 1] = 0;
if ((s[0] == '\t') && (key))
{
list = eina_list_append(list, eina_stringshare_add(s + 1));
}
else
{
if (key) eina_hash_set(hash, key, list);
list = NULL;
if (key) eina_stringshare_del(key);
key = eina_stringshare_add(s);
}
}
if (key) eina_hash_set(hash, key, list);
list = NULL;
if (key) eina_stringshare_del(key);
key = NULL;
}
static Eina_Bool
db_clear_hash_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
{
const char *s;
EINA_LIST_FREE(data, s)
{
eina_stringshare_del(s);
}
return EINA_TRUE;
}
static void
db_clear_hash(Eina_Hash *hash)
{
if (!hash) return;
eina_hash_foreach(hash, db_clear_hash_cb, NULL);
eina_hash_free(hash);
}
static void
db_clear(Mrk_Repodb *rdb)
{
Db *db;
EINA_LIST_FREE(rdb->dbs, db)
{
db_clear_hash(db->name_hash);
db_clear_hash(db->category_hash);
db_clear_hash(db->tag_hash);
db_clear_hash(db->key_hash);
free(db);
}
}
static void
db_load(Mrk_Repodb *rdb)
{
Eina_List *files;
char *s;
char tmp[PATH_MAX];
Db *db = NULL;
FILE *f;
files = ecore_file_ls(rdb->repodir);
EINA_LIST_FREE(files, s)
{
if ((s[0] == '.') || (!_mrk_util_arch_ok(s)))
{
free(s);
continue;
}
snprintf(tmp, sizeof(tmp), "%s/%s/.mrkdb-name.txt", rdb->repodir, s);
f = fopen(tmp, "rb");
if (f)
{
db = calloc(1, sizeof(Db));
if (db)
{
db->arch = eina_stringshare_add(s);
if (db->arch)
{
db->name_hash = eina_hash_string_superfast_new(NULL);
db->category_hash = eina_hash_string_superfast_new(NULL);
db->tag_hash = eina_hash_string_superfast_new(NULL);
db->key_hash = eina_hash_string_superfast_new(NULL);
rdb->dbs = eina_list_append(rdb->dbs, db);
db_load_hash(db->name_hash, f);
}
else
{
free(db);
db = NULL;
}
}
fclose(f);
}
if (db)
{
snprintf(tmp, sizeof(tmp), "%s/%s/.mrkdb-tag.txt", rdb->repodir, s);
f = fopen(tmp, "rb");
if (f)
{
db_load_hash(db->tag_hash, f);
fclose(f);
}
snprintf(tmp, sizeof(tmp), "%s/%s/.mrkdb-category.txt", rdb->repodir, s);
f = fopen(tmp, "rb");
if (f)
{
db_load_hash(db->category_hash, f);
fclose(f);
}
snprintf(tmp, sizeof(tmp), "%s/%s/.mrkdb-key.txt", rdb->repodir, s);
f = fopen(tmp, "rb");
if (f)
{
db_load_hash(db->key_hash, f);
fclose(f);
}
}
db = NULL;
}
}
static Db *
db_arch_find(Mrk_Repodb *rdb, const char *arch)
{
Eina_List *l;
Db *db;
if (!arch) return NULL;
EINA_LIST_FOREACH(rdb->dbs, l, db)
{
if (!strcmp(db->arch, arch))
{
if (rdb->dbs != l) rdb->dbs = eina_list_promote_list(rdb->dbs, l);
return db;
}
}
return NULL;
}
static Eina_List *
search_intersect(Eina_List *list_in, Eina_List *list2)
{
Eina_List *list = NULL, *ll;
const char *s, *ss;
int ok;
EINA_LIST_FREE(list_in, s)
{
ok = 0;
EINA_LIST_FOREACH(list2, ll, ss)
{
if (ss == s)
{
ok = 1;
break;
}
}
if (ok) list = eina_list_append(list, s);
else eina_stringshare_del(s);
}
return list;
}
static Eina_List *
db_search(Eina_Hash *hash, const char *search)
{
Eina_List *list = NULL, *tl, *l;
const char *s;
char *ts = strdup(search);
char *p, *end;
int i;
if (!ts) return NULL;
for (p = ts; *p; p++)
{
if (isspace(*p)) *p = 0;
end = p;
}
for (p = ts; p < end; p++)
{
if (!*p) continue;
tl = eina_hash_find(hash, p);
if (p == ts)
{
EINA_LIST_FOREACH(tl, l, s)
list = eina_list_append(list, eina_stringshare_add(s));
}
else
{
list = search_intersect(list, tl);
}
p += strlen(p);
}
free(ts);
return list;
}
static Eina_Bool
_mrk_cb_exe_del(void *data, int type, void *event)
{
Ecore_Exe_Event_Del *e = event;
Mrk_Repodb *rdb = data;
const char *tag;
if (!e->exe) return EINA_TRUE;
tag = ecore_exe_tag_get(e->exe);
if (!tag) return EINA_TRUE;
if (!strcmp(tag, "-=# mrk serve - db exe #=-"))
{
if (ecore_exe_data_get(e->exe) != rdb) return EINA_TRUE;
if (e->exe != rdb->exe) return EINA_TRUE;
rdb->exe = NULL;
db_clear(rdb);
db_load(rdb);
if (rdb->update)
{
rdb->update = EINA_FALSE;
mrk_repodb_update(rdb);
}
if (rdb->func.update) rdb->func.update(rdb->data.update, rdb);
return EINA_FALSE;
}
return EINA_TRUE;
}
EAPI Mrk_Repodb *
mrk_repodb_load(const char *repodir)
{
Mrk_Repodb *rdb;
rdb = calloc(1, sizeof(Mrk_Repodb));
if (!rdb) return NULL;
rdb->repodir = eina_stringshare_add(repodir);
rdb->handlers = eina_list_append(rdb->handlers,
ecore_event_handler_add
(ECORE_EXE_EVENT_DEL,
_mrk_cb_exe_del, rdb));
db_load(rdb);
return rdb;
}
EAPI void
mrk_repodb_free(Mrk_Repodb *rdb)
{
Ecore_Event_Handler *hnd;
EINA_LIST_FREE(rdb->handlers, hnd) ecore_event_handler_del(hnd);
db_clear(rdb);
if (rdb->exe) ecore_exe_free(rdb->exe);
free(rdb);
}
EAPI void
mrk_repodb_callback_update_set(Mrk_Repodb *rdb,
void (*update) (void *data, Mrk_Repodb *rdb),
void *update_data)
{
rdb->func.update = update;
rdb->data.update = update_data;
}
EAPI void
mrk_repodb_update(Mrk_Repodb *rdb)
{
char tmp[PATH_MAX];
if (rdb->exe)
{
rdb->update = EINA_TRUE;
return;
}
snprintf(tmp, sizeof(tmp), "mrk index %s/*-*", rdb->repodir);
rdb->exe = ecore_exe_pipe_run(tmp, 0, rdb);
if (rdb->exe) ecore_exe_tag_set(rdb->exe, "-=# mrk serve - db exe #=-");
}
EAPI const Eina_List *
mrk_repodb_category_list(Mrk_Repodb *rdb, const char *arch, const char *category)
{
Db *db = db_arch_find(rdb, arch);
Eina_List *list;
if (!db) return NULL;
if (!category) category = "@"; // @ is the "everything" category and list
return eina_hash_find(db->category_hash, category);
}
EAPI Eina_List *
mrk_repodb_search(Mrk_Repodb *rdb, const char *arch, const char *search)
{
Db *db = db_arch_find(rdb, arch);
if (!db) return NULL;
return db_search(db->key_hash, search);
}

425
mrklib_serv.c Normal file
View File

@ -0,0 +1,425 @@
#include "mrklib_priv.h"
struct _Mrk_Serve
{
const char *listen;
int port;
const char *repodir;
const char *bldsh;
Ecore_Ipc_Server *server;
Eina_List *handlers;
Eina_Inlist *clients;
Mrk_Repodb *rdb;
};
typedef struct
{
EINA_INLIST;
Mrk_Serve *server;
Ecore_Ipc_Client *client;
const char *uuid;
const char *arch;
const char *version;
const char *file;
const char *dir;
FILE *f;
Ecore_Exe *exe;
} Client;
static void
client_upload_cancel(Client *c)
{
if (c->f) fclose(c->f);
if (c->file) eina_stringshare_del(c->file);
if (c->dir)
{
ecore_file_recursive_rm(c->dir);
eina_stringshare_del(c->dir);
}
c->f = NULL;
c->file = NULL;
c->dir = NULL;
}
static void
client_upload_new(Client *c, const char *file)
{
char tmp[PATH_MAX];
Eina_Tmpstr *s = NULL;
if (c->f) client_upload_cancel(c);
c->file = eina_stringshare_add(file);
if (!c->file) return;
if (eina_file_mkdtemp("marrekesh-up-XXXXXX", &s))
{
c->dir = eina_stringshare_add(s);
eina_tmpstr_del(s);
if (c->dir)
{
snprintf(tmp, sizeof(tmp), "%s/%s", c->dir, c->file);
c->f = fopen(tmp, "wb");
}
}
}
static void
client_upload_data(Client *c, void *data, int size)
{
if (c->f) fwrite(data, size, 1, c->f);
}
static void
client_upload_end(Client *c)
{
char tmp[PATH_MAX];
if (c->f)
{
fclose(c->f);
c->f = NULL;
snprintf(tmp, sizeof(tmp), "%s %s %s",
c->server->bldsh, c->dir, c->server->repodir);
c->exe = ecore_exe_pipe_run(tmp,
ECORE_EXE_TERM_WITH_PARENT |
ECORE_EXE_NOT_LEADER, c);
if (c->exe) ecore_exe_tag_set(c->exe, "-=# mrk serve - build exe #=-");
}
}
static void
client_send(Client *c, const char *subrepo, const char *name, int op_start, int op_data, int op_end)
{
char tmp[PATH_MAX];
char *lnk;
snprintf(tmp, sizeof(tmp), "%s/%s/%s", c->server->repodir, subrepo, name);
lnk = ecore_file_readlink(tmp);
if (!lnk)
ecore_ipc_client_send(c->client, M_OP, op_start, 0, 0, 0,
NULL, 0);
else
{
FILE *f = fopen(tmp, "rb");
if (!f)
ecore_ipc_client_send(c->client, M_OP, op_start, 0, 0, 0,
NULL, 0);
else
{
long sz, pos;
fseek(f, 0, SEEK_END);
sz = ftell(f);
fseek(f, 0, SEEK_SET);
ecore_ipc_client_send(c->client, M_OP, op_start, (int)sz, 0, 0,
lnk, strlen(lnk));
for (pos = 0; pos < sz;)
{
size_t size;
char buf[10000];
size = fread(buf, 1, 10000, f);
if (size <= 0) break;
pos += size;
ecore_ipc_client_send(c->client, M_OP, op_data,
(int)pos, (int)sz, 0,
buf, size);
}
ecore_ipc_client_send(c->client, M_OP, op_end, 0, 0, 0,
NULL, 0);
fclose(f);
}
free(lnk);
}
}
static Eina_Bool
_mrk_id_data(Mrk_Serve *server, Client *c, Ecore_Ipc_Event_Client_Data *e)
{
if (e->minor == M_ID_UUID)
{
char *str = _mrk_util_proto_cli_string(e);
if (str)
{
eina_stringshare_replace(&(c->uuid), str);
free(str);
}
return EINA_TRUE;
}
else if (e->minor == M_ID_VERSION)
{
char *str = _mrk_util_proto_cli_string(e);
if (str)
{
eina_stringshare_replace(&(c->version), str);
free(str);
}
return EINA_TRUE;
}
else if (e->minor == M_ID_ARCH)
{
char *str = _mrk_util_proto_cli_string(e);
if (str)
{
if (_mrk_util_arch_ok(str))
eina_stringshare_replace(&(c->arch), str);
free(str);
}
return EINA_TRUE;
}
return EINA_FALSE;
}
static Eina_Bool
_mrk_upload_data(Mrk_Serve *server, Client *c, Ecore_Ipc_Event_Client_Data *e)
{
if ((!c->uuid) || (!c->version) || (!c->arch)) return EINA_FALSE;
if (e->minor == M_UP_START)
{
char *str = _mrk_util_proto_cli_string(e);
if (str)
{
if (_mrk_util_plain_file_check(str))
client_upload_new(c, str);
free(str);
}
return EINA_TRUE;
}
else if (e->minor == M_UP_DATA)
{
if ((e->data) && (e->size <= 10000))
client_upload_data(c, e->data, e->size);
return EINA_TRUE;
}
else if (e->minor == M_UP_END)
{
client_upload_end(c);
return EINA_TRUE;
}
return EINA_FALSE;
}
static Eina_Bool
_mrk_query_data(Mrk_Serve *server, Client *c, Ecore_Ipc_Event_Client_Data *e)
{
if ((!c->uuid) || (!c->version) || (!c->arch)) return EINA_FALSE;
if (e->minor == M_QRY_LIST)
{
const Eina_List *list = NULL, *l;
ecore_ipc_client_send(c->client, M_OP, M_ANS_START, 0, 0, 0, NULL, 0);
if (!e->data) list = mrk_repodb_category_list(c->server->rdb,
c->arch, NULL);
else
{
char *str = _mrk_util_proto_cli_string(e);
if (str)
{
list = mrk_repodb_category_list(c->server->rdb,
c->arch, str);
free(str);
}
}
if (list)
{
const char *s;
EINA_LIST_FOREACH(list, l, s)
{
ecore_ipc_client_send(c->client, M_OP, M_ANS_DATA,
0, 0, 0,
s, strlen(s));
}
}
ecore_ipc_client_send(c->client, M_OP, M_ANS_END, 0, 0, 0, NULL, 0);
return EINA_TRUE;
}
else if (e->minor == M_QRY_SEARCH)
{
ecore_ipc_client_send(c->client, M_OP, M_ANS_START, 0, 0, 0, NULL, 0);
if (e->data)
{
char *str = _mrk_util_proto_cli_string(e);
if (str)
{
Eina_List *list;
const char *s;
list = mrk_repodb_search(c->server->rdb, c->arch, str);
EINA_LIST_FREE(list, s)
{
ecore_ipc_client_send(c->client, M_OP, M_ANS_DATA,
0, 0, 0,
s, strlen(s));
eina_stringshare_del(s);
}
free(str);
}
}
ecore_ipc_client_send(c->client, M_OP, M_ANS_END, 0, 0, 0, NULL, 0);
return EINA_TRUE;
}
else if (e->minor == M_QRY_GET)
{
char *str = _mrk_util_proto_cli_string(e);
if (str)
{
if (_mrk_util_plain_file_check(str))
client_send(c, c->arch, str,
M_DOWN_START, M_DOWN_DATA, M_DOWN_END);
free(str);
}
return EINA_TRUE;
}
else if (e->minor == M_QRY_GETSRC)
{
char *str = _mrk_util_proto_cli_string(e);
if (str)
{
if (_mrk_util_plain_file_check(str))
client_send(c, "src", str,
M_SRC_START, M_SRC_DATA, M_SRC_END);
free(str);
}
return EINA_TRUE;
}
return EINA_FALSE;
}
static Eina_Bool
_mrk_data_handle(Mrk_Serve *server, Client *c, Ecore_Ipc_Event_Client_Data *e)
{
if ((e->minor > M_UP_B) && (e->minor < M_UP_E))
return _mrk_upload_data(server, c, e);
else if ((e->minor > M_QRY_B) && (e->minor < M_QRY_E))
return _mrk_query_data(server, c, e);
else if ((e->minor > M_ID_B) && (e->minor < M_ID_E))
return _mrk_id_data(server, c, e);
return EINA_FALSE;
}
static Eina_Bool
_mrk_cb_add(void *data, int type, void *event)
{
Ecore_Ipc_Event_Client_Add *e = event;
Mrk_Serve *server = data;
Client *c;
if (server->server != ecore_ipc_client_server_get(e->client)) return EINA_TRUE;
c = calloc(1, sizeof(Client));
c->server = server;
c->client = e->client;
ecore_ipc_client_data_set(e->client, c);
server->clients = eina_inlist_append(server->clients, EINA_INLIST_GET(c));
return EINA_FALSE;
}
static Eina_Bool
_mrk_cb_del(void *data, int type, void *event)
{
Ecore_Ipc_Event_Client_Del *e = event;
Mrk_Serve *server = data;
Client *c;
if (server->server != ecore_ipc_client_server_get(e->client)) return EINA_TRUE;
c = ecore_ipc_client_data_get(e->client);
if (c)
{
client_upload_cancel(c);
eina_stringshare_del(c->uuid);
eina_stringshare_del(c->arch);
eina_stringshare_del(c->version);
if (c->exe) ecore_exe_free(c->exe);
server->clients = eina_inlist_remove(server->clients,
EINA_INLIST_GET(c));
free(c);
}
return EINA_FALSE;
}
static Eina_Bool
_mrk_cb_data(void *data, int type, void *event)
{
Ecore_Ipc_Event_Client_Data *e = event;
Mrk_Serve *server = data;
Client *c;
if (server->server != ecore_ipc_client_server_get(e->client)) return EINA_TRUE;
c = ecore_ipc_client_data_get(e->client);
if (!c) return EINA_TRUE;
if (e->major != M_OP) return EINA_TRUE;
if (!_mrk_data_handle(server, c, e)) return EINA_TRUE;
return EINA_FALSE;
}
static Eina_Bool
_mrk_cb_exe_del(void *data, int type, void *event)
{
Ecore_Exe_Event_Del *e = event;
Mrk_Serve *server = data;
Client *c;
const char *tag;
if (!e->exe) return EINA_TRUE;
tag = ecore_exe_tag_get(e->exe);
if (!tag) return EINA_TRUE;
if (!strcmp(tag, "-=# mrk serve - build exe #=-"))
{
c = ecore_exe_data_get(e->exe);
if (!c) return EINA_TRUE;
if (c->exe != e->exe) return EINA_TRUE;
c->exe = NULL;
mrk_repodb_update(server->rdb);
return EINA_FALSE;
}
return EINA_TRUE;
}
EAPI Mrk_Serve *
mrk_serve(const char *listen, int port, const char *repodir, const char *bldsh)
{
Mrk_Serve *server;
server = calloc(1, sizeof(Mrk_Serve));
if (!server) return server;
if (!listen) listen = "0.0.0.0";
if (port <= 0) port = MRK_SERVER_PORT;
server->listen = eina_stringshare_add(listen);
server->port = port;
server->repodir = eina_stringshare_add(repodir);
server->bldsh = eina_stringshare_add(bldsh);
server->handlers = eina_list_append(server->handlers,
ecore_event_handler_add
(ECORE_IPC_EVENT_CLIENT_ADD,
_mrk_cb_add, server));
server->handlers = eina_list_append(server->handlers,
ecore_event_handler_add
(ECORE_IPC_EVENT_CLIENT_DEL,
_mrk_cb_del, server));
server->handlers = eina_list_append(server->handlers,
ecore_event_handler_add
(ECORE_IPC_EVENT_CLIENT_DATA,
_mrk_cb_data, server));
server->handlers = eina_list_append(server->handlers,
ecore_event_handler_add
(ECORE_EXE_EVENT_DEL,
_mrk_cb_exe_del, server));
server->server = ecore_ipc_server_add(ECORE_IPC_REMOTE_SYSTEM,
server->listen, server->port, server);
server->rdb = mrk_repodb_load(repodir);
return server;
}
EAPI void
mrk_unserve(Mrk_Serve *server)
{
Ecore_Event_Handler *hnd;
mrk_repodb_free(server->rdb);
ecore_ipc_server_del(server->server);
EINA_LIST_FREE(server->handlers, hnd) ecore_event_handler_del(hnd);
eina_stringshare_del(server->listen);
eina_stringshare_del(server->repodir);
eina_stringshare_del(server->bldsh);
if (!server) return;
free(server);
}

489
mrklib_svc.c Normal file
View File

@ -0,0 +1,489 @@
#include "mrklib_priv.h"
struct _Mrk
{
const char *host;
int port;
Ecore_Ipc_Server *server;
Eina_List *handlers;
FILE *f;
const char *file;
Eina_Bool query;
struct {
void (*connect) (void *data, Mrk *server);
void (*disconnect) (void *data, Mrk *server);
void (*upload_begin) (void *data, Mrk *server);
void (*upload_progress) (void *data, Mrk *server, double pos);
void (*upload_end) (void *data, Mrk *server);
void (*upload_success) (void *data, Mrk *server, Eina_Bool sucess);
void (*download_begin) (void *data, Mrk *server);
void (*download_progress) (void *data, Mrk *server, double pos);
void (*download_end) (void *data, Mrk *server);
void (*download_success) (void *data, Mrk *server, const char *file);
void (*answer_begin) (void *data, Mrk *server);
void (*answer_progress) (void *data, Mrk *server, const char *result);
void (*answer_end) (void *data, Mrk *server);
} func;
struct {
void *connect;
void *disconnect;
void *upload_begin;
void *upload_progress;
void *upload_end;
void *upload_success;
void *download_begin;
void *download_progress;
void *download_end;
void *download_success;
void *answer_begin;
void *answer_progress;
void *answer_end;
} data;
};
static void
_mrk_identify(Mrk *server)
{
char tmp[PATH_MAX];
// send client uuid - should be unique per client just to tell one
// apart from another - nothing more
ecore_ipc_server_send(server->server, M_OP, M_ID_UUID, 0, 0, 0,
_mrk_uuid, _mrk_uuid_len);
// send arch string - determined by compile time macros
snprintf(tmp, sizeof(tmp),
"%s-%s",
OS,
ARCH);
ecore_ipc_server_send(server->server, M_OP, M_ID_ARCH, 0, 0, 0,
tmp, strlen(tmp));
// send efl version - this is used by the server to filter results
// that are only relevent to you
snprintf(tmp, sizeof(tmp),
"%i.%i.%i",
eina_version->major,
eina_version->minor,
eina_version->micro);
ecore_ipc_server_send(server->server, M_OP, M_ID_VERSION, 0, 0, 0,
tmp, strlen(tmp));
}
static Eina_Bool
_mrk_upload(Mrk *server, const char *file)
{
FILE *f;
char buf[10000];
size_t size;
const char *fname;
if ((server->f) || (server->query)) return EINA_FALSE;
// XXX: adjust protocol so we get ack's for each buf
f = fopen(file, "rb");
if (!f) return;
server->f = f;
fname = ecore_file_file_get(file);
if (!fname) goto done;
ecore_ipc_server_send(server->server, M_OP, M_UP_START, 0, 0, 0,
fname, strlen(fname));
if (server->func.upload_begin)
server->func.upload_begin(server->data.upload_begin, server);
for (;;)
{
size = fread(buf, 1, 10000, f);
if (size > 0)
{
ecore_ipc_server_send(server->server, 10, M_UP_DATA, 0, 0, 0,
buf, size);
// XXX: calculate position 0.0 -> 1.0
if (server->func.upload_progress)
server->func.upload_progress(server->data.upload_progress, server, 0.5);
}
else break;
}
ecore_ipc_server_send(server->server, M_OP, M_UP_END, 0, 0, 0,
NULL, 0);
if (server->func.upload_end)
server->func.upload_end(server->data.upload_end, server);
done:
return EINA_TRUE;
}
static Eina_Bool
_mrk_upload_data(Mrk *server, Ecore_Ipc_Event_Server_Data *e)
{
if (e->minor == M_UP_OK)
{
if (server->f) fclose(server->f);
server->f = NULL;
if (server->func.upload_success)
server->func.upload_success(server->data.upload_success, server, EINA_TRUE);
return EINA_TRUE;
}
else if (e->minor == M_UP_FAIL)
{
if (server->f) fclose(server->f);
server->f = NULL;
// XXX: e->data should contain some failure string/info
if (server->func.upload_success)
server->func.upload_success(server->data.upload_success, server, EINA_FALSE);
return EINA_TRUE;
}
// XXX: we should have some other status - eg unpack src worked,
// src sanity check passed, some build failed when/where or succeeded
// etc. etc.
return EINA_FALSE;
}
static Eina_Bool
_mrk_download(Mrk *server, const char *package)
{
if ((server->f) || (server->query)) return EINA_FALSE;
ecore_ipc_server_send(server->server, M_OP, M_QRY_GET, 0, 0, 0,
package, strlen(package));
return EINA_TRUE;
}
static Eina_Bool
_mrk_download_data(Mrk *server, Ecore_Ipc_Event_Server_Data *e)
{
char *file = NULL;
if ((e->minor == M_DOWN_START) || (e->minor == M_SRC_START))
{
if ((e->size > 0) && (e->size <= 1000) && (e->data))
{
char *file = _mrk_util_proto_string(e);
if (file)
{
if (_mrk_util_plain_file_check(file))
{
FILE *f;
char tmp[PATH_MAX];
snprintf(tmp, sizeof(tmp), "%s/%s",
_mrk_appdir_tmp, file);
f = fopen(tmp, "wb");
if (!f) goto fail;
server->f = f;
server->file = eina_stringshare_add(tmp);
if (server->func.download_begin)
server->func.download_begin(server->data.download_begin, server);
}
else goto fail;
}
else goto fail;
}
else
{
fail:
if (server->func.download_success)
server->func.download_success(server->data.download_success, server, NULL);
}
free(file);
return EINA_TRUE;
}
else if ((e->minor == M_DOWN_DATA) || (e->minor == M_SRC_DATA))
{
if ((server->f) && (e->data) && (e->size > 0) && (e->size <= 10000))
{
fwrite(e->data, e->size, 1, server->f);
if (server->func.download_progress)
server->func.download_progress(server->data.download_progress, server, 0.5);
}
return EINA_TRUE;
}
else if ((e->minor == M_DOWN_END) || (e->minor == M_SRC_END))
{
const char *file = server->file;
server->file = NULL;
if (server->f) fclose(server->f);
server->f = NULL;
if (server->func.download_end)
server->func.download_end(server->data.download_end, server);
// XXX: check signature so we can verify dl is not broken and it's
// from a proper pkg server (signed by pkg server priv key, check
// with pub key
if (server->func.download_success)
server->func.download_success(server->data.download_success, server, file);
eina_stringshare_del(file);
return EINA_TRUE;
}
return EINA_FALSE;
}
static Eina_Bool
_mrk_download_src(Mrk *server, const char *package)
{
if ((server->f) || (server->query)) return EINA_FALSE;
ecore_ipc_server_send(server->server, M_OP, M_QRY_GETSRC, 0, 0, 0,
package, strlen(package));
return EINA_TRUE;
}
static Eina_Bool
_mrk_download_src_data(Mrk *server, Ecore_Ipc_Event_Server_Data *e)
{
return _mrk_download_data(server, e);
}
static Eina_Bool
_mrk_query_list(Mrk *server, const char *category)
{
if ((server->f) || (server->query)) return EINA_FALSE;
ecore_ipc_server_send(server->server, M_OP, M_QRY_LIST, 0, 0, 0,
category, category ? strlen(category) : 0);
return EINA_TRUE;
}
static Eina_Bool
_mrk_query_search(Mrk *server, const char *keywords)
{
if ((server->f) || (server->query)) return EINA_FALSE;
if (!keywords) return EINA_FALSE;
ecore_ipc_server_send(server->server, M_OP, M_QRY_SEARCH, 0, 0, 0,
keywords, strlen(keywords));
return EINA_TRUE;
}
static Eina_Bool
_mrk_query_data(Mrk *server, Ecore_Ipc_Event_Server_Data *e)
{
if (e->minor == M_ANS_START)
{
if (server->func.answer_begin)
server->func.answer_begin(server->data.answer_begin, server);
return EINA_TRUE;
}
else if (e->minor == M_ANS_DATA)
{
if ((e->data) && (e->size > 0) && (e->size <= 10000))
{
char *str = _mrk_util_proto_string(e);
if (str)
{
if (server->func.answer_progress)
server->func.answer_progress(server->data.answer_progress, server, str);
free(str);
}
}
return EINA_TRUE;
}
else if (e->minor == M_ANS_END)
{
server->query = EINA_FALSE;
if (server->func.answer_end)
server->func.answer_end(server->data.answer_end, server);
return EINA_TRUE;
}
return EINA_FALSE;
}
static Eina_Bool
_mrk_data_handle(Mrk *server, Ecore_Ipc_Event_Server_Data *e)
{
if ((e->minor > M_UP_B) && (e->minor < M_UP_E))
return _mrk_upload_data(server, e);
else if ((e->minor > M_DOWN_B) && (e->minor < M_DOWN_E))
return _mrk_download_data(server, e);
else if ((e->minor > M_SRC_B) && (e->minor < M_SRC_E))
return _mrk_download_src_data(server, e);
else if ((e->minor > M_ANS_B) && (e->minor < M_ANS_E))
return _mrk_query_data(server, e);
return EINA_FALSE;
}
static Eina_Bool
_mrk_cb_add(void *data, int type, void *event)
{
Ecore_Ipc_Event_Server_Add *e = event;
Mrk *server = data;
if (server->server != e->server) return EINA_TRUE;
if (server->func.connect)
server->func.connect(server->data.connect, server);
return EINA_FALSE;
}
static Eina_Bool
_mrk_cb_del(void *data, int type, void *event)
{
Ecore_Ipc_Event_Server_Del *e = event;
Mrk *server = data;
if (server->server != e->server) return EINA_TRUE;
if (server->func.disconnect)
server->func.disconnect(server->data.disconnect, server);
return EINA_FALSE;
}
static Eina_Bool
_mrk_cb_data(void *data, int type, void *event)
{
Ecore_Ipc_Event_Server_Data *e = event;
Mrk *server = data;
if (server->server != e->server) return EINA_TRUE;
if (e->major != M_OP) return EINA_TRUE;
if (!_mrk_data_handle(server, e)) return EINA_TRUE;
return EINA_FALSE;
}
EAPI Mrk *
mrk_connect(const char *host, int port)
{
Mrk *server;
if (!host) host = _mrk_server_host;
if (port <= 0) port = _mrk_server_port;
server = calloc(1, sizeof(Mrk));
if (!server) return NULL;
server->host = eina_stringshare_add(host);
server->port = port;
server->handlers = eina_list_append(server->handlers,
ecore_event_handler_add
(ECORE_IPC_EVENT_SERVER_ADD,
_mrk_cb_add, server));
server->handlers = eina_list_append(server->handlers,
ecore_event_handler_add
(ECORE_IPC_EVENT_SERVER_DEL,
_mrk_cb_del, server));
server->handlers = eina_list_append(server->handlers,
ecore_event_handler_add
(ECORE_IPC_EVENT_SERVER_DATA,
_mrk_cb_data, server));
server->server = ecore_ipc_server_connect(ECORE_IPC_REMOTE_SYSTEM,
(char *)server->host,
server->port,
server);
_mrk_identify(server);
return server;
}
EAPI void
mrk_disconnect(Mrk *server)
{
Ecore_Event_Handler *hnd;
if (!server) return;
ecore_ipc_server_del(server->server);
EINA_LIST_FREE(server->handlers, hnd) ecore_event_handler_del(hnd);
eina_stringshare_del(server->host);
if (server->f)
{
fclose(server->f);
if (server->file) ecore_file_unlink(server->file);
}
eina_stringshare_del(server->file);
free(server);
}
EAPI Eina_Bool
mrk_upload(Mrk *server, const char *file)
{
return _mrk_upload(server, file);
}
EAPI Eina_Bool
mrk_download(Mrk *server, const char *package)
{
return _mrk_download(server, package);
}
EAPI Eina_Bool
mrk_download_source(Mrk *server, const char *package)
{
return _mrk_download_src(server, package);
}
EAPI Eina_Bool
mrk_list(Mrk *server, const char *category)
{
return _mrk_query_list(server, category);
}
EAPI Eina_Bool
mrk_search(Mrk *server, const char *keys)
{
return _mrk_query_search(server, keys);
}
EAPI void
mrk_callback_connect_set(Mrk *server,
void (*connect) (void *data, Mrk *server),
void *connect_data,
void (*disconnect) (void *data, Mrk *server),
void *disconnect_data)
{
server->func.connect = connect;
server->data.connect = connect_data;
server->func.disconnect = disconnect;
server->data.disconnect = disconnect_data;
}
EAPI void
mrk_callback_upload_set(Mrk *server,
void (*upload_begin) (void *data, Mrk *server),
void *upload_begin_data,
void (*upload_progress) (void *data, Mrk *server, double pos),
void *upload_progress_data,
void (*upload_end) (void *data, Mrk *server),
void *upload_end_data,
void (*upload_success) (void *data, Mrk *server, Eina_Bool sucess),
void *upload_success_data)
{
server->func.upload_begin = upload_begin;
server->data.upload_begin = upload_begin_data;
server->func.upload_progress = upload_progress;
server->data.upload_progress = upload_progress_data;
server->func.upload_end = upload_end;
server->data.upload_end = upload_end_data;
server->func.upload_success = upload_success;
server->data.upload_success = upload_success_data;
}
EAPI void
mrk_callback_download_set(Mrk *server,
void (*download_begin) (void *data, Mrk *server),
void *download_begin_data,
void (*download_progress) (void *data, Mrk *server, double pos),
void *download_progress_data,
void (*download_end) (void *data, Mrk *server),
void *download_end_data,
void (*download_success) (void *data, Mrk *server, const char *file),
void *download_success_data)
{
server->func.download_begin = download_begin;
server->data.download_begin = download_begin_data;
server->func.download_progress = download_progress;
server->data.download_progress = download_progress_data;
server->func.download_end = download_end;
server->data.download_end = download_end_data;
server->func.download_success = download_success;
server->data.download_success = download_success_data;
}
EAPI void
mrk_callback_answer_set(Mrk *server,
void (*answer_begin) (void *data, Mrk *server),
void *answer_begin_data,
void (*answer_progress) (void *data, Mrk *server, const char *result),
void *answer_progress_data,
void (*answer_end) (void *data, Mrk *server),
void *answer_end_data)
{
server->func.answer_begin = answer_begin;
server->data.answer_begin = answer_begin_data;
server->func.answer_progress = answer_progress;
server->data.answer_progress = answer_progress_data;
server->func.answer_end = answer_end;
server->data.answer_end = answer_end_data;
}

95
mrklib_util.c Normal file
View File

@ -0,0 +1,95 @@
#include "mrklib_priv.h"
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 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;
}
Eina_Bool
_mrk_util_plain_file_check(const char *file)
{
if (_sane_forbidden_path(file, sane_name_veto) &&
_sane_allowed_path(file, sane_name_ok))
return EINA_TRUE;
return EINA_FALSE;
}
Eina_Bool
_mrk_util_plain_path_check(const char *file)
{
if (_sane_forbidden_path(file, sane_path_veto) &&
_sane_allowed_path(file, sane_path_ok))
return EINA_TRUE;
return EINA_FALSE;
}
char *
_mrk_util_proto_string(Ecore_Ipc_Event_Server_Data *e)
{
char *str = malloc(e->size + 1);
if (!str) return NULL;
memcpy(str, e->data, e->size);
str[e->size] = 0;
return str;
}
char *
_mrk_util_proto_cli_string(Ecore_Ipc_Event_Client_Data *e)
{
char *str = malloc(e->size + 1);
if (!str) return NULL;
memcpy(str, e->data, e->size);
str[e->size] = 0;
return str;
}
Eina_Bool
_mrk_util_arch_ok(const char *arch)
{
if (!strcmp(arch, "linux-x86_64")) return EINA_TRUE;
if (!strcmp(arch, "linux-ix86")) return EINA_TRUE;
if (!strcmp(arch, "linux-armv7")) return EINA_TRUE;
if (!strcmp(arch, "linux-armv6")) return EINA_TRUE;
if (!strcmp(arch, "linux-ppc64")) return EINA_TRUE;
if (!strcmp(arch, "linux-ppc")) return EINA_TRUE;
return EINA_FALSE;
}

1757
old/mrk.c Normal file

File diff suppressed because it is too large Load Diff