wgtpkg-install: set exec flag for application/vnd.agl.native
[src/app-framework-main.git] / src / wgtpkg-install.c
index 37a47ff..71a0ff6 100644 (file)
@@ -1,5 +1,7 @@
 /*
- Copyright 2015 IoT.bzh
+ Copyright 2015, 2016 IoT.bzh
+
+ author: José Bollo <jose.bollo@iot.bzh>
 
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
 
 #define _GNU_SOURCE
 
+#include <limits.h>
 #include <errno.h>
-#include <syslog.h>
 #include <string.h>
 #include <ctype.h>
 #include <assert.h>
 #include <unistd.h>
+#include <stdio.h>
+#include <sys/stat.h>
 
 #include "verbose.h"
-#include "wgtpkg.h"
 #include "wgt.h"
 #include "wgt-info.h"
+#include "wgtpkg-files.h"
+#include "wgtpkg-workdir.h"
+#include "wgtpkg-zip.h"
+#include "wgtpkg-permissions.h"
+#include "wgtpkg-digsig.h"
+#include "wgtpkg-install.h"
 #include "secmgr-wrap.h"
+#include "utils-dir.h"
+
+static const char permission_required[] = "required";
+static const char permission_optional[] = "optional";
+static const char feature_required_permissions[] = FWK_PREFIX "required-permissions";
+static const char* exec_type_strings[] = {
+       "application/x-executable",
+       "application/vnd.agl.native"
+};
 
 static int check_defined(const void *data, const char *name)
 {
        if (data)
                return 0;
-       syslog(LOG_ERR, "widget has no defined '%s' (temporary constraints)", name);
+       ERROR("widget has no defined '%s' (temporary constraints)", name);
        errno = EINVAL;
        return -1;
 }
@@ -47,14 +65,19 @@ static int check_valid_string(const char *value, const char *name)
                return -1;
        pos = 0;
        c = value[pos];
-       while(c) {
+       if (c == 0) {
+               ERROR("empty string forbidden in '%s' (temporary constraints)", name);
+               errno = EINVAL;
+               return -1;                      
+       }
+       do {
                if (!isalnum(c) && !strchr(".-_", c)) {
-                       syslog(LOG_ERR, "forbidden char %c in '%s' -> '%s' (temporary constraints)", c, name, value);
+                       ERROR("forbidden char %c in '%s' -> '%s' (temporary constraints)", c, name, value);
                        errno = EINVAL;
                        return -1;                      
                }
                c = value[++pos];
-       }
+       } while(c);
        return 0;
 }
 
@@ -62,32 +85,47 @@ static int check_temporary_constraints(const struct wgt_desc *desc)
 {
        int result = check_valid_string(desc->id, "id");
        result |= check_valid_string(desc->version, "version");
+       result |= check_valid_string(desc->ver, "ver");
        result |= check_defined(desc->icons, "icon");
        result |= check_defined(desc->content_src, "content");
        if (result)
                return result;
        if (desc->icons->next) {
-               syslog(LOG_ERR, "widget has more than one icon defined (temporary constraints)");
+               ERROR("widget has more than one icon defined (temporary constraints)");
                errno = EINVAL;
                result = -1;
        }
        return 0;
 }
 
-static int check_permissions(const char *name, int required)
+static int set_required_permissions(struct wgt_desc_param *params, int required)
 {
-       if (permission_exists(name)) {
-               if (request_permission(name)) {
-                       debug("granted permission: %s", name);
-               } else if (required) {
-                       syslog(LOG_ERR, "ungranted permission required: %s", name);
+       int optional;
+
+       while (params) {
+               /* check the value */
+               if (!strcmp(params->value, permission_required))
+                       optional = !required;
+               else if (!strcmp(params->value, permission_optional))
+                       optional = 1;
+               else {
+                       ERROR("unexpected parameter value: %s found for %s", params->value, params->name);
                        errno = EPERM;
-                       return 0;
+                       return -1;
+               }
+               /* set the permission */
+               if (request_permission(params->name)) {
+                       DEBUG("granted permission: %s", params->name);
+               } else if (optional) {
+                       INFO("optional permission ungranted: %s", params->name);
                } else {
-                       notice("ungranted permission optional: %s", name);
+                       ERROR("ungranted permission required: %s", params->name);
+                       errno = EPERM;
+                       return -1;
                }
+               params = params->next;
        }
-       return 1;
+       return 0;
 }
 
 static int check_widget(const struct wgt_desc *desc)
@@ -97,9 +135,9 @@ static int check_widget(const struct wgt_desc *desc)
 
        result = check_temporary_constraints(desc);
        feature = desc->features;
