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.
29 struct filedesc **files;
32 static struct fdb allfiles = { .count = 0, .files = NULL };
33 static struct fdb allsignatures = { .count = 0, .files = NULL };
35 static const char author_file[] = "author-signature.xml";
36 static const char distributor_file_prefix[] = "signature";
37 static const char distributor_file_suffix[] = ".xml";
39 static unsigned int what_signature(const char *name)
41 unsigned int len, id, nid;
43 if (!strcmp(name, author_file))
46 len = sizeof(distributor_file_prefix)-1;
47 if (memcmp(name, distributor_file_prefix, len))
49 if (name[len] <= '0' || name[len] > '9')
51 id = (unsigned int)(name[len++] - '0');
52 while ('0' <= name[len] && name[len] <= '9') {
53 nid = 10 * id + (unsigned int)(name[len++] - '0');
54 if (nid < id || nid == UINT_MAX) {
55 syslog(LOG_WARNING, "number too big for %s", name);
60 if (strcmp(name+len, distributor_file_suffix))
66 static struct filedesc *get_filedesc(const char *name, int create)
69 unsigned int low, up, mid, sig;
70 struct filedesc *result, **grow;
76 mid = (low + up) >> 1;
77 result = allfiles.files[mid];
78 cmp = strcmp(result->name, name);
80 return result; /* found */
87 /* not found, can create ? */
91 sig = what_signature(name);
94 grow = realloc(allfiles.files, (allfiles.count + 1) * sizeof(struct filedesc *));
96 syslog(LOG_ERR, "realloc failed in get_filedesc");
99 allfiles.files = grow;
102 grow = realloc(allsignatures.files, (allsignatures.count + 1) * sizeof(struct filedesc *));
104 syslog(LOG_ERR, "second realloc failed in get_filedesc");
107 allsignatures.files = grow;
110 result = malloc(sizeof(struct filedesc) + strlen(name));
112 syslog(LOG_ERR, "calloc failed in get_filedesc");
117 result->type = type_unset;
118 result->flags = sig == 0 ? 0 : sig == UINT_MAX ? flag_author_signature : flag_distributor_signature;
120 result->signum = sig;
121 strcpy(result->name, name);
124 if (low < allfiles.count)
125 memmove(allfiles.files+low+1, allfiles.files+low, (allfiles.count - low) * sizeof(struct filedesc *));
126 allfiles.files[low] = result;
129 for (low = 0 ; low < allsignatures.count && sig > allsignatures.files[low]->signum ; low++);
130 if (low < allsignatures.count)
131 memmove(allsignatures.files+low+1, allsignatures.files+low, (allsignatures.count - low) * sizeof(struct filedesc *));
132 allsignatures.files[low] = result;
133 allsignatures.count++;
140 static struct filedesc *file_add(const char *name, enum entrytype type)
142 struct filedesc *desc;
144 desc = get_filedesc(name, 1);
147 else if (desc->type == type_unset)
150 syslog(LOG_ERR, "redeclaration of %s in file_add", name);
161 allsignatures.count = 0;
162 for (i = 0 ; i < allfiles.count ; i++)
163 free(allfiles.files[i]);
167 unsigned int file_count()
169 return allfiles.count;
172 struct filedesc *file_of_index(unsigned int index)
174 assert(index < allfiles.count);
175 return allfiles.files[index];
178 struct filedesc *file_of_name(const char *name)
180 return get_filedesc(name, 0);
183 struct filedesc *file_add_directory(const char *name)
185 return file_add(name, type_directory);
188 struct filedesc *file_add_file(const char *name)
190 return file_add(name, type_file);
193 unsigned int signature_count()
195 return allsignatures.count;
198 struct filedesc *signature_of_index(unsigned int index)
200 assert(index < allsignatures.count);
201 return allsignatures.files[index];
204 struct filedesc *get_signature(unsigned int number)
210 for (idx = 0 ; idx < allsignatures.count ; idx++)
211 if (allsignatures.files[idx]->signum == number)
212 return allsignatures.files[idx];
216 struct filedesc *create_signature(unsigned int number)
218 struct filedesc *result;
223 if (number == 0 || number == UINT_MAX)
224 len = asprintf(&name, "%s", author_file);
226 len = asprintf(&name, "%s%u%s", distributor_file_prefix, number, distributor_file_suffix);
229 syslog(LOG_ERR, "asprintf failed in create_signature");
232 result = file_of_name(name);
234 result = file_add_file(name);
241 /* remove flags that are not related to being signature */
242 void file_clear_flags()
245 for (i = 0 ; i < allfiles.count ; i++)
246 allfiles.files[i]->flags &= flag_signature;
249 static int fill_files_rec(char name[PATH_MAX], int offset)
259 name[offset++] = '/';
262 syslog(LOG_ERR, "opendir %.*s failed in zwr", offset, name);
267 while (ent != NULL) {
268 len = strlen(ent->d_name);
269 if (ent->d_name[0] == '.' && (len == 1 ||
270 (ent->d_name[1] == '.' && len == 2)))
272 else if (offset + len >= PATH_MAX) {
274 syslog(LOG_ERR, "name too long in fill_files_rec");
275 errno = ENAMETOOLONG;
278 memcpy(name + offset, ent->d_name, 1+len);
279 switch (ent->d_type) {
281 if (file_add_directory(name) == NULL) {
285 err = fill_files_rec(name, offset + len);
292 if (file_add_file(name) == NULL) {
311 return fill_files_rec(name, 0);