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.
34 struct filedesc **files;
37 static struct fdb allfiles = { .count = 0, .files = NULL };
38 static struct fdb allsignatures = { .count = 0, .files = NULL };
40 static const char author_file[] = "author-signature.xml";
41 static const char distributor_file_prefix[] = "signature";
42 static const char distributor_file_suffix[] = ".xml";
44 static unsigned int what_signature(const char *name)
46 unsigned int len, id, nid;
48 if (!strcmp(name, author_file))
51 len = sizeof(distributor_file_prefix)-1;
52 if (memcmp(name, distributor_file_prefix, len))
54 if (name[len] <= '0' || name[len] > '9')
56 id = (unsigned int)(name[len++] - '0');
57 while ('0' <= name[len] && name[len] <= '9') {
58 nid = 10 * id + (unsigned int)(name[len++] - '0');
59 if (nid < id || nid == UINT_MAX) {
60 WARNING("number too big for %s", name);
65 if (strcmp(name+len, distributor_file_suffix))
71 static struct filedesc *get_filedesc(const char *name, int create)
74 unsigned int low, up, mid, sig;
75 struct filedesc *result, **grow;
81 mid = (low + up) >> 1;
82 result = allfiles.files[mid];
83 cmp = strcmp(result->name, name);
85 return result; /* found */
92 /* not found, can create ? */
96 sig = what_signature(name);
99 grow = realloc(allfiles.files, (allfiles.count + 1) * sizeof(struct filedesc *));
101 ERROR("realloc failed in get_filedesc");
104 allfiles.files = grow;
107 grow = realloc(allsignatures.files, (allsignatures.count + 1) * sizeof(struct filedesc *));
109 ERROR("second realloc failed in get_filedesc");
112 allsignatures.files = grow;
115 result = malloc(sizeof(struct filedesc) + strlen(name));
117 ERROR("calloc failed in get_filedesc");
122 result->type = type_unset;
123 result->flags = sig == 0 ? 0 : sig == UINT_MAX ? flag_author_signature : flag_distributor_signature;
125 result->signum = sig;
126 strcpy(result->name, name);
129 if (low < allfiles.count)
130 memmove(allfiles.files+low+1, allfiles.files+low, (allfiles.count - low) * sizeof(struct filedesc *));
131 allfiles.files[low] = result;
134 for (low = 0 ; low < allsignatures.count && sig > allsignatures.files[low]->signum ; low++);
135 if (low < allsignatures.count)
136 memmove(allsignatures.files+low+1, allsignatures.files+low, (allsignatures.count - low) * sizeof(struct filedesc *));
137 allsignatures.files[low] = result;
138 allsignatures.count++;
145 static struct filedesc *file_add(const char *name, enum entrytype type)
147 struct filedesc *desc;
149 desc = get_filedesc(name, 1);
152 else if (desc->type == type_unset)
155 ERROR("redeclaration of %s in file_add", name);
166 allsignatures.count = 0;
167 for (i = 0 ; i < allfiles.count ; i++)
168 free(allfiles.files[i]);
172 unsigned int file_count()
174 return allfiles.count;
177 struct filedesc *file_of_index(unsigned int index)
179 assert(index < allfiles.count);
180 return allfiles.files[index];
183 struct filedesc *file_of_name(const char *name)
185 return get_filedesc(name, 0);
188 struct filedesc *file_add_directory(const char *name)
190 return file_add(name, type_directory);
193 struct filedesc *file_add_file(const char *name)
195 return file_add(name, type_file);
198 unsigned int signature_count()
200 return allsignatures.count;
203 struct filedesc *signature_of_index(unsigned int index)
205 assert(index < allsignatures.count);
206 return allsignatures.files[index];
209 struct filedesc *get_signature(unsigned int number)
215 for (idx = 0 ; idx < allsignatures.count ; idx++)
216 if (allsignatures.files[idx]->signum == number)
217 return allsignatures.files[idx];
221 struct filedesc *create_signature(unsigned int number)
223 struct filedesc *result;
228 if (number == 0 || number == UINT_MAX)
229 len = asprintf(&name, "%s", author_file);
231 len = asprintf(&name, "%s%u%s", distributor_file_prefix, number, distributor_file_suffix);
234 ERROR("asprintf failed in create_signature");
237 result = file_of_name(name);
239 result = file_add_file(name);
246 /* remove flags that are not related to being signature */
247 void file_clear_flags()
250 for (i = 0 ; i < allfiles.count ; i++)
251 allfiles.files[i]->flags &= flag_signature;
254 static int fill_files_rec(char name[PATH_MAX], int offset)
260 fd = openat(workdirfd, offset ? name : ".", O_DIRECTORY|O_RDONLY);
262 ERROR("openat %.*s failed in fill_files_rec", offset, name);
267 ERROR("opendir %.*s failed in fill_files_rec", offset, name);
272 name[offset++] = '/';
275 while (ent != NULL) {
276 len = strlen(ent->d_name);
277 if (ent->d_name[0] == '.' && (len == 1 ||
278 (ent->d_name[1] == '.' && len == 2)))
280 else if (offset + len >= PATH_MAX) {
282 ERROR("name too long in fill_files_rec");
283 errno = ENAMETOOLONG;
286 memcpy(name + offset, ent->d_name, 1+len);
287 switch (ent->d_type) {
289 if (file_add_directory(name) == NULL) {
293 err = fill_files_rec(name, offset + len);
300 if (file_add_file(name) == NULL) {
319 return fill_files_rec(name, 0);