aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--src/Makefile.am22
-rw-r--r--src/appfwk.c224
-rw-r--r--src/verbose.c (renamed from src/wgtpkg-verbose.c)0
-rw-r--r--src/verbose.h24
-rw-r--r--src/wgt-config.c84
-rw-r--r--src/wgt-config.h36
-rw-r--r--src/wgt-info.c382
-rw-r--r--src/wgt-info.h74
-rw-r--r--src/wgt-locales.c121
-rw-r--r--src/wgt.c26
-rw-r--r--src/wgt.h4
-rw-r--r--src/wgtpkg-digsig.c1
-rw-r--r--src/wgtpkg-info.c182
-rw-r--r--src/wgtpkg-install.c258
-rw-r--r--src/wgtpkg-pack.c1
-rw-r--r--src/wgtpkg-sign.c10
-rw-r--r--src/wgtpkg-workdir.c94
-rw-r--r--src/wgtpkg.h13
19 files changed, 1334 insertions, 228 deletions
diff --git a/.gitignore b/.gitignore
index bdc386d..4773e7e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
wgtpkg-install
wgtpkg-pack
wgtpkg-sign
+wgtpkg-info
*.o
.deps/
@@ -15,7 +16,8 @@ depcomp
install-sh
missing
-PACK0/
+UNPACK*/
+PACK*/
TODO
a.pem
b.pem
@@ -28,3 +30,5 @@ tests/
tizen-certificates/
truc
*.wgt
+wrt-widgets
+
diff --git a/src/Makefile.am b/src/Makefile.am
index 0f35ac4..144d48a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,22 +1,28 @@
-bin_PROGRAMS = wgtpkg-install wgtpkg-pack wgtpkg-sign
+bin_PROGRAMS = wgtpkg-install wgtpkg-pack wgtpkg-sign wgtpkg-info appfwk
-COMMONSRCS = \
+OTHERSRCS = \
+ verbose.c
+
+WGTPKGSRCS = \
wgtpkg-base64.c \
wgtpkg-certs.c \
wgtpkg-digsig.c \
wgtpkg-files.c \
- wgtpkg-verbose.c \
wgtpkg-workdir.c \
wgtpkg-xmlsec.c \
wgtpkg-zip.c
WGTSRCS = \
wgt-config.c \
+ wgt-info.c \
wgt.c
SECWRP = \
secmgr-wrap.c
+APPFWK = \
+ appfwk.c
+
AM_CFLAGS = -Wall -Wno-pointer-sign
AM_CFLAGS += -ffunction-sections -fdata-sections
AM_CFLAGS += ${ZIP_CFLAGS} ${XML2_CFLAGS} ${OPENSSL_CFLAGS} ${XMLSEC_CFLAGS}
@@ -25,9 +31,13 @@ AM_LDFLAGS = -Wl,--gc-sections
LDADD = ${ZIP_LIBS} ${XML2_LIBS} ${OPENSSL_LIBS} ${XMLSEC_LIBS}
-wgtpkg_install_SOURCES = wgtpkg-install.c ${COMMONSRCS} ${WGTSRCS} ${SECWRP}
+wgtpkg_sign_SOURCES = wgtpkg-sign.c ${WGTPKGSRCS} ${OTHERSRCS}
+
+wgtpkg_pack_SOURCES = wgtpkg-pack.c ${WGTPKGSRCS} ${OTHERSRCS}
+
+wgtpkg_install_SOURCES = wgtpkg-install.c ${WGTPKGSRCS} ${WGTSRCS} ${SECWRP} ${OTHERSRCS}
-wgtpkg_sign_SOURCES = wgtpkg-sign.c ${COMMONSRCS}
+wgtpkg_info_SOURCES = wgtpkg-info.c ${WGTPKGSRCS} ${WGTSRCS} ${OTHERSRCS}
-wgtpkg_pack_SOURCES = wgtpkg-pack.c ${COMMONSRCS}
+appfwk_SOURCES = ${APPFWK} ${OTHERSRCS}
diff --git a/src/appfwk.c b/src/appfwk.c
new file mode 100644
index 0000000..6dc7182
--- /dev/null
+++ b/src/appfwk.c
@@ -0,0 +1,224 @@
+/*
+ Copyright 2015 IoT.bzh
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <wgt.h>
+
+struct stringset {
+ int count;
+ char **strings;
+};
+
+
+struct appfwk {
+ int refcount;
+ struct stringset paths;
+};
+
+struct appfwk *appfwk_create()
+{
+ struct appfwk *appfwk = malloc(sizeof * appfwk);
+ if (!appfwk)
+ errno = ENOMEM;
+ else {
+ appfwk->refcount = 1;
+ appfwk->paths.count = 0;
+ appfwk->paths.strings = NULL;
+ }
+ return appfwk;
+}
+
+void appfwk_addref(struct appfwk *appfwk)
+{
+ assert(appfwk);
+ appfwk->refcount++;
+}
+
+void appfwk_unref(struct appfwk *appfwk)
+{
+ assert(appfwk);
+ if (!--appfwk->refcount) {
+ while (appfwk->paths.count)
+ free(appfwk->paths.strings[--appfwk->paths.count]);
+ free(appfwk);
+ }
+}
+
+int appfwk_add_root(struct appfwk *appfwk, const char *path)
+{
+ int i, n;
+ char *r, **roots;
+ assert(appfwk);
+ r = realpath(path, NULL);
+ if (!r)
+ return -1;
+
+ /* avoiding duplications */
+ n = appfwk->paths.count;
+ roots = appfwk->paths.strings;
+ for (i = 0 ; i < n ; i++)
+ if (!strcmp(r, roots[i])) {
+ free(r);
+ return 0;
+ }
+
+ /* add */
+ roots = realloc(roots, (n + 1) * sizeof(roots[0]));
+ if (!roots) {
+ free(r);
+ errno = ENOMEM;
+ return -1;
+ }
+ roots[n++] = r;
+ appfwk->paths.strings = roots;
+ appfwk->paths.count = n;
+ return 0;
+}
+
+struct aea {
+ char *path;
+ char *appver;
+ char *ver;
+ const char *root;
+ const char *appid;
+ const char *version;
+ int (*callback)(struct wgt *wgt, void *data);
+ void *data;
+};
+
+struct appfwk_enumerate_applications_context {
+ const char *dirpath;
+ const char *appid;
+ const char *version;
+
+ void *data;
+};
+
+inline int testd(int dirfd, struct dirent *e)
+{
+ return e->d_name[0] != '.' || (e->d_name[1] && (e->d_name[1] != '.' || e->d_name[2]));
+}
+
+#include <stdio.h>
+static int aea3(int dirfd, struct aea *aea)
+{
+ printf("aea3 %s *** %s *** %s\n", aea->path, aea->appver, aea->ver);
+ return 0;
+}
+
+static int aea2(int dirfd, struct aea *aea)
+{
+ DIR *dir;
+ int rc, fd;
+ struct dirent entry, *e;
+
+ dir = fdopendir(dirfd);
+ if (!dir)
+ return -1;
+
+ aea->version = entry.d_name;
+
+ rc = readdir_r(dir, &entry, &e);
+ while (!rc && e) {
+ if (testd(dirfd, &entry)) {
+ fd = openat(dirfd, entry.d_name, O_DIRECTORY|O_RDONLY);
+ if (fd >= 0) {
+ strcpy(aea->ver, entry.d_name);
+ rc = aea3(fd, aea);
+ close(fd);
+ }
+ }
+ rc = readdir_r(dir, &entry, &e);
+ }
+ closedir(dir);
+ return rc;
+}
+
+static int aea1(int dirfd, struct aea *aea)
+{
+ DIR *dir;
+ int rc, fd;
+ struct dirent entry, *e;
+
+ dir = fdopendir(dirfd);
+ if (!dir)
+ return -1;
+
+ aea->appid = entry.d_name;
+
+ rc = readdir_r(dir, &entry, &e);
+ while (!rc && e) {
+ if (testd(dirfd, &entry)) {
+ fd = openat(dirfd, entry.d_name, O_DIRECTORY|O_RDONLY);
+ if (fd >= 0) {
+ aea->ver = stpcpy(aea->appver, entry.d_name);
+ *aea->ver++ = '/';
+ rc = aea2(fd, aea);
+ close(fd);
+ }
+ }
+ rc = readdir_r(dir, &entry, &e);
+ }
+ closedir(dir);
+ return rc;
+}
+
+int appfwk_enumerate_applications(struct appfwk *appfwk, int (*callback)(struct wgt *wgt, void *data), void *data)
+{
+ int rc, iroot, nroots;
+ char **roots;
+ int fd;
+ char buffer[PATH_MAX];
+ struct aea aea;
+
+ aea.callback = callback;
+ aea.data = data;
+ aea.path = buffer;
+
+ nroots = appfwk->paths.count;
+ roots = appfwk->paths.strings;
+ for (iroot = 0 ; iroot < nroots ; iroot++) {
+ aea.root = roots[iroot];
+ fd = openat(AT_FDCWD, aea.root, O_DIRECTORY|O_RDONLY);
+ if (fd >= 0) {
+ aea.appver = stpcpy(buffer, aea.root);
+ *aea.appver++ = '/';
+ rc = aea1(fd, &aea);
+ close(fd);
+ }
+ }
+ return 0;
+}
+/*
+ struct wgt *wgt;
+ wgt = wgt_create();
+ if (!wgt)
+ return -1;
+ wgt_unref(wgt);
+
+ rfd = AT_FDCWD;
+ if (pathname) {
+ rfd = openat(rfd, pathname, O_PATH|O_DIRECTORY);
+*/
+
diff --git a/src/wgtpkg-verbose.c b/src/verbose.c
index 1472a90..1472a90 100644
--- a/src/wgtpkg-verbose.c
+++ b/src/verbose.c
diff --git a/src/verbose.h b/src/verbose.h
new file mode 100644
index 0000000..0a15564
--- /dev/null
+++ b/src/verbose.h
@@ -0,0 +1,24 @@
+/*
+ Copyright 2015 IoT.bzh
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+
+extern int verbosity;
+#define warning(...) do{if(verbosity)syslog(LOG_WARNING,__VA_ARGS__);}while(0)
+#define notice(...) do{if(verbosity)syslog(LOG_NOTICE,__VA_ARGS__);}while(0)
+#define info(...) do{if(verbosity)syslog(LOG_INFO,__VA_ARGS__);}while(0)
+#define debug(...) do{if(verbosity>1)syslog(LOG_DEBUG,__VA_ARGS__);}while(0)
+extern int verbose_scan_args(int argc, char **argv);
+
diff --git a/src/wgt-config.c b/src/wgt-config.c
index 77358fd..04548c3 100644
--- a/src/wgt-config.c
+++ b/src/wgt-config.c
@@ -27,38 +27,48 @@
#include "wgt.h"
#include "wgt-config.h"
-const char wgt_config_string_xml_file[] = "config.xml";
-const char wgt_config_string_name[] = "name";
-const char wgt_config_string_description[] = "description";
const char wgt_config_string_author[] = "author";
-const char wgt_config_string_license[] = "license";
-const char wgt_config_string_icon[] = "icon";
const char wgt_config_string_content[] = "content";
+const char wgt_config_string_defaultlocale[] = "defaultlocale";
+const char wgt_config_string_description[] = "description";
+const char wgt_config_string_email[] = "email";
+const char wgt_config_string_encoding[] = "encoding";
const char wgt_config_string_feature[] = "feature";
+const char wgt_config_string_height[] = "height";
+const char wgt_config_string_href[] = "href";
+const char wgt_config_string_icon[] = "icon";
+const char wgt_config_string_id[] = "id";
+const char wgt_config_string_license[] = "license";
+const char wgt_config_string_name[] = "name";
+const char wgt_config_string_param[] = "param";
const char wgt_config_string_preference[] = "preference";
+const char wgt_config_string_readonly[] = "readonly";
+const char wgt_config_string_required[] = "required";
+const char wgt_config_string_short[] = "short";
+const char wgt_config_string_src[] = "src";
+const char wgt_config_string_type[] = "type";
+const char wgt_config_string_value[] = "value";
+const char wgt_config_string_version[] = "version";
+const char wgt_config_string_viewmodes[] = "viewmodes";
+const char wgt_config_string_widget[] = "widget";
const char wgt_config_string_width[] = "width";
-const char wgt_config_string_height[] = "height";
-
+const char wgt_config_string_xml_file[] = "config.xml";
static struct wgt *configwgt = NULL;
static xmlDocPtr configxml = NULL;
static xmlNodePtr next(xmlNodePtr node, const char *type)
{
- while (node && node->type != XML_ELEMENT_NODE && strcmp(type, node->name))
+ while (node && (node->type != XML_ELEMENT_NODE || strcmp(type, node->name)))
node = node->next;
return node;
}
static xmlNodePtr first(const char *type)
{
- xmlNodePtr root;
- if (configxml) {
- root = xmlDocGetRootElement(configxml);
- if (root)
- return next(root->children, type);
- }
- return NULL;
+ assert(configxml);
+ assert(xmlDocGetRootElement(configxml));
+ return next(xmlDocGetRootElement(configxml)->children, type);
}
static int scorelang(xmlNodePtr node)
@@ -78,7 +88,7 @@ static xmlNodePtr element_based_localisation(const char *type)
if (resu) {
sr = scorelang(resu);
elem = next(resu->next, type);
- while (resu) {
+ while (elem) {
s = scorelang(elem);
if (s < sr) {
resu = elem;
@@ -114,34 +124,48 @@ int wgt_config_open(struct wgt *wgt)
syslog(LOG_ERR, "xml parse of config file %s failed", wgt_config_string_xml_file);
return -1;
}
+ assert(xmlDocGetRootElement(configxml));
configwgt = wgt;
return 0;
}
+xmlNodePtr wgt_config_widget()
+{
+ xmlNodePtr root;
+ assert(configxml);
+ root = xmlDocGetRootElement(configxml);
+ return strcmp(wgt_config_string_widget, root->name) ? NULL : root;
+}
+
/* elements based on localisation */
xmlNodePtr wgt_config_name()
{
+ assert(configxml);
return element_based_localisation(wgt_config_string_name);
}
xmlNodePtr wgt_config_description()
{
+ assert(configxml);
return element_based_localisation(wgt_config_string_description);
}
xmlNodePtr wgt_config_license()
{
+ assert(configxml);
return element_based_localisation(wgt_config_string_license);
}
/* elements based on path localisation */
xmlNodePtr wgt_config_author()
{
+ assert(configxml);
return first(wgt_config_string_author);
}
xmlNodePtr wgt_config_content()
{
+ assert(configxml);
return first(wgt_config_string_content);
}
@@ -149,34 +173,57 @@ xmlNodePtr wgt_config_content()
xmlNodePtr wgt_config_first_feature()
{
+ assert(configxml);
return first(wgt_config_string_feature);
}
xmlNodePtr wgt_config_next_feature(xmlNodePtr node)
{
+ assert(configxml);
+ assert(node);
return next(node->next, wgt_config_string_feature);
}
xmlNodePtr wgt_config_first_preference()
{
+ assert(configxml);
return first(wgt_config_string_preference);
}
xmlNodePtr wgt_config_next_preference(xmlNodePtr node)
{
+ assert(configxml);
+ assert(node);
return next(node->next, wgt_config_string_preference);
}
xmlNodePtr wgt_config_first_icon()
{
+ assert(configxml);
return first(wgt_config_string_icon);
}
xmlNodePtr wgt_config_next_icon(xmlNodePtr node)
{
+ assert(configxml);
+ assert(node);
return next(node->next, wgt_config_string_icon);
}
+xmlNodePtr wgt_config_first_param(xmlNodePtr node)
+{
+ assert(configxml);
+ assert(node);
+ return next(node->children, wgt_config_string_param);
+}
+
+xmlNodePtr wgt_config_next_param(xmlNodePtr node)
+{
+ assert(configxml);
+ assert(node);
+ return next(node->next, wgt_config_string_param);
+}
+
/* best sized icon */
static int score_dim(xmlNodePtr ref, xmlNodePtr x, const char *dim, int request)
@@ -229,7 +276,7 @@ static int score_dim(xmlNodePtr ref, xmlNodePtr x, const char *dim, int request)
return r;
}
-static int better_icon(xmlNodePtr ref, xmlNodePtr x, int width, int height)
+static int is_better_icon(xmlNodePtr ref, xmlNodePtr x, int width, int height)
{
int sw = score_dim(ref, x, wgt_config_string_width, width);
int sh = score_dim(ref, x, wgt_config_string_height, height);
@@ -238,12 +285,13 @@ static int better_icon(xmlNodePtr ref, xmlNodePtr x, int width, int height)
xmlNodePtr wgt_config_icon(int width, int height)
{
+ assert(configxml);
xmlNodePtr resu, icon;
resu = wgt_config_first_icon();
icon = wgt_config_next_icon(resu);
while (icon) {
- if (better_icon(resu, icon, width, height))
+ if (is_better_icon(resu, icon, width, height))
resu = icon;
icon = wgt_config_next_icon(icon);
}
diff --git a/src/wgt-config.h b/src/wgt-config.h
index 07a5c4a..480b46c 100644
--- a/src/wgt-config.h
+++ b/src/wgt-config.h
@@ -14,31 +14,51 @@
limitations under the License.
*/
-extern const char wgt_config_string_xml_file[];
-extern const char wgt_config_string_name[];
-extern const char wgt_config_string_description[];
+
extern const char wgt_config_string_author[];
-extern const char wgt_config_string_license[];
-extern const char wgt_config_string_icon[];
extern const char wgt_config_string_content[];
+extern const char wgt_config_string_defaultlocale[];
+extern const char wgt_config_string_description[];
+extern const char wgt_config_string_email[];
+extern const char wgt_config_string_encoding[];
extern const char wgt_config_string_feature[];
+extern const char wgt_config_string_height[];
+extern const char wgt_config_string_href[];
+extern const char wgt_config_string_icon[];
+extern const char wgt_config_string_id[];
+extern const char wgt_config_string_license[];
+extern const char wgt_config_string_name[];
+extern const char wgt_config_string_param[];
extern const char wgt_config_string_preference[];
+extern const char wgt_config_string_readonly[];
+extern const char wgt_config_string_required[];
+extern const char wgt_config_string_short[];
+extern const char wgt_config_string_src[];
+extern const char wgt_config_string_type[];
+extern const char wgt_config_string_value[];
+extern const char wgt_config_string_version[];
+extern const char wgt_config_string_viewmodes[];
+extern const char wgt_config_string_widget[];
extern const char wgt_config_string_width[];
-extern const char wgt_config_string_height[];
+extern const char wgt_config_string_xml_file[];
struct wgt;
extern int wgt_config_open(struct wgt *wgt);
extern void wgt_config_close();
+extern xmlNodePtr wgt_config_widget();
extern xmlNodePtr wgt_config_name();
extern xmlNodePtr wgt_config_description();
extern xmlNodePtr wgt_config_license();
extern xmlNodePtr wgt_config_author();
extern xmlNodePtr wgt_config_content();
extern xmlNodePtr wgt_config_icon(int width, int height);
+extern xmlNodePtr wgt_config_first_icon();
+extern xmlNodePtr wgt_config_next_icon(xmlNodePtr node);
extern xmlNodePtr wgt_config_first_feature();
extern xmlNodePtr wgt_config_next_feature(xmlNodePtr node);
extern xmlNodePtr wgt_config_first_preference();
extern xmlNodePtr wgt_config_next_preference(xmlNodePtr node);
-extern xmlNodePtr wgt_config_first_icon();
-extern xmlNodePtr wgt_config_next_icon(xmlNodePtr node);
+extern xmlNodePtr wgt_config_first_param(xmlNodePtr node);
+extern xmlNodePtr wgt_config_next_param(xmlNodePtr node);
+
diff --git a/src/wgt-info.c b/src/wgt-info.c
new file mode 100644
index 0000000..1dbc147
--- /dev/null
+++ b/src/wgt-info.c
@@ -0,0 +1,382 @@
+/*
+ Copyright 2015 IoT.bzh
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <syslog.h>
+#include <libxml/tree.h>
+
+#include "verbose.h"
+#include "wgt.h"
+#include "wgt-config.h"
+#include "wgt-info.h"
+
+static int getpropbool(xmlNodePtr node, const char *prop, int def)
+{
+ int result;
+ char *val = xmlGetProp(node, prop);
+ if (!val)
+ result = def;
+ else {
+ if (!strcmp(val, "true"))
+ result = 1;
+ else if (!strcmp(val, "false"))
+ result = 0;
+ else
+ result = def;
+ xmlFree(val);
+ }
+ return result;
+}
+
+static int getpropnum(xmlNodePtr node, const char *prop, int def)
+{
+ int result;
+ char *val = xmlGetProp(node, prop);
+ if (!val)
+ result = def;
+ else {
+ result = atoi(val);
+ xmlFree(val);
+ }
+ return result;
+}
+
+static xmlChar *optprop(xmlNodePtr node, const char *prop)
+{
+ return node ? xmlGetProp(node, prop) : NULL;
+}
+
+static xmlChar *optcontent(xmlNodePtr node)
+{
+ return node ? xmlNodeGetContent(node) : NULL;
+}
+
+static int fill_info(struct wgt_info *ifo, int want_icons, int want_features, int want_preferences)
+{
+ xmlNodePtr node, pnode;
+ struct wgt_info_icon *icon, **icontail;
+ struct wgt_info_feature *feature, **featuretail;
+ struct wgt_info_preference *preference, **preferencetail;
+ struct wgt_info_param *param, **paramtail;
+
+ node = wgt_config_widget();
+ if (!node) {
+ warning("no widget");
+ errno = EINVAL;
+ return -1;
+ }
+ ifo->id = xmlGetProp(node, wgt_config_string_id);
+ ifo->version = xmlGetProp(node, wgt_config_string_version);
+ ifo->width = getpropnum(node, wgt_config_string_width, 0);
+ ifo->height = getpropnum(node, wgt_config_string_height, 0);
+ ifo->viewmodes = xmlGetProp(node, wgt_config_string_viewmodes);
+ ifo->defaultlocale = xmlGetProp(node, wgt_config_string_defaultlocale);
+
+ node = wgt_config_name();
+ ifo->name = optcontent(node);
+ ifo->name_short = optprop(node, wgt_config_string_short);
+
+ node = wgt_config_description();
+ ifo->description = optcontent(node);
+
+ node = wgt_config_author();
+ ifo->author = optcontent(node);
+ ifo->author_href = optprop(node, wgt_config_string_href);
+ ifo->author_email = optprop(node, wgt_config_string_email);
+
+ node = wgt_config_license();
+ ifo->license = optcontent(node);
+ ifo->license_href = optprop(node, wgt_config_string_href);
+
+ node = wgt_config_content();
+ ifo->content_src = optprop(node, wgt_config_string_src);
+ if (node && ifo->content_src == NULL) {
+ warning("content without src");
+ errno = EINVAL;
+ return -1;
+ }
+ ifo->content_type = optprop(node, wgt_config_string_type);
+ ifo->content_encoding = optprop(node, wgt_config_string_encoding);
+
+ if (want_icons) {
+ icontail = &ifo->icons;
+ node = wgt_config_first_icon();
+ while (node) {
+ icon = malloc(sizeof * icon);
+ if (icon == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ icon->src = xmlGetProp(node, wgt_config_string_src);
+ icon->width = getpropnum(node, wgt_config_string_width, 0);
+ icon->height = getpropnum(node, wgt_config_string_height, 0);
+
+ icon->next = NULL;
+ *icontail = icon;
+
+ if (icon->src == NULL) {
+ warning("icon without src");
+ errno = EINVAL;
+ return -1;
+ }
+ icontail = &icon->next;
+ node = wgt_config_next_icon(node);
+ }
+ }
+
+ if (want_features) {
+ featuretail = &ifo->features;
+ node = wgt_config_first_feature();
+ while (node) {
+ feature = malloc(sizeof * feature);
+ if (feature == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ feature->name = xmlGetProp(node, wgt_config_string_name);
+ feature->required = getpropbool(node, wgt_config_string_required, 1);
+
+ feature->next = NULL;
+ *featuretail = feature;
+
+ if (feature->name == NULL) {
+ warning("feature without name");
+ errno = EINVAL;
+ return -1;
+ }
+
+ paramtail = &feature->params;
+ pnode = wgt_config_first_param(node);
+ while (pnode) {
+ param = malloc(sizeof * param);
+ if (param == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ param->name = xmlGetProp(pnode, wgt_config_string_name);
+ param->value = xmlGetProp(pnode, wgt_config_string_value);
+
+ param->next = NULL;
+ *paramtail = param;
+
+ if (param->name == NULL || param->value == NULL) {
+ warning("param without name or value");
+ errno = EINVAL;
+ return -1;
+ }
+
+ paramtail = &param->next;
+ pnode = wgt_config_next_param(pnode);
+ }
+
+ featuretail = &feature->next;
+ node = wgt_config_next_feature(node);
+ }
+ }
+
+ if (want_preferences) {
+ preferencetail = &ifo->preferences;
+ node = wgt_config_first_preference();
+ while (node) {
+ preference = malloc(sizeof * preference);
+ if (preference == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ preference->name = xmlGetProp(node, wgt_config_string_name);
+ preference->value = xmlGetProp(node, wgt_config_string_value);
+ preference->readonly = getpropbool(node, wgt_config_string_readonly, 0);
+
+ *preferencetail = preference;
+ preference->next = NULL;
+
+ if (preference->name == NULL) {
+ warning("preference without name");
+ errno = EINVAL;
+ return -1;
+ }
+
+ preferencetail = &preference->next;
+ node = wgt_config_next_preference(node);
+ }
+ }
+ return 0;
+}
+
+struct wgt_info *wgt_info_get(struct wgt *wgt, int icons, int features, int preferences)
+{
+ int rc;
+ struct wgt_info *result;
+
+ assert(wgt);
+ assert(wgt_is_connected(wgt));
+ rc = wgt_config_open(wgt);
+ if (rc) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ result = calloc(sizeof * result, 1);
+ if (!result) {
+ wgt_config_close();
+ errno = ENOMEM;
+ return NULL;
+ }
+ result->refcount = 1;
+
+ rc = fill_info(result, icons, features, preferences);
+ wgt_config_close();
+ if (rc) {
+ wgt_info_unref(result);
+ return NULL;
+ }
+ return result;
+}
+
+void wgt_info_addref(struct wgt_info *ifo)
+{
+ assert(ifo);
+ assert(ifo->refcount > 0);
+ ifo->refcount++;
+}
+
+void wgt_info_unref(struct wgt_info *ifo)
+{
+ struct wgt_info_icon *icon;
+ struct wgt_info_feature *feature;
+ struct wgt_info_preference *preference;
+ struct wgt_info_param *param;
+
+ assert(ifo);
+ assert(ifo->refcount > 0);
+ if (--ifo->refcount)
+ return;
+
+ xmlFree(ifo->id);
+ xmlFree(ifo->version);
+ xmlFree(ifo->viewmodes);
+ xmlFree(ifo->defaultlocale);
+ xmlFree(ifo->name);
+ xmlFree(ifo->name_short);
+ xmlFree(ifo->description);
+ xmlFree(ifo->author);
+ xmlFree(ifo->author_href);
+ xmlFree(ifo->author_email);
+ xmlFree(ifo->license);
+ xmlFree(ifo->license_href);
+ xmlFree(ifo->content_src);
+ xmlFree(ifo->content_type);
+ xmlFree(ifo->content_encoding);
+
+ while(ifo->icons) {
+ icon = ifo->icons;
+ ifo->icons = icon->next;
+ xmlFree(icon->src);
+ free(icon);
+ }
+
+ while(ifo->features) {
+ feature = ifo->features;
+ ifo->features = feature->next;
+ xmlFree(feature->name);
+ while(feature->params) {
+ param = feature->params;
+ feature->params = param->next;
+ xmlFree(param->name);
+ xmlFree(param->value);
+ free(param);
+ }
+ free(feature);
+ }
+
+ while(ifo->preferences) {
+ preference = ifo->preferences;
+ ifo->preferences = preference->next;
+ xmlFree(preference->name);
+ xmlFree(preference->value);
+ free(preference);
+ }
+ free(ifo);
+}
+
+void wgt_info_dump(struct wgt_info *ifo, int fd, const char *prefix)
+{
+ FILE *f;
+ struct wgt_info_icon *icon;
+ struct wgt_info_feature *feature;
+ struct wgt_info_preference *preference;
+ struct wgt_info_param *param;
+
+ assert(ifo);
+ f = fdopen(fd, "w");
+ if (f == NULL) {
+ warning("can't fdopen in wgt_info_dump");
+ return;
+ }
+
+ if (ifo->id) fprintf(f, "%sid: %s\n", prefix, ifo->id);
+ if (ifo->width) fprintf(f, "%swidth: %d\n", prefix, ifo->width);
+ if (ifo->height) fprintf(f, "%sheight: %d\n", prefix, ifo->height);
+ if (ifo->version) fprintf(f, "%sversion: %s\n", prefix, ifo->version);
+ if (ifo->viewmodes) fprintf(f, "%sviewmodes: %s\n", prefix, ifo->viewmodes);
+ if (ifo->defaultlocale) fprintf(f, "%sdefaultlocale: %s\n", prefix, ifo->defaultlocale);
+ if (ifo->name) fprintf(f, "%sname: %s\n", prefix, ifo->name);
+ if (ifo->name_short) fprintf(f, "%sname_short: %s\n", prefix, ifo->name_short);
+ if (ifo->description) fprintf(f, "%sdescription: %s\n", prefix, ifo->description);
+ if (ifo->author) fprintf(f, "%sauthor: %s\n", prefix, ifo->author);
+ if (ifo->author_href) fprintf(f, "%sauthor_href: %s\n", prefix, ifo->author_href);
+ if (ifo->author_email) fprintf(f, "%sauthor_email: %s\n", prefix, ifo->author_email);
+ if (ifo->license) fprintf(f, "%slicense: %s\n", prefix, ifo->license);
+ if (ifo->license_href) fprintf(f, "%slicense_href: %s\n", prefix, ifo->license_href);
+ if (ifo->content_src) fprintf(f, "%scontent_src: %s\n", prefix, ifo->content_src);
+ if (ifo->content_type) fprintf(f, "%scontent_type: %s\n", prefix, ifo->content_type);
+ if (ifo->content_encoding) fprintf(f, "%scontent_encoding: %s\n", prefix, ifo->content_encoding);
+
+ icon = ifo->icons;
+ while(icon) {
+ fprintf(f, "%s+ icon src: %s\n", prefix, icon->src);
+ if (icon->width) fprintf(f, "%s width: %d\n", prefix, icon->width);
+ if (icon->height) fprintf(f, "%s height: %d\n", prefix, icon->height);
+ icon = icon->next;
+ }
+
+ feature = ifo->features;
+ while(feature) {
+ fprintf(f, "%s+ feature name: %s\n", prefix, feature->name);
+ fprintf(f, "%s required: %s\n", prefix, feature->required ? "true" : "false");
+ param = feature->params;
+ while(param) {
+ fprintf(f, "%s + param name: %s\n", prefix, param->name);
+ fprintf(f, "%s value: %s\n", prefix, param->value);
+ param = param->next;
+ }
+ feature = feature->next;
+ }
+
+ preference = ifo->preferences;
+ while(preference) {
+ fprintf(f, "%s+ preference name: %s\n", prefix, preference->name);
+ if (preference->value) fprintf(f, "%s value: %s\n", prefix, preference->value);
+ fprintf(f, "%s readonly: %s\n", prefix, preference->readonly ? "true" : "false");
+ preference = preference->next;
+ }
+
+ fclose(f);
+}
+
diff --git a/src/wgt-info.h b/src/wgt-info.h
new file mode 100644
index 0000000..57f8d82
--- /dev/null
+++ b/src/wgt-info.h
@@ -0,0 +1,74 @@
+/*
+ Copyright 2015 IoT.bzh
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+
+struct wgt_info_icon {
+ struct wgt_info_icon *next;
+ char *src;
+ int width;
+ int height;
+};
+
+struct wgt_info_param {
+ struct wgt_info_param *next;
+ char *name;
+ char *value;
+};
+
+struct wgt_info_feature {
+ struct wgt_info_feature *next;
+ char *name;
+ int required;
+ struct wgt_info_param *params;
+};
+
+struct wgt_info_preference {
+ struct wgt_info_preference *next;
+ char *name;
+ char *value;
+ int readonly;
+};
+
+struct wgt_info {
+ int refcount;
+ char *id;
+ char *version;
+ int width;
+ int height;
+ char *viewmodes;
+ char *defaultlocale;
+ char *name;
+ char *name_short;
+ char *description;
+ char *author;
+ char *author_href;
+ char *author_email;
+ char *license;
+ char *license_href;
+ char *content_src;
+ char *content_type;
+ char *content_encoding;
+ struct wgt_info_icon *icons;
+ struct wgt_info_feature *features;
+ struct wgt_info_preference *preferences;
+};
+
+struct wgt;
+extern struct wgt_info *wgt_info_get(struct wgt *wgt, int icons, int features, int preferences);
+extern void wgt_info_addref(struct wgt_info *info);
+extern void wgt_info_unref(struct wgt_info *info);
+extern void wgt_info_dump(struct wgt_info *info, int fd, const char *prefix);
+
diff --git a/src/wgt-locales.c b/src/wgt-locales.c
deleted file mode 100644
index 9b97cc4..0000000
--- a/src/wgt-locales.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- Copyright 2015 IoT.bzh
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-
-
-#define _GNU_SOURCE
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <ctype.h>
-
-#include "wgt.h"
-
-struct locarr {
- int count;
- char **arr;
-};
-
-static struct locarr locarr = { 0, NULL };
-
-static int add(const char *locstr, int length)
-{
- int i;
- char *item, **ptr;
-
- item = strndup(locstr, length);
- if (item != NULL) {
- for (i = 0 ; item[i] ; i++)
- item[i] = tolower(item[i]);
- for (i = 0 ; i < locarr.count ; i++)
- if (!strcmp(item, locarr.arr[i])) {
- free(item);
- return 0;
- }
-
- ptr = realloc(locarr.arr, (1 + locarr.count) * sizeof(locarr.arr[0]));
- if (ptr) {
- locarr.arr = ptr;
- locarr.arr[locarr.count++] = item;
- return 0;
- }
- free(item);
- }
- errno = ENOMEM;
- return -1;
-}
-
-void locales_reset()
-{
- while (locarr.count)
- free(locarr.arr[--locarr.count]);
-}
-
-int locales_add(const char *locstr)
-{
- const char *stop, *next;
- while (*locstr) {
- stop = strchrnul(locstr, ',');
- next = stop + !!*stop;
- while (locstr != stop) {
- if (add(locstr, stop - locstr))
- return -1;
- do { stop--; } while(stop > locstr && *stop != '-');
- }
- locstr = next;
- }
- return 0;
-}
-
-int locales_score(const char *lang)
-{
- int i;
-
- if (lang)
- for (i = 0 ; i < locarr.count ; i++)
- if (!strcasecmp(lang, locarr.arr[i]))
- return i;
-
- return INT_MAX;
-}
-
-char *locales_locate_file(const char *filename)
-{
- int i;
- char path[PATH_MAX];
- char * result;
-
- for (i = 0 ; i < locarr.count ; i++) {
- if (snprintf(path, sizeof path, "locales/%s/%s", locarr.arr[i], filename) >= (int)(sizeof path)) {
- errno = EINVAL;
- return NULL;
- }
- if (widget_has(path)) {
- result = strdup(path);
- if (!result)
- errno = ENOMEM;
- return result;
- }
- }
- if (widget_has(filename)) {
- result = strdup(filename);
- if (!result)
- errno = ENOMEM;
- return result;
- }
- errno = ENOENT;
- return NULL;
-}
-
diff --git a/src/wgt.c b/src/wgt.c
index dd889d5..db59091 100644
--- a/src/wgt.c
+++ b/src/wgt.c
@@ -30,6 +30,7 @@
#include "wgt.h"
struct wgt {
+ int refcount;
int rootfd;
int nrlocales;
char **locales;
@@ -73,7 +74,10 @@ static int validsubpath(const char *subpath)
struct wgt *wgt_create()
{
struct wgt *wgt = malloc(sizeof * wgt);
- if (wgt) {
+ if (!wgt)
+ errno = ENOMEM;
+ else {
+ wgt->refcount = 1;
wgt->rootfd = -1;
wgt->nrlocales = 0;
wgt->locales = NULL;
@@ -96,9 +100,16 @@ void wgt_locales_reset(struct wgt *wgt)
free(wgt->locales[--wgt->nrlocales]);
}
-void wgt_destroy(struct wgt *wgt)
+void wgt_addref(struct wgt *wgt)
+{
+ assert(wgt);
+ wgt->refcount++;
+}
+
+void wgt_unref(struct wgt *wgt)
{
- if (wgt) {
+ assert(wgt);
+ if (!--wgt->refcount) {
wgt_disconnect(wgt);
wgt_locales_reset(wgt);
free(wgt->locales);
@@ -106,13 +117,13 @@ void wgt_destroy(struct wgt *wgt)
}
}
-int wgt_connect(struct wgt *wgt, const char *pathname)
+int wgt_connectat(struct wgt *wgt, int dirfd, const char *pathname)
{
int rfd;
assert(wgt);
- rfd = AT_FDCWD;
+ rfd = dirfd;
if (pathname) {
rfd = openat(rfd, pathname, O_PATH|O_DIRECTORY);
if (rfd < 0)
@@ -124,6 +135,11 @@ int wgt_connect(struct wgt *wgt, const char *pathname)
return 0;
}
+int wgt_connect(struct wgt *wgt, const char *pathname)
+{
+ return wgt_connectat(wgt, AT_FDCWD, pathname);
+}
+
int wgt_is_connected(struct wgt *wgt)
{
assert(wgt);
diff --git a/src/wgt.h b/src/wgt.h
index 81aea1e..f159a3b 100644
--- a/src/wgt.h
+++ b/src/wgt.h
@@ -17,9 +17,11 @@
struct wgt;
extern struct wgt *wgt_create();
-extern void wgt_destroy(struct wgt *wgt);
+extern void wgt_addref(struct wgt *wgt);
+extern void wgt_unref(struct wgt *wgt);
extern int wgt_connect(struct wgt *wgt, const char *pathname);
+extern int wgt_connectat(struct wgt *wgt, int fd, const char *pathname);
extern void wgt_disconnect(struct wgt *wgt);
extern int wgt_is_connected(struct wgt *wgt);
diff --git a/src/wgtpkg-digsig.c b/src/wgtpkg-digsig.c
index 284acd1..6e66e38 100644
--- a/src/wgtpkg-digsig.c
+++ b/src/wgtpkg-digsig.c
@@ -24,6 +24,7 @@
#include <libxml/uri.h>
+#include "verbose.h"
#include "wgtpkg.h"
diff --git a/src/wgtpkg-info.c b/src/wgtpkg-info.c
new file mode 100644
index 0000000..1a7724b
--- /dev/null
+++ b/src/wgtpkg-info.c
@@ -0,0 +1,182 @@
+/*
+ Copyright 2015 IoT.bzh
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#define _BSD_SOURCE /* see readdir */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <syslog.h>
+#include <getopt.h>
+
+#include "verbose.h"
+#include "wgtpkg.h"
+#include "wgt.h"
+#include "wgt-info.h"
+
+static const char appname[] = "wgtpkg-info";
+
+static void show(const char *wgtfile);
+
+static void usage()
+{
+ printf(
+ "usage: %s [-f] [-q] [-v] wgtfile...\n"
+ "\n"
+ " -q quiet\n"
+ " -v verbose\n"
+ "\n",
+ appname
+ );
+}
+
+static struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "quiet", no_argument, NULL, 'q' },
+ { "verbose", no_argument, NULL, 'v' },
+ { NULL, 0, NULL, 0 }
+};
+
+/* info the widgets of the list */
+int main(int ac, char **av)
+{
+ int i;
+ char *wpath;
+
+ openlog(appname, LOG_PERROR, LOG_USER);
+
+ xmlsec_init();
+
+ for (;;) {
+ i = getopt_long(ac, av, "hqv", options, NULL);
+ if (i < 0)
+ break;
+ switch (i) {
+ case 'h':
+ usage();
+ return 0;
+ case 'q':
+ if (verbosity)
+ verbosity--;
+ break;
+ case 'v':
+ verbosity++;
+ break;
+ case ':':
+ syslog(LOG_ERR, "missing argument value");
+ return 1;
+ default:
+ syslog(LOG_ERR, "unrecognized option");
+ return 1;
+ }
+ }
+
+ /* canonic names for files */
+ av += optind;
+ for (i = 0 ; av[i] != NULL ; i++) {
+ wpath = realpath(av[i], NULL);
+ if (wpath == NULL) {
+ syslog(LOG_ERR, "error while getting realpath of %dth widget: %s", i+1, av[i]);
+ return 1;
+ }
+ av[i] = wpath;
+ }
+
+ /* info widgets */
+ for ( ; *av ; av++)
+ show(*av);
+
+ return 0;
+}
+
+static struct wgt *wgt_at_workdir()
+{
+ int rc, wfd;
+ struct wgt *wgt;
+
+ wfd = workdirfd();
+ if (wfd < 0)
+ return NULL;
+
+ wgt = wgt_create();
+ if (!wgt) {
+ syslog(LOG_ERR, "failed to allocate wgt");
+ close(wfd);
+ return NULL;
+ }
+
+ rc = wgt_connectat(wgt, wfd, NULL);
+ if (rc) {
+ syslog(LOG_ERR, "failed to connect wgt to workdir");
+ close(wfd);
+ wgt_unref(wgt);
+ return NULL;
+ }
+
+ return wgt;
+}
+
+
+static int check_and_show()
+{
+ struct wgt *wgt;
+ struct wgt_info *ifo;
+
+ wgt = wgt_at_workdir();
+ if (!wgt)
+ return -1;
+
+ ifo = wgt_info_get(wgt, 1, 1, 1);
+ if (!ifo) {
+ wgt_unref(wgt);
+ return -1;
+ }
+ wgt_info_dump(ifo, 1, "");
+ wgt_info_unref(ifo);
+ wgt_unref(wgt);
+ return 0;
+}
+
+/* install the widget of the file */
+static void show(const char *wgtfile)
+{
+ notice("-- INFO for widget %s --", wgtfile);
+
+ /* workdir */
+ if (make_workdir_base("/tmp", "UNPACK", 0)) {
+ syslog(LOG_ERR, "failed to create a working directory");
+ return;
+ }
+
+ if (enter_workdir(0))
+ goto error2;
+
+ if (zread(wgtfile, 0))
+ goto error2;
+
+ if (check_all_signatures())
+ goto error2;
+
+ check_and_show();
+
+error2:
+ remove_workdir();
+ return;
+}
+
diff --git a/src/wgtpkg-install.c b/src/wgtpkg-install.c
index 7a88ebf..1d79591 100644
--- a/src/wgtpkg-install.c
+++ b/src/wgtpkg-install.c
@@ -18,67 +18,259 @@
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <syslog.h>
+#include <getopt.h>
+#include "verbose.h"
#include "wgtpkg.h"
+#include "wgt.h"
+#include "wgt-info.h"
-/* install the widget of the file */
-static void install(const char *wgtfile)
-{
- notice("-- INSTALLING widget %s", wgtfile);
-
- if (enter_workdir(1))
- goto error;
-
- if (zread(wgtfile, 0))
- goto error;
+static const char appname[] = "wgtpkg-install";
+static const char *root;
+static char **permissions = NULL;
+static int force;
- if (check_all_signatures())
- goto error;
+static void install(const char *wgtfile);
+static void add_permissions(const char *list);
- return;
-
-error:
- return;
- exit(1);
+static void usage()
+{
+ printf(
+ "usage: %s [-f] [-q] [-v] [-p list] rootdir wgtfile...\n"
+ "\n"
+ " rootdir the root directory for installing\n"
+ " -p list a list of comma separated permissions to allow\n"
+ " -f force overwriting\n"
+ " -q quiet\n"
+ " -v verbose\n"
+ "\n",
+ appname
+ );
}
+static struct option options[] = {
+ { "permissions", required_argument, NULL, 'p' },
+ { "force", no_argument, NULL, 'f' },
+ { "help", no_argument, NULL, 'h' },
+ { "quiet", no_argument, NULL, 'q' },
+ { "verbose", no_argument, NULL, 'v' },
+ { NULL, 0, NULL, 0 }
+};
+
/* install the widgets of the list */
int main(int ac, char **av)
{
- int i, kwd;
+ int i;
+ char *wpath;
- openlog("wgtpkg-install", LOG_PERROR, LOG_AUTH);
+ openlog(appname, LOG_PERROR, LOG_AUTH);
xmlsec_init();
- ac = verbose_scan_args(ac, av);
-
- /* canonic names for files */
- for (i = 1 ; av[i] != NULL ; i++)
- if ((av[i] = realpath(av[i], NULL)) == NULL) {
- syslog(LOG_ERR, "error while getting realpath of %dth argument", i);
+ force = 0;
+ for (;;) {
+ i = getopt_long(ac, av, "hfqvp:", options, NULL);
+ if (i < 0)
+ break;
+ switch (i) {
+ case 'f':
+ force = 1;
+ break;
+ case 'h':
+ usage();
+ return 0;
+ case 'q':
+ if (verbosity)
+ verbosity--;
+ break;
+ case 'v':
+ verbosity++;
+ break;
+ case 'p':
+ add_permissions(optarg);
+ break;
+ case ':':
+ syslog(LOG_ERR, "missing argument value");
+ return 1;
+ default:
+ syslog(LOG_ERR, "unrecognized option");
return 1;
}
+ }
- /* workdir */
- kwd = 1;
- if (make_workdir(kwd)) {
- syslog(LOG_ERR, "failed to create a working directory");
+ ac -= optind;
+ if (ac < 2) {
+ syslog(LOG_ERR, "arguments are missing");
return 1;
}
- if (!kwd)
- atexit(remove_workdir);
+
+ /* canonic names for files */
+ av += optind;
+ for (i = 0 ; av[i] != NULL ; i++) {
+ wpath = realpath(av[i], NULL);
+ if (wpath == NULL) {
+ syslog(LOG_ERR, "error while getting realpath of %dth widget: %s", i+1, av[i]);
+ return 1;
+ }
+ av[i] = wpath;
+ }
+ root = *av++;
/* install widgets */
- for (av++ ; *av ; av++)
+ for ( ; *av ; av++)
install(*av);
- exit(0);
return 0;
}
+static int has_permission(const char *name)
+{
+ char **p = permissions;
+ if (p) {
+ while(*p) {
+ if (0 == strcmp(*p, name))
+ return 1;
+ p++;
+ }
+ }
+ return 0;
+}
+
+static void add_permissions(const char *list)
+{
+ char **ps, *p;
+ const char *iter;
+ int n, on;
+ static const char separators[] = " \t\n\r,";
+
+ n = 0;
+ iter = list + strspn(list, separators);
+ while(*iter) {
+ n++;
+ iter += strcspn(iter, separators);
+ iter += strspn(iter, separators);
+ }
+ if (n == 0)
+ return;
+
+ on = 0;
+ ps = permissions;
+ if (ps)
+ while(*ps++)
+ on++;
+
+ ps = realloc(permissions, (1 + on + n) * sizeof * ps);
+ if (!ps) {
+ syslog(LOG_ERR, "Can't allocate memory for permissions");
+ exit(1);
+ }
+
+ permissions = ps;
+ ps[on] = NULL;
+
+ iter = list + strspn(list, separators);
+ while(*iter) {
+ n = strcspn(iter, separators);
+ p = strndup(iter, n);
+ if (!p) {
+ syslog(LOG_ERR, "Can't allocate permission");
+ exit(1);
+ }
+ if (has_permission(p))
+ free(p);
+ else {
+ ps[on] = p;
+ ps[++on] = NULL;
+ }
+ iter += n;
+ iter += strspn(iter, separators);
+ }
+}
+
+static struct wgt *wgt_at_workdir()
+{
+ int rc, wfd;
+ struct wgt *wgt;
+
+ wfd = workdirfd();
+ if (wfd < 0)
+ return NULL;
+
+ wgt = wgt_create();
+ if (!wgt) {
+ syslog(LOG_ERR, "failed to allocate wgt");
+ close(wfd);
+ return NULL;
+ }
+
+ rc = wgt_connectat(wgt, wfd, NULL);
+ if (rc) {
+ syslog(LOG_ERR, "failed to connect wgt to workdir");
+ close(wfd);
+ wgt_unref(wgt);
+ return NULL;
+ }
+
+ return wgt;
+}
+
+
+static int check_and_place()
+{
+ struct wgt *wgt;
+ struct wgt_info *ifo;
+
+ wgt = wgt_at_workdir();
+ if (!wgt)
+ return -1;
+
+ ifo = wgt_info_get(wgt, 1, 1, 1);
+ if (!ifo) {
+ wgt_unref(wgt);
+ return -1;
+ }
+ wgt_info_dump(ifo, 1, "");
+ wgt_info_unref(ifo);
+ wgt_unref(wgt);
+ return 0;
+}
+
+/* install the widget of the file */
+static void install(const char *wgtfile)
+{
+ notice("-- INSTALLING widget %s --", wgtfile);
+
+ /* workdir */
+ if (make_workdir_base(root, "UNPACK", 0)) {
+ syslog(LOG_ERR, "failed to create a working directory");
+ goto error1;
+ }
+
+ if (enter_workdir(0))
+ goto error2;
+
+ if (zread(wgtfile, 0))
+ goto error2;
+
+ if (check_all_signatures())
+ goto error2;
+
+ if (check_and_place())
+ goto error2;
+
+ return;
+
+error2:
+ remove_workdir();
+
+error1:
+ return;
+}
+
+
diff --git a/src/wgtpkg-pack.c b/src/wgtpkg-pack.c
index a8aaa05..be1e5ab 100644
--- a/src/wgtpkg-pack.c
+++ b/src/wgtpkg-pack.c
@@ -26,6 +26,7 @@
#include <sys/stat.h>
#include <fcntl.h>
+#include "verbose.h"
#include "wgtpkg.h"
#if !defined(MAXCERT)
diff --git a/src/wgtpkg-sign.c b/src/wgtpkg-sign.c
index cd506fc..c4faf29 100644
--- a/src/wgtpkg-sign.c
+++ b/src/wgtpkg-sign.c
@@ -26,6 +26,7 @@
#include <sys/stat.h>
#include <fcntl.h>
+#include "verbose.h"
#include "wgtpkg.h"
#if !defined(MAXCERT)
@@ -96,7 +97,7 @@ int main(int ac, char **av)
number = UINT_MAX;
keyfile = directory = NULL;
for (;;) {
- i = getopt_long(ac, av, "hfak:c:d:", options, NULL);
+ i = getopt_long(ac, av, "hfqvak:c:d:", options, NULL);
if (i < 0)
break;
switch (i) {
@@ -112,6 +113,13 @@ int main(int ac, char **av)
case 'f': force = 1; continue;
case 'a': author = 1; continue;
case 'h': usage(); return 0;
+ case 'q':
+ if (verbosity)
+ verbosity--;
+ break;
+ case 'v':
+ verbosity++;
+ break;
case ':':
syslog(LOG_ERR, "missing argument");
return 1;
diff --git a/src/wgtpkg-workdir.c b/src/wgtpkg-workdir.c
index 0c184a5..12cfa24 100644
--- a/src/wgtpkg-workdir.c
+++ b/src/wgtpkg-workdir.c
@@ -14,27 +14,26 @@
limitations under the License.
*/
+#define _GNU_SOURCE
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <syslog.h>
#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
#include <sys/stat.h>
#include "wgtpkg.h"
-#ifndef PREDIR
-#define PREDIR "./"
-#endif
-
static int mode = 0700;
static char workdir[PATH_MAX];
/* removes recursively the content of a directory */
-static int clean_dir()
+static int clean_dirfd(int dirfd)
{
- int cr;
+ int cr, fd;
DIR *dir;
struct dirent *ent;
struct {
@@ -42,16 +41,16 @@ static int clean_dir()
char spare[PATH_MAX];
} entry;
- dir = opendir(".");
+ dir = fdopendir(dirfd);
if (dir == NULL) {
- syslog(LOG_ERR, "opendir failed in clean_dir");
+ syslog(LOG_ERR, "opendir failed in clean_dirfd");
return -1;
}
cr = -1;
for (;;) {
if (readdir_r(dir, &entry.entry, &ent) != 0) {
- syslog(LOG_ERR, "readdir_r failed in clean_dir");
+ syslog(LOG_ERR, "readdir_r failed in clean_dirfd");
goto error;
}
if (ent == NULL)
@@ -59,25 +58,25 @@ static int clean_dir()
if (ent->d_name[0] == '.' && (ent->d_name[1] == 0
|| (ent->d_name[1] == '.' && ent->d_name[2] == 0)))
continue;
- cr = unlink(ent->d_name);
+ cr = unlinkat(dirfd, ent->d_name, 0);
if (!cr)
continue;
if (errno != EISDIR) {
- syslog(LOG_ERR, "unlink of %s failed in clean_dir", ent->d_name);
+ syslog(LOG_ERR, "unlink of %s failed in clean_dirfd", ent->d_name);
goto error;
}
- if (chdir(ent->d_name)) {
- syslog(LOG_ERR, "enter directory %s failed in clean_dir", ent->d_name);
+ fd = openat(dirfd, ent->d_name, O_DIRECTORY|O_RDONLY);
+ if (fd < 0) {
+ syslog(LOG_ERR, "opening directory %s failed in clean_dirfd", ent->d_name);
goto error;
}
- cr = clean_dir();
+ cr = clean_dirfd(fd);
+ close(fd);
if (cr)
goto error;
- if (chdir(".."))
- goto error;
- cr = rmdir(ent->d_name);
+ cr = unlinkat(dirfd, ent->d_name, AT_REMOVEDIR);
if (cr) {
- syslog(LOG_ERR, "rmdir of %s failed in clean_dir", ent->d_name);
+ syslog(LOG_ERR, "rmdir of %s failed in clean_dirfd", ent->d_name);
goto error;
}
}
@@ -87,6 +86,21 @@ error:
return cr;
}
+/* removes recursively the content of a directory */
+static int clean_dir(const char *directory)
+{
+ int fd, rc;
+
+ fd = openat(AT_FDCWD, directory, O_DIRECTORY|O_RDONLY);
+ if (fd < 0) {
+ syslog(LOG_ERR, "opening directory %s failed in clean_dir", directory);
+ return fd;
+ }
+ rc = clean_dirfd(fd);
+ close(fd);
+ return rc;
+}
+
/* removes the content of the working directory */
int enter_workdir(int clean)
{
@@ -94,7 +108,7 @@ int enter_workdir(int clean)
if (rc)
syslog(LOG_ERR, "entring workdir %s failed", workdir);
else if (clean)
- rc = clean_dir();
+ rc = clean_dir(workdir);
return rc;
}
@@ -103,7 +117,7 @@ void remove_workdir()
{
enter_workdir(1);
chdir("..");
- unlink(workdir);
+ rmdir(workdir);
}
int set_workdir(const char *name, int create)
@@ -116,6 +130,7 @@ int set_workdir(const char *name, int create)
length = strlen(name);
if (length >= sizeof workdir) {
syslog(LOG_ERR, "workdir name too long");
+ errno = EINVAL;
return -1;
}
@@ -133,16 +148,24 @@ int set_workdir(const char *name, int create)
} else if (!S_ISDIR(s.st_mode)) {
syslog(LOG_ERR, "%s isn't a directory", name);
+ errno = ENOTDIR;
return -1;
}
memcpy(workdir, name, 1+length);
return 0;
}
-/* install the widgets of the list */
-int make_workdir(int reuse)
+int make_workdir_base(const char *root, const char *prefix, int reuse)
{
- int i;
+ int i, n, r, l;
+
+ n = snprintf(workdir, sizeof workdir, "%s/%s", root, prefix);
+ if (n >= sizeof workdir) {
+ syslog(LOG_ERR, "workdir prefix too long");
+ errno = EINVAL;
+ return -1;
+ }
+ r = (int)(sizeof workdir) - n;
/* create a temporary directory */
for (i = 0 ; ; i++) {
@@ -150,7 +173,12 @@ int make_workdir(int reuse)
syslog(LOG_ERR, "exhaustion of workdirs");
return -1;
}
- sprintf(workdir, PREDIR "PACK%d", i);
+ l = snprintf(workdir + n, r, "%d", i);
+ if (l >= r) {
+ syslog(LOG_ERR, "computed workdir too long");
+ errno = EINVAL;
+ return -1;
+ }
if (!mkdir(workdir, mode))
break;
if (errno != EEXIST) {
@@ -164,3 +192,21 @@ int make_workdir(int reuse)
return 0;
}
+int make_workdir(int reuse)
+{
+ return make_workdir_base(".", "PACK", reuse);
+}
+
+int workdirfd()
+{
+ int result = open(workdir, O_PATH|O_DIRECTORY);
+ if (result < 0)
+ syslog(LOG_ERR, "can't get fd for workdir %.*s: %m", PATH_MAX, workdir);
+ return result;
+}
+
+int move_workdir(const char *dest, int parents, int force)
+{
+
+}
+
diff --git a/src/wgtpkg.h b/src/wgtpkg.h
index d35b7f4..97af130 100644
--- a/src/wgtpkg.h
+++ b/src/wgtpkg.h
@@ -89,21 +89,14 @@ extern int file_set_prop(struct filedesc *file, const char *name, const char *va
extern const char *file_get_prop(struct filedesc *file, const char *name);
/**************************************************************/
-/* from wgtpkg-verbose */
-extern int verbosity;
-#define warning(...) do{if(verbosity)syslog(LOG_WARNING,__VA_ARGS__);}while(0)
-#define notice(...) do{if(verbosity)syslog(LOG_NOTICE,__VA_ARGS__);}while(0)
-#define info(...) do{if(verbosity)syslog(LOG_INFO,__VA_ARGS__);}while(0)
-#define debug(...) do{if(verbosity>1)syslog(LOG_DEBUG,__VA_ARGS__);}while(0)
-extern int verbose_scan_args(int argc, char **argv);
-
-/**************************************************************/
/* from wgtpkg-workdir */
extern int enter_workdir(int clean);
extern void remove_workdir();
-extern int make_workdir(int reuse);
extern int set_workdir(const char *name, int create);
+extern int make_workdir_base(const char *root, const char *prefix, int reuse);
+extern int make_workdir(int reuse);
+extern int workdirfd();
/**************************************************************/
/* from wgtpkg-xmlsec */