initial marakesh import - appstore and build system for efl apps
This commit is contained in:
commit
7ef6b73bb1
|
@ -0,0 +1,4 @@
|
|||
#!/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`
|
|
@ -0,0 +1,7 @@
|
|||
typedef struct
|
||||
{
|
||||
Eina_Hash *name_hash;
|
||||
Eina_Hash *category_hash;
|
||||
Eina_Hash *tag_hash;
|
||||
Eina_Hash *key_hash;
|
||||
} Mdb;
|
|
@ -0,0 +1,153 @@
|
|||
#include <Eina.h>
|
||||
#include <Ecore.h>
|
||||
#include <Eet.h>
|
||||
#include <Ecore_Ipc.h>
|
||||
#include <Ecore_File.h>
|
||||
|
||||
#include "mrk-db.h"
|
||||
|
||||
static char *repodir = "./repo";
|
||||
static Mdb *db = NULL;
|
||||
|
||||
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_add(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_add(hash, key, entries);
|
||||
}
|
||||
|
||||
static void
|
||||
key_str_add(Eina_Hash *hash, const char *string, const char *entry)
|
||||
{
|
||||
// XXX: parse "words" from string - add each to the key given
|
||||
}
|
||||
|
||||
static int
|
||||
index_file(const char *file, const char *fname)
|
||||
{
|
||||
Eet_File *ef;
|
||||
char *s;
|
||||
int i;
|
||||
char tmp[4096];
|
||||
|
||||
ef = eet_open(file, EET_FILE_MODE_READ);
|
||||
if (!ef) return 0;
|
||||
|
||||
s = read_string(ef, "name");
|
||||
if (s)
|
||||
{
|
||||
key_add(db->name_hash, s, fname);
|
||||
key_add(db->key_hash, s, fname);
|
||||
free(s);
|
||||
}
|
||||
s = read_string(ef, "version");
|
||||
if (s)
|
||||
{
|
||||
key_add(db->key_hash, s, fname);
|
||||
free(s);
|
||||
}
|
||||
for (i = 0; i < 9999; i++)
|
||||
{
|
||||
snprintf(tmp, sizeof(tmp), "tag/%i", i);
|
||||
s = read_string(ef, tmp);
|
||||
if (s)
|
||||
{
|
||||
key_add(db->tag_hash, s, fname);
|
||||
key_add(db->key_hash, s, fname);
|
||||
free(s);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 9999; i++)
|
||||
{
|
||||
snprintf(tmp, sizeof(tmp), "category/%i", i);
|
||||
s = read_string(ef, tmp);
|
||||
if (s)
|
||||
{
|
||||
key_add(db->category_hash, s, fname);
|
||||
key_add(db->key_hash, s, fname);
|
||||
free(s);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: weed duplicates from every key
|
||||
eet_close(ef);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
index_dir(const char *dir)
|
||||
{
|
||||
Eina_List *files;
|
||||
char *s;
|
||||
char tmp[4096];
|
||||
|
||||
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] == '.') continue;
|
||||
snprintf(tmp, sizeof(tmp), "%s/%s", dir, s);
|
||||
lnk = ecore_file_readlink(tmp);
|
||||
if (!lnk) continue;
|
||||
index_file(tmp, s);
|
||||
free(lnk);
|
||||
free(s);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
printf("usage:\n"
|
||||
" mrk-index /path/to/repo\n"
|
||||
"\n");
|
||||
exit(1);
|
||||
}
|
||||
eina_init();
|
||||
ecore_init();
|
||||
eet_init();
|
||||
ecore_file_init();
|
||||
|
||||
if (argc > 1) repodir = ecore_file_realpath(argv[1]);
|
||||
index_dir(repodir);
|
||||
|
||||
ecore_file_shutdown();
|
||||
eet_shutdown();
|
||||
ecore_shutdown();
|
||||
eina_shutdown();
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#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_START 11
|
||||
#define M_DOWN_DATA 12
|
||||
#define M_DOWN_END 13
|
||||
|
||||
#define M_QRY_LIST 21
|
||||
#define M_QRY_SEARCH 22
|
||||
#define M_QRY_GET 23
|
||||
|
||||
#define M_ANS_START 31
|
||||
#define M_ANS_DATA 32
|
||||
#define M_ANS_END 33
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh
|
||||
# build dir dstdir
|
||||
set -e
|
||||
|
||||
cd "$1"
|
||||
rm -f *.mkb || true
|
||||
rm -rf Marrakesh || true
|
||||
|
||||
export CC=gcc
|
||||
export CFLAGS="-O3 -ffast-math"
|
||||
export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig"
|
||||
|
||||
mrk extract *.mks
|
||||
mrk build
|
||||
mrk bin
|
||||
cp *.mkb "$2"/
|
||||
|
||||
export NAME=`grep "^PROJ:" Marrakesh.mrk | tail -1 | sed -e 's/PROJ://g' | sed -e 's/ *$//' -e 's/^ *//'`
|
||||
rm -f "$2"/"$NAME" || true
|
||||
ln -sf *.mkb "$2"/"$NAME"
|
||||
|
||||
cd /tmp
|
||||
rm -rf "$1"
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,352 @@
|
|||
#include <Eina.h>
|
||||
#include <Ecore.h>
|
||||
#include <Eet.h>
|
||||
#include <Ecore_Ipc.h>
|
||||
#include <Ecore_File.h>
|
||||
|
||||
#include "mrk-proto.h"
|
||||
#include "mrk-db.h"
|
||||
|
||||
static const char *sane_name_veto[] = {"../", "./", "/", NULL};
|
||||
static const char *sane_name_ok = "01234567890-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.";
|
||||
|
||||
static char *repodir = "./repo";
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Ecore_Ipc_Client *client;
|
||||
char *file;
|
||||
char *dir;
|
||||
FILE *f;
|
||||
Ecore_Exe *exe;
|
||||
} Client;
|
||||
|
||||
static Ecore_Ipc_Server *ipc = NULL;
|
||||
static Eina_List *clients = NULL;
|
||||
|
||||
static Client *
|
||||
client_find(Ecore_Ipc_Client *ipc_client)
|
||||
{
|
||||
Eina_List *l;
|
||||
Client *c;
|
||||
|
||||
EINA_LIST_FOREACH(clients, l, c)
|
||||
{
|
||||
if (c->client == ipc_client) return c;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Client *
|
||||
client_exe_find(Ecore_Exe *exe)
|
||||
{
|
||||
Eina_List *l;
|
||||
Client *c;
|
||||
|
||||
EINA_LIST_FOREACH(clients, l, c)
|
||||
{
|
||||
if (c->exe == exe) return c;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Client *
|
||||
client_new(void)
|
||||
{
|
||||
Client *c;
|
||||
|
||||
c = calloc(1, sizeof(Client));
|
||||
clients = eina_list_append(clients, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
static void
|
||||
client_free(Client *c)
|
||||
{
|
||||
if (c->f) fclose(c->f);
|
||||
if (c->file) free(c->file);
|
||||
if (c->dir)
|
||||
{
|
||||
ecore_file_recursive_rm(c->dir);
|
||||
free(c->dir);
|
||||
}
|
||||
clients = eina_list_remove(clients, c);
|
||||
free(c);
|
||||
}
|
||||
|
||||
static void
|
||||
client_upload_new(Client *c)
|
||||
{
|
||||
char tmp[4096];
|
||||
Eina_Tmpstr *s = NULL;
|
||||
|
||||
if (c->f) fclose(c->f);
|
||||
if (c->dir)
|
||||
{
|
||||
ecore_file_recursive_rm(c->dir);
|
||||
free(c->dir);
|
||||
c->dir = NULL;
|
||||
}
|
||||
if (eina_file_mkdtemp("marrekesh-up-XXXXXX", &s))
|
||||
{
|
||||
c->dir = strdup(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_end(Client *c)
|
||||
{
|
||||
char tmp[4096];
|
||||
|
||||
if (c->f)
|
||||
{
|
||||
fclose(c->f);
|
||||
c->f = NULL;
|
||||
snprintf(tmp, sizeof(tmp),
|
||||
"./mrk-srv-build.sh %s %s",
|
||||
c->dir, repodir);
|
||||
c->exe = ecore_exe_pipe_run(tmp,
|
||||
ECORE_EXE_TERM_WITH_PARENT |
|
||||
ECORE_EXE_NOT_LEADER, c);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
client_upload_fail(Client *c)
|
||||
{
|
||||
if (c->f) fclose(c->f);
|
||||
if (c->file) free(c->file);
|
||||
if (c->dir)
|
||||
{
|
||||
ecore_file_recursive_rm(c->dir);
|
||||
free(c->dir);
|
||||
}
|
||||
c->f = NULL;
|
||||
c->file = NULL;
|
||||
c->dir = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
client_upload_data(Client *c, void *data, int size)
|
||||
{
|
||||
if (c->f) fwrite(data, size, 1, c->f);
|
||||
}
|
||||
|
||||
static void
|
||||
client_send(Client *c, const char *name)
|
||||
{
|
||||
char tmp[4096];
|
||||
char *lnk;
|
||||
|
||||
snprintf(tmp, sizeof(tmp), "%s/%s", repodir, name);
|
||||
lnk = ecore_file_readlink(tmp);
|
||||
if (!lnk)
|
||||
ecore_ipc_client_send(c->client, 10, M_DOWN_START, 0, 0, 0, NULL, 0);
|
||||
else
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
f = fopen(tmp, "rb");
|
||||
if (!f)
|
||||
ecore_ipc_client_send(c->client, 10, M_DOWN_START, 0, 0, 0, NULL, 0);
|
||||
else
|
||||
{
|
||||
ecore_ipc_client_send(c->client, 10, M_DOWN_START, 0, 0, 0, lnk, strlen(lnk));
|
||||
for (;;)
|
||||
{
|
||||
size_t size;
|
||||
char buf[10000];
|
||||
|
||||
size = fread(buf, 1, 10000, f);
|
||||
if (size <= 0) break;
|
||||
ecore_ipc_client_send(c->client, 10, M_DOWN_DATA, 0, 0, 0, buf, size);
|
||||
}
|
||||
ecore_ipc_client_send(c->client, 10, M_DOWN_END, 0, 0, 0, NULL, 0);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_ipc_cb_add(void *data, int type, void *event)
|
||||
{
|
||||
Ecore_Ipc_Event_Client_Add *e = event;
|
||||
Client *c = client_new();
|
||||
c->client = e->client;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_ipc_cb_del(void *data, int type, void *event)
|
||||
{
|
||||
Ecore_Ipc_Event_Client_Del *e = event;
|
||||
Client *c = client_find(e->client);
|
||||
if (c) client_free(c);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_ipc_cb_dat(void *data, int type, void *event)
|
||||
{
|
||||
Ecore_Ipc_Event_Client_Data *e = event;
|
||||
Client *c = client_find(e->client);
|
||||
// e->major e->minor e->ref e->ref_to e->response | e->data e->size
|
||||
if (e->major != 10) return EINA_TRUE;
|
||||
switch (e->minor)
|
||||
{
|
||||
case M_UP_START:
|
||||
// e->data == filename
|
||||
if ((e->size > 0) && (e->size < 1000))
|
||||
{
|
||||
if (c->file) free(c->file);
|
||||
c->file = malloc(e->size + 1);
|
||||
memcpy(c->file, e->data, e->size);
|
||||
c->file[e->size] = 0;
|
||||
if (sane_forbidden_path(c->file, sane_name_veto) &&
|
||||
sane_allowed_path(c->file, sane_name_ok))
|
||||
{
|
||||
client_upload_new(c);
|
||||
}
|
||||
else client_upload_fail(c);
|
||||
}
|
||||
else client_upload_fail(c);
|
||||
break;
|
||||
case M_UP_DATA:
|
||||
// e->data == chunk of bytes to append
|
||||
if ((e->size > 0) && (e->size <= 10000))
|
||||
{
|
||||
client_upload_data(c, e->data, e->size);
|
||||
}
|
||||
else client_upload_fail(c);
|
||||
break;
|
||||
case M_UP_END:
|
||||
// e->data == ignored (EOF)
|
||||
client_upload_end(c);
|
||||
break;
|
||||
case M_QRY_LIST:
|
||||
// e->data == category (none if all)
|
||||
break;
|
||||
case M_QRY_SEARCH:
|
||||
// e->data == query string
|
||||
break;
|
||||
case M_QRY_GET:
|
||||
if ((e->size > 0) && (e->size < 1000))
|
||||
{
|
||||
char *name = malloc(e->size + 1);
|
||||
if (name)
|
||||
{
|
||||
memcpy(name, e->data, e->size);
|
||||
name[e->size] = 0;
|
||||
client_send(c, name);
|
||||
free(name);
|
||||
}
|
||||
}
|
||||
// e->data == appname (Terminology, Rage etc.)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_exe_cb_del(void *data, int type, void *event)
|
||||
{
|
||||
Ecore_Exe_Event_Del *ev = event;
|
||||
Client *c = client_exe_find(ev->exe);
|
||||
if (c)
|
||||
{
|
||||
if (ev->exit_code == 0)
|
||||
ecore_ipc_client_send(c->client, 10, M_UP_OK, 0, 0, 0, NULL, 0);
|
||||
else
|
||||
ecore_ipc_client_send(c->client, 10, M_UP_FAIL, 0, 0, 0, NULL, 0);
|
||||
c->exe = NULL;
|
||||
}
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
ipc_init(void)
|
||||
{
|
||||
ipc = ecore_ipc_server_add(ECORE_IPC_REMOTE_SYSTEM, "0.0.0.0", 10077, NULL);
|
||||
if (!ipc) return 0;
|
||||
ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_ADD, _ipc_cb_add, NULL);
|
||||
ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_DEL, _ipc_cb_del, NULL);
|
||||
ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_DATA, _ipc_cb_dat, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
printf("usage:\n"
|
||||
" mrk-srv /path/to/repo\n"
|
||||
"\n");
|
||||
exit(1);
|
||||
}
|
||||
eina_init();
|
||||
ecore_init();
|
||||
eet_init();
|
||||
ecore_file_init();
|
||||
ecore_ipc_init();
|
||||
|
||||
if (argc > 1) repodir = ecore_file_realpath(argv[1]);
|
||||
|
||||
if (ipc_init())
|
||||
{
|
||||
ecore_exe_run_priority_set(10);
|
||||
ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _exe_cb_del, NULL);
|
||||
ecore_main_loop_begin();
|
||||
}
|
||||
|
||||
ecore_ipc_shutdown();
|
||||
ecore_file_shutdown();
|
||||
eet_shutdown();
|
||||
ecore_shutdown();
|
||||
eina_shutdown();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue