added info retrieval
authorJosé Bollo <jose.bollo@iot.bzh>
Thu, 10 Dec 2015 15:39:05 +0000 (16:39 +0100)
committerJosé Bollo <jose.bollo@iot.bzh>
Thu, 10 Dec 2015 15:39:05 +0000 (16:39 +0100)
Change-Id: I6f91b15e87308cf01db4ddafa3c2715c251f5fe5

19 files changed:
.gitignore
src/Makefile.am
src/appfwk.c [new file with mode: 0644]
src/verbose.c [moved from src/wgtpkg-verbose.c with 100% similarity]
src/verbose.h [new file with mode: 0644]
src/wgt-config.c
src/wgt-config.h
src/wgt-info.c [new file with mode: 0644]
src/wgt-info.h [new file with mode: 0644]
src/wgt-locales.c [deleted file]
src/wgt.c
src/wgt.h
src/wgtpkg-digsig.c
src/wgtpkg-info.c [new file with mode: 0644]
src/wgtpkg-install.c
src/wgtpkg-pack.c
src/wgtpkg-sign.c
src/wgtpkg-workdir.c
src/wgtpkg.h

index bdc386d..4773e7e 100644 (file)
@@ -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
+
index 0f35ac4..144d48a 100644 (file)
@@ -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 (file)
index 0000000..6dc7182
--- /dev/null
@@ -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);
+*/
+
similarity index 100%
rename from src/wgtpkg-verbose.c
rename to src/verbose.c
diff --git a/src/verbose.h b/src/verbose.h
new file mode 100644 (file)
index 0000000..0a15564
--- /dev/null
@@ -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);
+
index 77358fd..04548c3 100644 (file)
 #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);
        }
index 07a5c4a..480b46c 100644 (file)
  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 (file)
index 0000000..1dbc147
--- /dev/null
@@ -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 (file)
index 0000000..57f8d82
--- /dev/null
@@ -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 (file)
index 9b97cc4..0000000
+++ /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;
-}
-
index dd889d5..db59091 100644 (file)
--- 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);
index 81aea1e..f159a3b 100644 (file)
--- a/src/wgt.h
+++ b/src/wgt.h
 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);
 
index 284acd1..6e66e38 100644 (file)
@@ -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 (file)
index 0000000..1a7724b
--- /dev/null
@@ -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;
+}
+
index 7a88ebf..1d79591 100644 (file)
 
 #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;
+}
+
+
index a8aaa05..be1e5ab 100644 (file)
@@ -26,6 +26,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 
+#include "verbose.h"
 #include "wgtpkg.h"
 
 #if !defined(MAXCERT)
index cd506fc..c4faf29 100644 (file)
@@ -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;
index 0c184a5..12cfa24 100644 (file)
  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)
+{
+       
+}
+
index d35b7f4..97af130 100644 (file)
@@ -88,22 +88,15 @@ extern struct filedesc *get_signature(unsigned int number);
 extern int file_set_prop(struct filedesc *file, const char *name, const char *value);
 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 */