added info retrieval
[src/app-framework-main.git] / src / wgtpkg-install.c
1 /*
2  Copyright 2015 IoT.bzh
3
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7
8      http://www.apache.org/licenses/LICENSE-2.0
9
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16
17 #define _BSD_SOURCE /* see readdir */
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <dirent.h>
23 #include <unistd.h>
24 #include <limits.h>
25 #include <errno.h>
26 #include <syslog.h>
27 #include <getopt.h>
28
29 #include "verbose.h"
30 #include "wgtpkg.h"
31 #include "wgt.h"
32 #include "wgt-info.h"
33
34 static const char appname[] = "wgtpkg-install";
35 static const char *root;
36 static char **permissions = NULL;
37 static int force;
38
39 static void install(const char *wgtfile);
40 static void add_permissions(const char *list);
41
42 static void usage()
43 {
44         printf(
45                 "usage: %s [-f] [-q] [-v] [-p list] rootdir wgtfile...\n"
46                 "\n"
47                 "   rootdir       the root directory for installing\n"
48                 "   -p list       a list of comma separated permissions to allow\n"
49                 "   -f            force overwriting\n"
50                 "   -q            quiet\n"
51                 "   -v            verbose\n"
52                 "\n",
53                 appname
54         );
55 }
56
57 static struct option options[] = {
58         { "permissions", required_argument, NULL, 'p' },
59         { "force",       no_argument,       NULL, 'f' },
60         { "help",        no_argument,       NULL, 'h' },
61         { "quiet",       no_argument,       NULL, 'q' },
62         { "verbose",     no_argument,       NULL, 'v' },
63         { NULL, 0, NULL, 0 }
64 };
65
66 /* install the widgets of the list */
67 int main(int ac, char **av)
68 {
69         int i;
70         char *wpath;
71
72         openlog(appname, LOG_PERROR, LOG_AUTH);
73
74         xmlsec_init();
75
76         force = 0;
77         for (;;) {
78                 i = getopt_long(ac, av, "hfqvp:", options, NULL);
79                 if (i < 0)
80                         break;
81                 switch (i) {
82                 case 'f':
83                         force = 1;
84                         break;
85                 case 'h':
86                         usage();
87                         return 0;
88                 case 'q':
89                         if (verbosity)
90                                 verbosity--;
91                         break;
92                 case 'v':
93                         verbosity++;
94                         break;
95                 case 'p':
96                         add_permissions(optarg);
97                         break;
98                 case ':':
99                         syslog(LOG_ERR, "missing argument value");
100                         return 1;
101                 default:
102                         syslog(LOG_ERR, "unrecognized option");
103                         return 1;
104                 }
105         }
106
107         ac -= optind;
108         if (ac < 2) {
109                 syslog(LOG_ERR, "arguments are missing");
110                 return 1;
111         }
112
113         /* canonic names for files */
114         av += optind;
115         for (i = 0 ; av[i] != NULL ; i++) {
116                 wpath = realpath(av[i], NULL);
117                 if (wpath == NULL) {
118                         syslog(LOG_ERR, "error while getting realpath of %dth widget: %s", i+1, av[i]);
119                         return 1;
120                 }
121                 av[i] = wpath;
122         }
123         root = *av++;
124
125         /* install widgets */
126         for ( ; *av ; av++)
127                 install(*av);
128
129         return 0;
130 }
131
132 static int has_permission(const char *name)
133 {
134         char **p = permissions;
135         if (p) {
136                 while(*p) {
137                         if (0 == strcmp(*p, name))
138                                 return 1;
139                         p++;
140                 }
141         }
142         return 0;
143 }
144
145 static void add_permissions(const char *list)
146 {
147         char **ps, *p;
148         const char *iter;
149         int n, on;
150         static const char separators[] = " \t\n\r,";
151
152         n = 0;
153         iter = list + strspn(list, separators);
154         while(*iter) {
155                 n++;
156                 iter += strcspn(iter, separators);
157                 iter += strspn(iter, separators);
158         }
159         if (n == 0)
160                 return;
161
162         on = 0;
163         ps = permissions;
164         if (ps)
165                 while(*ps++)
166                         on++;
167
168         ps = realloc(permissions, (1 + on + n) * sizeof * ps);
169         if (!ps) {
170                 syslog(LOG_ERR, "Can't allocate memory for permissions");
171                 exit(1);
172         }
173
174         permissions = ps;
175         ps[on] = NULL;
176
177         iter = list + strspn(list, separators);
178         while(*iter) {
179                 n = strcspn(iter, separators);
180                 p = strndup(iter, n);
181                 if (!p) {
182                         syslog(LOG_ERR, "Can't allocate permission");
183                         exit(1);
184                 }
185                 if (has_permission(p))
186                         free(p);
187                 else {
188                         ps[on] = p;
189                         ps[++on] = NULL;
190                 }
191                 iter += n;
192                 iter += strspn(iter, separators);
193         }
194 }
195
196 static struct wgt *wgt_at_workdir()
197 {
198         int rc, wfd;
199         struct wgt *wgt;
200
201         wfd = workdirfd();
202         if (wfd < 0)
203                 return NULL;
204
205         wgt = wgt_create();
206         if (!wgt) {
207                 syslog(LOG_ERR, "failed to allocate wgt");
208                 close(wfd);
209                 return NULL;
210         }
211
212         rc = wgt_connectat(wgt, wfd, NULL);
213         if (rc) {
214                 syslog(LOG_ERR, "failed to connect wgt to workdir");
215                 close(wfd);
216                 wgt_unref(wgt);
217                 return NULL;
218         }
219
220         return wgt;
221 }
222
223
224 static int check_and_place()
225 {
226         struct wgt *wgt;
227         struct wgt_info *ifo;
228
229         wgt = wgt_at_workdir();
230         if (!wgt)
231                 return -1;
232
233         ifo = wgt_info_get(wgt, 1, 1, 1);
234         if (!ifo) {
235                 wgt_unref(wgt);
236                 return -1;
237         }
238         wgt_info_dump(ifo, 1, "");
239         wgt_info_unref(ifo);
240         wgt_unref(wgt);
241         return 0;
242 }
243
244 /* install the widget of the file */
245 static void install(const char *wgtfile)
246 {
247         notice("-- INSTALLING widget %s --", wgtfile);
248
249         /* workdir */
250         if (make_workdir_base(root, "UNPACK", 0)) {
251                 syslog(LOG_ERR, "failed to create a working directory");
252                 goto error1;
253         }
254
255         if (enter_workdir(0))
256                 goto error2;
257
258         if (zread(wgtfile, 0))
259                 goto error2;
260
261         if (check_all_signatures())
262                 goto error2;
263
264         if (check_and_place())
265                 goto error2;
266         
267         return;
268
269 error2:
270         remove_workdir();
271
272 error1:
273         return;
274 }
275
276