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:
parent
01af8bc9c0
commit
9c3cb5a9f5
4
build.sh
4
build.sh
|
@ -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`
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue