4 author: José Bollo <jose.bollo@iot.bzh>
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
10 http://www.apache.org/licenses/LICENSE-2.0
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.
30 #include "wgtpkg-workdir.h"
31 #include "wgtpkg-files.h"
35 struct filedesc **files;
38 static struct fdb allfiles = { .count = 0, .files = NULL };
39 static struct fdb allsignatures = { .count = 0, .files = NULL };
41 static const char author_file[] = "author-signature.xml";
42 static const char distributor_file_prefix[] = "signature";
43 static const char distributor_file_suffix[] = ".xml";
45 static unsigned int what_signature(const char *name)
47 unsigned int len, id, nid;
49 if (!strcmp(name, author_file))
52 len = sizeof(distributor_file_prefix)-1;
53 if (memcmp(name, distributor_file_prefix, len))
55 if (name[len] <= '0' || name[len] > '9')
57 id = (unsigned int)(name[len++] - '0');
58 while ('0' <= name[len] && name[len] <= '9') {
59 nid = 10 * id + (unsigned int)(name[len++] - '0');
60 if (nid < id || nid == UINT_MAX) {
61 WARNING("number too big for %s", name);
66 if (strcmp(name+len, distributor_file_suffix))
72 static struct filedesc *get_filedesc(const char *name, int create)
75 unsigned int low, up, mid, sig;
76 struct filedesc *result, **grow;
82 mid = (low + up) >> 1;
83 result = allfiles.files[mid];
84 cmp = strcmp(result->name, name);
86 return result; /* found */
93 /* not found, can create ? */
97 sig = what_signature(name);
100 grow = realloc(allfiles.files, (allfiles.count + 1) * sizeof(struct filedesc *));
102 ERROR("realloc failed in get_filedesc");
105 allfiles.files = grow;
108 grow = realloc(allsignatures.files, (allsignatures.count + 1) * sizeof(struct filedesc *));
110 ERROR("second realloc failed in get_filedesc");
113 allsignatures.files = grow;
116 result = malloc(sizeof(struct filedesc) + strlen(name));
118 ERROR("calloc failed in get_filedesc");
123 result->type = type_unset;
124 result->flags = sig == 0 ? 0 : sig == UINT_MAX ? flag_author_signature : flag_distributor_signature;
126 result->signum = sig;
127 strcpy(result->name, name);
130 if (low < allfiles.count)
131 memmove(allfiles.files+low+1, allfiles.files+low, (allfiles.count - low) * sizeof(struct filedesc *));
132 allfiles.files[low] = result;
135 for (low = 0 ; low < allsignatures.count && sig > allsignatures.files[low]->signum ; low++);
136 if (low < allsignatures.count)
137 memmove(allsignatures.files+low+1, allsignatures.files+low, (allsignatures.count - low) * sizeof(struct filedesc *));
138 allsignatures.files[low] = result;
139 allsignatures.count++;
146 static struct filedesc *file_add(const char *name, enum entrytype type)
148 struct filedesc *desc;
150 desc = get_filedesc(name, 1);
153 else if (desc->type == type_unset)
156 ERROR("redeclaration of %s in file_add", name);
167 allsignatures.count = 0;
168 for (i = 0 ; i < allfiles.count ; i++)
169 free(allfiles.files[i]);
173 unsigned int file_count()
175 return allfiles.count;
178 struct filedesc *file_of_index(unsigned int index)
180 assert(index < allfiles.count);
181 return allfiles.files[index];
184 struct filedesc *file_of_name(const char *name)
186 return get_filedesc(name, 0);
189 struct filedesc *file_add_directory(const char *name)
191 return file_add(name, type_directory);
194 struct filedesc *file_add_file(const char *name)
196 return file_add(name, type_file);
199 unsigned int signature_count()
201 return allsignatures.count;
204 struct filedesc *signature_of_index(unsigned int index)
206 assert(index < allsignatures.count);
207 return allsignatures.files[index];
210 struct filedesc *get_signature(unsigned int number)
216 for (idx = 0 ; idx < allsignatures.count ; idx++)
217 if (allsignatures.files[idx]->signum == number)
218 return allsignatures.files[idx];
222 struct filedesc *create_signature(unsigned int number)
224 struct filedesc *result;
229 if (number == 0 || number == UINT_MAX)
230 len = asprintf(&name, "%s", author_file);
232 len = asprintf(&name, "%s%u%s", distributor_file_prefix, number, distributor_file_suffix);
235 ERROR("asprintf failed in create_signature");
238 result = file_of_name(name);
240 result = file_add_file(name);
247 /* remove flags that are not related to being signature */
248 void file_clear_flags()
251 for (i = 0 ; i < allfiles.count ; i++)
252 allfiles.files[i]->flags &= flag_signature;
255 static int fill_files_rec(char name[PATH_MAX], int offset)
261 fd = openat(workdirfd, offset ? name : ".", O_DIRECTORY|O_RDONLY);
263 ERROR("openat %.*s failed in fill_files_rec", offset, name);
268 ERROR("opendir %.*s failed in fill_files_rec", offset, name);
273 name[offset++] = '/';
276 while (ent != NULL) {
277 len = strlen(ent->d_name);
278 if (ent->d_name[0] == '.' && (len == 1 ||
279 (ent->d_name[1] == '.' && len == 2)))
281 else if (offset + len >= PATH_MAX) {
283 ERROR("name too long in fill_files_rec");
284 errno = ENAMETOOLONG;
287 memcpy(name + offset, ent->d_name, 1+len);
288 switch (ent->d_type) {
290 if (file_add_directory(name) == NULL) {
294 err = fill_files_rec(name, offset + len);
301 if (file_add_file(name) == NULL) {
320 return fill_files_rec(name, 0);