Adding error message for the lock file.
[project/opkg-lede.git] / libopkg / opkg_conf.c
1 /* opkg_conf.c - the opkg package management system
2
3 Carl D. Worth
4
5 Copyright (C) 2001 University of Southern California
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2, or (at
10 your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16 */
17
18 #include "includes.h"
19 #include "opkg_conf.h"
20 #include "opkg_error.h"
21
22 #include "xregex.h"
23 #include "sprintf_alloc.h"
24 #include "args.h"
25 #include "opkg_message.h"
26 #include "file_util.h"
27 #include "str_util.h"
28 #include "xsystem.h"
29 #include <glob.h>
30 #include "opkg_defines.h"
31
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include <errno.h>
36
37 extern char *conf_file_dir;
38
39 static int opkg_conf_parse_file(opkg_conf_t *conf, const char *filename,
40 pkg_src_list_t *pkg_src_list,
41 nv_pair_list_t *tmp_dest_nv_pair_list,
42 char **tmp_lists_dir);
43 static int opkg_conf_set_option(const opkg_option_t *options,
44 const char *name, const char *value);
45 static int opkg_conf_set_default_dest(opkg_conf_t *conf,
46 const char *default_dest_name);
47 static int set_and_load_pkg_src_list(opkg_conf_t *conf,
48 pkg_src_list_t *nv_pair_list);
49 static int set_and_load_pkg_dest_list(opkg_conf_t *conf,
50 nv_pair_list_t *nv_pair_list, char * lists_dir);
51
52 int opkg_init_options_array(const opkg_conf_t *conf, opkg_option_t **options)
53 {
54 opkg_option_t tmp[] = {
55 { "cache", OPKG_OPT_TYPE_STRING, &conf->cache},
56 { "force_defaults", OPKG_OPT_TYPE_BOOL, &conf->force_defaults },
57 { "force_maintainer", OPKG_OPT_TYPE_BOOL, &conf->force_maintainer },
58 { "force_depends", OPKG_OPT_TYPE_BOOL, &conf->force_depends },
59 { "force_overwrite", OPKG_OPT_TYPE_BOOL, &conf->force_overwrite },
60 { "force_downgrade", OPKG_OPT_TYPE_BOOL, &conf->force_downgrade },
61 { "force_reinstall", OPKG_OPT_TYPE_BOOL, &conf->force_reinstall },
62 { "force_space", OPKG_OPT_TYPE_BOOL, &conf->force_space },
63 { "check_signature", OPKG_OPT_TYPE_INT, &conf->check_signature },
64 { "ftp_proxy", OPKG_OPT_TYPE_STRING, &conf->ftp_proxy },
65 { "http_proxy", OPKG_OPT_TYPE_STRING, &conf->http_proxy },
66 { "no_proxy", OPKG_OPT_TYPE_STRING, &conf->no_proxy },
67 { "test", OPKG_OPT_TYPE_INT, &conf->noaction },
68 { "noaction", OPKG_OPT_TYPE_INT, &conf->noaction },
69 { "nodeps", OPKG_OPT_TYPE_BOOL, &conf->nodeps },
70 { "offline_root", OPKG_OPT_TYPE_STRING, &conf->offline_root },
71 { "offline_root_path", OPKG_OPT_TYPE_STRING, &conf->offline_root_path },
72 { "offline_root_post_script_cmd", OPKG_OPT_TYPE_STRING, &conf->offline_root_post_script_cmd },
73 { "offline_root_pre_script_cmd", OPKG_OPT_TYPE_STRING, &conf->offline_root_pre_script_cmd },
74 { "proxy_passwd", OPKG_OPT_TYPE_STRING, &conf->proxy_passwd },
75 { "proxy_user", OPKG_OPT_TYPE_STRING, &conf->proxy_user },
76 { "query-all", OPKG_OPT_TYPE_BOOL, &conf->query_all },
77 { "verbosity", OPKG_OPT_TYPE_BOOL, &conf->verbosity },
78 { NULL }
79 };
80
81 *options = (opkg_option_t *)calloc(1, sizeof(tmp));
82 if ( options == NULL ){
83 fprintf(stderr,"%s: Unable to allocate memory\n",__FUNCTION__);
84 return -1;
85 }
86
87 memcpy(*options, tmp, sizeof(tmp));
88 return 0;
89 };
90
91 static void opkg_conf_override_string(char **conf_str, char *arg_str)
92 {
93 if (arg_str) {
94 if (*conf_str) {
95 free(*conf_str);
96 }
97 *conf_str = strdup(arg_str);
98 }
99 }
100
101 static void opkg_conf_free_string(char **conf_str)
102 {
103 if (*conf_str) {
104 free(*conf_str);
105 *conf_str = NULL;
106 }
107 }
108
109 int opkg_conf_init(opkg_conf_t *conf, const args_t *args)
110 {
111 int err;
112 int errno_copy;
113 char *tmp_dir_base;
114 nv_pair_list_t tmp_dest_nv_pair_list;
115 char *lists_dir = NULL, *lock_file = NULL;
116 glob_t globbuf;
117 char *etc_opkg_conf_pattern;
118 char *pending_dir = NULL;
119
120 memset(conf, 0, sizeof(opkg_conf_t));
121
122 pkg_src_list_init(&conf->pkg_src_list);
123
124 nv_pair_list_init(&tmp_dest_nv_pair_list);
125 pkg_dest_list_init(&conf->pkg_dest_list);
126
127 nv_pair_list_init(&conf->arch_list);
128
129 conf->restrict_to_default_dest = 0;
130 conf->default_dest = NULL;
131
132 /* check for lock file */
133 if (args->offline_root)
134 sprintf_alloc (&lock_file, "%s/%s/lock", args->offline_root, OPKG_STATE_DIR_PREFIX);
135 else
136 sprintf_alloc (&lock_file, "%s/lock", OPKG_STATE_DIR_PREFIX);
137
138 conf->lock_fd = creat (lock_file, S_IRUSR | S_IWUSR | S_IRGRP);
139 err = lockf (conf->lock_fd, F_TLOCK, 0);
140 errno_copy = errno;
141
142 free (lock_file);
143
144 if (err)
145 {
146 if(args->offline_root) {
147 opkg_message (conf, OPKG_ERROR, "Could not obtain administrative lock for offline root (ERR: %s) at %s/%s/lock\n",
148 strerror(errno_copy), args->offline_root, OPKG_STATE_DIR_PREFIX);
149 } else {
150 opkg_message (conf, OPKG_ERROR, "Could not obtain administrative lock (ERR: %s) at %s/lock\n",
151 strerror(errno_copy), OPKG_STATE_DIR_PREFIX);
152 }
153 return OPKG_CONF_ERR_LOCK;
154 }
155
156 if (args->tmp_dir)
157 tmp_dir_base = args->tmp_dir;
158 else
159 tmp_dir_base = getenv("TMPDIR");
160 sprintf_alloc(&conf->tmp_dir, "%s/%s",
161 tmp_dir_base ? tmp_dir_base : OPKG_CONF_DEFAULT_TMP_DIR_BASE,
162 OPKG_CONF_TMP_DIR_SUFFIX);
163 conf->tmp_dir = mkdtemp(conf->tmp_dir);
164 if (conf->tmp_dir == NULL) {
165 fprintf(stderr, "%s: Failed to create temporary directory `%s': %s\n",
166 __FUNCTION__, conf->tmp_dir, strerror(errno));
167 return OPKG_CONF_ERR_TMP_DIR;
168 }
169
170 pkg_hash_init("pkg-hash", &conf->pkg_hash, OPKG_CONF_DEFAULT_HASH_LEN);
171 hash_table_init("file-hash", &conf->file_hash, OPKG_CONF_DEFAULT_HASH_LEN);
172 hash_table_init("obs-file-hash", &conf->obs_file_hash, OPKG_CONF_DEFAULT_HASH_LEN);
173 lists_dir=(char *)malloc(1);
174 lists_dir[0]='\0';
175 if (args->conf_file) {
176 struct stat stat_buf;
177 err = stat(args->conf_file, &stat_buf);
178 if (err == 0)
179 if (opkg_conf_parse_file(conf, args->conf_file,
180 &conf->pkg_src_list, &tmp_dest_nv_pair_list,&lists_dir)<0) {
181 /* Memory leakage from opkg_conf_parse-file */
182 return OPKG_CONF_ERR_PARSE;
183 }
184 }
185
186 if (strlen(lists_dir)<=1 ){
187 lists_dir = realloc(lists_dir,strlen(OPKG_CONF_LISTS_DIR)+2);
188 sprintf (lists_dir,"%s",OPKG_CONF_LISTS_DIR);
189 }
190
191 if (args->offline_root) {
192 char *tmp;
193 sprintf_alloc(&tmp, "%s/%s",args->offline_root,lists_dir);
194 free(lists_dir);
195 lists_dir = tmp;
196 }
197
198 pending_dir = calloc(1, strlen(lists_dir)+strlen("/pending")+5);
199 snprintf(pending_dir,strlen(lists_dir)+strlen("/pending") ,"%s%s",lists_dir,"/pending");
200
201 conf->lists_dir = strdup(lists_dir);
202 conf->pending_dir = strdup(pending_dir);
203
204 if (args->offline_root)
205 sprintf_alloc(&etc_opkg_conf_pattern, "%s/etc/opkg/*.conf", args->offline_root);
206 else
207 sprintf_alloc(&etc_opkg_conf_pattern, "%s/*.conf", conf_file_dir);
208 memset(&globbuf, 0, sizeof(globbuf));
209 err = glob(etc_opkg_conf_pattern, 0, NULL, &globbuf);
210 free (etc_opkg_conf_pattern);
211 if (!err) {
212 int i;
213 for (i = 0; i < globbuf.gl_pathc; i++) {
214 if (globbuf.gl_pathv[i])
215 if ( opkg_conf_parse_file(conf, globbuf.gl_pathv[i],
216 &conf->pkg_src_list, &tmp_dest_nv_pair_list,&lists_dir)<0) {
217 /* Memory leakage from opkg_conf_parse-file */
218 return OPKG_CONF_ERR_PARSE;
219 }
220 }
221 }
222 globfree(&globbuf);
223
224 /* if no architectures were defined, then default all, noarch, and host architecture */
225 if (nv_pair_list_empty(&conf->arch_list)) {
226 nv_pair_list_append(&conf->arch_list, "all", "1");
227 nv_pair_list_append(&conf->arch_list, "noarch", "1");
228 nv_pair_list_append(&conf->arch_list, HOST_CPU_STR, "10");
229 }
230
231 /* Even if there is no conf file, we'll need at least one dest. */
232 if (nv_pair_list_empty(&tmp_dest_nv_pair_list)) {
233 nv_pair_list_append(&tmp_dest_nv_pair_list,
234 OPKG_CONF_DEFAULT_DEST_NAME,
235 OPKG_CONF_DEFAULT_DEST_ROOT_DIR);
236 }
237
238 /* After parsing the file, set options from command-line, (so that
239 command-line arguments take precedence) */
240 /* XXX: CLEANUP: The interaction between args.c and opkg_conf.c
241 really needs to be cleaned up. There is so much duplication
242 right now it is ridiculous. Maybe opkg_conf_t should just save
243 a pointer to args_t (which could then not be freed), rather
244 than duplicating every field here? */
245 if (args->autoremove) {
246 conf->autoremove = 1;
247 }
248 if (args->force_depends) {
249 conf->force_depends = 1;
250 }
251 if (args->force_defaults) {
252 conf->force_defaults = 1;
253 }
254 if (args->force_maintainer) {
255 conf->force_maintainer = 1;
256 }
257 if (args->force_overwrite) {
258 conf->force_overwrite = 1;
259 }
260 if (args->force_downgrade) {
261 conf->force_downgrade = 1;
262 }
263 if (args->force_reinstall) {
264 conf->force_reinstall = 1;
265 }
266 if (args->force_removal_of_dependent_packages) {
267 conf->force_removal_of_dependent_packages = 1;
268 }
269 if (args->force_removal_of_essential_packages) {
270 conf->force_removal_of_essential_packages = 1;
271 }
272 if (args->nodeps) {
273 conf->nodeps = 1;
274 }
275 if (args->noaction) {
276 conf->noaction = 1;
277 }
278 if (args->query_all) {
279 conf->query_all = 1;
280 }
281 if (args->verbosity != conf->verbosity) {
282 conf->verbosity = args->verbosity;
283 }
284
285 opkg_conf_override_string(&conf->offline_root,
286 args->offline_root);
287 opkg_conf_override_string(&conf->offline_root_path,
288 args->offline_root_path);
289 opkg_conf_override_string(&conf->offline_root_pre_script_cmd,
290 args->offline_root_pre_script_cmd);
291 opkg_conf_override_string(&conf->offline_root_post_script_cmd,
292 args->offline_root_post_script_cmd);
293
294 opkg_conf_override_string(&conf->cache, args->cache);
295
296 /* Pigi: added a flag to disable the checking of structures if the command does not need to
297 read anything from there.
298 */
299 if ( !(args->nocheckfordirorfile)){
300 /* need to run load the source list before dest list -Jamey */
301 if ( !(args->noreadfeedsfile))
302 set_and_load_pkg_src_list(conf, &conf->pkg_src_list);
303
304 /* Now that we have resolved conf->offline_root, we can commit to
305 the directory names for the dests and load in all the package
306 lists. */
307 set_and_load_pkg_dest_list(conf, &tmp_dest_nv_pair_list,lists_dir);
308
309 if (args->dest) {
310 err = opkg_conf_set_default_dest(conf, args->dest);
311 if (err) {
312 return OPKG_CONF_ERR_DEFAULT_DEST;
313 }
314 }
315 }
316 nv_pair_list_deinit(&tmp_dest_nv_pair_list);
317 free(lists_dir);
318 free(pending_dir);
319
320 return 0;
321 }
322
323 void opkg_conf_deinit(opkg_conf_t *conf)
324 {
325 #ifdef OPKG_DEBUG_NO_TMP_CLEANUP
326 #error
327 fprintf(stderr, "%s: Not cleaning up %s since opkg compiled "
328 "with OPKG_DEBUG_NO_TMP_CLEANUP\n",
329 __FUNCTION__, conf->tmp_dir);
330 #else
331 int err;
332
333 err = rmdir(conf->tmp_dir);
334 if (err) {
335 if (errno == ENOTEMPTY) {
336 char *cmd;
337 sprintf_alloc(&cmd, "rm -fr %s\n", conf->tmp_dir);
338 err = xsystem(cmd);
339 free(cmd);
340 }
341 if (err)
342 fprintf(stderr, "WARNING: Unable to remove temporary directory: %s: %s\n", conf->tmp_dir, strerror(errno));
343 }
344 #endif /* OPKG_DEBUG_NO_TMP_CLEANUP */
345
346 free(conf->tmp_dir); /*XXX*/
347 free(conf->lists_dir);
348 free(conf->pending_dir);
349
350 pkg_src_list_deinit(&conf->pkg_src_list);
351 pkg_dest_list_deinit(&conf->pkg_dest_list);
352 nv_pair_list_deinit(&conf->arch_list);
353 if (&conf->pkg_hash)
354 pkg_hash_deinit(&conf->pkg_hash);
355 if (&conf->file_hash)
356 hash_table_deinit(&conf->file_hash);
357 if (&conf->obs_file_hash)
358 hash_table_deinit(&conf->obs_file_hash);
359
360 opkg_conf_free_string(&conf->offline_root);
361 opkg_conf_free_string(&conf->offline_root_path);
362 opkg_conf_free_string(&conf->offline_root_pre_script_cmd);
363 opkg_conf_free_string(&conf->offline_root_post_script_cmd);
364
365 opkg_conf_free_string(&conf->cache);
366
367 if (conf->verbosity > 1) {
368 int i;
369 hash_table_t *hashes[] = {
370 &conf->pkg_hash,
371 &conf->file_hash,
372 &conf->obs_file_hash };
373 for (i = 0; i < 3; i++) {
374 hash_table_t *hash = hashes[i];
375 int c = 0;
376 int n_conflicts = 0;
377 int j;
378 for (j = 0; j < hash->n_entries; j++) {
379 int len = 0;
380 hash_entry_t *e = &hash->entries[j];
381 if (e->next)
382 n_conflicts++;
383 while (e && e->key) {
384 len++;
385 e = e->next;
386 }
387 if (len > c)
388 c = len;
389 }
390 opkg_message(conf, OPKG_DEBUG, "hash_table[%s] n_buckets=%d n_elements=%d max_conflicts=%d n_conflicts=%d\n",
391 hash->name, hash->n_entries, hash->n_elements, c, n_conflicts);
392 hash_table_deinit(hash);
393 }
394 }
395 }
396
397 static int opkg_conf_set_default_dest(opkg_conf_t *conf,
398 const char *default_dest_name)
399 {
400 pkg_dest_list_elt_t *iter;
401 pkg_dest_t *dest;
402
403 for (iter = void_list_first(&conf->pkg_dest_list); iter; iter = void_list_next(&conf->pkg_dest_list, iter)) {
404 dest = (pkg_dest_t *)iter->data;
405 if (strcmp(dest->name, default_dest_name) == 0) {
406 conf->default_dest = dest;
407 conf->restrict_to_default_dest = 1;
408 return 0;
409 }
410 }
411
412 fprintf(stderr, "ERROR: Unknown dest name: `%s'\n", default_dest_name);
413
414 return 1;
415 }
416
417 static int set_and_load_pkg_src_list(opkg_conf_t *conf, pkg_src_list_t *pkg_src_list)
418 {
419 pkg_src_list_elt_t *iter;
420 pkg_src_t *src;
421 char *list_file;
422
423 for (iter = void_list_first(pkg_src_list); iter; iter = void_list_next(pkg_src_list, iter)) {
424 src = (pkg_src_t *)iter->data;
425 if (src == NULL) {
426 continue;
427 }
428
429 sprintf_alloc(&list_file, "%s/%s",
430 conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir,
431 src->name);
432
433 if (file_exists(list_file)) {
434 pkg_hash_add_from_file(conf, list_file, src, NULL, 0);
435 }
436 free(list_file);
437 }
438
439 return 0;
440 }
441
442 static int set_and_load_pkg_dest_list(opkg_conf_t *conf, nv_pair_list_t *nv_pair_list, char *lists_dir )
443 {
444 nv_pair_list_elt_t *iter;
445 nv_pair_t *nv_pair;
446 pkg_dest_t *dest;
447 char *root_dir;
448
449 for (iter = nv_pair_list_first(nv_pair_list); iter; iter = nv_pair_list_next(nv_pair_list, iter)) {
450 nv_pair = (nv_pair_t *)iter->data;
451
452 if (conf->offline_root) {
453 sprintf_alloc(&root_dir, "%s%s", conf->offline_root, nv_pair->value);
454 } else {
455 root_dir = strdup(nv_pair->value);
456 }
457 dest = pkg_dest_list_append(&conf->pkg_dest_list, nv_pair->name, root_dir, lists_dir);
458 free(root_dir);
459 if (dest == NULL) {
460 continue;
461 }
462 if (conf->default_dest == NULL) {
463 conf->default_dest = dest;
464 }
465 if (file_exists(dest->status_file_name)) {
466 pkg_hash_add_from_file(conf, dest->status_file_name,
467 NULL, dest, 1);
468 }
469 }
470
471 return 0;
472 }
473
474 static int opkg_conf_parse_file(opkg_conf_t *conf, const char *filename,
475 pkg_src_list_t *pkg_src_list,
476 nv_pair_list_t *tmp_dest_nv_pair_list,
477 char **lists_dir)
478 {
479 int err;
480 opkg_option_t * options;
481 FILE *file = fopen(filename, "r");
482 regex_t valid_line_re, comment_re;
483 #define regmatch_size 12
484 regmatch_t regmatch[regmatch_size];
485
486 if (opkg_init_options_array(conf, &options)<0)
487 return ENOMEM;
488
489 if (file == NULL) {
490 fprintf(stderr, "%s: failed to open %s: %s\n",
491 __FUNCTION__, filename, strerror(errno));
492 free(options);
493 return errno;
494 }
495 opkg_message(conf, OPKG_NOTICE, "loading conf file %s\n", filename);
496
497 err = xregcomp(&comment_re,
498 "^[[:space:]]*(#.*|[[:space:]]*)$",
499 REG_EXTENDED);
500 if (err) {
501 free(options);
502 return err;
503 }
504 err = xregcomp(&valid_line_re, "^[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))([[:space:]]+([^[:space:]]+))?[[:space:]]*$", REG_EXTENDED);
505 if (err) {
506 free(options);
507 return err;
508 }
509
510 while(1) {
511 int line_num = 0;
512 char *line;
513 char *type, *name, *value, *extra;
514
515 line = file_read_line_alloc(file);
516 line_num++;
517 if (line == NULL) {
518 break;
519 }
520
521 str_chomp(line);
522
523 if (regexec(&comment_re, line, 0, 0, 0) == 0) {
524 goto NEXT_LINE;
525 }
526
527 if (regexec(&valid_line_re, line, regmatch_size, regmatch, 0) == REG_NOMATCH) {
528 str_chomp(line);
529 fprintf(stderr, "%s:%d: Ignoring invalid line: `%s'\n",
530 filename, line_num, line);
531 goto NEXT_LINE;
532 }
533
534 /* This has to be so ugly to deal with optional quotation marks */
535 if (regmatch[2].rm_so > 0) {
536 type = strndup(line + regmatch[2].rm_so,
537 regmatch[2].rm_eo - regmatch[2].rm_so);
538 } else {
539 type = strndup(line + regmatch[3].rm_so,
540 regmatch[3].rm_eo - regmatch[3].rm_so);
541 }
542 if (regmatch[5].rm_so > 0) {
543 name = strndup(line + regmatch[5].rm_so,
544 regmatch[5].rm_eo - regmatch[5].rm_so);
545 } else {
546 name = strndup(line + regmatch[6].rm_so,
547 regmatch[6].rm_eo - regmatch[6].rm_so);
548 }
549 if (regmatch[8].rm_so > 0) {
550 value = strndup(line + regmatch[8].rm_so,
551 regmatch[8].rm_eo - regmatch[8].rm_so);
552 } else {
553 value = strndup(line + regmatch[9].rm_so,
554 regmatch[9].rm_eo - regmatch[9].rm_so);
555 }
556 extra = NULL;
557 if (regmatch[11].rm_so > 0) {
558 extra = strndup (line + regmatch[11].rm_so,
559 regmatch[11].rm_eo - regmatch[11].rm_so);
560 }
561
562 /* We use the tmp_dest_nv_pair_list below instead of
563 conf->pkg_dest_list because we might encounter an
564 offline_root option later and that would invalidate the
565 directories we would have computed in
566 pkg_dest_list_init. (We do a similar thing with
567 tmp_src_nv_pair_list for sake of symmetry.) */
568 if (strcmp(type, "option") == 0) {
569 opkg_conf_set_option(options, name, value);
570 } else if (strcmp(type, "src") == 0) {
571 if (!nv_pair_list_find((nv_pair_list_t*) pkg_src_list, name)) {
572 pkg_src_list_append (pkg_src_list, name, value, extra, 0);
573 } else {
574 opkg_message(conf, OPKG_ERROR, "ERROR: duplicate src declaration. Skipping:\n\t src %s %s\n",
575 name, value);
576 }
577 } else if (strcmp(type, "src/gz") == 0) {
578 if (!nv_pair_list_find((nv_pair_list_t*) pkg_src_list, name)) {
579 pkg_src_list_append (pkg_src_list, name, value, extra, 1);
580 } else {
581 opkg_message(conf, OPKG_ERROR, "ERROR: duplicate src declaration. Skipping:\n\t src %s %s\n",
582 name, value);
583 }
584 } else if (strcmp(type, "dest") == 0) {
585 nv_pair_list_append(tmp_dest_nv_pair_list, name, value);
586 } else if (strcmp(type, "lists_dir") == 0) {
587 *lists_dir = realloc(*lists_dir,strlen(value)+1);
588 if (*lists_dir == NULL) {
589 opkg_message(conf, OPKG_ERROR, "ERROR: Not enough memory\n");
590 free(options);
591 return EINVAL;
592 }
593 sprintf (*lists_dir,"%s",value);
594 } else if (strcmp(type, "arch") == 0) {
595 opkg_message(conf, OPKG_INFO, "supported arch %s priority (%s)\n", name, value);
596 if (!value) {
597 opkg_message(conf, OPKG_NOTICE, "defaulting architecture %s priority to 10\n", name);
598 value = strdup("10");
599 }
600 nv_pair_list_append(&conf->arch_list, name, value);
601 } else {
602 fprintf(stderr, "WARNING: Ignoring unknown configuration "
603 "parameter: %s %s %s\n", type, name, value);
604 free(options);
605 return EINVAL;
606 }
607
608 free(type);
609 free(name);
610 free(value);
611 if (extra)
612 free (extra);
613
614 NEXT_LINE:
615 free(line);
616 }
617
618 free(options);
619 regfree(&comment_re);
620 regfree(&valid_line_re);
621 fclose(file);
622
623 return 0;
624 }
625
626 static int opkg_conf_set_option(const opkg_option_t *options,
627 const char *name, const char *value)
628 {
629 int i = 0;
630 while (options[i].name) {
631 if (strcmp(options[i].name, name) == 0) {
632 switch (options[i].type) {
633 case OPKG_OPT_TYPE_BOOL:
634 *((int *)options[i].value) = 1;
635 return 0;
636 case OPKG_OPT_TYPE_INT:
637 if (value) {
638 *((int *)options[i].value) = atoi(value);
639 return 0;
640 } else {
641 printf("%s: Option %s need an argument\n",
642 __FUNCTION__, name);
643 return EINVAL;
644 }
645 case OPKG_OPT_TYPE_STRING:
646 if (value) {
647 *((char **)options[i].value) = strdup(value);
648 return 0;
649 } else {
650 printf("%s: Option %s need an argument\n",
651 __FUNCTION__, name);
652 return EINVAL;
653 }
654 }
655 }
656 i++;
657 }
658
659 fprintf(stderr, "%s: Unrecognized option: %s=%s\n",
660 __FUNCTION__, name, value);
661 return EINVAL;
662 }
663
664 int opkg_conf_write_status_files(opkg_conf_t *conf)
665 {
666 pkg_dest_t *dest;
667 pkg_vec_t *all;
668 pkg_t *pkg;
669 register int i;
670 int err;
671 FILE * status_file=NULL;
672
673 if (conf->noaction)
674 return 0;
675
676 dest = (pkg_dest_t *)void_list_first(&conf->pkg_dest_list)->data;
677 status_file = fopen(dest->status_file_tmp_name, "w");
678 if (status_file == NULL) {
679 fprintf(stderr, "%s: Can't open status file: %s for writing: %s\n",
680 __FUNCTION__, dest->status_file_tmp_name, strerror(errno));
681 }
682
683 all = pkg_vec_alloc();
684 pkg_hash_fetch_available(&conf->pkg_hash, all);
685
686 for(i = 0; i < all->len; i++) {
687 pkg = all->pkgs[i];
688 /* We don't need most uninstalled packages in the status file */
689 if (pkg->state_status == SS_NOT_INSTALLED
690 && (pkg->state_want == SW_UNKNOWN
691 || pkg->state_want == SW_DEINSTALL
692 || pkg->state_want == SW_PURGE)) {
693 continue;
694 }
695 if (!pkg) {
696 fprintf(stderr, "Null package\n");
697 }
698 if (pkg->dest == NULL) {
699 fprintf(stderr, "%s: ERROR: Can't write status for "
700 "package %s since it has a NULL dest\n",
701 __FUNCTION__, pkg->name);
702 continue;
703 }
704 if (status_file) {
705 pkg_print_status(pkg, status_file);
706 }
707 }
708
709 pkg_vec_free(all);
710
711 if (status_file) {
712 err = ferror(status_file);
713 fclose(status_file);
714 if (!err) {
715 file_move(dest->status_file_tmp_name, dest->status_file_name);
716 } else {
717 fprintf(stderr, "%s: ERROR: An error has occurred writing %s, "
718 "retaining old %s\n", __FUNCTION__,
719 dest->status_file_tmp_name, dest->status_file_name);
720 }
721 status_file = NULL;
722 }
723 return 0;
724 }
725
726
727 char *root_filename_alloc(opkg_conf_t *conf, char *filename)
728 {
729 char *root_filename;
730 sprintf_alloc(&root_filename, "%s%s", (conf->offline_root ? conf->offline_root : ""), filename);
731 return root_filename;
732 }