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.
30 struct filedesc **files;
33 static struct fdb allfiles = { .count = 0, .files = NULL };
34 static struct fdb allsignatures = { .count = 0, .files = NULL };
36 static const char author_file[] = "author-signature.xml";
37 static const char distributor_file_prefix[] = "signature";
38 static const char distributor_file_suffix[] = ".xml";
40 static unsigned int what_signature(const char *name)
42 unsigned int len, id, nid;
44 if (!strcmp(name, author_file))
47 len = sizeof(distributor_file_prefix)-1;
48 if (memcmp(name, distributor_file_prefix, len))
50 if (name[len] <= '0' || name[len] > '9')
52 id = (unsigned int)(name[len++] - '0');
53 while ('0' <= name[len] && name[len] <= '9') {
54 nid = 10 * id + (unsigned int)(name[len++] - '0');
55 if (nid < id || nid == UINT_MAX) {
56 syslog(LOG_WARNING, "number too big for %s", name);
61 if (strcmp(name+len, distributor_file_suffix))
67 static struct filedesc *get_filedesc(const char *name, int create)
70 unsigned int low, up, mid, sig;
71 struct filedesc *result, **grow;
77 mid = (low + up) >> 1;
78 result = allfiles.files[mid];
79 cmp = strcmp(result->name, name);
81 return result; /* found */
88 /* not found, can create ? */
92 sig = what_signature(name);
95 grow = realloc(allfiles.files, (allfiles.count + 1) * sizeof(struct filedesc *));
97 syslog(LOG_ERR, "realloc failed in get_filedesc");
100 allfiles.files = grow;
103 grow = realloc(allsignatures.files, (allsignatures.count + 1) * sizeof(struct filedesc *));
105 syslog(LOG_ERR, "second realloc failed in get_filedesc");
108 allsignatures.files = grow;
111 result = malloc(sizeof(struct filedesc) + strlen(name));
113 syslog(LOG_ERR, "calloc failed in get_filedesc");
118 result->type = type_unset;
119 result->flags = sig == 0 ? 0 : sig == UINT_MAX ? flag_author_signature : flag_distributor_signature;
121 result->signum = sig;
122 strcpy(result->name, name);
125 if (low < allfiles.count)
126 memmove(allfiles.files+low+1, allfiles.files+low, (allfiles.count - low) * sizeof(struct filedesc *));
127 allfiles.files[low] = result;
130 for (low = 0 ; low < allsignatures.count && sig > allsignatures.files[low]->signum ; low++);
131 if (low < allsignatures.count)
132 memmove(allsignatures.files+low+1, allsignatures.files+low, (allsignatures.count - low) * sizeof(struct filedesc *));
133 allsignatures.files[low] = result;
134 allsignatures.count++;
141 static struct filedesc *file_add(const char *name, enum entrytype type)
143 struct filedesc *desc;
145 desc = get_filedesc(name, 1);
148 else if (desc->type == type_unset)
151 syslog(LOG_ERR, "redeclaration of %s in file_add", name);
162 allsignatures.count = 0;
163 for (i = 0 ; i < allfiles.count ; i++)
164 free(allfiles.files[i]);
168 unsigned int file_count()
170 return allfiles.count;
173 struct filedesc *file_of_index(unsigned int index)
175 assert(index < allfiles.count);
176 return allfiles.files[index];
179 struct filedesc *file_of_name(const char *name)
181 return get_filedesc(name, 0);
184 struct filedesc *file_add_directory(const char *name)
186 return file_add(name, type_directory);
189 struct filedesc *file_add_file(const char *name)
191 return file_add(name, type_file);
194 unsigned int signature_count()
196 return allsignatures.count;
199 struct filedesc *signature_of_index(unsigned int index)
201 assert(index < allsignatures.count);
202 return allsignatures.files[index];
205 struct filedesc *get_signature(unsigned int number)
211 for (idx = 0 ; idx < allsignatures.count ; idx++)
212 if (allsignatures.files[idx]->signum == number)
213 return allsignatures.files[idx];
217 struct filedesc *create_signature(unsigned int number)
219 struct filedesc *result;
224 if (number == 0 || number == UINT_MAX)
225 len = asprintf(&name, "%s", author_file);
227 len = asprintf(&name, "%s%u%s", distributor_file_prefix, number, distributor_file_suffix);
230 syslog(LOG_ERR, "asprintf failed in create_signature");
233 result = file_of_name(name);
235 result = file_add_file(name);
242 /* remove flags that are not related to being signature */
243 void file_clear_flags()
246 for (i = 0 ; i < allfiles.count ; i++)
247 allfiles.files[i]->flags &= flag_signature;
250 static int fill_files_rec(char name[PATH_MAX], int offset)
256 fd = openat(workdirfd, offset ? name : ".", O_DIRECTORY|O_RDONLY);
258 syslog(LOG_ERR, "openat %.*s failed in fill_files_rec", offset, name);
263 syslog(LOG_ERR, "opendir %.*s failed in fill_files_rec", offset, name);
268 name[offset++] = '/';
271 while (ent != NULL) {
272 len = strlen(ent->d_name);
273 if (ent->d_name[0] == '.' && (len == 1 ||
274 (ent->d_name[1] == '.' && len == 2)))
276 else if (offset + len >= PATH_MAX) {
278 syslog(LOG_ERR, "name too long in fill_files_rec");
279 errno = ENAMETOOLONG;
282 memcpy(name + offset, ent->d_name, 1+len);
283 switch (ent->d_type) {
285 if (file_add_directory(name) == NULL) {
289 err = fill_files_rec(name, offset + len);
296 if (file_add_file(name) == NULL) {
315 return fill_files_rec(name, 0);