_alpm_checkconflicts split
[pacman.git] / lib / libalpm / be_files.c
blob078136ed7e22c3b906601c05f979a2caf2e9efa2
1 /*
2 * be_files.c
4 * Copyright (c) 2006 by Christian Hamar <krics@linuxforum.hu>
5 * Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 * USA.
23 #include "config.h"
25 #include <unistd.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <stdint.h> /* uintmax_t */
31 #include <sys/stat.h>
32 #include <dirent.h>
33 #include <ctype.h>
34 #include <time.h>
35 #include <limits.h> /* PATH_MAX */
36 #include <locale.h> /* setlocale */
38 /* libalpm */
39 #include "db.h"
40 #include "alpm_list.h"
41 #include "log.h"
42 #include "util.h"
43 #include "alpm.h"
44 #include "error.h"
45 #include "handle.h"
46 #include "package.h"
47 #include "delta.h"
48 #include "deps.h"
51 /* This function is used to convert the downloaded db file to the proper backend
52 * format
54 int _alpm_db_install(pmdb_t *db, const char *dbfile)
56 ALPM_LOG_FUNC;
58 /* TODO we should not simply unpack the archive, but better parse it and
59 * db_write each entry (see sync_load_dbarchive to get archive content) */
60 _alpm_log(PM_LOG_DEBUG, "unpacking database '%s'\n", dbfile);
62 if(_alpm_unpack(dbfile, db->path, NULL)) {
63 RET_ERR(PM_ERR_SYSTEM, -1);
66 return unlink(dbfile);
69 int _alpm_db_open(pmdb_t *db)
71 ALPM_LOG_FUNC;
73 if(db == NULL) {
74 RET_ERR(PM_ERR_DB_NULL, -1);
77 _alpm_log(PM_LOG_DEBUG, "opening database from path '%s'\n", db->path);
78 db->handle = opendir(db->path);
79 if(db->handle == NULL) {
80 RET_ERR(PM_ERR_DB_OPEN, -1);
83 return(0);
86 void _alpm_db_close(pmdb_t *db)
88 ALPM_LOG_FUNC;
90 if(db == NULL) {
91 return;
94 if(db->handle) {
95 closedir(db->handle);
96 db->handle = NULL;
100 void _alpm_db_rewind(pmdb_t *db)
102 ALPM_LOG_FUNC;
104 if(db == NULL || db->handle == NULL) {
105 return;
108 rewinddir(db->handle);
111 static int _alpm_db_splitname(const char *target, char *name, char *version)
113 /* the format of a db entry is as follows:
114 * package-version-rel/
115 * package name can contain hyphens, so parse from the back- go back
116 * two hyphens and we have split the version from the name.
118 char *tmp, *p, *q;
120 if(target == NULL) {
121 return(-1);
123 tmp = strdup(target);
124 p = tmp + strlen(tmp);
126 /* do the magic parsing- find the beginning of the version string
127 * by doing two iterations of same loop to lop off two hyphens */
128 for(q = --p; *q && *q != '-'; q--);
129 for(p = --q; *p && *p != '-'; p--);
130 if(*p != '-' || p == tmp) {
131 return(-1);
134 /* copy into fields and return */
135 if(version) {
136 strncpy(version, p+1, PKG_VERSION_LEN);
138 /* insert a terminator at the end of the name (on hyphen)- then copy it */
139 *p = '\0';
140 if(name) {
141 strncpy(name, tmp, PKG_NAME_LEN);
144 free(tmp);
145 return(0);
148 pmpkg_t *_alpm_db_scan(pmdb_t *db, const char *target)
150 struct dirent *ent = NULL;
151 struct stat sbuf;
152 char path[PATH_MAX];
153 char name[PKG_FULLNAME_LEN];
154 char *ptr = NULL;
155 int found = 0;
156 pmpkg_t *pkg = NULL;
158 ALPM_LOG_FUNC;
160 if(db == NULL) {
161 RET_ERR(PM_ERR_DB_NULL, NULL);
164 /* We loop here until we read a valid package. When an iteration of this loop
165 * fails, it means alpm_db_read failed to read a valid package, so we'll read
166 * the next so as not to abort whole-db operations early
168 while(!pkg) {
169 if(target != NULL) {
170 /* search for a specific package (by name only) */
171 rewinddir(db->handle);
172 while(!found && (ent = readdir(db->handle)) != NULL) {
173 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {
174 continue;
176 /* stat the entry, make sure it's a directory */
177 snprintf(path, PATH_MAX, "%s/%s", db->path, ent->d_name);
178 if(stat(path, &sbuf) || !S_ISDIR(sbuf.st_mode)) {
179 continue;
181 strncpy(name, ent->d_name, PKG_FULLNAME_LEN);
182 /* truncate the string at the second-to-last hyphen, */
183 /* which will give us the package name */
184 if((ptr = rindex(name, '-'))) {
185 *ptr = '\0';
187 if((ptr = rindex(name, '-'))) {
188 *ptr = '\0';
190 if(!strcmp(name, target)) {
191 found = 1;
194 if(!found) {
195 return(NULL);
197 } else { /* target == NULL, full scan */
198 int isdir = 0;
199 while(!isdir) {
200 ent = readdir(db->handle);
201 if(ent == NULL) {
202 return(NULL);
204 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {
205 isdir = 0;
206 continue;
208 /* stat the entry, make sure it's a directory */
209 snprintf(path, PATH_MAX, "%s/%s", db->path, ent->d_name);
210 if(!stat(path, &sbuf) && S_ISDIR(sbuf.st_mode)) {
211 isdir = 1;
216 pkg = _alpm_pkg_new(NULL, NULL);
217 if(pkg == NULL) {
218 _alpm_log(PM_LOG_DEBUG, "db scan could not find package: %s\n", target);
219 return(NULL);
221 /* split the db entry name */
222 if(_alpm_db_splitname(ent->d_name, pkg->name, pkg->version) != 0) {
223 _alpm_log(PM_LOG_ERROR, _("invalid name for database entry '%s'\n"),
224 ent->d_name);
225 alpm_pkg_free(pkg);
226 pkg = NULL;
227 continue;
230 /* explicitly read with only 'BASE' data, accessors will handle the rest */
231 if(_alpm_db_read(db, pkg, INFRQ_BASE) == -1) {
232 /* TODO removed corrupt entry from the FS here */
233 _alpm_pkg_free(pkg);
234 } else {
235 pkg->origin = PKG_FROM_CACHE;
236 pkg->origin_data.db = db;
240 return(pkg);
243 int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
245 FILE *fp = NULL;
246 struct stat buf;
247 char path[PATH_MAX+1];
248 char line[513];
250 ALPM_LOG_FUNC;
252 if(db == NULL) {
253 RET_ERR(PM_ERR_DB_NULL, -1);
256 if(info == NULL || info->name[0] == 0 || info->version[0] == 0) {
257 _alpm_log(PM_LOG_DEBUG, "invalid package entry provided to _alpm_db_read, skipping\n");
258 return(-1);
261 if(info->origin == PKG_FROM_FILE) {
262 _alpm_log(PM_LOG_DEBUG, "request to read database info for a file-based package '%s', skipping...\n", info->name);
263 return(-1);
266 /* bitmask logic here:
267 * infolevel: 00001111
268 * inforeq: 00010100
269 * & result: 00000100
270 * == to inforeq? nope, we need to load more info. */
271 if((info->infolevel & inforeq) == inforeq) {
272 /* already loaded this info, do nothing */
273 return(0);
275 _alpm_log(PM_LOG_FUNCTION, _("loading package data for %s : level=%d\n"), info->name, inforeq);
277 /* clear out 'line', to be certain - and to make valgrind happy */
278 memset(line, 0, 513);
280 snprintf(path, PATH_MAX, "%s/%s-%s", db->path, info->name, info->version);
281 if(stat(path, &buf)) {
282 /* directory doesn't exist or can't be opened */
283 _alpm_log(PM_LOG_DEBUG, "cannot find '%s-%s' in db '%s'\n",
284 info->name, info->version, db->treename);
285 return(-1);
288 /* DESC */
289 if(inforeq & INFRQ_DESC) {
290 snprintf(path, PATH_MAX, "%s/%s-%s/desc", db->path, info->name, info->version);
291 if((fp = fopen(path, "r")) == NULL) {
292 _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno));
293 goto error;
295 while(!feof(fp)) {
296 if(fgets(line, 256, fp) == NULL) {
297 break;
299 _alpm_strtrim(line);
300 if(!strcmp(line, "%FILENAME%")) {
301 /* filename is _new_ - it provides the real name of the package, on the
302 * server, to allow for us to not tie the name of the actual file to the
303 * data of the package
305 if(fgets(info->filename, sizeof(info->filename), fp) == NULL) {
306 goto error;
308 _alpm_strtrim(info->filename);
309 } else if(!strcmp(line, "%DESC%")) {
310 if(fgets(info->desc, sizeof(info->desc), fp) == NULL) {
311 goto error;
313 _alpm_strtrim(info->desc);
314 } else if(!strcmp(line, "%GROUPS%")) {
315 while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
316 info->groups = alpm_list_add(info->groups, strdup(line));
318 } else if(!strcmp(line, "%URL%")) {
319 if(fgets(info->url, sizeof(info->url), fp) == NULL) {
320 goto error;
322 _alpm_strtrim(info->url);
323 } else if(!strcmp(line, "%LICENSE%")) {
324 while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
325 info->licenses = alpm_list_add(info->licenses, strdup(line));
327 } else if(!strcmp(line, "%ARCH%")) {
328 if(fgets(info->arch, sizeof(info->arch), fp) == NULL) {
329 goto error;
331 _alpm_strtrim(info->arch);
332 } else if(!strcmp(line, "%BUILDDATE%")) {
333 char tmp[32];
334 if(fgets(tmp, sizeof(tmp), fp) == NULL) {
335 goto error;
337 _alpm_strtrim(tmp);
339 char first = tolower(tmp[0]);
340 if(first > 'a' && first < 'z') {
341 struct tm tmp_tm = {0}; //initialize to null incase of failure
342 setlocale(LC_TIME, "C");
343 strptime(tmp, "%a %b %e %H:%M:%S %Y", &tmp_tm);
344 info->builddate = mktime(&tmp_tm);
345 setlocale(LC_TIME, "");
346 } else {
347 info->builddate = atol(tmp);
349 } else if(!strcmp(line, "%INSTALLDATE%")) {
350 char tmp[32];
351 if(fgets(tmp, sizeof(tmp), fp) == NULL) {
352 goto error;
354 _alpm_strtrim(tmp);
356 char first = tolower(tmp[0]);
357 if(first > 'a' && first < 'z') {
358 struct tm tmp_tm = {0}; //initialize to null incase of failure
359 setlocale(LC_TIME, "C");
360 strptime(tmp, "%a %b %e %H:%M:%S %Y", &tmp_tm);
361 info->installdate = mktime(&tmp_tm);
362 setlocale(LC_TIME, "");
363 } else {
364 info->installdate = atol(tmp);
366 } else if(!strcmp(line, "%PACKAGER%")) {
367 if(fgets(info->packager, sizeof(info->packager), fp) == NULL) {
368 goto error;
370 _alpm_strtrim(info->packager);
371 } else if(!strcmp(line, "%REASON%")) {
372 char tmp[32];
373 if(fgets(tmp, sizeof(tmp), fp) == NULL) {
374 goto error;
376 _alpm_strtrim(tmp);
377 info->reason = atol(tmp);
378 } else if(!strcmp(line, "%SIZE%") || !strcmp(line, "%CSIZE%")) {
379 /* NOTE: the CSIZE and SIZE fields both share the "size" field
380 * in the pkginfo_t struct. This can be done b/c CSIZE
381 * is currently only used in sync databases, and SIZE is
382 * only used in local databases.
384 char tmp[32];
385 if(fgets(tmp, sizeof(tmp), fp) == NULL) {
386 goto error;
388 _alpm_strtrim(tmp);
389 info->size = atol(tmp);
390 /* also store this value to isize if isize is unset */
391 if(info->isize == 0) {
392 info->isize = atol(tmp);
394 } else if(!strcmp(line, "%ISIZE%")) {
395 /* ISIZE (installed size) tag only appears in sync repositories,
396 * not the local one. */
397 char tmp[32];
398 if(fgets(tmp, sizeof(tmp), fp) == NULL) {
399 goto error;
401 _alpm_strtrim(tmp);
402 info->isize = atol(tmp);
403 } else if(!strcmp(line, "%MD5SUM%")) {
404 /* MD5SUM tag only appears in sync repositories,
405 * not the local one. */
406 if(fgets(info->md5sum, sizeof(info->md5sum), fp) == NULL) {
407 goto error;
409 } else if(!strcmp(line, "%REPLACES%")) {
410 /* the REPLACES tag is special -- it only appears in sync repositories,
411 * not the local one. */
412 while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
413 info->replaces = alpm_list_add(info->replaces, strdup(line));
415 } else if(!strcmp(line, "%FORCE%")) {
416 /* FORCE tag only appears in sync repositories,
417 * not the local one. */
418 info->force = 1;
421 fclose(fp);
422 fp = NULL;
425 /* FILES */
426 if(inforeq & INFRQ_FILES) {
427 snprintf(path, PATH_MAX, "%s/%s-%s/files", db->path, info->name, info->version);
428 if((fp = fopen(path, "r")) == NULL) {
429 _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno));
430 goto error;
432 while(fgets(line, 256, fp)) {
433 _alpm_strtrim(line);
434 if(!strcmp(line, "%FILES%")) {
435 while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
436 info->files = alpm_list_add(info->files, strdup(line));
438 } else if(!strcmp(line, "%BACKUP%")) {
439 while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
440 info->backup = alpm_list_add(info->backup, strdup(line));
444 fclose(fp);
445 fp = NULL;
448 /* DEPENDS */
449 if(inforeq & INFRQ_DEPENDS) {
450 snprintf(path, PATH_MAX, "%s/%s-%s/depends", db->path, info->name, info->version);
451 if((fp = fopen(path, "r")) == NULL) {
452 _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno));
453 goto error;
455 while(!feof(fp)) {
456 fgets(line, 255, fp);
457 _alpm_strtrim(line);
458 if(!strcmp(line, "%DEPENDS%")) {
459 while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
460 pmdepend_t *dep = alpm_splitdep(line);
461 info->depends = alpm_list_add(info->depends, dep);
463 } else if(!strcmp(line, "%OPTDEPENDS%")) {
464 while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
465 info->optdepends = alpm_list_add(info->optdepends, strdup(line));
467 } else if(!strcmp(line, "%CONFLICTS%")) {
468 while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
469 info->conflicts = alpm_list_add(info->conflicts, strdup(line));
471 } else if(!strcmp(line, "%PROVIDES%")) {
472 while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
473 info->provides = alpm_list_add(info->provides, strdup(line));
476 /* TODO: we were going to move these things here, but it should wait.
477 * A better change would be to figure out how to restructure the DB. */
478 /* else if(!strcmp(line, "%REPLACES%")) {
479 * the REPLACES tag is special -- it only appears in sync repositories,
480 * not the local one. *
481 while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
482 info->replaces = alpm_list_add(info->replaces, strdup(line));
484 } else if(!strcmp(line, "%FORCE%")) {
485 * FORCE tag only appears in sync repositories,
486 * not the local one. *
487 info->force = 1;
488 } */
490 fclose(fp);
491 fp = NULL;
494 /* DELTAS */
495 if(inforeq & INFRQ_DELTAS) {
496 snprintf(path, PATH_MAX, "%s/%s-%s/deltas", db->path, info->name, info->version);
497 if((fp = fopen(path, "r"))) {
498 while(!feof(fp)) {
499 fgets(line, 255, fp);
500 _alpm_strtrim(line);
501 if(!strcmp(line, "%DELTAS%")) {
502 while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
503 info->deltas = alpm_list_add(info->deltas, _alpm_delta_parse(line));
507 fclose(fp);
508 fp = NULL;
512 /* INSTALL */
513 if(inforeq & INFRQ_SCRIPTLET) {
514 snprintf(path, PATH_MAX, "%s/%s-%s/install", db->path, info->name, info->version);
515 if(!stat(path, &buf)) {
516 info->scriptlet = 1;
520 /* internal */
521 info->infolevel |= inforeq;
523 return(0);
525 error:
526 if(fp) {
527 fclose(fp);
529 return(-1);
532 int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
534 FILE *fp = NULL;
535 char path[PATH_MAX];
536 mode_t oldmask;
537 alpm_list_t *lp = NULL;
538 int retval = 0;
539 int local = 0;
541 ALPM_LOG_FUNC;
543 if(db == NULL || info == NULL) {
544 return(-1);
547 snprintf(path, PATH_MAX, "%s/%s-%s", db->path, info->name, info->version);
548 oldmask = umask(0000);
549 mkdir(path, 0755);
550 /* make sure we have a sane umask */
551 umask(0022);
553 if(strcmp(db->treename, "local") == 0) {
554 local = 1;
557 /* DESC */
558 if(inforeq & INFRQ_DESC) {
559 _alpm_log(PM_LOG_DEBUG, "writing %s-%s DESC information back to db\n",
560 info->name, info->version);
561 snprintf(path, PATH_MAX, "%s/%s-%s/desc", db->path, info->name, info->version);
562 if((fp = fopen(path, "w")) == NULL) {
563 _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno));
564 retval = -1;
565 goto cleanup;
567 fprintf(fp, "%%NAME%%\n%s\n\n"
568 "%%VERSION%%\n%s\n\n", info->name, info->version);
569 if(info->desc[0]) {
570 fprintf(fp, "%%DESC%%\n"
571 "%s\n\n", info->desc);
573 if(info->groups) {
574 fputs("%GROUPS%\n", fp);
575 for(lp = info->groups; lp; lp = lp->next) {
576 fprintf(fp, "%s\n", (char *)lp->data);
578 fprintf(fp, "\n");
580 if(local) {
581 if(info->url[0]) {
582 fprintf(fp, "%%URL%%\n"
583 "%s\n\n", info->url);
585 if(info->licenses) {
586 fputs("%LICENSE%\n", fp);
587 for(lp = info->licenses; lp; lp = lp->next) {
588 fprintf(fp, "%s\n", (char *)lp->data);
590 fprintf(fp, "\n");
592 if(info->arch[0]) {
593 fprintf(fp, "%%ARCH%%\n"
594 "%s\n\n", info->arch);
596 if(info->builddate) {
597 fprintf(fp, "%%BUILDDATE%%\n"
598 "%ju\n\n", (uintmax_t)info->builddate);
600 if(info->installdate) {
601 fprintf(fp, "%%INSTALLDATE%%\n"
602 "%ju\n\n", (uintmax_t)info->installdate);
604 if(info->packager[0]) {
605 fprintf(fp, "%%PACKAGER%%\n"
606 "%s\n\n", info->packager);
608 if(info->size) {
609 /* only write installed size, csize is irrelevant once installed */
610 fprintf(fp, "%%SIZE%%\n"
611 "%lu\n\n", info->isize);
613 if(info->reason) {
614 fprintf(fp, "%%REASON%%\n"
615 "%u\n\n", info->reason);
617 } else {
618 if(info->size) {
619 fprintf(fp, "%%CSIZE%%\n"
620 "%lu\n\n", info->size);
622 if(info->isize) {
623 fprintf(fp, "%%ISIZE%%\n"
624 "%lu\n\n", info->isize);
626 if(info->md5sum) {
627 fprintf(fp, "%%MD5SUM%%\n"
628 "%s\n\n", info->md5sum);
631 fclose(fp);
632 fp = NULL;
635 /* FILES */
636 if(local && (inforeq & INFRQ_FILES)) {
637 _alpm_log(PM_LOG_DEBUG, "writing %s-%s FILES information back to db\n",
638 info->name, info->version);
639 snprintf(path, PATH_MAX, "%s/%s-%s/files", db->path, info->name, info->version);
640 if((fp = fopen(path, "w")) == NULL) {
641 _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno));
642 retval = -1;
643 goto cleanup;
645 if(info->files) {
646 fprintf(fp, "%%FILES%%\n");
647 for(lp = info->files; lp; lp = lp->next) {
648 fprintf(fp, "%s\n", (char *)lp->data);
650 fprintf(fp, "\n");
652 if(info->backup) {
653 fprintf(fp, "%%BACKUP%%\n");
654 for(lp = info->backup; lp; lp = lp->next) {
655 fprintf(fp, "%s\n", (char *)lp->data);
657 fprintf(fp, "\n");
659 fclose(fp);
660 fp = NULL;
663 /* DEPENDS */
664 if(inforeq & INFRQ_DEPENDS) {
665 _alpm_log(PM_LOG_DEBUG, "writing %s-%s DEPENDS information back to db\n",
666 info->name, info->version);
667 snprintf(path, PATH_MAX, "%s/%s-%s/depends", db->path, info->name, info->version);
668 if((fp = fopen(path, "w")) == NULL) {
669 _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno));
670 retval = -1;
671 goto cleanup;
673 if(info->depends) {
674 fputs("%DEPENDS%\n", fp);
675 for(lp = info->depends; lp; lp = lp->next) {
676 char *depstring = alpm_dep_get_string(lp->data);
677 fprintf(fp, "%s\n", depstring);
678 free(depstring);
680 fprintf(fp, "\n");
682 if(info->optdepends) {
683 fputs("%OPTDEPENDS%\n", fp);
684 for(lp = info->optdepends; lp; lp = lp->next) {
685 fprintf(fp, "%s\n", (char *)lp->data);
687 fprintf(fp, "\n");
689 if(info->conflicts) {
690 fputs("%CONFLICTS%\n", fp);
691 for(lp = info->conflicts; lp; lp = lp->next) {
692 fprintf(fp, "%s\n", (char *)lp->data);
694 fprintf(fp, "\n");
696 if(info->provides) {
697 fputs("%PROVIDES%\n", fp);
698 for(lp = info->provides; lp; lp = lp->next) {
699 fprintf(fp, "%s\n", (char *)lp->data);
701 fprintf(fp, "\n");
703 if(!local) {
704 if(info->replaces) {
705 fputs("%REPLACES%\n", fp);
706 for(lp = info->replaces; lp; lp = lp->next) {
707 fprintf(fp, "%s\n", (char *)lp->data);
709 fprintf(fp, "\n");
711 if(info->force) {
712 fprintf(fp, "%%FORCE%%\n"
713 "\n");
716 fclose(fp);
717 fp = NULL;
720 /* INSTALL */
721 /* nothing needed here (script is automatically extracted) */
723 cleanup:
724 umask(oldmask);
726 if(fp) {
727 fclose(fp);
730 return(retval);
733 int _alpm_db_remove(pmdb_t *db, pmpkg_t *info)
735 char path[PATH_MAX];
737 ALPM_LOG_FUNC;
739 if(db == NULL || info == NULL) {
740 RET_ERR(PM_ERR_DB_NULL, -1);
743 snprintf(path, PATH_MAX, "%s%s-%s", db->path, info->name, info->version);
744 if(_alpm_rmrf(path) == -1) {
745 return(-1);
748 return(0);
752 * Return the last update time as number of seconds from the epoch.
753 * Returns 0 if the value is unknown or can't be read.
755 time_t _alpm_db_getlastupdate(const pmdb_t *db)
757 FILE *fp;
758 char file[PATH_MAX];
759 time_t ret = 0;
761 ALPM_LOG_FUNC;
763 if(db == NULL) {
764 return(ret);
767 snprintf(file, PATH_MAX, "%s.lastupdate", db->path);
769 /* get the last update time, if it's there */
770 if((fp = fopen(file, "r")) == NULL) {
771 return(ret);
772 } else {
773 char line[64];
774 if(fgets(line, sizeof(line), fp)) {
775 ret = atol(line);
778 fclose(fp);
779 return(ret);
783 * writes the dbpath/.lastupdate file with the value in time
785 int _alpm_db_setlastupdate(const pmdb_t *db, time_t time)
787 FILE *fp;
788 char file[PATH_MAX];
789 int ret = 0;
791 ALPM_LOG_FUNC;
793 if(db == NULL || time == 0) {
794 return(-1);
797 snprintf(file, PATH_MAX, "%s.lastupdate", db->path);
799 if((fp = fopen(file, "w")) == NULL) {
800 return(-1);
802 if(fprintf(fp, "%ju", (uintmax_t)time) <= 0) {
803 ret = -1;
805 fclose(fp);
807 return(ret);
810 /* vim: set ts=2 sw=2 noet: */