Add feature of autosigning widgets
[src/app-framework-main.git] / src / main-wgtpkg-pack.c
1 /*
2  Copyright (C) 2015-2020 IoT.bzh
3
4  author: José Bollo <jose.bollo@iot.bzh>
5
6  Licensed under the Apache License, Version 2.0 (the "License");
7  you may not use this file except in compliance with the License.
8  You may obtain a copy of the License at
9
10      http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  See the License for the specific language governing permissions and
16  limitations under the License.
17 */
18
19 #define _GNU_SOURCE
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <limits.h>
25 #include <errno.h>
26 #include <getopt.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29
30 #include "verbose.h"
31 #include "wgtpkg-files.h"
32 #include "wgtpkg-workdir.h"
33 #include "wgtpkg-zip.h"
34 #include "wgtpkg-digsig.h"
35
36 const char appname[] = "wgtpkg-pack";
37
38 static void version()
39 {
40         printf(
41                 "\n"
42                 "  %s  version="AFM_VERSION"\n"
43                 "\n"
44                 "  Copyright (C) 2015-2020 \"IoT.bzh\"\n"
45                 "  AFB comes with ABSOLUTELY NO WARRANTY.\n"
46                 "  Licence Apache 2\n"
47                 "\n",
48                 appname
49         );
50 }
51
52 static void usage()
53 {
54         printf(
55                 "usage: %s [-f] [-o wgtfile] directory\n"
56                 "\n"
57                 "   -o wgtfile       the output widget file\n"
58                 "   -f               force overwriting\n"
59                 "   -N               no auto-sign"
60                 "   -q               quiet\n"
61                 "   -S               auto-sign"
62                 "   -v               verbose\n"
63                 "   -V               version\n"
64                 "\n",
65                 appname
66         );
67 }
68
69 static struct option options[] = {
70         { "output",      required_argument, NULL, 'o' },
71         { "force",       no_argument,       NULL, 'f' },
72         { "help",        no_argument,       NULL, 'h' },
73         { "no-auto-sign",no_argument,       NULL, 'N' },
74         { "quiet",       no_argument,       NULL, 'q' },
75         { "auto-sign",   no_argument,       NULL, 'S' },
76         { "verbose",     no_argument,       NULL, 'v' },
77         { "version",     no_argument,       NULL, 'V' },
78         { NULL, 0, NULL, 0 }
79 };
80
81 /* install the widgets of the list */
82 int main(int ac, char **av)
83 {
84         int i, force, autosign;
85         char *wgtfile, *directory, *x;
86         struct stat s;
87
88         LOGUSER(appname);
89
90         autosign = 1;
91         force = 0;
92         wgtfile = directory = NULL;
93         for (;;) {
94                 i = getopt_long(ac, av, "qvVhfo:", options, NULL);
95                 if (i < 0)
96                         break;
97                 switch (i) {
98                 case 'o':
99                         wgtfile = optarg;
100                         break;
101                 case 'q':
102                         if (verbosity)
103                                 verbosity--;
104                         break;
105                 case 'v':
106                         verbosity++;
107                         break;
108                 case 'f':
109                         force = 1;
110                         break;
111                 case 'h':
112                         usage();
113                         return 0;
114                 case 'N':
115                         autosign = 0;
116                         break;
117                 case 'V':
118                         version();
119                         return 0;
120                 case 'S':
121                         autosign = 1;
122                         break;
123                 case ':':
124                         ERROR("missing argument");
125                         return 1;
126                 default:
127                         ERROR("unrecognized option");
128                         return 1;
129                 }
130         }
131
132         /* remaining arguments and final checks */
133         if (optind >= ac) {
134                 ERROR("no directory set");
135                 return 1;
136         }
137         directory = av[optind++];
138         if (optind < ac) {
139                 ERROR("extra parameters found");
140                 return 1;
141         }
142
143         /* set default values */
144         if (wgtfile == NULL && 0 > asprintf(&wgtfile, "%s.wgt", directory)) {
145                 ERROR("asprintf failed");
146                 return 1;
147         }
148
149         /* check values */
150         if (stat(directory, &s)) {
151                 ERROR("can't find directory %s", directory);
152                 return 1;
153         }
154         if (!S_ISDIR(s.st_mode)) {
155                 ERROR("%s isn't a directory", directory);
156                 return 1;
157         }
158         if (access(wgtfile, F_OK) == 0 && force == 0) {
159                 ERROR("can't overwrite existing %s", wgtfile);
160                 return 1;
161         }
162
163         NOTICE("-- PACKING widget %s from directory %s", wgtfile, directory);
164
165         /* creates an existing widget (for realpath it must exist) */
166         i = open(wgtfile, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0644);
167         if (i < 0) {
168                 ERROR("can't write widget %s", wgtfile);
169                 return 1;
170         }
171         close(i);
172
173         /* compute absolutes paths */
174         x = realpath(wgtfile, NULL);
175         if (x == NULL) {
176                 ERROR("realpath failed for %s", wgtfile);
177                 return 1;
178         }
179         wgtfile = x;
180
181         /* set and enter the workdir */
182         if (chdir(directory)) {
183                 ERROR("failed to enter directory %s", directory);
184                 return 1;
185         }
186         if (set_workdir(".", 0))
187                 return 1;
188
189         if (fill_files())
190                 return 1;
191
192         if (autosign && create_auto_digsig() < 0)
193                 return 1;
194
195         return !!zwrite(wgtfile);
196 }
197
198