From f3d64b7c741677cd28e2a11deed67196cd02b46a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Bollo?= Date: Thu, 10 Dec 2015 16:39:05 +0100 Subject: [PATCH] added info retrieval Change-Id: I6f91b15e87308cf01db4ddafa3c2715c251f5fe5 --- .gitignore | 6 +- src/Makefile.am | 22 ++- src/appfwk.c | 224 +++++++++++++++++++++ src/{wgtpkg-verbose.c => verbose.c} | 0 src/verbose.h | 24 +++ src/wgt-config.c | 84 ++++++-- src/wgt-config.h | 36 +++- src/wgt-info.c | 382 ++++++++++++++++++++++++++++++++++++ src/wgt-info.h | 74 +++++++ src/wgt-locales.c | 121 ------------ src/wgt.c | 26 ++- src/wgt.h | 4 +- src/wgtpkg-digsig.c | 1 + src/wgtpkg-info.c | 182 +++++++++++++++++ src/wgtpkg-install.c | 258 ++++++++++++++++++++---- src/wgtpkg-pack.c | 1 + src/wgtpkg-sign.c | 10 +- src/wgtpkg-workdir.c | 94 ++++++--- src/wgtpkg.h | 13 +- 19 files changed, 1334 insertions(+), 228 deletions(-) create mode 100644 src/appfwk.c rename src/{wgtpkg-verbose.c => verbose.c} (100%) create mode 100644 src/verbose.h create mode 100644 src/wgt-info.c create mode 100644 src/wgt-info.h delete mode 100644 src/wgt-locales.c create mode 100644 src/wgtpkg-info.c 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +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 +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 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 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 +#include +#include +#include +#include +#include + +#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 = ¶m->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 -#include -#include -#include - -#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 +#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 +#include +#include +#include +#include +#include +#include +#include + +#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 #include +#include #include #include #include #include #include +#include +#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 #include +#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 #include +#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 #include #include #include #include +#include +#include #include #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 @@ -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 */ -- 2.16.6