-       while(feature) {
-               if (!check_permissions(feature->name, feature->required))
-                       result = -1;
+       while(result >= 0 && feature) {
+               if (!strcmp(feature->name, feature_required_permissions))
+                       result = set_required_permissions(feature->params, feature->required);
                feature = feature->next;
        }
        return result;
@@ -110,9 +148,9 @@ static int move_widget(const char *root, const struct wgt_desc *desc, int force)
        char newdir[PATH_MAX];
        int rc;
 
-       rc = snprintf(newdir, sizeof newdir, "%s/%s/%s", root, desc->id, desc->version);
-       if (rc >= sizeof newdir) {
-               syslog(LOG_ERR, "path to long in move_widget");
+       rc = snprintf(newdir, sizeof newdir, "%s/%s/%s", root, desc->id, desc->ver);
+       if (rc >= (int)sizeof newdir) {
+               ERROR("path too long in move_widget");
                errno = EINVAL;
                return -1;
        }
@@ -126,16 +164,17 @@ static int install_icon(const struct wgt_desc *desc)
        char target[PATH_MAX];
        int rc;
 
-       rc = snprintf(link, sizeof link, "%s/%s@%s", ICONDESTDIR, desc->id, desc->version);
-       if (rc >= sizeof link) {
-               syslog(LOG_ERR, "link to long in install_icon");
+       create_directory(FWK_ICON_DIR, 0755, 1);
+       rc = snprintf(link, sizeof link, "%s/%s", FWK_ICON_DIR, desc->idaver);
+       if (rc >= (int)sizeof link) {
+               ERROR("link too long in install_icon");
                errno = EINVAL;
                return -1;
        }
 
        rc = snprintf(target, sizeof target, "%s/%s", workdir, desc->icons->src);
-       if (rc >= sizeof target) {
-               syslog(LOG_ERR, "target to long in install_icon");
+       if (rc >= (int)sizeof target) {
+               ERROR("target too long in install_icon");
                errno = EINVAL;
                return -1;
        }
@@ -143,16 +182,30 @@ static int install_icon(const struct wgt_desc *desc)
        unlink(link);
        rc = symlink(target, link);
        if (rc)
-               syslog(LOG_ERR, "can't create link %s -> %s", link, target);
+               ERROR("can't create link %s -> %s", link, target);
        return rc;
 }
 
+static int install_exec_flag(const struct wgt_desc *desc)
+{
+       int i;
+
+       if (desc->content_type) {
+               i = sizeof exec_type_strings / sizeof *exec_type_strings;
+               while (i) {
+                       if (!strcasecmp(desc->content_type, exec_type_strings[--i]))
+                               return fchmodat(workdirfd, desc->content_src, 0755, 0);
+               }
+       }
+       return 0;
+}
+
 static int install_security(const struct wgt_desc *desc)
 {
        char path[PATH_MAX], *head;
        const char *icon, *perm;
-       int rc, len, lic, lf;
-       unsigned int i, n;
+       int rc;
+       unsigned int i, n, len, lic, lf;
        struct filedesc *f;
 
        rc = secmgr_init(desc->id);
@@ -165,24 +218,24 @@ static int install_security(const struct wgt_desc *desc)
 
        /* instal the files */
        head = stpcpy(path, workdir);
-       assert(sizeof path > (head - path));
-       len = (int)(sizeof path - (head - path));
+       assert(head < path + sizeof path);
+       len = (unsigned)((path + sizeof path) - head);
        if (!len) {
-               syslog(LOG_ERR, "root path too long in install_security");
+               ERROR("root path too long in install_security");
                errno = ENAMETOOLONG;
                goto error2;
        }
        len--;
        *head++ = '/';
        icon = desc->icons->src;
-       lic = (int)strlen(icon);
+       lic = (unsigned)strlen(icon);
        n = file_count();
        i = 0;
        while(i < n) {
                f = file_of_index(i++);
-               lf = (int)strlen(f->name);
+               lf = (unsigned)strlen(f->name);
                if (lf >= len) {
-                       syslog(LOG_ERR, "path too long in install_security");
+                       ERROR("path too long in install_security");
                        errno = ENAMETOOLONG;
                        goto error2;
                }
@@ -213,16 +266,17 @@ error:
 }
 
 /* install the widget of the file */
-void install_widget(const char *wgtfile, const char *root, int force)
+struct wgt_info *install_widget(const char *wgtfile, const char *root, int force)
 {
        struct wgt_info *ifo;
        const struct wgt_desc *desc;
 
-       notice("-- INSTALLING widget %s --", wgtfile);
+       NOTICE("-- INSTALLING widget %s to %s --", wgtfile, root);
 
        /* workdir */
-       if (make_workdir_base(root, "TMP", 0)) {
-               syslog(LOG_ERR, "failed to create a working directory");
+       create_directory(root, 0755, 1);
+       if (make_workdir(root, "TMP", 0)) {
+               ERROR("failed to create a working directory");
                goto error1;
        }
 
@@ -236,6 +290,7 @@ void install_widget(const char *wgtfile, const char *root, int force)
        if (!ifo)
                goto error2;
 
+       reset_requested_permissions();
        desc = wgt_info_desc(ifo);
        if (check_widget(desc))
                goto error3;
@@ -246,10 +301,14 @@ void install_widget(const char *wgtfile, const char *root, int force)
        if (install_icon(desc))
                goto error3;
 
+       if (install_exec_flag(desc))
+               goto error3;
+
        if (install_security(desc))
                goto error3;
-       
-       return;
+
+       file_reset();
+       return ifo;
 
 error3:
        wgt_info_unref(ifo);
@@ -258,6 +317,7 @@ error2:
        remove_workdir();
 
 error1:
-       return;
+       file_reset();
+       return NULL;
 }