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
8 http://www.apache.org/licenses/LICENSE-2.0
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.
32 struct filedesc **files;
35 static struct fdb allfiles = { .count = 0, .files = NULL };
36 static struct fdb allsignatures = { .count = 0, .files = NULL };
38 static const char author_file[] = "author-signature.xml";
39 static const char distributor_file_prefix[] = "signature";
40 static const char distributor_file_suffix[] = ".xml";
42 static unsigned int what_signature(const char *name)
44 unsigned int len, id, nid;
46 if (!strcmp(name, author_file))
49 len = sizeof(distributor_file_prefix)-1;
50 if (memcmp(name, distributor_file_prefix, len))
52 if (name[len] <= '0' || name[len] > '9')
54 id = (unsigned int)(name[len++] - '0');
55 while ('0' <= name[len] && name[len] <= '9') {
56 nid = 10 * id + (unsigned int)(name[len++] - '0');
57 if (nid < id || nid == UINT_MAX) {
58 WARNING("number too big for %s", name);
63 if (strcmp(name+len, distributor_file_suffix))
69 static struct filedesc *get_filedesc(const char *name, int create)
72 unsigned int low, up, mid, sig;
73 struct filedesc *result, **grow;
79 mid = (low + up) >> 1;
80 result = allfiles.files[mid];
81 cmp = strcmp(result->name, name);
83 return result; /* found */
90 /* not found, can create ? */
94 sig = what_signature(name);
97 grow = realloc(allfiles.files, (allfiles.count + 1) * sizeof(struct filedesc *));
99 ERROR("realloc failed in get_filedesc");
102 allfiles.files = grow;
105 grow = realloc(allsignatures.files, (allsignatures.count + 1) * sizeof(struct filedesc *));
107 ERROR("second realloc failed in get_filedesc");
110 allsignatures.files = grow;
113 result = malloc(sizeof(struct filedesc) + strlen(name));
115 ERROR("calloc failed in get_filedesc");
120 result->type = type_unset;
121 result->flags = sig == 0 ? 0 : sig == UINT_MAX ? flag_author_signature : flag_distributor_signature;
123 result->signum = sig;
124 strcpy(result->name, name);
127 if (low < allfiles.count)
128 memmove(allfiles.files+low+1, allfiles.files+low, (allfiles.count - low) * sizeof(struct filedesc *));
129 allfiles.files[low] = result;
132 for (low = 0 ; low < allsignatures.count && sig > allsignatures.files[low]->signum ; low++);
133 if (low < allsignatures.count)
134 memmove(allsignatures.files+low+1, allsignatures.files+low, (allsignatures.count - low) * sizeof(struct filedesc *));
135 allsignatures.files[low] = result;
136 allsignatures.count++;
143 static struct filedesc *file_add(const char *name, enum entrytype type)
145 struct filedesc *desc;
147 desc = get_filedesc(name, 1);
150 else if (desc->type == type_unset)
153 ERROR("redeclaration of %s in file_add", name);
164 allsignatures.count = 0;
165 for (i = 0 ; i < allfiles.count ; i++)
166 free(allfiles.files[i]);
170 unsigned int file_count()
172 return allfiles.count;
175 struct filedesc *file_of_index(unsigned int index)
177 assert(index < allfiles.count);
178 return allfiles.files[index];
181 struct filedesc *file_of_name(const char *name)
183 return get_filedesc(name, 0);
186 struct filedesc *file_add_directory(const char *name)
188 return file_add(name, type_directory);
191 struct filedesc *file_add_file(const char *name)
193 return file_add(name, type_file);
196 unsigned int signature_count()
198 return allsignatures.count;
201 struct filedesc *signature_of_index(unsigned int index)
203 assert(index < allsignatures.count);
204 return allsignatures.files[index];
207 struct filedesc *get_signature(unsigned int number)
213 for (idx = 0 ; idx < allsignatures.count ; idx++)
214 if (allsignatures.files[idx]->signum == number)
215 return allsignatures.files[idx];
219 struct filedesc *create_signature(unsigned int number)
221 struct filedesc *result;
226 if (number == 0 || number == UINT_MAX)
227 len = asprintf(&name, "%s", author_file);
229 len = asprintf(&name, "%s%u%s", distributor_file_prefix, number, distributor_file_suffix);
232 ERROR("asprintf failed in create_signature");
235 result = file_of_name(name);
237 result = file_add_file(name);
244 /* remove flags that are not related to being signature */
245 void file_clear_flags()
248 for (i = 0 ; i < allfiles.count ; i++)
249 allfiles.files[i]->flags &= flag_signature;
252 static int fill_files_rec(char name[PATH_MAX], int offset)
258 fd = openat(workdirfd, offset ? name : ".", O_DIRECTORY|O_RDONLY);
260 ERROR("openat %.*s failed in fill_files_rec", offset, name);
265 ERROR("opendir %.*s failed in fill_files_rec", offset, name);
270 name[offset++] = '/';
273 while (ent != NULL) {
274 len = strlen(ent->d_name);
275 if (ent->d_name[0] == '.' && (len == 1 ||
276 (ent->d_name[1] == '.' && len == 2)))
278 else if (offset + len >= PATH_MAX) {
280 ERROR("name too long in fill_files_rec");
281 errno = ENAMETOOLONG;
284 memcpy(name + offset, ent->d_name, 1+len);
285 switch (ent->d_type) {
287 if (file_add_directory(name) == NULL) {
291 err = fill_files_rec(name, offset + len);
298 if (file_add_file(name) == NULL) {
317 return fill_files_rec(name, 0);