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.
31 struct filedesc **files;
34 static struct fdb allfiles = { .count = 0, .files = NULL };
35 static struct fdb allsignatures = { .count = 0, .files = NULL };
37 static const char author_file[] = "author-signature.xml";
38 static const char distributor_file_prefix[] = "signature";
39 static const char distributor_file_suffix[] = ".xml";
41 static unsigned int what_signature(const char *name)
43 unsigned int len, id, nid;
45 if (!strcmp(name, author_file))
48 len = sizeof(distributor_file_prefix)-1;
49 if (memcmp(name, distributor_file_prefix, len))
51 if (name[len] <= '0' || name[len] > '9')
53 id = (unsigned int)(name[len++] - '0');
54 while ('0' <= name[len] && name[len] <= '9') {
55 nid = 10 * id + (unsigned int)(name[len++] - '0');
56 if (nid < id || nid == UINT_MAX) {
57 syslog(LOG_WARNING, "number too big for %s", name);
62 if (strcmp(name+len, distributor_file_suffix))
68 static struct filedesc *get_filedesc(const char *name, int create)
71 unsigned int low, up, mid, sig;
72 struct filedesc *result, **grow;
78 mid = (low + up) >> 1;
79 result = allfiles.files[mid];
80 cmp = strcmp(result->name, name);
82 return result; /* found */
89 /* not found, can create ? */
93 sig = what_signature(name);
96 grow = realloc(allfiles.files, (allfiles.count + 1) * sizeof(struct filedesc *));
98 syslog(LOG_ERR, "realloc failed in get_filedesc");
101 allfiles.files = grow;
104 grow = realloc(allsignatures.files, (allsignatures.count + 1) * sizeof(struct filedesc *));
106 syslog(LOG_ERR, "second realloc failed in get_filedesc");
109 allsignatures.files = grow;
112 result = malloc(sizeof(struct filedesc) + strlen(name));
114 syslog(LOG_ERR, "calloc failed in get_filedesc");
119 result->type = type_unset;
120 result->flags = sig == 0 ? 0 : sig == UINT_MAX ? flag_author_signature : flag_distributor_signature;
122 result->signum = sig;
123 strcpy(result->name, name);
126 if (low < allfiles.count)
127 memmove(allfiles.files+low+1, allfiles.files+low, (allfiles.count - low) * sizeof(struct filedesc *));
128 allfiles.files[low] = result;
131 for (low = 0 ; low < allsignatures.count && sig > allsignatures.files[low]->signum ; low++);
132 if (low < allsignatures.count)
133 memmove(allsignatures.files+low+1, allsignatures.files+low, (allsignatures.count - low) * sizeof(struct filedesc *));
134 allsignatures.files[low] = result;
135 allsignatures.count++;
142 static struct filedesc *file_add(const char *name, enum entrytype type)
144 struct filedesc *desc;
146 desc = get_filedesc(name, 1);
149 else if (desc->type == type_unset)
152 syslog(LOG_ERR, "redeclaration of %s in file_add", name);
163 allsignatures.count = 0;
164 for (i = 0 ; i < allfiles.count ; i++)
165 free(allfiles.files[i]);
169 unsigned int file_count()
171 return allfiles.count;
174 struct filedesc *file_of_index(unsigned int index)
176 assert(index < allfiles.count);
177 return allfiles.files[index];
180 struct filedesc *file_of_name(const char *name)
182 return get_filedesc(name, 0);
185 struct filedesc *file_add_directory(const char *name)
187 return file_add(name, type_directory);
190 struct filedesc *file_add_file(const char *name)
192 return file_add(name, type_file);
195 unsigned int signature_count()
197 return allsignatures.count;
200 struct filedesc *signature_of_index(unsigned int index)
202 assert(index < allsignatures.count);
203 return allsignatures.files[index];
206 struct filedesc *get_signature(unsigned int number)
212 for (idx = 0 ; idx < allsignatures.count ; idx++)
213 if (allsignatures.files[idx]->signum == number)
214 return allsignatures.files[idx];
218 struct filedesc *create_signature(unsigned int number)
220 struct filedesc *result;
225 if (number == 0 || number == UINT_MAX)
226 len = asprintf(&name, "%s", author_file);
228 len = asprintf(&name, "%s%u%s", distributor_file_prefix, number, distributor_file_suffix);
231 syslog(LOG_ERR, "asprintf failed in create_signature");
234 result = file_of_name(name);
236 result = file_add_file(name);
243 /* remove flags that are not related to being signature */
244 void file_clear_flags()
247 for (i = 0 ; i < allfiles.count ; i++)
248 allfiles.files[i]->flags &= flag_signature;
251 static int fill_files_rec(char name[PATH_MAX], int offset)
257 fd = openat(workdirfd, offset ? name : ".", O_DIRECTORY|O_RDONLY);
259 syslog(LOG_ERR, "openat %.*s failed in fill_files_rec", offset, name);
264 syslog(LOG_ERR, "opendir %.*s failed in fill_files_rec", offset, name);
269 name[offset++] = '/';
272 while (ent != NULL) {
273 len = strlen(ent->d_name);
274 if (ent->d_name[0] == '.' && (len == 1 ||
275 (ent->d_name[1] == '.' && len == 2)))
277 else if (offset + len >= PATH_MAX) {
279 syslog(LOG_ERR, "name too long in fill_files_rec");
280 errno = ENAMETOOLONG;
283 memcpy(name + offset, ent->d_name, 1+len);
284 switch (ent->d_type) {
286 if (file_add_directory(name) == NULL) {
290 err = fill_files_rec(name, offset + len);
297 if (file_add_file(name) == NULL) {
316 return fill_files_rec(name, 0);