summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2014-10-25 18:34:14 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2014-10-25 18:34:14 +0900
commit9c3cb5a9f51a5ebafda287fefcb277e7051442f8 (patch)
treefe07d31a33332cd54b6b4e8220e2b9f0d7968c1b
parent01af8bc9c0fb31bda347a62409b2b40d0a2ad9b5 (diff)
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.
-rwxr-xr-xbuild.sh4
-rw-r--r--mrk.c1853
-rw-r--r--mrklib.c162
-rw-r--r--mrklib.h143
-rw-r--r--mrklib_buildfile.c711
-rw-r--r--mrklib_index.c302
-rw-r--r--mrklib_package.c281
-rw-r--r--mrklib_priv.h99
-rw-r--r--mrklib_repodb.c338
-rw-r--r--mrklib_serv.c425
-rw-r--r--mrklib_svc.c489
-rw-r--r--mrklib_util.c95
-rw-r--r--old/mrk-db.h (renamed from mrk-db.h)0
-rw-r--r--old/mrk-index.c (renamed from mrk-index.c)0
-rw-r--r--old/mrk-proto.h (renamed from mrk-proto.h)0
-rw-r--r--old/mrk-srv.c (renamed from mrk-srv.c)0
-rw-r--r--old/mrk.c1757
17 files changed, 5036 insertions, 1623 deletions
diff --git a/build.sh b/build.sh
index 7b17756..90bde3d 100755
--- a/build.sh
+++ b/build.sh
@@ -1,4 +1,2 @@
1#!/bin/sh 1#!/bin/sh
2gcc mrk.c -o mrk `pkg-config --cflags --libs eina ecore ecore-file ecore-ipc eet` 2gcc mrklib*.c mrk.c -o mrk `pkg-config --cflags --libs eina ecore ecore-file ecore-ipc eet`
3gcc mrk-srv.c -o mrk-srv `pkg-config --cflags --libs eina ecore ecore-ipc ecore-file eet`
4gcc mrk-index.c -o mrk-index `pkg-config --cflags --libs eina ecore ecore-ipc ecore-file eet`
diff --git a/mrk.c b/mrk.c
index 23b4595..88c2d0d 100644
--- a/mrk.c
+++ b/mrk.c
@@ -1,1595 +1,136 @@
1/*
2gcc mrk.c -o mrk `pkg-config --cflags --libs eina ecore-file eet`
3 */
4// note that this code is far from clean or nice at all. it's not very robust
5// but it works for the purposes of a proof of concept and getting things off
6// the ground - so please judge it by that for now
7#include <stdio.h> 1#include <stdio.h>
8#include <stdlib.h> 2#include <stdlib.h>
9#include <string.h> 3#include <string.h>
10#include <unistd.h> 4#include <unistd.h>
11#include <sys/stat.h>
12#include <Eina.h> 5#include <Eina.h>
13#include <Ecore.h> 6#include <Ecore.h>
14#include <Ecore_File.h> 7#include <Ecore_File.h>
15#include <Ecore_Ipc.h>
16#include <Eet.h>
17 8
18#include "mrk-proto.h" 9#include "mrklib.h"
19 10
20typedef enum 11#define _mrk_err(args...) do { fprintf(stderr, ##args); exit(-1); } while (0)
21{
22 TMODE_EOL,
23 TMODE_PATH,
24 TMODE_TEXT,
25 TMODE_PATH_CP,
26 TMODE_PATH_CP_LIST,
27 TMODE_PATH_LIST,
28} Tag_Mode;
29
30typedef struct
31{
32 const char *tag;
33 Tag_Mode mode;
34} Tag_Type;
35
36typedef struct
37{
38 char *bin;
39 Eina_List *srcs;
40 Eina_List *deps;
41 Eina_List *incs;
42} Build_Bin;
43
44typedef struct
45{
46 char *src;
47 char *dest;
48} Build_Data;
49 12
50typedef struct 13static const char *server_host = "devs.enlightenment.org";
51{ 14static int server_port = 10077;
52 char *name; 15static const char *build_tmpdir = "Marrakesh";
53 char *icon; 16static const char *arch = NULL;
54 char *brief; 17static const char *os = NULL;
55 char *version;
56 char *license;
57 char *domain;
58 char *repo;
59 char *devrepo;
60 char *contact;
61 Eina_List *tags;
62 Eina_List *categories;
63 Eina_List *copying;
64 char *needs;
65 Eina_List *bins;
66 Eina_List *data;
67 Eina_List *desktops;
68 Eina_List *icons;
69 Eina_List *po;
70} Build;
71 18
72 19static Eina_Bool move_to_cwd = EINA_FALSE;
73static const Tag_Type tags[] = 20static Eina_Bool install_bin = EINA_FALSE;
74{
75 {"PROJ:", TMODE_EOL},
76 {"PROJICON:", TMODE_PATH},
77 {"BRIEF:", TMODE_TEXT},
78 {"VERSION:", TMODE_EOL},
79 {"LICENSE:", TMODE_EOL},
80 {"COPYING:", TMODE_PATH_LIST},
81 {"NEEDS:", TMODE_EOL},
82 {"DOMAIN:", TMODE_PATH},
83 {"REPO:", TMODE_EOL},
84 {"DEVREPO:", TMODE_EOL},
85 {"CONTACT:", TMODE_TEXT},
86 {"CATEGORY:", TMODE_PATH_LIST},
87 {"TAGS:", TMODE_PATH_LIST},
88 {"BIN:", TMODE_PATH},
89 {"SRC:", TMODE_PATH_LIST},
90 {"DEPS:", TMODE_PATH_LIST},
91 {"INC:", TMODE_PATH_LIST},
92 {"DATA:", TMODE_PATH_CP_LIST},
93 {"DESKTOP:", TMODE_PATH_LIST},
94 {"ICON:", TMODE_PATH_LIST},
95 {"PODOMAIN:", TMODE_PATH},
96 {"PO:", TMODE_PATH_LIST},
97 {NULL, 0} // END OF LIST
98};
99
100static Build build = { 0 };
101static char *tmpd = "Marrakesh";
102static const char *sane_name_veto[] = {"../", "./", "/", NULL};
103static const char *sane_name_ok = "01234567890-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ. ";
104static const char *sane_path_veto[] = {"../", "./", NULL};
105static const char *sane_path_ok = "01234567890-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ. ";
106static char *server = "devs.enlightenment.org";
107static int server_port = 10077;
108static char *arch = ARCH;
109static char *os = OS;
110 21
111static void 22static void
112err(char *msg) 23_cb_connect(void *data, Mrk *server)
113{
114 fprintf(stderr, "ERROR: %s\n", msg);
115 exit(1);
116}
117
118static int
119sane_forbidden_path(const char *file, const char **forbidden)
120{
121 int i;
122
123 for (i = 0; forbidden[i]; i++)
124 {
125 if (strstr(forbidden[i], file)) return 0;
126 }
127 return 1;
128}
129
130static int
131sane_allowed_path(const char *file, const char *allowed)
132{ 24{
133 int i, j;
134
135 for (i = 0; file[i]; i++)
136 {
137 int ok;
138
139 ok = 0;
140 for (j = 0; allowed[j]; j++)
141 {
142 if (file[i] == allowed[j])
143 {
144 ok = 1;
145 break;
146 }
147 }
148 if (!ok) return 0;
149 }
150 return 1;
151}
152
153static char *
154parse_token(char **p, char *end)
155{
156 char *tok, *seg;
157
158 while ((*p < end) && (isspace(**p))) (*p)++;
159 if (*p >= end) return NULL;
160 tok = *p;
161
162 while (*p < end)
163 {
164 if (isspace(**p)) goto token;
165 (*p)++;
166 }
167token:
168 seg = malloc(*p - tok + 1);
169 if (!seg) return NULL;
170 memcpy(seg, tok, *p - tok);
171 seg[*p - tok] = 0;
172 return seg;
173}
174
175static char *
176parse_eol(char **p, char *end)
177{
178 char *tok, *seg;
179
180 while ((*p < end) && (isspace(**p))) (*p)++;
181 if (*p >= end) return NULL;
182 tok = *p;
183
184 while (*p < end)
185 {
186 if (**p == '\n') goto token;
187 (*p)++;
188 }
189token:
190 seg = malloc(*p - tok + 1);
191 if (!seg) return NULL;
192 memcpy(seg, tok, *p - tok);
193 seg[*p - tok] = 0;
194 return seg;
195}
196
197static char *
198path_check(char *tok)
199{
200 // XXX: check me
201 return strdup(tok);
202}
203
204static int
205parse_content(char *mem, size_t size)
206{
207 char prevc = '\n';
208 char *end = mem + size;
209 char *p = mem;
210 int skipline = 0;
211 int startline = 0;
212 char *seg = NULL, *s;
213 char *data1 = NULL, *data2 = NULL;
214 int i;
215 Tag_Mode mode = TMODE_TEXT;
216
217 while (p < end)
218 {
219 if (prevc == '\n')
220 {
221 if (*p == '#') skipline = 1;
222 else skipline = 0;
223 startline = 1;
224 }
225 if (!skipline)
226 {
227 char *tok;
228 char *prevp;
229
230 prevp = p;
231 tok = parse_token(&p, end);
232 if (!tok) return 1;
233 if (startline)
234 {
235 for (i = 0; tags[i].tag; i++)
236 {
237 if (!strcmp(tok, tags[i].tag))
238 {
239// printf("#: %s\n", tok);
240 free(seg);
241 seg = strdup(tok);
242 mode = tags[i].mode;
243 break;
244 }
245 }
246 if (!tags[i].tag) goto not_tag;
247 }
248 else
249 {
250not_tag:
251 switch (mode)
252 {
253 case TMODE_EOL:
254 case TMODE_TEXT:
255 // prse eol of prevp
256 p = prevp;
257 data1 = parse_eol(&p, end);
258 if (!data1) err("no content");
259 break;
260 case TMODE_PATH:
261 case TMODE_PATH_LIST:
262 // sanitize (check) path tok put into data1
263 data1 = path_check(tok);
264 if (!data1) err("path invalid");
265 break;
266 case TMODE_PATH_CP:
267 case TMODE_PATH_CP_LIST:
268 // sanitize path, then next token > then path 2 -> data1, data2
269 data1 = path_check(tok);
270 if (!data1) err("path invalid");
271 s = parse_token(&p, end);
272 if (!s) err("missing > in path copy");
273 if (!(!strcmp(s, ">"))) err("copy token is not >");
274 free(s);
275 s = parse_token(&p, end);
276 if (!s) err("missing destination path in path copy");
277 data2 = path_check(s);
278 if (!data2) err("destination path not valid");
279 free(s);
280 break;
281 default:
282 break;
283 }
284// if (data2)
285// printf(" %i> %s '%s' '%s'\n",
286// mode, seg, data1, data2);
287// else
288// printf(" %i> %s '%s'\n",
289// mode, seg, data1);
290 if (seg)
291 {
292 if (!strcmp(seg, "PROJ:"))
293 {
294 if (!(sane_forbidden_path(data1, sane_name_veto) &&
295 sane_allowed_path(data1, sane_name_ok)))
296 err("name failed sanity check");
297 free(build.name);
298 build.name = strdup(data1);
299 }
300 else if (!strcmp(seg, "PROJICON:"))
301 {
302 free(build.icon);
303 build.icon = strdup(data1);
304 }
305 else if (!strcmp(seg, "BRIEF:"))
306 {
307 if (!build.brief) build.brief = strdup(data1);
308 else
309 {
310 s = malloc(strlen(build.brief) + 1 + strlen(data1) + 1);
311 if (s)
312 {
313 strcpy(s, build.brief);
314 strcat(s, " ");
315 strcat(s, data1);
316 free(build.brief);
317 build.brief = s;
318 }
319 }
320 }
321 else if (!strcmp(seg, "VERSION:"))
322 {
323 free(build.version);
324 build.version = strdup(data1);
325 }
326 else if (!strcmp(seg, "LICENSE:"))
327 {
328 free(build.license);
329 build.license = strdup(data1);
330 }
331 else if (!strcmp(seg, "COPYING:"))
332 {
333 build.copying = eina_list_append(build.copying,
334 strdup(data1));
335 }
336 else if (!strcmp(seg, "NEEDS:"))
337 {
338 free(build.needs);
339 build.license = strdup(data1);
340 }
341 else if (!strcmp(seg, "DOMAIN:"))
342 {
343 free(build.domain);
344 build.domain = strdup(data1);
345 }
346 else if (!strcmp(seg, "REPO:"))
347 {
348 free(build.repo);
349 build.repo = strdup(data1);
350 }
351 else if (!strcmp(seg, "DEVREPO:"))
352 {
353 free(build.devrepo);
354 build.devrepo = strdup(data1);
355 }
356 else if (!strcmp(seg, "CATEGORY:"))
357 {
358 build.categories = eina_list_append(build.categories,
359 strdup(data1));
360 }
361 else if (!strcmp(seg, "TAGS:"))
362 {
363 build.tags = eina_list_append(build.tags,
364 strdup(data1));
365 }
366 else if (!strcmp(seg, "CONTACT:"))
367 {
368 if (!build.contact) build.contact = strdup(data1);
369 else
370 {
371 s = malloc(strlen(build.contact) + 1 + strlen(data1) + 1);
372 if (s)
373 {
374 strcpy(s, build.contact);
375 strcat(s, " ");
376 strcat(s, data1);
377 free(build.contact);
378 build.contact = s;
379 }
380 }
381 }
382 else if (!strcmp(seg, "BIN:"))
383 {
384 Build_Bin *build_bin = calloc(1, sizeof(Build_Bin));
385 if (build_bin)
386 {
387 build_bin->bin = strdup(data1);
388 build.bins = eina_list_append(build.bins,
389 build_bin);
390 }
391 }
392 else if (!strcmp(seg, "SRC:"))
393 {
394 Build_Bin *build_bin = eina_list_data_get(eina_list_last(build.bins));
395 if (build_bin)
396 {
397 build_bin->srcs = eina_list_append(build_bin->srcs,
398 strdup(data1));
399 }
400 }
401 else if (!strcmp(seg, "DEPS:"))
402 {
403 Build_Bin *build_bin = eina_list_data_get(eina_list_last(build.bins));
404 if (build_bin)
405 {
406 build_bin->deps = eina_list_append(build_bin->deps,
407 strdup(data1));
408 }
409 }
410 else if (!strcmp(seg, "INC:"))
411 {
412 Build_Bin *build_bin = eina_list_data_get(eina_list_last(build.bins));
413 if (build_bin)
414 {
415 build_bin->incs = eina_list_append(build_bin->incs,
416 strdup(data1));
417 }
418 }
419 else if (!strcmp(seg, "DATA:"))
420 {
421 Build_Data *build_data = calloc(1, sizeof(Build_Data));
422 if (build_data)
423 {
424 build_data->src = strdup(data1);
425 build_data->dest = strdup(data2);
426 build.data = eina_list_append(build.data,
427 build_data);
428 }
429 }
430 else if (!strcmp(seg, "DESKTOP:"))
431 {
432 build.desktops = eina_list_append(build.desktops,
433 strdup(data1));
434 }
435 else if (!strcmp(seg, "ICON:"))
436 {
437 build.icons = eina_list_append(build.icons,
438 strdup(data1));
439 }
440 else if (!strcmp(seg, "PO:"))
441 {
442 build.po = eina_list_append(build.po,
443 strdup(data1));
444 }
445 }
446 free(data1);
447 free(data2);
448 data1 = NULL;
449 data2 = NULL;
450 }
451 free(tok);
452 prevc = *p;
453 }
454 else
455 {
456 prevc = *p;
457 p++;
458 }
459 startline = 0;
460 }
461 return 1;
462}
463
464static int
465parse_bld(const char *file)
466{
467 Eina_File *ef;
468 char *mem;
469 size_t size;
470 int ret;
471
472 ef = eina_file_open(file, EINA_FALSE);
473 if (!ef) return 0;
474
475 size = eina_file_size_get(ef);
476 mem = eina_file_map_all(ef, EINA_FILE_SEQUENTIAL);
477 if ((size == 0) || (!mem)) return 0;
478
479 ret = parse_content(mem, size);
480
481 eina_file_close(ef);
482 return ret;
483}
484
485static int
486build_proj(void)
487{
488 Eina_List *l, *ll;
489 Build_Bin *bin;
490 Build_Data *data;
491 Eina_Strbuf *buf;
492 char *s, *extn, *s2;
493 char tmp[4096];
494 char tmp2[4096];
495 const char *ss, *cc;
496
497 EINA_LIST_FOREACH(build.po, l, s)
498 {
499 snprintf(tmp, sizeof(tmp), "%s/share/locale/%s/LC_MESSAGES/", tmpd, s);
500 ecore_file_mkpath(tmp);
501 snprintf(tmp2, sizeof(tmp2), "po/%s.gmo", s);
502 snprintf(tmp, sizeof(tmp), "%s/share/locale/%s/LC_MESSAGES/%s.mo", tmpd, s, build.domain);
503 ecore_file_cp(tmp2, tmp);
504 }
505 EINA_LIST_FOREACH(build.data, l, data)
506 {
507 s = ecore_file_dir_get(data->dest);
508 if (s)
509 {
510 snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, s);
511 ecore_file_mkpath(tmp);
512 free(s);
513 }
514 snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, data->dest);
515 ecore_file_cp(data->src, tmp);
516 }
517 snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, "share/applications");
518 ecore_file_mkpath(tmp);
519 EINA_LIST_FOREACH(build.desktops, l, s)
520 {
521 ss = ecore_file_file_get(s);
522 if (!(!strncmp(ss, build.domain, strlen(build.domain))))
523 err("destkop file wrong domain");
524 snprintf(tmp, sizeof(tmp), "%s/share/applications/%s", tmpd, ss);
525 ecore_file_cp(s, tmp);
526 }
527 snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, "share/icons");
528 ecore_file_mkpath(tmp);
529 EINA_LIST_FOREACH(build.icons, l, s)
530 {
531 ss = ecore_file_file_get(s);
532 if (!(!strncmp(ss, build.domain, strlen(build.domain))))
533 err("icon file wrong domain");
534 snprintf(tmp, sizeof(tmp), "%s/share/icons/%s", tmpd, ss);
535 ecore_file_cp(s, tmp);
536 }
537 EINA_LIST_FOREACH(build.copying, l, s)
538 {
539 if (strchr(s, '/'))
540 {
541 s2 = ecore_file_dir_get(s);
542 snprintf(tmp, sizeof(tmp), "%s/share/licenses/%s", tmpd, s2);
543 free(s2);
544 }
545 else
546 snprintf(tmp, sizeof(tmp), "%s/share/licenses", tmpd);
547 ecore_file_mkpath(tmp);
548 snprintf(tmp, sizeof(tmp), "%s/share/licenses/%s", tmpd, s);
549 ecore_file_cp(s, tmp);
550 }
551 EINA_LIST_FOREACH(build.bins, l, bin)
552 {
553 if ((buf = eina_strbuf_new()))
554 {
555 s = ecore_file_dir_get(bin->bin);
556 if (s)
557 {
558 snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, s);
559 ecore_file_mkpath(tmp);
560 free(s);
561 }
562 cc = getenv("CC");
563 if (!cc) cc = "gcc";
564 eina_strbuf_append(buf, cc);
565 eina_strbuf_append(buf, " -I. -lm -o ");
566 eina_strbuf_append(buf, tmpd);
567 eina_strbuf_append(buf, "/");
568 eina_strbuf_append(buf, bin->bin);
569
570 eina_strbuf_append(buf, " -DLOCALEDIR=\\\"/tmp/X/share/locale\\\"");
571 eina_strbuf_append(buf, " -DPACKAGE_BIN_DIR=\\\"/tmp/X/bin\\\"");
572 eina_strbuf_append(buf, " -DPACKAGE_LIB_DIR=\\\"/tmp/X/lib\\\"");
573 eina_strbuf_append(buf, " -DPACKAGE_DATA_DIR=\\\"/tmp/X/share/");
574 eina_strbuf_append(buf, build.domain);
575 eina_strbuf_append(buf, "\\\"");
576
577 eina_strbuf_append(buf, " -DPACKAGE_NAME=\\\"");
578 eina_strbuf_append(buf, build.domain);
579 eina_strbuf_append(buf, "\\\"");
580
581 eina_strbuf_append(buf, " -DPACKAGE_VERSION=\\\"");
582 eina_strbuf_append(buf, build.version);
583 eina_strbuf_append(buf, "\\\"");
584
585 eina_strbuf_append(buf, " -D_REENTRANT -DHAVE_CONFIG_H -pthread ");
586 eina_strbuf_append(buf, " $CFLAGS ");
587
588 EINA_LIST_FOREACH(bin->srcs, ll, s)
589 {
590 extn = strrchr(s, '.');
591 if ((extn) && (!strcasecmp(extn, ".c")))
592 {
593 eina_strbuf_append(buf, s);
594 eina_strbuf_append(buf, " ");
595 }
596 }
597 EINA_LIST_FOREACH(bin->deps, ll, s)
598 {
599 eina_strbuf_append(buf, " `pkg-config --cflags --libs ");
600 eina_strbuf_append(buf, s);
601 eina_strbuf_append(buf, "` ");
602 }
603 EINA_LIST_FOREACH(bin->incs, ll, s)
604 {
605 eina_strbuf_append(buf, " -I");
606 eina_strbuf_append(buf, s);
607 eina_strbuf_append(buf, " ");
608 }
609 s = (char *)eina_strbuf_string_get(buf);
610 if (s) system(s);
611 eina_strbuf_free(buf);
612 }
613 }
614 return 1;
615} 25}
616 26
617static void 27static void
618package_file(Eet_File *ef, const char *file, const char *key) 28_cb_disconnect(void *data, Mrk *server)
619{ 29{
620 Eina_File *enf = eina_file_open(file, EINA_FALSE); 30 _mrk_err("Disconnect\n");
621 if (enf)
622 {
623 void *mem = eina_file_map_all(enf, EINA_FILE_SEQUENTIAL);
624 if (mem)
625 {
626 size_t size = eina_file_size_get(enf);
627 eet_write(ef, key, mem, size, EET_COMPRESSION_VERYFAST);
628 }
629 eina_file_close(enf);
630 }
631} 31}
632 32
633static void 33static void
634package_bin_iter(Eet_File *ef, const char *dir, const char *key) 34_cb_upload_begin(void *data, Mrk *server)
635{ 35{
636 Eina_List *files; 36 printf("[");
637 Eina_File *enf; 37 fflush(stdout);
638 char *s;
639 char tmp[4096];
640 char tmp2[4096];
641
642 files = ecore_file_ls(dir);
643 EINA_LIST_FREE(files, s)
644 {
645 if (!strcmp(s, ".")) continue;
646 else if (!strcmp(s, "..")) continue;
647 snprintf(tmp, sizeof(tmp), "%s/%s", dir, s);
648 snprintf(tmp2, sizeof(tmp2), "%s/%s", key, s);
649 if (ecore_file_is_dir(tmp))
650 {
651 if (ecore_file_can_exec(tmp)) tmp2[4] = 'D';
652 package_bin_iter(ef, tmp, tmp2);
653 }
654 else
655 {
656 if (ecore_file_can_exec(tmp)) tmp2[4] = 'X';
657 else tmp2[4] = 'f';
658 package_file(ef, tmp, tmp2);
659 }
660 free(s);
661 }
662} 38}
663 39
664static int 40static void
665pakage_bin(void) 41_cb_upload_progress(void *data, Mrk *server, double pos)
666{
667 Eet_File *ef;
668 char tmp[4096];
669 Eina_List *l;
670 char *s;
671 int i;
672
673 snprintf(tmp, sizeof(tmp), "%s-%s.mkb", build.name, build.version);
674 ef = eet_open(tmp, EET_FILE_MODE_WRITE);
675 if (ef)
676 {
677#define WRTS(key, var) \
678 if (var) eet_write(ef, key, var, strlen(var), EET_COMPRESSION_VERYFAST)
679 WRTS("name", build.name);
680 if (build.icon) package_file(ef, build.icon, "icon");
681 WRTS("brief", build.brief);
682 WRTS("version", build.version);
683 WRTS("license", build.license);
684 WRTS("repo", build.repo);
685 WRTS("devrepo", build.devrepo);
686 WRTS("contact", build.contact);
687 WRTS("needs", build.needs);
688 snprintf(tmp, sizeof(tmp), "%s-%s", os, arch);
689 WRTS("arch", tmp);
690 i = 0;
691 EINA_LIST_FOREACH(build.tags, l, s)
692 {
693 snprintf(tmp, sizeof(tmp), "tag/%i", i++);
694 WRTS(tmp, s);
695 }
696 i = 0;
697 EINA_LIST_FOREACH(build.categories, l, s)
698 {
699 snprintf(tmp, sizeof(tmp), "category/%i", i++);
700 WRTS(tmp, s);
701 }
702 package_bin_iter(ef, tmpd, "bin/f");
703 eet_close(ef);
704 return 1;
705 }
706 return 0;
707}
708
709static int
710pakage_src(const char *file)
711{
712 Eet_File *ef;
713 char tmp[4096];
714 char tmp2[4096];
715
716 snprintf(tmp, sizeof(tmp), "%s-%s.mks", build.name, build.version);
717 ef = eet_open(tmp, EET_FILE_MODE_WRITE);
718 if (ef)
719 {
720 Eina_File *enf;
721 Eina_List *l, *ll;
722 void *mem;
723 size_t size;
724 char *s;
725 Build_Bin *bin;
726 Build_Data *data;
727
728 enf = eina_file_open(file, EINA_FALSE);
729 if (!enf) err("can't open build file");
730 mem = eina_file_map_all(enf, EINA_FILE_SEQUENTIAL);
731 if (!mem) err("can't map build file");
732 size = eina_file_size_get(enf);
733 eet_write(ef, "buildinfo", mem, size, EET_COMPRESSION_VERYFAST);
734 eina_file_close(enf);
735
736 EINA_LIST_FOREACH(build.copying, l, s)
737 {
738 snprintf(tmp, sizeof(tmp), "src/%s", s);
739 package_file(ef, s, tmp);
740 }
741 EINA_LIST_FOREACH(build.desktops, l, s)
742 {
743 snprintf(tmp, sizeof(tmp), "src/%s", s);
744 package_file(ef, s, tmp);
745 }
746 EINA_LIST_FOREACH(build.icons, l, s)
747 {
748 snprintf(tmp, sizeof(tmp), "src/%s", s);
749 package_file(ef, s, tmp);
750 }
751 EINA_LIST_FOREACH(build.po, l, s)
752 {
753 snprintf(tmp2, sizeof(tmp2), "po/%s.gmo", s);
754 snprintf(tmp, sizeof(tmp), "src/po/%s.gmo", s);
755 package_file(ef, tmp2, tmp);
756 }
757 EINA_LIST_FOREACH(build.bins, l, bin)
758 {
759 EINA_LIST_FOREACH(bin->srcs, ll, s)
760 {
761 snprintf(tmp, sizeof(tmp), "src/%s", s);
762 package_file(ef, s, tmp);
763 }
764 }
765 EINA_LIST_FOREACH(build.data, l, data)
766 {
767 snprintf(tmp, sizeof(tmp), "src/%s", data->src);
768 package_file(ef, data->src, tmp);
769 }
770 eet_close(ef);
771 return 1;
772 }
773 return 0;
774}
775
776static int
777write_file(Eet_File *ef, const char *key, const char *file)
778{
779 FILE *f;
780 void *mem;
781 int size;
782 char *s;
783
784 mem = eet_read(ef, key, &size);
785 if (mem)
786 {
787 s = ecore_file_dir_get(file);
788 if (s)
789 {
790 ecore_file_mkpath(s);
791 free(s);
792 }
793 f = fopen(file, "wb");
794 if (f)
795 {
796 fwrite(mem, size, 1, f);
797 fclose(f);
798 return 1;
799 }
800 }
801 err("file write failed");
802 return 0;
803}
804
805static int
806package_extract(const char *file)
807{ 42{
808 Eet_File *ef; 43 printf("%1.02f_", pos);
809 44 fflush(stdout);
810 ef = eet_open(file, EET_FILE_MODE_READ);
811 if (ef)
812 {
813 int i, num = 0;
814 char **keys = eet_list(ef, "src/*", &num);
815
816 if (keys)
817 {
818 for (i = 0; i < num; i++)
819 {
820 if (!strncmp(keys[i], "src/", 4))
821 {
822 if (!sane_forbidden_path(keys[i], sane_path_veto)) continue;
823 write_file(ef, keys[i], &(keys[i][4]));
824 }
825 }
826 }
827 write_file(ef, "buildinfo", "Marrakesh.mrk");
828 eet_close(ef);
829 return 1;
830 }
831 err("file does not open");
832 return 0;
833} 45}
834 46
835static char * 47static void
836read_string(Eet_File *ef, const char *key) 48_cb_upload_end(void *data, Mrk *server)
837{ 49{
838 int size = 0; 50 printf("]\n");
839 char *str; 51 fflush(stdout);
840 char *s = eet_read(ef, key, &size);
841 if (!s) return NULL;
842 str = malloc(size + 1);
843 if (!str)
844 {
845 free(s);
846 return NULL;
847 }
848 memcpy(str, s, size);
849 str[size] = 0;
850 free(s);
851 return str;
852} 52}
853 53
854static void 54static void
855clean_symlinks(const char *dir) 55_cb_upload_success(void *data, Mrk *server, Eina_Bool success)
856{ 56{
857 Eina_List *files; 57 if (!success) _mrk_err("Upload Failed\n");
858 char *s, *ss; 58 ecore_main_loop_quit();
859 char tmp[4096];
860
861 files = ecore_file_ls(dir);
862 EINA_LIST_FREE(files, s)
863 {
864 snprintf(tmp, sizeof(tmp), "%s/%s", dir, s);
865 ss = ecore_file_readlink(tmp);
866 if (ss)
867 {
868 free(ss);
869 if (!ecore_file_exists(tmp))
870 {
871 printf("clean '%s'\n", tmp);
872 ecore_file_unlink(tmp);
873 }
874 }
875 free(s);
876 }
877} 59}
878 60
879static int 61static void
880field_copy(Eet_File *ef, Eet_File *ef2, const char *key) 62_cb_download_begin(void *data, Mrk *server)
881{ 63{
882 int size = 0; 64 printf("[");
883 char *s = eet_read(ef, key, &size); 65 fflush(stdout);
884 if (s)
885 {
886 eet_write(ef2, key, s, size, EET_COMPRESSION_VERYFAST);
887 free(s);
888 return 1;
889 }
890 return 0;
891} 66}
892 67
893static const char * 68static void
894get_home(void) 69_cb_download_progress(void *data, Mrk *server, double pos)
895{ 70{
896 static char buf[4096] = ""; 71 printf("%1.02f_", pos);
897 const char *tmps, *home; 72 fflush(stdout);
898
899 if (buf[0]) return buf;
900 tmps = getenv("XDG_DATA_HOME");
901 home = getenv("HOME");
902 if (!home) home = "/tmp";
903 if (tmps) snprintf(buf, sizeof(buf), "%s", tmps);
904 else snprintf(buf, sizeof(buf), "%s", home);
905 return buf;
906} 73}
907 74
908static int 75static void
909package_clean(void) 76_cb_download_end(void *data, Mrk *server)
910{ 77{
911 char tmp[4096]; 78 printf("]\n");
912 79 fflush(stdout);
913 snprintf(tmp, sizeof(tmp), "%s/.local/share/icons", get_home());
914 clean_symlinks(tmp);
915 snprintf(tmp, sizeof(tmp), "%s/.local/share/applications", get_home());
916 clean_symlinks(tmp);
917 snprintf(tmp, sizeof(tmp), "%s/Applications/.bin", get_home());
918 clean_symlinks(tmp);
919 return 1;
920} 80}
921 81
922static int 82static void
923package_install(const char *file) 83_cb_download_success(void *data, Mrk *server, const char *file)
924{ 84{
925 Eet_File *ef, *ef2; 85 if (!file) _mrk_err("Download Failed\n");
926 86 if (move_to_cwd)
927 ef = eet_open(file, EET_FILE_MODE_READ);
928 if (ef)
929 { 87 {
930 int i, num = 0; 88 const char *fname = ecore_file_file_get(file);
931 char **keys = eet_list(ef, "bin/*", &num); 89 char tmp[PATH_MAX], wd[PATH_MAX];
932 char inst[4096];
933 char dir[4096];
934 char tmp[4096];
935 char tmp2[4096];
936 char *s;
937 Eina_List *files;
938 char *name;
939 90
940 name = read_string(ef, "name"); 91 if (fname)
941 if (!name) err("no name");
942 if (!(sane_forbidden_path(name, sane_name_veto) &&
943 sane_allowed_path(name, sane_name_ok)))
944 err("name failed sanity check");
945 snprintf(tmp, sizeof(tmp), "%s/Applications/.bin", get_home());
946 ecore_file_mkpath(tmp);
947 snprintf(inst, sizeof(inst), "%s/Applications/%s", get_home(), name);
948 if (ecore_file_exists(inst)) err("destination already exists");
949 ecore_file_mkpath(inst);
950 if (keys)
951 {
952 for (i = 0; i < num; i++)
953 {
954 if (!strncmp(keys[i], "bin/", 4))
955 {
956 if (!sane_forbidden_path(keys[i], sane_path_veto)) continue;
957 snprintf(tmp, sizeof(tmp), "%s/%s", inst, &(keys[i][6]));
958 write_file(ef, keys[i], tmp);
959 if (keys[i][4] == 'X')
960 {
961 printf("+x '%s'\n", &(keys[i][6]));
962 chmod(tmp, 00500);
963 }
964 }
965 }
966 }
967 snprintf(dir, sizeof(dir), "%s/share/icons", inst);
968 files = ecore_file_ls(dir);
969 EINA_LIST_FREE(files, s)
970 {
971 if (!strcmp(s, ".")) continue;
972 else if (!strcmp(s, "..")) continue;
973 snprintf(tmp, sizeof(tmp), "../../../Applications/%s/share/icons/%s", name, s);
974 snprintf(tmp2, sizeof(tmp2), "%s/.local/share/icons/%s", get_home(), s);
975 if (ecore_file_exists(tmp2)) err("icon file symlink already exists");
976 ecore_file_symlink(tmp, tmp2);
977 free(s);
978 }
979 snprintf(dir, sizeof(dir), "%s/share/applications", inst);
980 files = ecore_file_ls(dir);
981 EINA_LIST_FREE(files, s)
982 {
983 if (!strcmp(s, ".")) continue;
984 else if (!strcmp(s, "..")) continue;
985 snprintf(tmp, sizeof(tmp), "../../../Applications/%s/share/applications/%s", name, s);
986 snprintf(tmp2, sizeof(tmp2), "%s/.local/share/applications/%s", get_home(), s);
987 if (ecore_file_exists(tmp2)) err("desktop file symlink already exists");
988 ecore_file_symlink(tmp, tmp2);
989 free(s);
990 }
991 snprintf(dir, sizeof(dir), "%s/bin", inst);
992 files = ecore_file_ls(dir);
993 EINA_LIST_FREE(files, s)
994 { 92 {
995 if (!strcmp(s, ".")) continue; 93 if (ecore_file_exists(fname)) _mrk_err("File: '%s' exists in ./\n", fname);
996 else if (!strcmp(s, "..")) continue; 94 if (getcwd(wd, sizeof(wd)))
997 snprintf(tmp, sizeof(tmp), "../%s/bin/%s", name, s);
998 snprintf(tmp2, sizeof(tmp2), "%s/Applications/.bin/%s", get_home(), s);
999 if (ecore_file_exists(tmp2)) err("bin file symlink already exists");
1000 ecore_file_symlink(tmp, tmp2);
1001 free(s);
1002 }
1003 snprintf(tmp, sizeof(tmp), "%s/Applications/%s/.icon.png", get_home(), name);
1004 write_file(ef, "icon", tmp);
1005 snprintf(tmp, sizeof(tmp), "%s/Applications/%s/.info.mki", get_home(), name);
1006 ef2 = eet_open(tmp, EET_FILE_MODE_WRITE);
1007 free(name);
1008 if (ef2)
1009 {
1010 field_copy(ef, ef2, "name");
1011 field_copy(ef, ef2, "brief");
1012 field_copy(ef, ef2, "version");
1013 field_copy(ef, ef2, "license");
1014 field_copy(ef, ef2, "repo");
1015 field_copy(ef, ef2, "devrepo");
1016 field_copy(ef, ef2, "contact");
1017 field_copy(ef, ef2, "needs");
1018 for (i = 0; i < 9999; i++)
1019 {
1020 snprintf(tmp, sizeof(tmp), "tag/%i", i);
1021 if (!field_copy(ef, ef2, tmp)) break;
1022 }
1023 for (i = 0; i < 9999; i++)
1024 { 95 {
1025 snprintf(tmp, sizeof(tmp), "category/%i", i); 96 snprintf(tmp, sizeof(tmp), "%s/%s", wd, fname);
1026 if (!field_copy(ef, ef2, tmp)) break; 97 ecore_file_mv(file, tmp);
1027 } 98 }
1028 eet_close(ef2);
1029 } 99 }
1030 eet_close(ef);
1031 return 1;
1032 } 100 }
1033 err("file does not open"); 101 else if (install_bin)
1034 return 0;
1035}
1036
1037static int
1038package_remove(const char *name)
1039{
1040 char tmp[4096];
1041
1042 snprintf(tmp, sizeof(tmp), "%s/Applications/%s", get_home(), name);
1043 if (!ecore_file_recursive_rm(tmp)) return 0;
1044 return 1;
1045}
1046
1047static Ecore_Ipc_Server *ipc = NULL;
1048static char *up_file = NULL;
1049static char *up_path = NULL;
1050
1051static Eina_Bool
1052_ipc_cb_add(void *data, int type, void *event)
1053{
1054 Ecore_Ipc_Event_Server_Add *e = event;
1055 FILE *f;
1056
1057 char tmp[4096];
1058
1059 snprintf(tmp, sizeof(tmp), "%s-%s", os, arch);
1060 ecore_ipc_server_send(ipc, 10, M_ID_ARCH, 0, 0, 0,
1061 tmp, strlen(tmp));
1062 snprintf(tmp, sizeof(tmp), "%i.%i.%i",
1063 eina_version->major, eina_version->minor, eina_version->micro);
1064 ecore_ipc_server_send(ipc, 10, M_ID_VERSION, 0, 0, 0,
1065 tmp, strlen(tmp));
1066 f = fopen(up_path, "rb");
1067 if (f)
1068 { 102 {
1069 char buf[10000]; 103 if (!mrk_package_bin_install(file)) _mrk_err("Failed to install\n");
1070 size_t size; 104 if (!mrk_package_bin_clean()) _mrk_err("Failed to clean\n");
1071 105 ecore_file_unlink(file);
1072 ecore_ipc_server_send(ipc, 10, M_UP_START, 0, 0, 0,
1073 up_file, strlen(up_file));
1074 for (;;)
1075 {
1076 size = fread(buf, 1, 10000, f);
1077 if (size > 0)
1078 ecore_ipc_server_send(ipc, 10, M_UP_DATA, 0, 0, 0,
1079 buf, size);
1080 else break;
1081 }
1082 ecore_ipc_server_send(ipc, 10, M_UP_END, 0, 0, 0,
1083 NULL, 0);
1084 fclose(f);
1085 } 106 }
1086 return EINA_TRUE;
1087}
1088
1089static Eina_Bool
1090_ipc_cb_del(void *data, int type, void *event)
1091{
1092 Ecore_Ipc_Event_Server_Del *e = event;
1093 err("disconnect...");
1094 ecore_main_loop_quit(); 107 ecore_main_loop_quit();
1095 return EINA_TRUE;
1096} 108}
1097 109
1098static Eina_Bool 110static void
1099_ipc_cb_dat(void *data, int type, void *event) 111_cb_answer_begin(void *data, Mrk *server)
1100{
1101 Ecore_Ipc_Event_Server_Data *e = event;
1102 if (e->major == 10)
1103 {
1104 if (e->minor == M_UP_OK)
1105 {
1106 printf("OK\n");
1107 ecore_main_loop_quit();
1108 }
1109 else if (e->minor == M_UP_FAIL)
1110 {
1111 printf("FAIL\n");
1112 err("upload rejected");
1113 }
1114 }
1115 return EINA_TRUE;
1116}
1117
1118static int
1119package_up(const char *file)
1120{
1121 ipc = ecore_ipc_server_connect(ECORE_IPC_REMOTE_SYSTEM, server, server_port, NULL);
1122 if (!ipc) return 0;
1123 ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_ADD, _ipc_cb_add, NULL);
1124 ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DEL, _ipc_cb_del, NULL);
1125 ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DATA, _ipc_cb_dat, NULL);
1126 up_path = strdup(file);
1127 up_file = strdup(ecore_file_file_get(file));
1128 ecore_main_loop_begin();
1129 return 1;
1130}
1131
1132static char *down_name = NULL;
1133static char *down_file = NULL;
1134static FILE *down_f = NULL;
1135
1136static Eina_Bool
1137_ipc2_cb_add(void *data, int type, void *event)
1138{
1139 Ecore_Ipc_Event_Server_Add *e = event;
1140 char tmp[4096];
1141
1142 snprintf(tmp, sizeof(tmp), "%s-%s", os, arch);
1143 ecore_ipc_server_send(ipc, 10, M_ID_ARCH, 0, 0, 0,
1144 tmp, strlen(tmp));
1145 snprintf(tmp, sizeof(tmp), "%i.%i.%i",
1146 eina_version->major, eina_version->minor, eina_version->micro);
1147 ecore_ipc_server_send(ipc, 10, M_ID_VERSION, 0, 0, 0,
1148 tmp, strlen(tmp));
1149 ecore_ipc_server_send(ipc, 10, M_QRY_GET, 0, 0, 0,
1150 down_name, strlen(down_name));
1151 return EINA_TRUE;
1152}
1153
1154static Eina_Bool
1155_ipc2_cb_del(void *data, int type, void *event)
1156{
1157 Ecore_Ipc_Event_Server_Del *e = event;
1158 err("disconnect...");
1159 ecore_main_loop_quit();
1160 return EINA_TRUE;
1161}
1162
1163static Eina_Bool
1164_ipc2_cb_dat(void *data, int type, void *event)
1165{
1166 Ecore_Ipc_Event_Server_Data *e = event;
1167 if (e->major == 10)
1168 {
1169 switch (e->minor)
1170 {
1171 case M_DOWN_START:
1172 if ((e->size > 0) && (e->size <= 1000) && (e->data))
1173 {
1174 char *file = malloc(e->size + 1);
1175 if (file)
1176 {
1177 memcpy(file, e->data, e->size);
1178 file[e->size] = 0;
1179 if ((sane_forbidden_path(file, sane_name_veto) &&
1180 sane_allowed_path(file, sane_name_ok)))
1181 {
1182 if (!down_f)
1183 {
1184 char tmp[4096];
1185
1186 down_file = file;
1187 snprintf(tmp, sizeof(tmp),
1188 "%s/Applications/.tmp",
1189 getenv("HOME"));
1190 ecore_file_mkpath(tmp);
1191 snprintf(tmp, sizeof(tmp),
1192 "%s/Applications/.tmp/%s",
1193 getenv("HOME"), down_file);
1194 if (ecore_file_exists(tmp))
1195 err("file already exists");
1196 down_f = fopen(file, "wb");
1197 printf("%s\n", file);
1198 }
1199 else err("already have download");
1200 }
1201 else err("mangled filename");
1202 }
1203 else err("download file not sane");
1204 }
1205 else err("no such package");
1206 break;
1207 case M_DOWN_DATA:
1208 if ((down_f) && (e->data) && (e->size > 0) && (e->size <= 10000))
1209 {
1210 fwrite(e->data, e->size, 1, down_f);
1211 }
1212 break;
1213 case M_DOWN_END:
1214 if (down_f)
1215 {
1216 fclose(down_f);
1217 down_f = NULL;
1218 ecore_main_loop_quit();
1219 }
1220 break;
1221 default:
1222 break;
1223 }
1224 }
1225 return EINA_TRUE;
1226}
1227
1228static int
1229package_down(const char *name)
1230{
1231 ipc = ecore_ipc_server_connect(ECORE_IPC_REMOTE_SYSTEM, server, server_port, NULL);
1232 if (!ipc) return 0;
1233 ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_ADD, _ipc2_cb_add, NULL);
1234 ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DEL, _ipc2_cb_del, NULL);
1235 ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DATA, _ipc2_cb_dat, NULL);
1236 down_name = strdup(name);
1237 ecore_main_loop_begin();
1238 return 1;
1239}
1240
1241static char *downsrc_name = NULL;
1242static char *downsrc_file = NULL;
1243static FILE *downsrc_f = NULL;
1244
1245static Eina_Bool
1246_ipc3_cb_add(void *data, int type, void *event)
1247{
1248 Ecore_Ipc_Event_Server_Add *e = event;
1249 char tmp[4096];
1250
1251 snprintf(tmp, sizeof(tmp), "%s-%s", os, arch);
1252 ecore_ipc_server_send(ipc, 10, M_ID_ARCH, 0, 0, 0,
1253 tmp, strlen(tmp));
1254 snprintf(tmp, sizeof(tmp), "%i.%i.%i",
1255 eina_version->major, eina_version->minor, eina_version->micro);
1256 ecore_ipc_server_send(ipc, 10, M_ID_VERSION, 0, 0, 0,
1257 tmp, strlen(tmp));
1258 ecore_ipc_server_send(ipc, 10, M_QRY_GETSRC, 0, 0, 0,
1259 downsrc_name, strlen(downsrc_name));
1260 return EINA_TRUE;
1261}
1262
1263static Eina_Bool
1264_ipc3_cb_del(void *data, int type, void *event)
1265{
1266 Ecore_Ipc_Event_Server_Del *e = event;
1267 err("disconnect...");
1268 ecore_main_loop_quit();
1269 return EINA_TRUE;
1270}
1271
1272static Eina_Bool
1273_ipc3_cb_dat(void *data, int type, void *event)
1274{
1275 Ecore_Ipc_Event_Server_Data *e = event;
1276 if (e->major == 10)
1277 {
1278 switch (e->minor)
1279 {
1280 case M_SRC_START:
1281 if ((e->size > 0) && (e->size <= 1000) && (e->data))
1282 {
1283 char *file = malloc(e->size + 1);
1284 if (file)
1285 {
1286 memcpy(file, e->data, e->size);
1287 file[e->size] = 0;
1288 if ((sane_forbidden_path(file, sane_name_veto) &&
1289 sane_allowed_path(file, sane_name_ok)))
1290 {
1291 if (!downsrc_f)
1292 {
1293 char tmp[4096];
1294
1295 downsrc_file = file;
1296 snprintf(tmp, sizeof(tmp),
1297 "%s/Applications/.tmp",
1298 getenv("HOME"));
1299 ecore_file_mkpath(tmp);
1300 snprintf(tmp, sizeof(tmp),
1301 "%s/Applications/.tmp/%s",
1302 getenv("HOME"), downsrc_file);
1303 if (ecore_file_exists(tmp))
1304 err("file already exists");
1305 downsrc_f = fopen(file, "wb");
1306 printf("%s\n", file);
1307 }
1308 else err("already have download");
1309 }
1310 else err("mangled filename");
1311 }
1312 else err("download file not sane");
1313 }
1314 else err("no such package");
1315 break;
1316 case M_SRC_DATA:
1317 if ((downsrc_f) && (e->data) && (e->size > 0) && (e->size <= 10000))
1318 {
1319 fwrite(e->data, e->size, 1, downsrc_f);
1320 }
1321 break;
1322 case M_SRC_END:
1323 if (downsrc_f)
1324 {
1325 fclose(downsrc_f);
1326 downsrc_f = NULL;
1327 ecore_main_loop_quit();
1328 }
1329 break;
1330 default:
1331 break;
1332 }
1333 }
1334 return EINA_TRUE;
1335}
1336
1337static int
1338package_downsrc(const char *name)
1339{ 112{
1340 ipc = ecore_ipc_server_connect(ECORE_IPC_REMOTE_SYSTEM, server, server_port, NULL);
1341 if (!ipc) return 0;
1342 ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_ADD, _ipc3_cb_add, NULL);
1343 ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DEL, _ipc3_cb_del, NULL);
1344 ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DATA, _ipc3_cb_dat, NULL);
1345 downsrc_name = strdup(name);
1346 ecore_main_loop_begin();
1347 return 1;
1348} 113}
1349 114
1350static int qry_op = 0; 115static void
1351static char *qry_data; 116_cb_answer_progress(void *data, Mrk *server, const char *result)
1352
1353static Eina_Bool
1354_ipc4_cb_add(void *data, int type, void *event)
1355{ 117{
1356 Ecore_Ipc_Event_Server_Add *e = event; 118 printf("%s\n", result);
1357 char tmp[4096];
1358
1359 snprintf(tmp, sizeof(tmp), "%s-%s", os, arch);
1360 ecore_ipc_server_send(ipc, 10, M_ID_ARCH, 0, 0, 0,
1361 tmp, strlen(tmp));
1362 snprintf(tmp, sizeof(tmp), "%i.%i.%i",
1363 eina_version->major, eina_version->minor, eina_version->micro);
1364 ecore_ipc_server_send(ipc, 10, M_ID_VERSION, 0, 0, 0,
1365 tmp, strlen(tmp));
1366 ecore_ipc_server_send(ipc, 10, qry_op, 0, 0, 0,
1367 qry_data, qry_data ? strlen(qry_data) : 0);
1368 return EINA_TRUE;
1369} 119}
1370 120
1371static Eina_Bool 121static void
1372_ipc4_cb_del(void *data, int type, void *event) 122_cb_answer_end(void *data, Mrk *server)
1373{ 123{
1374 Ecore_Ipc_Event_Server_Del *e = event;
1375 err("disconnect...");
1376 ecore_main_loop_quit(); 124 ecore_main_loop_quit();
1377 return EINA_TRUE;
1378}
1379
1380static Eina_Bool
1381_ipc4_cb_dat(void *data, int type, void *event)
1382{
1383 Ecore_Ipc_Event_Server_Data *e = event;
1384 if (e->major == 10)
1385 {
1386 switch (e->minor)
1387 {
1388 case M_ANS_START:
1389 break;
1390 case M_ANS_DATA:
1391 if ((e->data) && (e->size > 0) && (e->size <= 10000))
1392 {
1393 fwrite(e->data, e->size, 1, stdout);
1394 fwrite("\n", 1, 1, stdout);
1395 }
1396 break;
1397 case M_ANS_END:
1398 if (qry_data) free(qry_data);
1399 qry_data = NULL;
1400 ecore_main_loop_quit();
1401 break;
1402 default:
1403 break;
1404 }
1405 }
1406 return EINA_TRUE;
1407}
1408
1409static int
1410package_qry(int op, const char *opdat)
1411{
1412 ipc = ecore_ipc_server_connect(ECORE_IPC_REMOTE_SYSTEM, server, server_port, NULL);
1413 if (!ipc) return 0;
1414 ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_ADD, _ipc4_cb_add, NULL);
1415 ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DEL, _ipc4_cb_del, NULL);
1416 ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DATA, _ipc4_cb_dat, NULL);
1417 qry_op = op;
1418 if (opdat) qry_data = strdup(opdat);
1419 ecore_main_loop_begin();
1420 return 1;
1421}
1422
1423static int
1424package_file_isbin(const char *file)
1425{
1426 const char *p;
1427
1428 p = strchr(file, '.');
1429 if (p)
1430 {
1431 if (!strcasecmp(p, ".png")) return 1;
1432 if (!strcasecmp(p, ".jpg")) return 1;
1433 if (!strcasecmp(p, ".edj")) return 1;
1434 if (!strcasecmp(p, ".gif")) return 1;
1435 if (!strcasecmp(p, ".bmp")) return 1;
1436 }
1437 return 0;
1438}
1439
1440static Eina_Bool
1441string_rep(const Eina_Hash *hash, const void *key, void *data, void *fdata)
1442{
1443 eina_strbuf_replace_all(fdata, key, data);
1444 return EINA_TRUE;
1445}
1446
1447static int
1448package_dir_dup(const char *src, const char *dst, Eina_Hash *vars)
1449{
1450 char tmp[4096];
1451 char tmp2[4096];
1452 Eina_Strbuf *dstsbuf;
1453
1454 dstsbuf = eina_strbuf_new();
1455 if (!dstsbuf) return 0;
1456 eina_strbuf_append(dstsbuf, dst);
1457 eina_hash_foreach(vars, string_rep, dstsbuf);
1458 if (ecore_file_is_dir(src))
1459 {
1460 Eina_List *files;
1461 char *s;
1462
1463 ecore_file_mkdir(eina_strbuf_string_get(dstsbuf));
1464 files = ecore_file_ls(src);
1465 EINA_LIST_FREE(files, s)
1466 {
1467 if (s[0] != '.')
1468 {
1469 snprintf(tmp, sizeof(tmp), "%s/%s", src, s);
1470 snprintf(tmp2, sizeof(tmp2), "%s/%s", eina_strbuf_string_get(dstsbuf), s);
1471 package_dir_dup(tmp, tmp2, vars);
1472 }
1473 free(s);
1474 }
1475 }
1476 else
1477 {
1478 if (package_file_isbin(src))
1479 ecore_file_cp(src, eina_strbuf_string_get(dstsbuf));
1480 else
1481 {
1482 FILE *fsrc, *fdst;
1483
1484 fsrc = fopen(src, "rb");
1485 fdst = fopen(eina_strbuf_string_get(dstsbuf), "wb");
1486 if ((fsrc) && (fdst))
1487 {
1488 long size;
1489
1490 fseek(fsrc, 0, SEEK_END);
1491 size = ftell(fsrc);
1492 fseek(fsrc, 0, SEEK_SET);
1493 if (size > 0)
1494 {
1495 char *buf = malloc(size + 1);
1496
1497 if (buf)
1498 {
1499 Eina_Strbuf *tmpsbuf;
1500
1501 tmpsbuf = eina_strbuf_new();
1502 if (tmpsbuf)
1503 {
1504 fread(buf, size, 1, fsrc);
1505 buf[size] = 0;
1506 eina_strbuf_append(tmpsbuf, buf);
1507 eina_hash_foreach(vars, string_rep, tmpsbuf);
1508 fwrite(eina_strbuf_string_get(tmpsbuf),
1509 eina_strbuf_length_get(tmpsbuf),
1510 1, fdst);
1511 eina_strbuf_free(tmpsbuf);
1512 }
1513 free(buf);
1514 }
1515 }
1516 }
1517 if (fsrc) fclose(fsrc);
1518 if (fdst) fclose(fdst);
1519 }
1520 }
1521 eina_strbuf_free(dstsbuf);
1522 return 1;
1523}
1524
1525static int
1526package_gen(const char *tmpldir, const char *tmpl, Eina_Hash *vars)
1527{
1528 char tmp[4096];
1529 char tmp2[4096];
1530 const char *domain;
1531
1532 domain = eina_hash_find(vars, "@APPDOM@");
1533 ecore_file_mkdir(domain);
1534 snprintf(tmp, sizeof(tmp), "%s/apps/%s", tmpldir, tmpl);
1535 package_dir_dup(tmp, domain, vars);
1536 snprintf(tmp, sizeof(tmp), "%s/licenses/%s",
1537 tmpldir, eina_hash_find(vars, "@APPCOPY@"));
1538 snprintf(tmp2, sizeof(tmp2), "%s/COPYING", domain);
1539 ecore_file_cp(tmp, tmp2);
1540}
1541
1542static int
1543package_new(void)
1544{
1545 Eina_Hash *vars = eina_hash_string_superfast_new(NULL);
1546 char tmp[4096];
1547
1548 if (!vars) return 0;
1549 printf("App Name: (e.g. Hello)\n");
1550 if (scanf("%500s", tmp) <= 0) return 0;
1551 eina_hash_add(vars, "@APPNAME@", eina_stringshare_add(tmp));
1552 printf("App Domain: (e.g. hello)\n");
1553 if (scanf("%500s", tmp) <= 0) return 0;
1554 eina_hash_add(vars, "@APPDOM@", eina_stringshare_add(tmp));
1555 printf("App Version: (e.g. 1.0.0)\n");
1556 if (scanf("%150s", tmp) <= 0) return 0;
1557 eina_hash_add(vars, "@APPVER@", eina_stringshare_add(tmp));
1558 printf("App License: (e.g. BSD-2 | GPL2 | APACHE | GPL3)\n");
1559 if (scanf("%20s", tmp) <= 0) return 0;
1560 eina_hash_add(vars, "@APPCOPY@", eina_stringshare_add(tmp));
1561 printf("App Brief Description: (1 line)\n");
1562 if (scanf("%400s", tmp) <= 0) return 0;
1563 eina_hash_add(vars, "@APPDESC@", eina_stringshare_add(tmp));
1564 printf("App Categories: (e.g. media)\n");
1565 if (scanf("%1000s", tmp) <= 0) return 0;
1566 eina_hash_add(vars, "@APPCATEGORIES@", eina_stringshare_add(tmp));
1567 printf("App Tags: (e.g. video audio media film movies music player)\n");
1568 if (scanf("%4000s", tmp) <= 0) return 0;
1569 eina_hash_add(vars, "@APPTAGS@", eina_stringshare_add(tmp));
1570 printf("Developer Name + E-Mail: Bob Jones <bob@bob.com>\n");
1571 if (scanf("%1000s", tmp) <= 0) return 0;
1572 eina_hash_add(vars, "@DEVMAIL@", eina_stringshare_add(tmp));
1573 printf("App EFL Minimum Version: (e.g. 1.11)\n");
1574 if (scanf("%50s", tmp) <= 0) return 0;
1575 eina_hash_add(vars, "@EFLVER@", eina_stringshare_add(tmp));
1576 package_gen("/home/raster/C/marrakesh/tmpl", "default", vars);
1577 return 1;
1578} 125}
1579 126
1580int 127int
1581main(int argc, char **argv) 128main(int argc, char **argv)
1582{ 129{
1583 char *s;
1584
1585 eina_init();
1586 eet_init();
1587 ecore_ipc_init();
1588 ecore_file_init();
1589 if (argc < 2) 130 if (argc < 2)
1590 { 131 {
1591 printf("sub commands:\n" 132 printf("mrk sub commands:\n"
1592 " new\n" 133// " new\n"
1593 " build\n" 134 " build\n"
1594 " bin\n" 135 " bin\n"
1595 " check\n" 136 " check\n"
@@ -1598,160 +139,232 @@ main(int argc, char **argv)
1598 " inst FILE\n" 139 " inst FILE\n"
1599 " rm PKGNAME\n" 140 " rm PKGNAME\n"
1600 " rel [FILE]\n" 141 " rel [FILE]\n"
142 " clean\n"
1601 " down PKGNAME\n" 143 " down PKGNAME\n"
1602 " get PKGNAME\n" 144 " get PKGNAME\n"
1603 " getsrc PKGNAME\n" 145 " getsrc PKGNAME\n"
1604 " clean\n"
1605 " list [CATEGORY]\n" 146 " list [CATEGORY]\n"
1606 " search KEY1 [KEY2] [KEY3] [...]\n" 147 " search KEY1 [KEY2] [KEY3] [...]\n"
148 " server REPODIR BUILDSCRIPT\n"
149 " index DIR1 [DIR2] [DIR3] [...]\n"
1607 "\n"); 150 "\n");
1608 return -1; 151 return -1;
1609 } 152 }
153 eina_init();
154 ecore_init();
155 mrk_init();
1610 156
1611 s = getenv("DESTDIR"); 157 os = mrk_os_get();
1612 if (s) tmpd = s; 158 arch = mrk_arch_get();
1613 159
1614 if (getenv("MRKHOST")) server = getenv("MRKHOST"); 160 if (getenv("MRKHOST")) server_host = getenv("MRKHOST");
1615 if (getenv("MRKPORT")) server_port = atoi(getenv("MRKPORT")); 161 if (getenv("MRKPORT")) server_port = atoi(getenv("MRKPORT"));
1616 if (getenv("MRKARCH")) arch = getenv("MRKARCH"); 162 if (getenv("MRKARCH")) arch = getenv("MRKARCH");
1617 if (getenv("MRKOS")) os = getenv("MRKOS"); 163 if (getenv("MRKOS")) os = getenv("MRKOS");
164 if (getenv("MRKDIR")) build_tmpdir = getenv("MRKDIR");
1618 165
1619 if (!strcmp(argv[1], "build")) 166 if (!strcmp(argv[1], "build"))
1620 { 167 {
1621 if (!parse_bld("Marrakesh.mrk")) return 1; 168 Mrk_Build *bld = mrk_build_load("Marrakesh.mrk");
1622 if (!build_proj()) return 1; 169 if (!bld) _mrk_err("Failed to load Marrakesh.mrk\n");
170 if (!mrk_build_do(bld, build_tmpdir))
171 {
172 mrk_build_free(bld);
173 _mrk_err("Failed to build Marrakesh.mrk\n");
174 }
175 mrk_build_free(bld);
1623 } 176 }
1624 else if (!strcmp(argv[1], "src")) 177 else if (!strcmp(argv[1], "src"))
1625 { 178 {
1626 if (!parse_bld("Marrakesh.mrk")) return 1; 179 char tmp[4096];
1627 if (!pakage_src("Marrakesh.mrk")) return 1; 180 Mrk_Build *bld = mrk_build_load("Marrakesh.mrk");
181 if (!bld) _mrk_err("Failed to load Marrakesh.mrk\n");
182 snprintf(tmp, sizeof(tmp), "%s-%s.mks", bld->name, bld->version);
183 if (!mrk_build_package_src(bld, "Marrakesh.mrk", tmp))
184 {
185 mrk_build_free(bld);
186 _mrk_err("Failed to package up source\n");
187 }
188 mrk_build_free(bld);
1628 } 189 }
1629 else if (!strcmp(argv[1], "bin")) 190 else if (!strcmp(argv[1], "bin"))
1630 { 191 {
1631 if (!parse_bld("Marrakesh.mrk")) return 1; 192 char tmp[4096];
1632 if (!pakage_bin()) return 1; 193 Mrk_Build *bld = mrk_build_load("Marrakesh.mrk");
194 if (!bld) _mrk_err("Failed to load Marrakesh.mrk\n");
195 snprintf(tmp, sizeof(tmp), "%s-%s.mkb", bld->name, bld->version);
196 if (!mrk_build_package_bin(bld, tmp, build_tmpdir, os, arch))
197 {
198 mrk_build_free(bld);
199 _mrk_err("Failed to package up binary\n");
200 }
201 mrk_build_free(bld);
1633 } 202 }
1634 else if (!strcmp(argv[1], "extract")) 203 else if (!strcmp(argv[1], "extract"))
1635 { 204 {
1636 if (argc < 3) err("need file to extract"); 205 if (argc < 2) _mrk_err("Must provide FILE.MKS\n");
1637 if (!package_extract(argv[2])) return 1; 206 if (!mrk_package_src_extract(argv[2], "./")) _mrk_err("Failed to extract\n");
1638 } 207 }
1639 else if (!strcmp(argv[1], "inst")) 208 else if (!strcmp(argv[1], "inst"))
1640 { 209 {
1641 if (argc < 3) err("need file to install"); 210 if (argc < 2) _mrk_err("Must provide FILE.MKB\n");
1642 package_clean(); 211 if (!mrk_package_bin_install(argv[2])) _mrk_err("Failed to install\n");
1643 if (!package_install(argv[2])) return 1; 212 if (!mrk_package_bin_clean()) _mrk_err("Failed to clean\n");
1644 } 213 }
1645 else if (!strcmp(argv[1], "clean")) 214 else if (!strcmp(argv[1], "clean"))
1646 { 215 {
1647 package_clean(); 216 if (!mrk_package_bin_clean()) _mrk_err("Failed to clean\n");
1648 } 217 }
1649 else if (!strcmp(argv[1], "rm")) 218 else if (!strcmp(argv[1], "rm"))
1650 { 219 {
1651 if (argc < 3) err("need package to remove"); 220 if (argc < 2) _mrk_err("Must provide PACKAGENAME\n");
1652 if (!package_remove(argv[2])) return 1; 221 if (!mrk_package_bin_remove(argv[2])) _mrk_err("Failed to remove\n");
1653 package_clean(); 222 if (!mrk_package_bin_clean()) _mrk_err("Failed to clean\n");
1654 } 223 }
1655 else if (!strcmp(argv[1], "rel")) 224 else if (!strcmp(argv[1], "new"))
225 {
226 }
227 else if (!strcmp(argv[1], "check"))
1656 { 228 {
229 Mrk_Build *bld;
1657 char tmp[4096]; 230 char tmp[4096];
1658 char *pk;
1659 231
1660 if (argc < 3) 232 ecore_file_recursive_rm("Marrakesh-Check");
233 ecore_file_mkdir("Marrakesh-Check");
234 bld = mrk_build_load("Marrakesh.mrk");
235 if (!bld) _mrk_err("Failed to load Marrakesh.mrk\n");
236 if (!mrk_build_do(bld, build_tmpdir))
1661 { 237 {
1662 printf("making src...\n"); 238 mrk_build_free(bld);
1663 if (!parse_bld("Marrakesh.mrk")) return 1; 239 _mrk_err("Failed to build Marrakesh.mrk\n");
1664 if (!pakage_src("Marrakesh.mrk")) return 1;
1665 snprintf(tmp, sizeof(tmp), "%s-%s.mks", build.name, build.version);
1666 pk = tmp;
1667 } 240 }
1668 else pk = argv[2]; 241 snprintf(tmp, sizeof(tmp), "%s-%s.mks", bld->name, bld->version);
1669 printf("upload + build...\n"); 242 if (!mrk_build_package_src(bld, "Marrakesh.mrk", tmp))
1670 if (!package_up(pk)) return 1; 243 {
1671 } 244 mrk_build_free(bld);
1672 else if (!strcmp(argv[1], "down")) 245 _mrk_err("Failed to package up source\n");
1673 { 246 }
1674 if (argc < 3) err("need package to download"); 247 snprintf(tmp, sizeof(tmp), "%s-%s.mkb", bld->name, bld->version);
1675 if (!package_down(argv[2])) return 1; 248 if (!mrk_build_package_bin(bld, tmp, build_tmpdir, os, arch))
249 {
250 mrk_build_free(bld);
251 _mrk_err("Failed to package up binary\n");
252 }
253 mrk_build_free(bld);
1676 } 254 }
1677 else if (!strcmp(argv[1], "get")) 255 else if (!strcmp(argv[1], "index"))
1678 { 256 {
1679 if (argc < 3) err("need package to get"); 257 int i;
1680 if (!package_down(argv[2])) return 1; 258
1681 if (!down_file) err("no download"); 259 for (i = 2; i < argc; i++) mrk_index(argv[i]);
1682 package_remove(argv[2]);
1683 package_clean();
1684 if (!package_install(down_file)) return 1;
1685 ecore_file_unlink(down_file);
1686 } 260 }
1687 else if (!strcmp(argv[1], "list")) 261 else if (!strcmp(argv[1], "server"))
1688 { 262 {
1689 if (argc < 3) package_qry(M_QRY_LIST, NULL); 263 Mrk_Serve *serve;
1690 else package_qry(M_QRY_LIST, argv[2]); 264
265 if (argc < 3) _mrk_err("Must provide REPODIR BUILDSCRIPT as arguments\n");
266 serve = mrk_serve(NULL, server_port, argv[2], argv[3]);
267 ecore_main_loop_begin();
268 mrk_unserve(serve);
1691 } 269 }
1692 else if (!strcmp(argv[1], "search")) 270 else
1693 { 271 {
1694 if (argc < 3) err("need search strings"); 272 static Mrk *server;
1695 else 273
1696 { 274 server = mrk_connect(server_host, server_port);
1697 int i; 275 if (server)
1698 int len = 0; 276 {
1699 char *ts; 277
1700 278 mrk_callback_connect_set(server,
1701 for (i = 2; i < argc; i++) 279 _cb_connect, NULL,
280 _cb_disconnect, NULL);
281 mrk_callback_upload_set(server,
282 _cb_upload_begin, NULL,
283 _cb_upload_progress, NULL,
284 _cb_upload_end, NULL,
285 _cb_upload_success, NULL);
286 mrk_callback_download_set(server,
287 _cb_download_begin, NULL,
288 _cb_download_progress, NULL,
289 _cb_download_end, NULL,
290 _cb_download_success, NULL);
291 mrk_callback_answer_set(server,
292 _cb_answer_begin, NULL,
293 _cb_answer_progress, NULL,
294 _cb_answer_end, NULL);
295
296 if (!strcmp(argv[1], "down"))
297 {
298 if (argc < 2) _mrk_err("Must provide PKGNAME as argument\n");
299 move_to_cwd = EINA_TRUE;
300 mrk_download(server, argv[2]);
301 }
302 else if (!strcmp(argv[1], "get"))
303 {
304 install_bin = EINA_TRUE;
305 if (argc < 2) _mrk_err("Must provide PKGNAME as argument\n");
306 move_to_cwd = EINA_TRUE;
307 mrk_download(server, argv[2]);
308 }
309 else if (!strcmp(argv[1], "rel"))
310 {
311 // XXX: src THEN upload
312 char tmp[4096];
313 Mrk_Build *bld = mrk_build_load("Marrakesh.mrk");
314 if (!bld) _mrk_err("Failed to load Marrakesh.mrk\n");
315 snprintf(tmp, sizeof(tmp), "%s-%s.mks", bld->name, bld->version);
316 if (!mrk_build_package_src(bld, "Marrakesh.mrk", tmp))
317 {
318 mrk_build_free(bld);
319 _mrk_err("Failed to package up source\n");
320 }
321 mrk_build_free(bld);
322 mrk_upload(server, tmp);
323 }
324 else if (!strcmp(argv[1], "list"))
1702 { 325 {
1703 len += strlen(argv[i]); 326 if (argc < 2) mrk_list(server, NULL);
1704 len++; 327 else mrk_list(server, argv[2]);
1705 } 328 }
1706 ts = malloc(len); 329 else if (!strcmp(argv[1], "search"))
1707 if (ts)
1708 { 330 {
1709 ts[0] = 0; 331 int i;
332 int len = 0;
333 char *ts;
334
335 if (argc < 2) _mrk_err("Must provide 1 or more keys as aruments\n");
1710 for (i = 2; i < argc; i++) 336 for (i = 2; i < argc; i++)
1711 { 337 {
1712 strcat(ts, argv[i]); 338 len += strlen(argv[i]);
1713 if (i < (argc - 1)) strcat(ts, " "); 339 len++;
340 }
341 ts = malloc(len);
342 if (ts)
343 {
344 ts[0] = 0;
345 for (i = 2; i < argc; i++)
346 {
347 strcat(ts, argv[i]);
348 if (i < (argc - 1)) strcat(ts, " ");
349 }
350 mrk_search(server, ts);
351 free(ts);
1714 } 352 }
1715 package_qry(M_QRY_SEARCH, ts);
1716 free(ts);
1717 } 353 }
354 else if (!strcmp(argv[1], "getsrc"))
355 {
356 if (argc < 2) _mrk_err("Must provide PKGNAME as argument\n");
357 move_to_cwd = EINA_TRUE;
358 mrk_download_source(server, argv[2]);
359 }
360 ecore_main_loop_begin();
361 mrk_disconnect(server);
1718 } 362 }
363 else _mrk_err("Cannot connect\n");
1719 } 364 }
1720 else if (!strcmp(argv[1], "new")) 365
1721 { 366 mrk_shutdown();
1722 package_new(); 367 ecore_shutdown();
1723 }
1724 else if (!strcmp(argv[1], "getsrc"))
1725 {
1726 if (argc < 3) err("need package to download");
1727 if (!package_downsrc(argv[2])) return 1;
1728 }
1729 else if (!strcmp(argv[1], "check"))
1730 {
1731 char tmp[4096];
1732 ecore_file_recursive_rm("Marrakesh-Check");
1733 ecore_file_mkdir("Marrakesh-Check");
1734 if (!parse_bld("Marrakesh.mrk")) err("Parse build failed");
1735 if (!pakage_src("Marrakesh.mrk")) err("Source packaging failed");
1736 chdir("Marrakesh-Check");
1737 snprintf(tmp, sizeof(tmp), "../%s-%s.mks", build.name, build.version);
1738 if (!package_extract(tmp)) err("Source extract failed");
1739 memset(&build, 0, sizeof(Build));
1740 if (!parse_bld("Marrakesh.mrk")) err("Parse build 2 from source failed");
1741 if (!build_proj()) err("Build project failed");
1742 memset(&build, 0, sizeof(Build));
1743 if (!parse_bld("Marrakesh.mrk")) err("Parse build 3 failed");
1744 if (!pakage_bin()) err("Package binary failed");
1745 printf("OK\n");
1746 }
1747 else
1748 {
1749 err("unknown subcommand!");
1750 return 1;
1751 }
1752 ecore_file_shutdown();
1753 ecore_ipc_shutdown();
1754 eet_shutdown();
1755 eina_shutdown(); 368 eina_shutdown();
1756 return 0; 369 return 0;
1757} 370}
diff --git a/mrklib.c b/mrklib.c
new file mode 100644
index 0000000..f9dd53f
--- /dev/null
+++ b/mrklib.c
@@ -0,0 +1,162 @@
1#include "mrklib_priv.h"
2
3const char *_mrk_server_host = MRK_SERVER_HOST;
4int _mrk_server_port = MRK_SERVER_PORT;
5const char *_mrk_appdir = NULL;
6const char *_mrk_appdir_tmp = NULL;
7const char *_mrk_appdir_bin = NULL;
8unsigned char *_mrk_uuid = NULL;
9int _mrk_uuid_len = 0;
10
11static int _mrk_init = 0;
12
13static void
14_entropy_get(unsigned char *dat, int len)
15{
16 int fd;
17 Eina_Bool ok = EINA_FALSE;
18
19 fd = open("/dev/random", O_RDONLY);
20 if (fd >= 0)
21 {
22 if (read(fd, dat, len) == len) ok = EINA_TRUE;
23 close(fd);
24 }
25 if (!ok)
26 {
27 struct timeval tv;
28 unsigned int seed = 0x12345678;
29 int i;
30
31 if (gettimeofday(&tv, NULL) == 0)
32 seed = ((tv.tv_sec << 16) | (tv.tv_sec >> 16)) ^ tv.tv_usec;
33 else
34 seed = (unsigned int)time(NULL);
35 srand(seed);
36 for (i = 0; i < len; i++) dat[i] = rand() & 0xff;
37 }
38}
39
40static void
41_mrk_config_new(const char *file)
42{
43 Eet_File *ef;
44 unsigned char uuid[32];
45 int uuid_len = sizeof(uuid);
46
47 ef = eet_open(file, EET_FILE_MODE_WRITE);
48 if (!ef) return;
49 _entropy_get(uuid, uuid_len);
50 eet_write(ef, "uuid", uuid, uuid_len, EET_COMPRESSION_VERYFAST);
51 eet_close(ef);
52}
53
54static void
55_mrk_config_init(const char *file)
56{
57 Eet_File *ef;
58 int len;
59
60 ef = eet_open(file, EET_FILE_MODE_READ);
61 if (!ef)
62 {
63 _mrk_config_new(file);
64 ef = eet_open(file, EET_FILE_MODE_READ);
65 }
66 if (!ef) return;
67 _mrk_uuid = eet_read(ef, "uuid", &len);
68 if ((!_mrk_uuid) || (len != 32))
69 {
70 free(_mrk_uuid);
71 _mrk_uuid = NULL;
72 eet_close(ef);
73 _mrk_config_new(file);
74 ef = eet_open(file, EET_FILE_MODE_READ);
75 if (!ef) return;
76 _mrk_uuid = eet_read(ef, "uuid", &len);
77 if ((!_mrk_uuid) || (len != 32))
78 {
79 free(_mrk_uuid);
80 _mrk_uuid = NULL;
81 eet_close(ef);
82 return;
83 }
84 }
85 _mrk_uuid_len = len;
86 eet_close(ef);
87}
88
89static void
90_mrk_appdir_init(void)
91{
92 char tmp[4096];
93 const char *home;
94
95 home = getenv("XDG_DATA_HOME");
96 if (!home) home = getenv("HOME");
97 if (!home) home = "/tmp";
98
99 snprintf(tmp, sizeof(tmp), "%s/Applications", home);
100 if (!ecore_file_exists(tmp)) ecore_file_mkdir(tmp);
101 _mrk_appdir = eina_stringshare_add(tmp);
102
103 snprintf(tmp, sizeof(tmp), "%s/Applications/.bin", home);
104 if (!ecore_file_exists(tmp)) ecore_file_mkdir(tmp);
105 _mrk_appdir_bin = eina_stringshare_add(tmp);
106
107 snprintf(tmp, sizeof(tmp), "%s/Applications/.tmp", home);
108 if (!ecore_file_exists(tmp)) ecore_file_mkdir(tmp);
109 _mrk_appdir_tmp = eina_stringshare_add(tmp);
110
111 snprintf(tmp, sizeof(tmp), "%s/Applications/.marrakesh.cfg", home);
112 _mrk_config_init(tmp);
113}
114
115EAPI Eina_Bool
116mrk_init(void)
117{
118 _mrk_init++;
119 if (_mrk_init == 1)
120 {
121 eina_init();
122 eet_init();
123 ecore_init();
124 ecore_ipc_init();
125 ecore_file_init();
126 _mrk_appdir_init();
127 }
128 return EINA_TRUE;
129}
130
131EAPI void
132mrk_shutdown(void)
133{
134 _mrk_init--;
135 if (_mrk_init == 0)
136 {
137 eina_stringshare_del(_mrk_appdir);
138 _mrk_appdir = NULL;
139 eina_stringshare_del(_mrk_appdir_bin);
140 _mrk_appdir_bin = NULL;
141 eina_stringshare_del(_mrk_appdir_tmp);
142 _mrk_appdir_tmp = NULL;
143 ecore_file_shutdown();
144 ecore_ipc_shutdown();
145 eet_shutdown();
146 ecore_shutdown();
147 eina_shutdown();
148 }
149}
150
151EAPI const char *
152mrk_arch_get(void)
153{
154 return ARCH;
155}
156
157EAPI const char *
158mrk_os_get(void)
159{
160 return OS;
161}
162
diff --git a/mrklib.h b/mrklib.h
new file mode 100644
index 0000000..ac87880
--- /dev/null
+++ b/mrklib.h
@@ -0,0 +1,143 @@
1#ifndef MRKLIB_H
2#define MRKLIB_H
3
4#include <Eina.h>
5
6EAPI Eina_Bool mrk_init(void);
7EAPI void mrk_shutdown(void);
8EAPI const char *mrk_arch_get(void);
9EAPI const char *mrk_os_get(void);
10
11// yes - this should become an eo object - later. right now... cleaning up
12// the mess that was putting the pipeline together
13
14// mrk client api - for clients that conne3ct to an mrk server to upload,
15// download, query etc. etc. the server - so the "main" set of api for a
16// client-server api. in future protocol should be extendable in api
17// below with sending extended requests and handling return data
18typedef struct _Mrk Mrk;
19
20EAPI Mrk *mrk_connect(const char *host, int port);
21EAPI void mrk_disconnect(Mrk *server);
22EAPI Eina_Bool mrk_upload(Mrk *server, const char *file);
23EAPI Eina_Bool mrk_download(Mrk *server, const char *package);
24EAPI Eina_Bool mrk_download_source(Mrk *server, const char *package);
25EAPI Eina_Bool mrk_list(Mrk *server, const char *category);
26EAPI Eina_Bool mrk_search(Mrk *server, const char *keys);
27EAPI void mrk_callback_connect_set(Mrk *server,
28 void (*connect) (void *data, Mrk *server),
29 void *connect_data,
30 void (*disconnect) (void *data, Mrk *server),
31 void *disconnect_data);
32EAPI void mrk_callback_upload_set(Mrk *server,
33 void (*upload_begin) (void *data, Mrk *server),
34 void *upload_begin_data,
35 void (*upload_progress) (void *data, Mrk *server, double pos),
36 void *upload_progress_data,
37 void (*upload_end) (void *data, Mrk *server),
38 void *upload_end_data,
39 void (*upload_success) (void *data, Mrk *server, Eina_Bool sucess),
40 void *upload_success_data);
41EAPI void mrk_callback_download_set(Mrk *server,
42 void (*download_begin) (void *data, Mrk *server),
43 void *download_begin_data,
44 void (*download_progress) (void *data, Mrk *server, double pos),
45 void *download_progress_data,
46 void (*download_end) (void *data, Mrk *server),
47 void *download_end_data,
48 void (*download_success) (void *data, Mrk *server, const char *file),
49 void *download_success_data);
50EAPI void mrk_callback_answer_set(Mrk *server,
51 void (*answer_begin) (void *data, Mrk *server),
52 void *answer_begin_data,
53 void (*answer_progress) (void *data, Mrk *server, const char *result),
54 void *answer_progress_data,
55 void (*answer_end) (void *data, Mrk *server),
56 void *answer_end_data);
57
58// api to run a mrk server - right now you have very little choice here
59// as everything is just magically handled internally - in future some way
60// to access the repodb that a serve loads (and auto-updates) as well as
61// get callbacks when things happen and also to extend protocol
62typedef struct _Mrk_Serve Mrk_Serve;
63
64EAPI Mrk_Serve *mrk_serve(const char *listen, int port, const char *repodir, const char *bldsh);
65EAPI void mrk_unserve(Mrk_Serve *server);
66
67// this is the api to deal with a repository database of files and to
68// request and update of them, auto-reload when update done and tell you
69// when it's done
70typedef struct _Mrk_Repodb Mrk_Repodb;
71
72EAPI Mrk_Repodb *mrk_repodb_load(const char *repodir);
73EAPI void mrk_repodb_free(Mrk_Repodb *rdb);
74EAPI void mrk_repodb_callback_update_set(Mrk_Repodb *rdb,
75 void (*update) (void *data, Mrk_Repodb *rdb),
76 void *update_data);
77EAPI void mrk_repodb_update(Mrk_Repodb *rdb);
78EAPI const Eina_List *mrk_repodb_category_list(Mrk_Repodb *rdb,
79 const char *arch,
80 const char *category);
81EAPI Eina_List *mrk_repodb_search(Mrk_Repodb *rdb,
82 const char *arch,
83 const char *search);
84// this iapi si very simple - it scans the dir of mrk binary packages and
85// updates the database files inside
86EAPI Eina_Bool mrk_index(const char *dir);
87
88typedef struct _Mrk_Build Mrk_Build;
89typedef struct _Mrk_Build_Bin Mrk_Build_Bin;
90typedef struct _Mrk_Build_Data Mrk_Build_Data;
91
92struct _Mrk_Build_Bin
93{
94 const char *bin;
95 Eina_List *srcs;
96 Eina_List *deps;
97 Eina_List *incs;
98};
99
100struct _Mrk_Build_Data
101{
102 const char *src;
103 const char *dest;
104};
105
106struct _Mrk_Build
107{
108 const char *name;
109 const char *icon;
110 const char *brief;
111 const char *version;
112 const char *license;
113 const char *domain;
114 const char *repo;
115 const char *devrepo;
116 const char *contact;
117 Eina_List *tags;
118 Eina_List *categories;
119 Eina_List *copying;
120 const char *needs;
121 Eina_List *bins;
122 Eina_List *data;
123 Eina_List *desktops;
124 Eina_List *icons;
125 Eina_List *po;
126};
127
128EAPI Mrk_Build *mrk_build_load(const char *file);
129EAPI void mrk_build_free(Mrk_Build *bld);
130EAPI Eina_Bool mrk_build_do(Mrk_Build *bld, const char *tmpd);
131EAPI Eina_Bool mrk_build_pakage_bin(Mrk_Build *bld, const char *file, const char *tmpd, const char *os, const char *arch);
132EAPI Eina_Bool mrk_build_package_src(Mrk_Build *bld, const char *buildfile, const char *file);
133
134EAPI Eina_Bool mrk_package_src_extract(const char *file, const char *dst);
135EAPI Eina_Bool mrk_package_bin_clean(void);
136EAPI Eina_Bool mrk_package_bin_install(const char *file);
137EAPI Eina_Bool mrk_package_bin_remove(const char *name);
138
139// XXX: .mrk parsing api handled/exposed and other related functions
140// XXX: installation/uninstallation handling apis
141// XXX: cleanup apis
142
143#endif
diff --git a/mrklib_buildfile.c b/mrklib_buildfile.c
new file mode 100644
index 0000000..fa0ebad
--- /dev/null
+++ b/mrklib_buildfile.c
@@ -0,0 +1,711 @@
1#include "mrklib_priv.h"
2
3typedef enum
4{
5 TMODE_EOL,
6 TMODE_PATH,
7 TMODE_TEXT,
8 TMODE_PATH_CP,
9 TMODE_PATH_CP_LIST,
10 TMODE_PATH_LIST,
11} Tag_Mode;
12
13typedef struct
14{
15 const char *tag;
16 Tag_Mode mode;
17} Tag_Type;
18
19static const Tag_Type tags[] =
20{
21 {"PROJ:", TMODE_EOL},
22 {"PROJICON:", TMODE_PATH},
23 {"BRIEF:", TMODE_TEXT},
24 {"VERSION:", TMODE_EOL},
25 {"LICENSE:", TMODE_EOL},
26 {"COPYING:", TMODE_PATH_LIST},
27 {"NEEDS:", TMODE_EOL},
28 {"DOMAIN:", TMODE_PATH},
29 {"REPO:", TMODE_EOL},
30 {"DEVREPO:", TMODE_EOL},
31 {"CONTACT:", TMODE_TEXT},
32 {"CATEGORY:", TMODE_PATH_LIST},
33 {"TAGS:", TMODE_PATH_LIST},
34 {"BIN:", TMODE_PATH},
35 {"SRC:", TMODE_PATH_LIST},
36 {"DEPS:", TMODE_PATH_LIST},
37 {"INC:", TMODE_PATH_LIST},
38 {"DATA:", TMODE_PATH_CP_LIST},
39 {"DESKTOP:", TMODE_PATH_LIST},
40 {"ICON:", TMODE_PATH_LIST},
41 {"PODOMAIN:", TMODE_PATH},
42 {"PO:", TMODE_PATH_LIST},
43 {NULL, 0} // END OF LIST
44};
45
46static char *
47parse_token(char **p, char *end)
48{
49 char *tok, *seg;
50
51 while ((*p < end) && (isspace(**p))) (*p)++;
52 if (*p >= end) return NULL;
53 tok = *p;
54
55 while (*p < end)
56 {
57 if (isspace(**p)) goto token;
58 (*p)++;
59 }
60token:
61 seg = malloc(*p - tok + 1);
62 if (!seg) return NULL;
63 memcpy(seg, tok, *p - tok);
64 seg[*p - tok] = 0;
65 return seg;
66}
67
68static char *
69parse_eol(char **p, char *end)
70{
71 char *tok, *seg;
72
73 while ((*p < end) && (isspace(**p))) (*p)++;
74 if (*p >= end) return NULL;
75 tok = *p;
76
77 while (*p < end)
78 {
79 if (**p == '\n') goto token;
80 (*p)++;
81 }
82token:
83 seg = malloc(*p - tok + 1);
84 if (!seg) return NULL;
85 memcpy(seg, tok, *p - tok);
86 seg[*p - tok] = 0;
87 return seg;
88}
89
90static char *
91path_check(char *tok)
92{
93 // XXX: check me
94 return strdup(tok);
95}
96
97static Mrk_Build *
98parse_content(char *mem, size_t size)
99{
100 Mrk_Build *bld = NULL;
101 char prevc = '\n';
102 char *end = mem + size;
103 char *p = mem;
104 int skipline = 0;
105 int startline = 0;
106 char *seg = NULL, *s;
107 char *data1 = NULL, *data2 = NULL;
108 int i;
109 Tag_Mode mode = TMODE_TEXT;
110#define err(reason) do { fprintf(stderr, "%s\n", reason); goto error; } while (0)
111
112 bld = calloc(1, sizeof(Mrk_Build));
113 if (!bld) return NULL;
114
115 while (p < end)
116 {
117 if (prevc == '\n')
118 {
119 if (*p == '#') skipline = 1;
120 else skipline = 0;
121 startline = 1;
122 }
123 if (!skipline)
124 {
125 char *tok;
126 char *prevp;
127
128 prevp = p;
129 tok = parse_token(&p, end);
130 if (!tok) err("token parse error");
131 if (startline)
132 {
133 for (i = 0; tags[i].tag; i++)
134 {
135 if (!strcmp(tok, tags[i].tag))
136 {
137 free(seg);
138 seg = strdup(tok);
139 mode = tags[i].mode;
140 break;
141 }
142 }
143 if (!tags[i].tag) goto not_tag;
144 }
145 else
146 {
147not_tag:
148 switch (mode)
149 {
150 case TMODE_EOL:
151 case TMODE_TEXT:
152 p = prevp;
153 data1 = parse_eol(&p, end);
154 if (!data1) err("no content");
155 break;
156 case TMODE_PATH:
157 case TMODE_PATH_LIST:
158 data1 = path_check(tok);
159 if (!data1) err("path invalid");
160 break;
161 case TMODE_PATH_CP:
162 case TMODE_PATH_CP_LIST:
163 data1 = path_check(tok);
164 if (!data1) err("path invalid");
165 s = parse_token(&p, end);
166 if (!s) err("missing > in path copy");
167 if (!(!strcmp(s, ">"))) err("copy token is not >");
168 free(s);
169 s = parse_token(&p, end);
170 if (!s) err("missing destination path in path copy");
171 data2 = path_check(s);
172 if (!data2) err("destination path not valid");
173 free(s);
174 break;
175 default:
176 break;
177 }
178 if (seg)
179 {
180 if (!strcmp(seg, "PROJ:"))
181 {
182 if (!_mrk_util_plain_file_check(data1))
183 err("name failed sanity check");
184 eina_stringshare_del(bld->name);
185 bld->name = eina_stringshare_add(data1);
186 }
187 else if (!strcmp(seg, "PROJICON:"))
188 {
189 eina_stringshare_del(bld->icon);
190 bld->icon = eina_stringshare_add(data1);
191 }
192 else if (!strcmp(seg, "BRIEF:"))
193 {
194 if (!bld->brief) bld->brief = eina_stringshare_add(data1);
195 else
196 {
197 s = malloc(strlen(bld->brief) + 1 + strlen(data1) + 1);
198 if (s)
199 {
200 strcpy(s, bld->brief);
201 strcat(s, " ");
202 strcat(s, data1);
203 eina_stringshare_del(bld->brief);
204 bld->brief = s;
205 }
206 }
207 }
208 else if (!strcmp(seg, "VERSION:"))
209 {
210 eina_stringshare_del(bld->version);
211 bld->version = eina_stringshare_add(data1);
212 }
213 else if (!strcmp(seg, "LICENSE:"))
214 {
215 eina_stringshare_del(bld->license);
216 bld->license = eina_stringshare_add(data1);
217 }
218 else if (!strcmp(seg, "COPYING:"))
219 {
220 bld->copying = eina_list_append(bld->copying,
221 eina_stringshare_add(data1));
222 }
223 else if (!strcmp(seg, "NEEDS:"))
224 {
225 eina_stringshare_del(bld->needs);
226 bld->license = eina_stringshare_add(data1);
227 }
228 else if (!strcmp(seg, "DOMAIN:"))
229 {
230 eina_stringshare_del(bld->domain);
231 bld->domain = eina_stringshare_add(data1);
232 }
233 else if (!strcmp(seg, "REPO:"))
234 {
235 eina_stringshare_del(bld->repo);
236 bld->repo = eina_stringshare_add(data1);
237 }
238 else if (!strcmp(seg, "DEVREPO:"))
239 {
240 eina_stringshare_del(bld->devrepo);
241 bld->devrepo = eina_stringshare_add(data1);
242 }
243 else if (!strcmp(seg, "CATEGORY:"))
244 {
245 bld->categories = eina_list_append(bld->categories,
246 eina_stringshare_add(data1));
247 }
248 else if (!strcmp(seg, "TAGS:"))
249 {
250 bld->tags = eina_list_append(bld->tags,
251 eina_stringshare_add(data1));
252 }
253 else if (!strcmp(seg, "CONTACT:"))
254 {
255 if (!bld->contact) bld->contact = eina_stringshare_add(data1);
256 else
257 {
258 s = malloc(strlen(bld->contact) + 1 + strlen(data1) + 1);
259 if (s)
260 {
261 strcpy(s, bld->contact);
262 strcat(s, " ");
263 strcat(s, data1);
264 eina_stringshare_del(bld->contact);
265 bld->contact = s;
266 }
267 }
268 }
269 else if (!strcmp(seg, "BIN:"))
270 {
271 Mrk_Build_Bin *build_bin = calloc(1, sizeof(Mrk_Build_Bin));
272 if (build_bin)
273 {
274 build_bin->bin = eina_stringshare_add(data1);
275 bld->bins = eina_list_append(bld->bins,
276 build_bin);
277 }
278 }
279 else if (!strcmp(seg, "SRC:"))
280 {
281 Mrk_Build_Bin *build_bin = eina_list_data_get(eina_list_last(bld->bins));
282 if (build_bin)
283 {
284 build_bin->srcs = eina_list_append(build_bin->srcs,
285 eina_stringshare_add(data1));
286 }
287 }
288 else if (!strcmp(seg, "DEPS:"))
289 {
290 Mrk_Build_Bin *build_bin = eina_list_data_get(eina_list_last(bld->bins));
291 if (build_bin)
292 {
293 build_bin->deps = eina_list_append(build_bin->deps,
294 eina_stringshare_add(data1));
295 }
296 }
297 else if (!strcmp(seg, "INC:"))
298 {
299 Mrk_Build_Bin *build_bin = eina_list_data_get(eina_list_last(bld->bins));
300 if (build_bin)
301 {
302 build_bin->incs = eina_list_append(build_bin->incs,
303 eina_stringshare_add(data1));
304 }
305 }
306 else if (!strcmp(seg, "DATA:"))
307 {
308 Mrk_Build_Data *build_data = calloc(1, sizeof(Mrk_Build_Data));
309 if (build_data)
310 {
311 build_data->src = eina_stringshare_add(data1);
312 build_data->dest = eina_stringshare_add(data2);
313 bld->data = eina_list_append(bld->data,
314 build_data);
315 }
316 }
317 else if (!strcmp(seg, "DESKTOP:"))
318 {
319 bld->desktops = eina_list_append(bld->desktops,
320 eina_stringshare_add(data1));
321 }
322 else if (!strcmp(seg, "ICON:"))
323 {
324 bld->icons = eina_list_append(bld->icons,
325 eina_stringshare_add(data1));
326 }
327 else if (!strcmp(seg, "PO:"))
328 {
329 bld->po = eina_list_append(bld->po,
330 eina_stringshare_add(data1));
331 }
332 }
333 free(data1);
334 free(data2);
335 data1 = NULL;
336 data2 = NULL;
337 }
338 free(tok);
339 prevc = *p;
340 }
341 else
342 {
343 prevc = *p;
344 p++;
345 }
346 startline = 0;
347 }
348 return bld;
349error:
350 mrk_build_free(bld);
351 return NULL;
352#undef err
353}
354
355EAPI Mrk_Build *
356mrk_build_load(const char *file)
357{
358 Mrk_Build *bld;
359 Eina_File *ef;
360 char *mem;
361 size_t size;
362 int ret;
363
364 ef = eina_file_open(file, EINA_FALSE);
365 if (!ef) return NULL;
366
367 size = eina_file_size_get(ef);
368 mem = eina_file_map_all(ef, EINA_FILE_SEQUENTIAL);
369 if ((size == 0) || (!mem)) return NULL;
370
371 bld = parse_content(mem, size);
372
373 eina_file_close(ef);
374 return bld;
375}
376
377EAPI void
378mrk_build_free(Mrk_Build *bld)
379{
380 const char *s;
381 Mrk_Build_Bin *build_bin;
382 Mrk_Build_Data *build_data;
383
384 if (!bld) return;
385 eina_stringshare_del(bld->name);
386 eina_stringshare_del(bld->icon);
387 eina_stringshare_del(bld->brief);
388 eina_stringshare_del(bld->version);
389 eina_stringshare_del(bld->license);
390 eina_stringshare_del(bld->domain);
391 eina_stringshare_del(bld->repo);
392 eina_stringshare_del(bld->devrepo);
393 eina_stringshare_del(bld->contact);
394 EINA_LIST_FREE(bld->tags, s) eina_stringshare_del(s);
395 EINA_LIST_FREE(bld->categories, s) eina_stringshare_del(s);
396 EINA_LIST_FREE(bld->copying, s) eina_stringshare_del(s);
397 eina_stringshare_del(bld->needs);
398 EINA_LIST_FREE(bld->desktops, s) eina_stringshare_del(s);
399 EINA_LIST_FREE(bld->bins, build_bin)
400 {
401 eina_stringshare_del(build_bin->bin);
402 EINA_LIST_FREE(build_bin->srcs, s) eina_stringshare_del(s);
403 EINA_LIST_FREE(build_bin->deps, s) eina_stringshare_del(s);
404 EINA_LIST_FREE(build_bin->incs, s) eina_stringshare_del(s);
405 free(build_bin);
406 }
407 EINA_LIST_FREE(bld->data, build_data)
408 {
409 eina_stringshare_del(build_data->src);
410 eina_stringshare_del(build_data->dest);
411 free(build_data);
412 }
413 EINA_LIST_FREE(bld->icons, s) eina_stringshare_del(s);
414 EINA_LIST_FREE(bld->po, s) eina_stringshare_del(s);
415 free(bld);
416}
417
418EAPI Eina_Bool
419mrk_build_do(Mrk_Build *bld, const char *tmpd)
420{
421 Eina_List *l, *ll;
422 Mrk_Build_Bin *bin;
423 Mrk_Build_Data *data;
424 Eina_Strbuf *buf;
425 char *s, *extn, *s2;
426 char tmp[4096];
427 char tmp2[4096];
428 const char *ss, *cc;
429#define err(reason) do { fprintf(stderr, "%s\n", reason); goto error; } while (0)
430
431 EINA_LIST_FOREACH(bld->po, l, s)
432 {
433 snprintf(tmp, sizeof(tmp), "%s/share/locale/%s/LC_MESSAGES/", tmpd, s);
434 ecore_file_mkpath(tmp);
435 snprintf(tmp2, sizeof(tmp2), "po/%s.gmo", s);
436 snprintf(tmp, sizeof(tmp), "%s/share/locale/%s/LC_MESSAGES/%s.mo", tmpd, s, bld->domain);
437 ecore_file_cp(tmp2, tmp);
438 }
439 EINA_LIST_FOREACH(bld->data, l, data)
440 {
441 s = ecore_file_dir_get(data->dest);
442 if (s)
443 {
444 snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, s);
445 ecore_file_mkpath(tmp);
446 free(s);
447 }
448 snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, data->dest);
449 ecore_file_cp(data->src, tmp);
450 }
451 snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, "share/applications");
452 ecore_file_mkpath(tmp);
453 EINA_LIST_FOREACH(bld->desktops, l, s)
454 {
455 ss = ecore_file_file_get(s);
456 if (!(!strncmp(ss, bld->domain, strlen(bld->domain))))
457 err("destkop file wrong domain");
458 snprintf(tmp, sizeof(tmp), "%s/share/applications/%s", tmpd, ss);
459 ecore_file_cp(s, tmp);
460 }
461 snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, "share/icons");
462 ecore_file_mkpath(tmp);
463 EINA_LIST_FOREACH(bld->icons, l, s)
464 {
465 ss = ecore_file_file_get(s);
466 if (!(!strncmp(ss, bld->domain, strlen(bld->domain))))
467 err("icon file wrong domain");
468 snprintf(tmp, sizeof(tmp), "%s/share/icons/%s", tmpd, ss);
469 ecore_file_cp(s, tmp);
470 }
471 EINA_LIST_FOREACH(bld->copying, l, s)
472 {
473 if (strchr(s, '/'))
474 {
475 s2 = ecore_file_dir_get(s);
476 snprintf(tmp, sizeof(tmp), "%s/share/licenses/%s", tmpd, s2);
477 free(s2);
478 }
479 else
480 snprintf(tmp, sizeof(tmp), "%s/share/licenses", tmpd);
481 ecore_file_mkpath(tmp);
482 snprintf(tmp, sizeof(tmp), "%s/share/licenses/%s", tmpd, s);
483 ecore_file_cp(s, tmp);
484 }
485 EINA_LIST_FOREACH(bld->bins, l, bin)
486 {
487 if ((buf = eina_strbuf_new()))
488 {
489 s = ecore_file_dir_get(bin->bin);
490 if (s)
491 {
492 snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, s);
493 ecore_file_mkpath(tmp);
494 free(s);
495 }
496 cc = getenv("CC");
497 if (!cc) cc = "gcc";
498 eina_strbuf_append(buf, cc);
499 eina_strbuf_append(buf, " -I. -lm -o ");
500 eina_strbuf_append(buf, tmpd);
501 eina_strbuf_append(buf, "/");
502 eina_strbuf_append(buf, bin->bin);
503
504 eina_strbuf_append(buf, " -DLOCALEDIR=\\\"/tmp/X/share/locale\\\"");
505 eina_strbuf_append(buf, " -DPACKAGE_BIN_DIR=\\\"/tmp/X/bin\\\"");
506 eina_strbuf_append(buf, " -DPACKAGE_LIB_DIR=\\\"/tmp/X/lib\\\"");
507 eina_strbuf_append(buf, " -DPACKAGE_DATA_DIR=\\\"/tmp/X/share/");
508 eina_strbuf_append(buf, bld->domain);
509 eina_strbuf_append(buf, "\\\"");
510
511 eina_strbuf_append(buf, " -DPACKAGE_NAME=\\\"");
512 eina_strbuf_append(buf, bld->domain);
513 eina_strbuf_append(buf, "\\\"");
514
515 eina_strbuf_append(buf, " -DPACKAGE_VERSION=\\\"");
516 eina_strbuf_append(buf, bld->version);
517 eina_strbuf_append(buf, "\\\"");
518
519 eina_strbuf_append(buf, " -D_REENTRANT -DHAVE_CONFIG_H -pthread ");
520 eina_strbuf_append(buf, " $CFLAGS ");
521
522 EINA_LIST_FOREACH(bin->srcs, ll, s)
523 {
524 extn = strrchr(s, '.');
525 if ((extn) && (!strcasecmp(extn, ".c")))
526 {
527 eina_strbuf_append(buf, s);
528 eina_strbuf_append(buf, " ");
529 }
530 }
531 EINA_LIST_FOREACH(bin->deps, ll, s)
532 {
533 eina_strbuf_append(buf, " pkg-config --cflags --libs ");
534 eina_strbuf_append(buf, s);
535 eina_strbuf_append(buf, " ");
536 }
537 EINA_LIST_FOREACH(bin->incs, ll, s)
538 {
539 eina_strbuf_append(buf, " -I");
540 eina_strbuf_append(buf, s);
541 eina_strbuf_append(buf, " ");
542 }
543 s = (char *)eina_strbuf_string_get(buf);
544 if (s) system(s);
545 eina_strbuf_free(buf);
546 }
547 }
548 return EINA_TRUE;
549error:
550 return EINA_FALSE;
551#undef err
552}
553
554static void
555package_file(Eet_File *ef, const char *file, const char *key)
556{
557 Eina_File *enf = eina_file_open(file, EINA_FALSE);
558 if (enf)
559 {
560 void *mem = eina_file_map_all(enf, EINA_FILE_SEQUENTIAL);
561 if (mem)
562 {
563 size_t size = eina_file_size_get(enf);
564 eet_write(ef, key, mem, size, EET_COMPRESSION_VERYFAST);
565 }
566 eina_file_close(enf);
567 }
568}
569
570static void
571package_bin_iter(Eet_File *ef, const char *dir, const char *key)
572{
573 Eina_List *files;
574 Eina_File *enf;
575 char *s;
576 char tmp[4096];
577 char tmp2[4096];
578
579 files = ecore_file_ls(dir);
580 EINA_LIST_FREE(files, s)
581 {
582 if (!strcmp(s, ".")) continue;
583 else if (!strcmp(s, "..")) continue;
584 snprintf(tmp, sizeof(tmp), "%s/%s", dir, s);
585 snprintf(tmp2, sizeof(tmp2), "%s/%s", key, s);
586 if (ecore_file_is_dir(tmp))
587 {
588 if (ecore_file_can_exec(tmp)) tmp2[4] = 'D';
589 package_bin_iter(ef, tmp, tmp2);
590 }
591 else
592 {
593 if (ecore_file_can_exec(tmp)) tmp2[4] = 'X';
594 else tmp2[4] = 'f';
595 package_file(ef, tmp, tmp2);
596 }
597 free(s);
598 }
599}
600
601EAPI Eina_Bool
602mrk_build_package_bin(Mrk_Build *bld, const char *file, const char *tmpd, const char *os, const char *arch)
603{
604 Eet_File *ef;
605 char tmp[4096];
606 Eina_List *l;
607 char *s;
608 int i;
609
610// snprintf(tmp, sizeof(tmp), "%s-%s.mkb", bld->name, bld->version);
611 ef = eet_open(file, EET_FILE_MODE_WRITE);
612 if (ef)
613 {
614#define WRTS(key, var) \
615 if (var) eet_write(ef, key, var, strlen(var), EET_COMPRESSION_VERYFAST)
616 WRTS("name", bld->name);
617 if (bld->icon) package_file(ef, bld->icon, "icon");
618 WRTS("brief", bld->brief);
619 WRTS("version", bld->version);
620 WRTS("license", bld->license);
621 WRTS("repo", bld->repo);
622 WRTS("devrepo", bld->devrepo);
623 WRTS("contact", bld->contact);
624 WRTS("needs", bld->needs);
625 snprintf(tmp, sizeof(tmp), "%s-%s", os, arch);
626 WRTS("arch", tmp);
627 i = 0;
628 EINA_LIST_FOREACH(bld->tags, l, s)
629 {
630 snprintf(tmp, sizeof(tmp), "tag/%i", i++);
631 WRTS(tmp, s);
632 }
633 i = 0;
634 EINA_LIST_FOREACH(bld->categories, l, s)
635 {
636 snprintf(tmp, sizeof(tmp), "category/%i", i++);
637 WRTS(tmp, s);
638 }
639 package_bin_iter(ef, tmpd, "bin/f");
640 eet_close(ef);
641 return EINA_TRUE;
642 }
643 return EINA_FALSE;
644}
645
646EAPI Eina_Bool
647mrk_build_package_src(Mrk_Build *bld, const char *buildfile, const char *file)
648{
649 Eet_File *ef;
650 char tmp[4096];
651 char tmp2[4096];
652
653// snprintf(tmp, sizeof(tmp), "%s-%s.mks", bld->name, bld->version);
654 ef = eet_open(file, EET_FILE_MODE_WRITE);
655 if (ef)
656 {
657 Eina_File *enf;
658 Eina_List *l, *ll;
659 void *mem;
660 size_t size;
661 char *s;
662 Mrk_Build_Bin *bin;
663 Mrk_Build_Data *data;
664
665 enf = eina_file_open(buildfile, EINA_FALSE);
666 if (!enf) err("can't open build file");
667 mem = eina_file_map_all(enf, EINA_FILE_SEQUENTIAL);
668 if (!mem) err("can't map build file");
669 size = eina_file_size_get(enf);
670 eet_write(ef, "buildinfo", mem, size, EET_COMPRESSION_VERYFAST);
671 eina_file_close(enf);
672
673 EINA_LIST_FOREACH(bld->copying, l, s)
674 {
675 snprintf(tmp, sizeof(tmp), "src/%s", s);
676 package_file(ef, s, tmp);
677 }
678 EINA_LIST_FOREACH(bld->desktops, l, s)
679 {
680 snprintf(tmp, sizeof(tmp), "src/%s", s);
681 package_file(ef, s, tmp);
682 }
683 EINA_LIST_FOREACH(bld->icons, l, s)
684 {
685 snprintf(tmp, sizeof(tmp), "src/%s", s);
686 package_file(ef, s, tmp);
687 }
688 EINA_LIST_FOREACH(bld->po, l, s)
689 {
690 snprintf(tmp2, sizeof(tmp2), "po/%s.gmo", s);
691 snprintf(tmp, sizeof(tmp), "src/po/%s.gmo", s);
692 package_file(ef, tmp2, tmp);
693 }
694 EINA_LIST_FOREACH(bld->bins, l, bin)
695 {
696 EINA_LIST_FOREACH(bin->srcs, ll, s)
697 {
698 snprintf(tmp, sizeof(tmp), "src/%s", s);
699 package_file(ef, s, tmp);
700 }
701 }
702 EINA_LIST_FOREACH(bld->data, l, data)
703 {
704 snprintf(tmp, sizeof(tmp), "src/%s", data->src);
705 package_file(ef, data->src, tmp);
706 }
707 eet_close(ef);
708 return EINA_TRUE;
709 }
710 return EINA_FALSE;
711}
diff --git a/mrklib_index.c b/mrklib_index.c
new file mode 100644
index 0000000..2f249b2
--- /dev/null
+++ b/mrklib_index.c
@@ -0,0 +1,302 @@
1#include "mrklib_priv.h"
2
3typedef struct
4{
5 Eina_Hash *name_hash;
6 Eina_Hash *category_hash;
7 Eina_Hash *tag_hash;
8 Eina_Hash *key_hash;
9} Mdb;
10
11static char *
12read_string(Eet_File *ef, const char *key)
13{
14 int size = 0;
15 char *str;
16 char *s = eet_read(ef, key, &size);
17 if (!s) return NULL;
18 str = malloc(size + 1);
19 if (!str)
20 {
21 free(s);
22 return NULL;
23 }
24 memcpy(str, s, size);
25 str[size] = 0;
26 free(s);
27 return str;
28}
29
30static void
31key_register(Eina_Hash *hash, const char *key, const char *entry)
32{
33 const char *ss;
34 Eina_List *entries;
35
36 ss = eina_stringshare_add(entry);
37 entries = eina_hash_find(hash, key);
38 entries = eina_list_sorted_insert(entries, EINA_COMPARE_CB(strcasecmp), ss);
39 eina_hash_set(hash, key, entries);
40}
41
42typedef struct
43{
44 Eina_Hash *master;
45 const char *entry;
46} Inf;
47
48static Eina_Bool
49key_enter_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
50{
51 Inf *inf = fdata;
52 key_register(inf->master, key, inf->entry);
53 return EINA_TRUE;
54}
55
56static void
57key_enter(Eina_Hash *master, Eina_Hash *keys, const char *entry)
58{
59 Inf inf = { master, entry };
60
61 eina_hash_foreach(keys, key_enter_cb, &inf);
62}
63
64static Eina_Hash *
65key_new(void)
66{
67 return eina_hash_string_superfast_new(NULL);
68}
69
70static void
71key_free(Eina_Hash *hash)
72{
73 eina_hash_free(hash);
74}
75
76static void
77key_add(Eina_Hash *hash, const char *key)
78{
79 if (eina_hash_find(hash, key)) return;
80 eina_hash_add(hash, key, hash);
81}
82
83static void
84key_str_add(Eina_Hash *hash, const char *str)
85{
86 char *ts = strdup(str);
87 char *p, *pe;
88 if (!ts) return;
89 for (p = ts; *p; p++)
90 {
91 if (!(((*p >= 'a') && (*p <= 'z')) ||
92 ((*p >= 'A') && (*p <= 'Z')) ||
93 ((*p >= '0') && (*p <= '9')))) *p = 0;
94 else *p = tolower(*p);
95 pe = p;
96 }
97 for (p = ts; p < pe; p++)
98 {
99 if (*p)
100 {
101 key_add(hash, p);
102 p += strlen(p);
103 }
104 }
105 free(ts);
106}
107
108static Eina_Bool
109key_merge_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
110{
111 key_add(fdata, key);
112 return EINA_TRUE;
113}
114
115static void
116key_merge(Eina_Hash *master, Eina_Hash *keys)
117{
118 eina_hash_foreach(keys, key_merge_cb, master);
119}
120
121static Eina_Bool
122index_file(Mdb *db, const char *file, const char *fname)
123{
124 Eet_File *ef;
125 char *s;
126 int i;
127 char tmp[4096];
128 Eina_Hash *ky;
129 Eina_Hash *tk;
130
131 ef = eet_open(file, EET_FILE_MODE_READ);
132 if (!ef) return EINA_FALSE;
133
134 ky = key_new();
135 s = read_string(ef, "name");
136 if (s)
137 {
138 tk = key_new();
139 key_add(tk, s);
140 key_str_add(ky, s);
141 key_enter(db->name_hash, tk, fname);
142 key_free(tk);
143 tk = key_new();
144 key_str_add(tk, s);
145 key_merge(ky, tk);
146 key_free(tk);
147 free(s);
148 }
149 for (i = 0; i < 9999; i++)
150 {
151 tk = key_new();
152 snprintf(tmp, sizeof(tmp), "tag/%i", i);
153 s = read_string(ef, tmp);
154 if (s)
155 {
156 key_str_add(tk, s);
157 free(s);
158 }
159 key_enter(db->tag_hash, tk, fname);
160 key_merge(ky, tk);
161 key_free(tk);
162 }
163 key_register(db->category_hash, "@", fname);
164 for (i = 0; i < 9999; i++)
165 {
166 tk = key_new();
167 snprintf(tmp, sizeof(tmp), "category/%i", i);
168 s = read_string(ef, tmp);
169 if (s)
170 {
171 key_str_add(tk, s);
172 free(s);
173 }
174 key_enter(db->category_hash, tk, fname);
175 key_merge(ky, tk);
176 key_free(tk);
177 }
178
179 s = read_string(ef, "brief");
180 if (s)
181 {
182 tk = key_new();
183 key_str_add(tk, s);
184 key_merge(ky, tk);
185 key_free(tk);
186 free(s);
187 }
188
189 key_enter(db->key_hash, ky, fname);
190 key_free(ky);
191
192 eet_close(ef);
193 return EINA_TRUE;
194}
195
196static Eina_Bool
197index_out_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
198{
199 FILE *f = fdata;
200 const char *s;
201
202 fprintf(f, "%s\n", (const char *)key);
203 EINA_LIST_FREE(data, s)
204 {
205 fprintf(f, "\t%s\n", s);
206 eina_stringshare_del(s);
207 }
208 return EINA_TRUE;
209}
210
211static Eina_Bool
212index_dir(const char *dir)
213{
214 Eina_List *files;
215 char *s;
216 char tmp[4096];
217 FILE *f;
218 Mdb *db;
219
220 db = calloc(1, sizeof(Mdb));
221 if (!db) return 0;
222 db->name_hash = eina_hash_string_superfast_new(NULL);
223 db->category_hash = eina_hash_string_superfast_new(NULL);
224 db->tag_hash = eina_hash_string_superfast_new(NULL);
225 db->key_hash = eina_hash_string_superfast_new(NULL);
226
227 files = ecore_file_ls(dir);
228 EINA_LIST_FREE(files, s)
229 {
230 char *lnk;
231
232 if (s[0] == '.')
233 {
234 free(s);
235 continue;
236 }
237 snprintf(tmp, sizeof(tmp), "%s/%s", dir, s);
238 lnk = ecore_file_readlink(tmp);
239 if (!lnk)
240 {
241 free(s);
242 continue;
243 }
244 index_file(db, tmp, s);
245 free(lnk);
246 free(s);
247 }
248
249 snprintf(tmp, sizeof(tmp), "%s/.mrkdb-name.txt", dir);
250 f = fopen(tmp, "wb");
251 if (f)
252 {
253 eina_hash_foreach(db->name_hash, index_out_cb, f);
254 eina_hash_free(db->name_hash);
255 fclose(f);
256 }
257 snprintf(tmp, sizeof(tmp), "%s/.mrkdb-tag.txt", dir);
258 f = fopen(tmp, "wb");
259 if (f)
260 {
261 eina_hash_foreach(db->tag_hash, index_out_cb, f);
262 eina_hash_free(db->tag_hash);
263 fclose(f);
264 }
265 snprintf(tmp, sizeof(tmp), "%s/.mrkdb-category.txt", dir);
266 f = fopen(tmp, "wb");
267 if (f)
268 {
269 eina_hash_foreach(db->category_hash, index_out_cb, f);
270 eina_hash_free(db->category_hash);
271 fclose(f);
272 }
273 snprintf(tmp, sizeof(tmp), "%s/.mrkdb-key.txt", dir);
274 f = fopen(tmp, "wb");
275 if (f)
276 {
277 eina_hash_foreach(db->key_hash, index_out_cb, f);
278 eina_hash_free(db->key_hash);
279 fclose(f);
280 }
281 free(db);
282 return 1;
283}
284
285EAPI Eina_Bool
286mrk_index(const char *dir)
287{
288 Eina_Bool ok = EINA_FALSE;
289 char *repodir;
290 const char *file;
291
292 file = ecore_file_file_get(dir);
293 if (!file) return ok;
294 if (!_mrk_util_arch_ok(file)) return ok;
295 repodir = ecore_file_realpath(dir);
296 if (repodir)
297 {
298 ok = index_dir(repodir);
299 free(repodir);
300 }
301 return ok;
302}
diff --git a/mrklib_package.c b/mrklib_package.c
new file mode 100644
index 0000000..a355317
--- /dev/null
+++ b/mrklib_package.c
@@ -0,0 +1,281 @@
1#include "mrklib_priv.h"
2
3static int
4write_file(Eet_File *ef, const char *key, const char *file)
5{
6 FILE *f;
7 void *mem;
8 int size;
9 char *s;
10
11 mem = eet_read(ef, key, &size);
12 if (mem)
13 {
14 s = ecore_file_dir_get(file);
15 if (s)
16 {
17 ecore_file_mkpath(s);
18 free(s);
19 }
20 f = fopen(file, "wb");
21 if (f)
22 {
23 fwrite(mem, size, 1, f);
24 fclose(f);
25 return 1;
26 }
27 }
28 return 0;
29}
30
31EAPI Eina_Bool
32mrk_package_src_extract(const char *file, const char *dst)
33{
34 Eet_File *ef = NULL;
35 char tmp[4096];
36
37 ef = eet_open(file, EET_FILE_MODE_READ);
38 if (ef)
39 {
40 int i, num = 0;
41 char **keys = eet_list(ef, "src/*", &num);
42
43 if (keys)
44 {
45 for (i = 0; i < num; i++)
46 {
47 if (!strncmp(keys[i], "src/", 4))
48 {
49 if (!_mrk_util_plain_path_check(&(keys[i][4])))
50 continue;
51 snprintf(tmp, sizeof(tmp), "%s/%s", dst, &(keys[i][4]));
52 if (!write_file(ef, keys[i], tmp))
53 {
54 free(keys);
55 goto error;
56 }
57 }
58 }
59 free(keys);
60 }
61 snprintf(tmp, sizeof(tmp), "%s/%s", dst, "Marrakesh.mrk");
62 if (!write_file(ef, "buildinfo", tmp)) goto error;
63 eet_close(ef);
64 return EINA_TRUE;
65 }
66error:
67 if (ef) eet_close(ef);
68 return EINA_FALSE;
69}
70
71static char *
72read_string(Eet_File *ef, const char *key)
73{
74 int size = 0;
75 char *str;
76 char *s = eet_read(ef, key, &size);
77 if (!s) return NULL;
78 str = malloc(size + 1);
79 if (!str)
80 {
81 free(s);
82 return NULL;
83 }
84 memcpy(str, s, size);
85 str[size] = 0;
86 free(s);
87 return str;
88}
89
90static void
91clean_symlinks(const char *dir)
92{
93 Eina_List *files;
94 char *s, *ss;
95 char tmp[4096];
96
97 files = ecore_file_ls(dir);
98 EINA_LIST_FREE(files, s)
99 {
100 snprintf(tmp, sizeof(tmp), "%s/%s", dir, s);
101 ss = ecore_file_readlink(tmp);
102 if (ss)
103 {
104 free(ss);
105 if (!ecore_file_exists(tmp))
106 {
107 printf("clean '%s'\n", tmp);
108 ecore_file_unlink(tmp);
109 }
110 }
111 free(s);
112 }
113}
114
115static int
116field_copy(Eet_File *ef, Eet_File *ef2, const char *key)
117{
118 int size = 0;
119 char *s = eet_read(ef, key, &size);
120 if (s)
121 {
122 eet_write(ef2, key, s, size, EET_COMPRESSION_VERYFAST);
123 free(s);
124 return 1;
125 }
126 return 0;
127}
128
129static const char *
130get_home(void)
131{
132 static char buf[4096] = "";
133 const char *tmps, *home;
134
135 if (buf[0]) return buf;
136 tmps = getenv("XDG_DATA_HOME");
137 home = getenv("HOME");
138 if (!home) home = "/tmp";
139 if (tmps) snprintf(buf, sizeof(buf), "%s", tmps);
140 else snprintf(buf, sizeof(buf), "%s", home);
141 return buf;
142}
143
144EAPI Eina_Bool
145mrk_package_bin_clean(void)
146{
147 char tmp[4096];
148
149 snprintf(tmp, sizeof(tmp), "%s/.local/share/icons", get_home());
150 clean_symlinks(tmp);
151 snprintf(tmp, sizeof(tmp), "%s/.local/share/applications", get_home());
152 clean_symlinks(tmp);
153 snprintf(tmp, sizeof(tmp), "%s/Applications/.bin", get_home());
154 clean_symlinks(tmp);
155 return 1;
156}
157
158EAPI Eina_Bool
159mrk_package_bin_install(const char *file)
160{
161 Eet_File *ef, *ef2;
162#define err(reason) do { fprintf(stderr, "%s\n", reason); goto error; } while (0)
163
164 ef = eet_open(file, EET_FILE_MODE_READ);
165 if (ef)
166 {
167 int i, num = 0;
168 char **keys = eet_list(ef, "bin/*", &num);
169 char inst[4096];
170 char dir[4096];
171 char tmp[4096];
172 char tmp2[4096];
173 char *s;
174 Eina_List *files;
175 char *name;
176
177 name = read_string(ef, "name");
178 if (!name) err("no name");
179 if (!_mrk_util_plain_file_check(name)) err("name failed sanity check");
180 snprintf(tmp, sizeof(tmp), "%s/Applications/.bin", get_home());
181 ecore_file_mkpath(tmp);
182 snprintf(inst, sizeof(inst), "%s/Applications/%s", get_home(), name);
183 if (ecore_file_exists(inst)) err("destination already exists");
184 ecore_file_mkpath(inst);
185 if (keys)
186 {
187 for (i = 0; i < num; i++)
188 {
189 if (!strncmp(keys[i], "bin/", 4))
190 {
191 if (!_mrk_util_plain_path_check(&(keys[i][6]))) continue;
192 snprintf(tmp, sizeof(tmp), "%s/%s", inst, &(keys[i][6]));
193 write_file(ef, keys[i], tmp);
194 if (keys[i][4] == 'X')
195 {
196 printf("+x '%s'\n", &(keys[i][6]));
197 chmod(tmp, 00500);
198 }
199 }
200 }
201 }
202 snprintf(dir, sizeof(dir), "%s/share/icons", inst);
203 files = ecore_file_ls(dir);
204 EINA_LIST_FREE(files, s)
205 {
206 if (!strcmp(s, ".")) continue;
207 else if (!strcmp(s, "..")) continue;
208 snprintf(tmp, sizeof(tmp), "../../../Applications/%s/share/icons/%s", name, s);
209 snprintf(tmp2, sizeof(tmp2), "%s/.local/share/icons/%s", get_home(), s);
210 if (ecore_file_exists(tmp2)) err("icon file symlink already exists");
211 ecore_file_symlink(tmp, tmp2);
212 free(s);
213 }
214 snprintf(dir, sizeof(dir), "%s/share/applications", inst);
215 files = ecore_file_ls(dir);
216 EINA_LIST_FREE(files, s)
217 {
218 if (!strcmp(s, ".")) continue;
219 else if (!strcmp(s, "..")) continue;
220 snprintf(tmp, sizeof(tmp), "../../../Applications/%s/share/applications/%s", name, s);
221 snprintf(tmp2, sizeof(tmp2), "%s/.local/share/applications/%s", get_home(), s);
222 if (ecore_file_exists(tmp2)) err("desktop file symlink already exists");
223 ecore_file_symlink(tmp, tmp2);
224 free(s);
225 }
226 snprintf(dir, sizeof(dir), "%s/bin", inst);
227 files = ecore_file_ls(dir);
228 EINA_LIST_FREE(files, s)
229 {
230 if (!strcmp(s, ".")) continue;
231 else if (!strcmp(s, "..")) continue;
232 snprintf(tmp, sizeof(tmp), "../%s/bin/%s", name, s);
233 snprintf(tmp2, sizeof(tmp2), "%s/Applications/.bin/%s", get_home(), s);
234 if (ecore_file_exists(tmp2)) err("bin file symlink already exists");
235 ecore_file_symlink(tmp, tmp2);
236 free(s);
237 }
238 snprintf(tmp, sizeof(tmp), "%s/Applications/%s/.icon.png", get_home(), name);
239 write_file(ef, "icon", tmp);
240 snprintf(tmp, sizeof(tmp), "%s/Applications/%s/.info.mki", get_home(), name);
241 ef2 = eet_open(tmp, EET_FILE_MODE_WRITE);
242 free(name);
243 if (ef2)
244 {
245 field_copy(ef, ef2, "name");
246 field_copy(ef, ef2, "brief");
247 field_copy(ef, ef2, "version");
248 field_copy(ef, ef2, "license");
249 field_copy(ef, ef2, "repo");
250 field_copy(ef, ef2, "devrepo");
251 field_copy(ef, ef2, "contact");
252 field_copy(ef, ef2, "needs");
253 for (i = 0; i < 9999; i++)
254 {
255 snprintf(tmp, sizeof(tmp), "tag/%i", i);
256 if (!field_copy(ef, ef2, tmp)) break;
257 }
258 for (i = 0; i < 9999; i++)
259 {
260 snprintf(tmp, sizeof(tmp), "category/%i", i);
261 if (!field_copy(ef, ef2, tmp)) break;
262 }
263 eet_close(ef2);
264 }
265 eet_close(ef);
266 return EINA_TRUE;
267 }
268error:
269 if (ef) eet_close(ef);
270 return EINA_FALSE;
271}
272
273EAPI Eina_Bool
274mrk_package_bin_remove(const char *name)
275{
276 char tmp[4096];
277
278 snprintf(tmp, sizeof(tmp), "%s/Applications/%s", get_home(), name);
279 if (!ecore_file_recursive_rm(tmp)) return EINA_FALSE;
280 return EINA_TRUE;
281}
diff --git a/mrklib_priv.h b/mrklib_priv.h
new file mode 100644
index 0000000..8903e29
--- /dev/null
+++ b/mrklib_priv.h
@@ -0,0 +1,99 @@
1#include "mrklib.h"
2
3#include <Ecore.h>
4#include <Ecore_File.h>
5#include <Ecore_Ipc.h>
6#include <Eet.h>
7#include <stdio.h>
8#include <string.h>
9#include <unistd.h>
10#include <stdlib.h>
11#include <time.h>
12#include <sys/time.h>
13#include <sys/types.h>
14#include <sys/stat.h>
15#include <fcntl.h>
16
17#define MRK_SERVER_HOST "devs.enlightenment.org"
18#define MRK_SERVER_PORT 10077
19
20extern const char *_mrk_server_host;
21extern int _mrk_server_port;
22extern const char *_mrk_appdir;
23extern const char *_mrk_appdir_tmp;
24extern const char *_mrk_appdir_bin;
25extern unsigned char *_mrk_uuid;
26extern int _mrk_uuid_len;
27
28#define M_OP 10
29
30#define M_UP_B 0
31#define M_UP_E 10
32#define M_UP_START 1
33#define M_UP_DATA 2
34#define M_UP_END 3
35#define M_UP_OK 4
36#define M_UP_FAIL 5
37
38#define M_DOWN_B 10
39#define M_DOWN_E 20
40#define M_DOWN_START 11
41#define M_DOWN_DATA 12
42#define M_DOWN_END 13
43
44#define M_QRY_B 20
45#define M_QRY_E 30
46#define M_QRY_LIST 21
47#define M_QRY_SEARCH 22
48#define M_QRY_GET 23
49#define M_QRY_GETSRC 24
50
51#define M_ANS_B 30
52#define M_ANS_E 40
53#define M_ANS_START 31
54#define M_ANS_DATA 32
55#define M_ANS_END 33
56
57#define M_SRC_B 40
58#define M_SRC_E 50
59#define M_SRC_START 41
60#define M_SRC_DATA 42
61#define M_SRC_END 43
62
63#define M_ID_B 50
64#define M_ID_E 60
65#define M_ID_UUID 51
66#define M_ID_VERSION 52
67#define M_ID_ARCH 53
68
69#if defined(__x86_64__)
70# define ARCH "x86_64"
71#elif defined(__i386__)
72# define ARCH "ix86"
73#elif defined(__arm__)
74# ifdef __ARM_V7__
75# define ARCH "armv7"
76# else
77# define ARCH "armv6"
78# endif
79#elif defined(__ppc64__) || defined(__powerpc64__)
80# define ARCH "ppc64"
81#elif defined(__ppc__) || defined(__powerpc__)
82# define ARCH "ppc"
83#endif
84
85#if defined(__linux__)
86# define OS "linux"
87#elif defined(__MACH__)
88# define OS "osx"
89#elif defined(__FreeBSD__)
90# define OS "freebsd"
91#elif defined(_WIN32) || defined(_WIN64)
92# define OS "win"
93#endif
94
95Eina_Bool _mrk_util_plain_file_check(const char *file);
96Eina_Bool _mrk_util_plain_path_check(const char *file);
97char *_mrk_util_proto_string(Ecore_Ipc_Event_Server_Data *e);
98char *_mrk_util_proto_cli_string(Ecore_Ipc_Event_Client_Data *e);
99Eina_Bool _mrk_util_arch_ok(const char *arch);
diff --git a/mrklib_repodb.c b/mrklib_repodb.c
new file mode 100644
index 0000000..0ac1652
--- /dev/null
+++ b/mrklib_repodb.c
@@ -0,0 +1,338 @@
1#include "mrklib_priv.h"
2
3typedef struct
4{
5 const char *arch;
6 Eina_Hash *name_hash;
7 Eina_Hash *category_hash;
8 Eina_Hash *tag_hash;
9 Eina_Hash *key_hash;
10} Db;
11
12struct _Mrk_Repodb
13{
14 const char *repodir;
15 Eina_List *dbs;
16 Ecore_Exe *exe;
17 Eina_Bool update;
18 Eina_List *handlers;
19 struct {
20 void (*update) (void *data, Mrk_Repodb *repodb);
21 } func;
22 struct {
23 void *update;
24 } data;
25};
26
27static void
28db_load_hash(Eina_Hash *hash, FILE *f)
29{
30 char line[16384], *s;
31 int len;
32 Eina_List *list = NULL;
33 const char *key = NULL;
34
35 for (;;)
36 {
37 s = fgets(line, sizeof(line), f);
38 if (!s) break;;
39 len = strlen(s);
40 if (len < 1) continue;
41 s[len - 1] = 0;
42 if ((s[0] == '\t') && (key))
43 {
44 list = eina_list_append(list, eina_stringshare_add(s + 1));
45 }
46 else
47 {
48 if (key) eina_hash_set(hash, key, list);
49 list = NULL;
50 if (key) eina_stringshare_del(key);
51 key = eina_stringshare_add(s);
52 }
53 }
54 if (key) eina_hash_set(hash, key, list);
55 list = NULL;
56 if (key) eina_stringshare_del(key);
57 key = NULL;
58}
59
60static Eina_Bool
61db_clear_hash_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
62{
63 const char *s;
64
65 EINA_LIST_FREE(data, s)
66 {
67 eina_stringshare_del(s);
68 }
69 return EINA_TRUE;
70}
71
72static void
73db_clear_hash(Eina_Hash *hash)
74{
75 if (!hash) return;
76 eina_hash_foreach(hash, db_clear_hash_cb, NULL);
77 eina_hash_free(hash);
78}
79
80static void
81db_clear(Mrk_Repodb *rdb)
82{
83 Db *db;
84
85 EINA_LIST_FREE(rdb->dbs, db)
86 {
87 db_clear_hash(db->name_hash);
88 db_clear_hash(db->category_hash);
89 db_clear_hash(db->tag_hash);
90 db_clear_hash(db->key_hash);
91 free(db);
92 }
93}
94
95static void
96db_load(Mrk_Repodb *rdb)
97{
98 Eina_List *files;
99 char *s;
100 char tmp[PATH_MAX];
101 Db *db = NULL;
102 FILE *f;
103
104 files = ecore_file_ls(rdb->repodir);
105 EINA_LIST_FREE(files, s)
106 {
107 if ((s[0] == '.') || (!_mrk_util_arch_ok(s)))
108 {
109 free(s);
110 continue;
111 }
112 snprintf(tmp, sizeof(tmp), "%s/%s/.mrkdb-name.txt", rdb->repodir, s);
113 f = fopen(tmp, "rb");
114 if (f)
115 {
116 db = calloc(1, sizeof(Db));
117 if (db)
118 {
119 db->arch = eina_stringshare_add(s);
120 if (db->arch)
121 {
122 db->name_hash = eina_hash_string_superfast_new(NULL);
123 db->category_hash = eina_hash_string_superfast_new(NULL);
124 db->tag_hash = eina_hash_string_superfast_new(NULL);
125 db->key_hash = eina_hash_string_superfast_new(NULL);
126 rdb->dbs = eina_list_append(rdb->dbs, db);
127 db_load_hash(db->name_hash, f);
128 }
129 else
130 {
131 free(db);
132 db = NULL;
133 }
134 }
135 fclose(f);
136 }
137 if (db)
138 {
139 snprintf(tmp, sizeof(tmp), "%s/%s/.mrkdb-tag.txt", rdb->repodir, s);
140 f = fopen(tmp, "rb");
141 if (f)
142 {
143 db_load_hash(db->tag_hash, f);
144 fclose(f);
145 }
146 snprintf(tmp, sizeof(tmp), "%s/%s/.mrkdb-category.txt", rdb->repodir, s);
147 f = fopen(tmp, "rb");
148 if (f)
149 {
150 db_load_hash(db->category_hash, f);
151 fclose(f);
152 }
153 snprintf(tmp, sizeof(tmp), "%s/%s/.mrkdb-key.txt", rdb->repodir, s);
154 f = fopen(tmp, "rb");
155 if (f)
156 {
157 db_load_hash(db->key_hash, f);
158 fclose(f);
159 }
160 }
161 db = NULL;
162 }
163}
164
165static Db *
166db_arch_find(Mrk_Repodb *rdb, const char *arch)
167{
168 Eina_List *l;
169 Db *db;
170
171 if (!arch) return NULL;
172 EINA_LIST_FOREACH(rdb->dbs, l, db)
173 {
174 if (!strcmp(db->arch, arch))
175 {
176 if (rdb->dbs != l) rdb->dbs = eina_list_promote_list(rdb->dbs, l);
177 return db;
178 }
179 }
180 return NULL;
181}
182
183static Eina_List *
184search_intersect(Eina_List *list_in, Eina_List *list2)
185{
186 Eina_List *list = NULL, *ll;
187 const char *s, *ss;
188 int ok;
189
190 EINA_LIST_FREE(list_in, s)
191 {
192 ok = 0;
193 EINA_LIST_FOREACH(list2, ll, ss)
194 {
195 if (ss == s)
196 {
197 ok = 1;
198 break;
199 }
200 }
201 if (ok) list = eina_list_append(list, s);
202 else eina_stringshare_del(s);
203 }
204 return list;
205}
206
207static Eina_List *
208db_search(Eina_Hash *hash, const char *search)
209{
210 Eina_List *list = NULL, *tl, *l;
211 const char *s;
212 char *ts = strdup(search);
213 char *p, *end;
214 int i;
215
216 if (!ts) return NULL;
217 for (p = ts; *p; p++)
218 {
219 if (isspace(*p)) *p = 0;
220 end = p;
221 }
222 for (p = ts; p < end; p++)
223 {
224 if (!*p) continue;
225 tl = eina_hash_find(hash, p);
226 if (p == ts)
227 {
228 EINA_LIST_FOREACH(tl, l, s)
229 list = eina_list_append(list, eina_stringshare_add(s));
230 }
231 else
232 {
233 list = search_intersect(list, tl);
234 }
235 p += strlen(p);
236 }
237 free(ts);
238 return list;
239}
240
241static Eina_Bool
242_mrk_cb_exe_del(void *data, int type, void *event)
243{
244 Ecore_Exe_Event_Del *e = event;
245 Mrk_Repodb *rdb = data;
246 const char *tag;
247
248 if (!e->exe) return EINA_TRUE;
249 tag = ecore_exe_tag_get(e->exe);
250 if (!tag) return EINA_TRUE;
251 if (!strcmp(tag, "-=# mrk serve - db exe #=-"))
252 {
253 if (ecore_exe_data_get(e->exe) != rdb) return EINA_TRUE;
254 if (e->exe != rdb->exe) return EINA_TRUE;
255 rdb->exe = NULL;
256 db_clear(rdb);
257 db_load(rdb);
258 if (rdb->update)
259 {
260 rdb->update = EINA_FALSE;
261 mrk_repodb_update(rdb);
262 }
263 if (rdb->func.update) rdb->func.update(rdb->data.update, rdb);
264 return EINA_FALSE;
265 }
266 return EINA_TRUE;
267}
268
269EAPI Mrk_Repodb *
270mrk_repodb_load(const char *repodir)
271{
272 Mrk_Repodb *rdb;
273
274 rdb = calloc(1, sizeof(Mrk_Repodb));
275 if (!rdb) return NULL;
276 rdb->repodir = eina_stringshare_add(repodir);
277 rdb->handlers = eina_list_append(rdb->handlers,
278 ecore_event_handler_add
279 (ECORE_EXE_EVENT_DEL,
280 _mrk_cb_exe_del, rdb));
281 db_load(rdb);
282 return rdb;
283}
284
285EAPI void
286mrk_repodb_free(Mrk_Repodb *rdb)
287{
288 Ecore_Event_Handler *hnd;
289
290 EINA_LIST_FREE(rdb->handlers, hnd) ecore_event_handler_del(hnd);
291 db_clear(rdb);
292 if (rdb->exe) ecore_exe_free(rdb->exe);
293 free(rdb);
294}
295
296EAPI void
297mrk_repodb_callback_update_set(Mrk_Repodb *rdb,
298 void (*update) (void *data, Mrk_Repodb *rdb),
299 void *update_data)
300{
301 rdb->func.update = update;
302 rdb->data.update = update_data;
303}
304
305EAPI void
306mrk_repodb_update(Mrk_Repodb *rdb)
307{
308 char tmp[PATH_MAX];
309
310 if (rdb->exe)
311 {
312 rdb->update = EINA_TRUE;
313 return;
314 }
315 snprintf(tmp, sizeof(tmp), "mrk index %s/*-*", rdb->repodir);
316 rdb->exe = ecore_exe_pipe_run(tmp, 0, rdb);
317 if (rdb->exe) ecore_exe_tag_set(rdb->exe, "-=# mrk serve - db exe #=-");
318}
319
320EAPI const Eina_List *
321mrk_repodb_category_list(Mrk_Repodb *rdb, const char *arch, const char *category)
322{
323 Db *db = db_arch_find(rdb, arch);
324 Eina_List *list;
325
326 if (!db) return NULL;
327 if (!category) category = "@"; // @ is the "everything" category and list
328 return eina_hash_find(db->category_hash, category);
329}
330
331EAPI Eina_List *
332mrk_repodb_search(Mrk_Repodb *rdb, const char *arch, const char *search)
333{
334 Db *db = db_arch_find(rdb, arch);
335
336 if (!db) return NULL;
337 return db_search(db->key_hash, search);
338}
diff --git a/mrklib_serv.c b/mrklib_serv.c
new file mode 100644
index 0000000..08db755
--- /dev/null
+++ b/mrklib_serv.c
@@ -0,0 +1,425 @@
1#include "mrklib_priv.h"
2
3struct _Mrk_Serve
4{
5 const char *listen;
6 int port;
7 const char *repodir;
8 const char *bldsh;
9 Ecore_Ipc_Server *server;
10 Eina_List *handlers;
11 Eina_Inlist *clients;
12 Mrk_Repodb *rdb;
13};
14
15typedef struct
16{
17 EINA_INLIST;
18 Mrk_Serve *server;
19 Ecore_Ipc_Client *client;
20 const char *uuid;
21 const char *arch;
22 const char *version;
23 const char *file;
24 const char *dir;
25 FILE *f;
26 Ecore_Exe *exe;
27} Client;
28
29static void
30client_upload_cancel(Client *c)
31{
32 if (c->f) fclose(c->f);
33 if (c->file) eina_stringshare_del(c->file);
34 if (c->dir)
35 {
36 ecore_file_recursive_rm(c->dir);
37 eina_stringshare_del(c->dir);
38 }
39 c->f = NULL;
40 c->file = NULL;
41 c->dir = NULL;
42}
43
44static void
45client_upload_new(Client *c, const char *file)
46{
47 char tmp[PATH_MAX];
48 Eina_Tmpstr *s = NULL;
49
50 if (c->f) client_upload_cancel(c);
51 c->file = eina_stringshare_add(file);
52 if (!c->file) return;
53 if (eina_file_mkdtemp("marrekesh-up-XXXXXX", &s))
54 {
55 c->dir = eina_stringshare_add(s);
56 eina_tmpstr_del(s);
57 if (c->dir)
58 {
59 snprintf(tmp, sizeof(tmp), "%s/%s", c->dir, c->file);
60 c->f = fopen(tmp, "wb");
61 }
62 }
63}
64
65static void
66client_upload_data(Client *c, void *data, int size)
67{
68 if (c->f) fwrite(data, size, 1, c->f);
69}
70
71static void
72client_upload_end(Client *c)
73{
74 char tmp[PATH_MAX];
75
76 if (c->f)
77 {
78 fclose(c->f);
79 c->f = NULL;
80 snprintf(tmp, sizeof(tmp), "%s %s %s",
81 c->server->bldsh, c->dir, c->server->repodir);
82 c->exe = ecore_exe_pipe_run(tmp,
83 ECORE_EXE_TERM_WITH_PARENT |
84 ECORE_EXE_NOT_LEADER, c);
85 if (c->exe) ecore_exe_tag_set(c->exe, "-=# mrk serve - build exe #=-");
86 }
87}
88
89static void
90client_send(Client *c, const char *subrepo, const char *name, int op_start, int op_data, int op_end)
91{
92 char tmp[PATH_MAX];
93 char *lnk;
94
95 snprintf(tmp, sizeof(tmp), "%s/%s/%s", c->server->repodir, subrepo, name);
96 lnk = ecore_file_readlink(tmp);
97 if (!lnk)
98 ecore_ipc_client_send(c->client, M_OP, op_start, 0, 0, 0,
99 NULL, 0);
100 else
101 {
102 FILE *f = fopen(tmp, "rb");
103 if (!f)
104 ecore_ipc_client_send(c->client, M_OP, op_start, 0, 0, 0,
105 NULL, 0);
106 else
107 {
108 long sz, pos;
109
110 fseek(f, 0, SEEK_END);
111 sz = ftell(f);
112 fseek(f, 0, SEEK_SET);
113 ecore_ipc_client_send(c->client, M_OP, op_start, (int)sz, 0, 0,
114