Implemented force install
[spkg.git] / src / pkgdb.c
blob756989d2ecee1ff269ad82ba67fd9b3c8658e8cf
1 /*----------------------------------------------------------------------*\
2 |* spkg - The Unofficial Slackware Linux Package Manager *|
3 |* designed by Ondøej Jirman, 2005 *|
4 |*----------------------------------------------------------------------*|
5 |* No copy/usage restrictions are imposed on anybody. *|
6 \*----------------------------------------------------------------------*/
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <sys/stat.h>
10 #include <dirent.h>
11 #include <unistd.h>
12 #include <fcntl.h>
13 #include <string.h>
14 #include <utime.h>
15 #include <errno.h>
16 #include <zlib.h>
18 #include <Judy.h>
20 #include "sys.h"
21 #include "misc.h"
22 #include "path.h"
23 #include "pkgdb.h"
24 #include "bench.h"
26 #ifdef __WIN32__
27 extern int posix_utime (const char *path, struct utimbuf *buf);
28 #endif
30 /* private
31 ************************************************************************/
33 struct db_state {
34 gboolean is_open;
35 gboolean filelist_loaded;
36 gboolean readonly;
37 gchar* topdir;
38 gchar* pkgdir; /* /var/log/packages/ */
39 gchar* scrdir; /* /var/log/scripts/ */
40 struct error* err;
41 void* paths;
42 gint fd_lock;
45 static struct db_state _db; // yeah, this is really not uninitialized
47 #define e_set(n, fmt, args...) e_add(_db.err, "pkgdb", __func__, n, fmt, ##args)
49 #define _db_open_check(v) \
50 if (!_db.is_open) \
51 { \
52 e_set(E_ERROR|DB_NOPEN, "Package database is NOT open."); \
53 return v; \
56 #define LINEMATCH(s) (strncmp(line, s, sizeof(s)-1) == 0)
57 #define LINESIZE(s) (sizeof(s)-1)
59 /* public - open/close
60 ************************************************************************/
62 gint db_open(const gchar* root, gboolean readonly, struct error* e)
64 gchar** d;
65 gchar* checkdirs[] = { "packages", "scripts", "removed_packages",
66 "removed_scripts", "setup", NULL };
68 g_assert(e != NULL);
69 _db.err = e;
70 _db.readonly = readonly;
72 if (_db.is_open)
74 e_set(E_ERROR|DB_OPEN, "Package database is already open.");
75 goto err_0;
78 gchar* sane_root = sanitize_root_path(root);
79 if (g_path_is_absolute(sane_root))
80 _db.topdir = g_strdup_printf("%s%s", sane_root, PKGDB_DIR);
81 else
83 gchar* cwd = g_get_current_dir();
84 _db.topdir = g_strdup_printf("%s/%s%s", cwd, sane_root, PKGDB_DIR);
85 g_free(cwd);
87 _db.pkgdir = g_strdup_printf("%s/packages", _db.topdir);
88 _db.scrdir = g_strdup_printf("%s/scripts", _db.topdir);
89 g_free(sane_root);
91 /* check db dirs */
92 for (d = checkdirs; *d != NULL; d++)
94 gchar* tmpdir = g_strdup_printf("%s/%s", _db.topdir, *d);
95 /* if it is not a directory, clean it and create it */
96 if (sys_file_type(tmpdir, 1) != SYS_DIR)
98 if (readonly)
100 e_set(E_FATAL, "Package database directory does not exist and can't be created in readonly mode. (%s)", tmpdir);
101 g_free(tmpdir);
102 goto err_1;
104 sys_rm_rf(tmpdir);
105 sys_mkdir_p(tmpdir);
106 chmod(tmpdir, 0755);
107 /* if it is still not a directory, return with error */
108 if (sys_file_type(tmpdir, 1) != SYS_DIR)
110 e_set(E_FATAL, "Can't access package database directory. (%s)", tmpdir);
111 g_free(tmpdir);
112 goto err_1;
115 g_free(tmpdir);
118 if (!readonly)
120 /* get lock */
121 gchar *path_lock = g_strdup_printf("%s/.lock", _db.pkgdir);
122 _db.fd_lock = sys_lock_new(path_lock, e);
123 g_free(path_lock);
124 if (_db.fd_lock == -1)
126 e_set(E_FATAL, "Can't lock package database. (lock creation failed)");
127 goto err_1;
129 if (sys_lock_trywait(_db.fd_lock, 20, e))
131 e_set(E_FATAL, "Can't lock package database. (database is already locked)");
132 goto err_2;
136 _db.is_open = 1;
137 return 0;
139 err_2:
140 sys_lock_del(_db.fd_lock);
141 err_1:
142 g_free(_db.topdir);
143 g_free(_db.pkgdir);
144 g_free(_db.scrdir);
145 memset(&_db, 0, sizeof(_db));
146 err_0:
147 return 1;
150 void db_close()
152 if (!_db.is_open)
154 e_set(E_ERROR, "Package database is NOT open.");
155 return;
158 if (!_db.readonly)
159 sys_lock_del(_db.fd_lock);
161 Word_t used;
162 JSLFA(used, _db.paths);
164 g_free(_db.topdir);
165 g_free(_db.pkgdir);
166 g_free(_db.scrdir);
167 memset(&_db, 0, sizeof(_db));
170 /* public - filelist
171 ************************************************************************/
173 void db_filelist_rem_pkg_paths(const struct db_pkg* pkg)
175 gchar path[MAXPATHLEN];
176 gint rc;
177 Word_t *p1, *p2;
179 strcpy(path, "");
180 JSLF(p1, pkg->paths, path);
181 while (p1 != NULL)
183 JSLG(p2, _db.paths, path);
184 if (p2)
186 Word_t* refs = p2;
187 if (*refs == 1)
189 JSLD(rc, _db.paths, path);
191 else
193 (*refs)--;
196 JSLN(p1, pkg->paths, path);
200 void db_filelist_add_pkg_paths(const struct db_pkg* pkg)
202 gchar path[MAXPATHLEN];
203 Word_t *p1, *p2;
205 strcpy(path, "");
206 JSLF(p1, pkg->paths, path);
207 while (p1 != NULL)
209 JSLI(p2, _db.paths, path);
210 (*p2)++;
211 JSLN(p1, pkg->paths, path);
215 gint db_filelist_load(gboolean force_reload)
217 _db_open_check(1)
219 if (_db.filelist_loaded && !force_reload)
220 return 0;
222 DIR* d = opendir(_db.pkgdir);
223 if (d == NULL)
225 e_set(E_FATAL, "Can't open db directory. (%s)", strerror(errno));
226 goto err_0;
228 gchar sbuf[1024*128];
230 db_filelist_free();
232 gchar* line = NULL;
233 size_t size = 0;
234 Word_t* refs;
235 struct dirent* de;
237 /* for each package database entry */
238 while ((de = readdir(d)) != NULL)
240 gchar* name = de->d_name;
241 /* is this valid package database entry file? */
242 if (parse_pkgname(name, 6) == NULL)
243 continue;
245 /* open it */
246 gchar* tmpstr = g_strdup_printf("%s/%s", _db.pkgdir, name);
247 FILE* f = fopen(tmpstr, "r");
248 g_free(tmpstr);
249 if (f == NULL) /* main package entry can't be open */
251 e_set(E_ERROR, "Can't open package database file %s. (%s)", name, strerror(errno));
252 goto err_1;
254 /* set bigger buffer */
255 setvbuf(f, sbuf, _IOFBF, sizeof(sbuf));
257 /* for each line */
258 gint linelen;
259 gint files = 0;
260 while ((linelen = getline(&line, &size, f)) >= 0)
262 /* remove new line character from the end of the line */
263 if (linelen > 0 && line[linelen-1] == '\n')
264 line[linelen-1] = '\0', linelen--;
265 /* if we are in the files section, add path to the list */
266 if (files)
268 /* remove trailing / character from the end of the line */
269 if (linelen > 0 && line[linelen-1] == '/')
270 line[linelen-1] = '\0', linelen--;
271 /* check path size limit */
272 if (linelen >= MAXPATHLEN)
274 fclose(f);
275 strcpy(line+100, "...");
276 e_set(E_ERROR, "Path too long in the package database file %s. (%s)", name, line);
277 goto err_1;
279 #if ASSUME_BROKEN_PKGDB == 1
280 gchar* sane_path = path_simplify(line);
281 if (sane_path[0] == '\0')
283 JSLI(refs, _db.paths, ".");
285 else
287 JSLI(refs, _db.paths, sane_path);
289 g_free(sane_path);
290 #else
291 JSLI(refs, _db.paths, line);
292 #endif
293 (*refs)++;
295 else if (LINEMATCH("FILE LIST:"))
296 files++;
298 fclose(f);
300 /* open and parse installation script for symbolic links */
301 tmpstr = g_strdup_printf("%s/%s", _db.scrdir, name);
302 f = fopen(tmpstr, "r");
303 g_free(tmpstr);
304 if (f == NULL) /* script package entry can't be open */
305 continue; /* ignore if can't be open (may not exist) XXX: check if errno is NOTEX */
306 setvbuf(f, sbuf, _IOFBF, sizeof(sbuf));
308 /* for each line */
309 while ((linelen = getline(&line, &size, f)) >= 0)
311 /* remove new line character from the end of the line */
312 if (linelen > 0 && line[linelen-1] == '\n')
313 line[linelen-1] = '\0', linelen--;
315 /* parse create link line */
316 gchar *dir, *link, *target;
317 if (parse_createlink(line, &dir, &link, &target))
319 gchar* path = g_strdup_printf("%s/%s", dir, link);
320 gchar* sane_path = path_simplify(path);
321 g_free(path);
322 g_free(dir);
323 g_free(link);
324 g_free(target);
325 /* add */
326 /* check path size limit */
327 if (strlen(sane_path) >= MAXPATHLEN)
329 strcpy(sane_path+100, "...");
330 e_set(E_ERROR, "Path too long in the package database file %s. (%s)", name, line);
331 fclose(f);
332 g_free(sane_path);
333 goto err_1;
335 JSLI(refs, _db.paths, sane_path);
336 (*refs)++;
337 g_free(sane_path);
340 fclose(f);
343 if (line)
344 free(line);
346 closedir(d);
347 _db.filelist_loaded = TRUE;
348 return 0;
349 err_1:
350 db_filelist_free();
351 closedir(d);
352 err_0:
353 return 1;
356 gulong db_filelist_get_path_refs(const gchar* path)
358 Word_t* refs;
359 JSLG(refs, _db.paths, path);
360 if (refs == NULL)
361 return 0;
362 return (gulong)(*refs);
365 void db_filelist_free()
367 Word_t used;
368 JSLFA(used, _db.paths);
369 _db.filelist_loaded = FALSE;
372 /* public - memmory management
373 ************************************************************************/
375 struct db_pkg* db_alloc_pkg(gchar* name)
377 struct db_pkg* p;
378 if (name == NULL)
380 e_set(E_ERROR, "Package name can't be NULL.");
381 return NULL;
383 if (parse_pkgname(name, 6) != (gchar*)-1)
385 e_set(E_ERROR, "Invalid package name. (%s)", name);
386 return NULL;
388 p = g_new0(struct db_pkg, 1);
389 p->name = parse_pkgname(name, 5);
390 p->shortname = parse_pkgname(name, 1);
391 p->version = parse_pkgname(name, 2);
392 p->arch = parse_pkgname(name, 3);
393 p->build = parse_pkgname(name, 4);
394 p->time = time(NULL);
395 return p;
398 void db_free_pkg(struct db_pkg* pkg)
400 if (pkg == NULL)
401 return;
403 Word_t freed;
404 JSLFA(freed, pkg->paths);
405 g_free(pkg->name);
406 g_free(pkg->shortname);
407 g_free(pkg->version);
408 g_free(pkg->arch);
409 g_free(pkg->build);
410 g_free(pkg->location);
411 g_free(pkg->desc);
412 g_free(pkg->doinst);
413 memset(pkg, 0, sizeof(*pkg));
414 g_free(pkg);
417 gint db_pkg_add_path(struct db_pkg* pkg, const gchar* path, db_path_type type)
419 Word_t* ptype;
420 /* check path size limit */
421 if (strlen(path) >= MAXPATHLEN)
422 return 1;
423 JSLI(ptype, pkg->paths, path);
424 *ptype = type;
425 return 0;
428 db_path_type db_pkg_get_path(struct db_pkg* pkg, const gchar* path)
430 Word_t* ptype;
431 JSLG(ptype, pkg->paths, path);
432 if (ptype != NULL)
433 return (db_path_type)(*ptype);
434 return DB_PATH_NONE;
437 /* public - main database package operations
438 ************************************************************************/
440 static gint _db_add_pkg(struct db_pkg* pkg, gchar* origname)
442 FILE *pf, *sf;
443 gchar *ppath, *spath, *ppath_tmp, *spath_tmp;
445 _db_open_check(1)
447 /* check if pkg contains everthing required */
448 if (pkg == NULL || pkg->name == NULL || pkg->paths == NULL)
450 e_set(E_BADARG, "Incomplete package structure.");
451 goto err_0;
454 if (_db.readonly)
456 e_set(E_FATAL, "Can't add packages to the database in the readonly mode.");
457 goto err_0;
460 ppath = g_strdup_printf("%s/%s", _db.pkgdir, pkg->name);
461 spath = g_strdup_printf("%s/%s", _db.scrdir, pkg->name);
462 ppath_tmp = g_strdup_printf("%s/.%s", _db.pkgdir, pkg->name);
463 spath_tmp = g_strdup_printf("%s/.%s", _db.scrdir, pkg->name);
465 /* check if package file exists */
466 if (origname == NULL)
468 if (sys_file_type(ppath, 1) != SYS_NONE)
470 e_set(E_FATAL|DB_EXIST, "Package is already in the database %s. (%s)", ppath, strerror(errno));
471 goto err_1;
475 /* write package file (tmp) */
476 pf = fopen(ppath_tmp, "w");
477 if (pf == NULL)
479 e_set(E_FATAL, "Can't open package file %s. (%s)", ppath_tmp, strerror(errno));
480 goto err_1;
482 #ifndef __WIN32__
483 fchmod(fileno(pf), 0644);
484 #endif
486 /* construct header */
487 if (fprintf(pf,
488 "PACKAGE NAME: %s\n"
489 "COMPRESSED PACKAGE SIZE: %u K\n"
490 "UNCOMPRESSED PACKAGE SIZE: %u K\n"
491 "PACKAGE LOCATION: %s\n"
492 "PACKAGE DESCRIPTION:\n"
493 "%s"
494 "FILE LIST:\n",
495 pkg->name, pkg->csize, pkg->usize,
496 pkg->location ? pkg->location : "",
497 pkg->desc ? pkg->desc : "") < 0)
499 goto err_2;
502 /* construct filelist */
503 gchar path[MAXPATHLEN];
504 Word_t* ptype;
505 strcpy(path, "");
506 JSLF(ptype, pkg->paths, path);
507 while (ptype != NULL)
509 if (*ptype == DB_PATH_FILE)
511 if (fprintf(pf, "%s\n", path) < 0)
512 goto err_2;
514 else if (*ptype == DB_PATH_DIR)
516 if (fprintf(pf, "%s/\n", path) < 0)
517 goto err_2;
519 JSLN(ptype, pkg->paths, path);
522 /* close it */
523 fclose(pf);
525 /* change mtime */
526 struct utimbuf dt = { pkg->time, pkg->time };
527 #ifdef __WIN32__
528 if (posix_utime(ppath_tmp, &dt) == -1)
529 #else
530 if (utime(ppath_tmp, &dt) == -1)
531 #endif
533 e_set(E_ERROR, "Can't utime package entry %s. (%s)", ppath_tmp, strerror(errno));
534 goto err_1;
537 /* wirte script file if necessary */
538 if (pkg->doinst)
540 sf = fopen(spath_tmp, "w");
541 if (sf == NULL)
543 e_set(E_FATAL, "Can't open script file %s. (%s)", spath_tmp, strerror(errno));
544 goto err_1;
546 #ifndef __WIN32__
547 fchmod(fileno(sf), 0755);
548 #endif
549 if (fprintf(sf, "%s", pkg->doinst) < 0)
551 e_set(E_FATAL, "Can't write into script file %s. (%s)", spath_tmp, strerror(errno));
552 fclose(sf);
553 goto err_1;
555 fclose(sf);
558 if (origname)
560 if (db_rem_pkg(origname))
562 e_set(E_FATAL, "Can't remove original package from the database. (%s)", origname);
563 goto err_1;
567 /* finally put package and script files into place */
568 #ifdef __WIN32__
569 if (access(ppath, 0) == 0)
570 remove(ppath);
571 #endif
572 if (rename(ppath_tmp, ppath) < 0)
574 e_set(E_FATAL, "Can't finalize package database update. Rename failed %s. You'll need to fix package database by hand. (%s)", ppath_tmp, strerror(errno));
575 goto err_1;
578 if (pkg->doinst)
580 #ifdef __WIN32__
581 if (access(spath, 0) == 0)
582 remove(spath);
583 #endif
584 if (rename(spath_tmp, spath) < 0)
586 e_set(E_FATAL, "Can't finalize package database update. Rename failed %s. You'll need to fix package database by hand. (%s)", spath_tmp, strerror(errno));
587 goto err_1;
591 g_free(ppath);
592 g_free(spath);
593 g_free(ppath_tmp);
594 g_free(spath_tmp);
595 return 0;
597 err_2:
598 e_set(E_FATAL, "Can't write into package file %s. (%s)", ppath_tmp, strerror(errno));
599 fclose(pf);
600 err_1:
601 /* just ingore errors here */
602 g_free(ppath);
603 g_free(spath);
604 g_free(ppath_tmp);
605 g_free(spath_tmp);
606 err_0:
607 return 1;
610 gint db_add_pkg(struct db_pkg* pkg)
612 return _db_add_pkg(pkg, NULL);
615 gint db_replace_pkg(gchar* origname, struct db_pkg* pkg)
617 return _db_add_pkg(pkg, origname);
620 struct db_pkg* db_get_pkg(gchar* name, db_get_type type)
622 FILE *fp, *fs;
623 gchar *tmpstr;
624 gchar stream_buf1[1024*128];
625 gchar stream_buf2[1024*64];
626 struct db_pkg* p = NULL;
628 if (name == NULL)
630 e_set(E_BADARG, "Package name can't be NULL.");
631 goto err_0;
633 if (parse_pkgname(name, 6) != (gchar*)-1)
635 e_set(E_ERROR, "Invalid package name. (%s)", name);
636 goto err_0;
638 if (type != DB_GET_WITHOUT_FILES && type != DB_GET_FULL)
640 e_set(E_BADARG, "Invalid get type value. (must be DB_GET_WITHOUT_FILES or DB_GET_FULL)");
641 goto err_0;
644 _db_open_check(NULL)
646 /* open package db entries */
647 tmpstr = g_strdup_printf("%s/%s", _db.pkgdir, name);
648 fp = fopen(tmpstr, "r");
649 time_t mtime = sys_file_mtime(tmpstr, 1);
650 g_free(tmpstr);
651 if (fp == NULL) /* main package entry can't be open */
653 e_set(E_ERROR | (errno == ENOENT ? DB_NOTEX : 0), "Can't open package database entry file %s. (%s)", name, strerror(errno));
654 goto err_0;
656 if (mtime == (time_t)-1) /* package time can't be retrieved */
658 e_set(E_ERROR, "Can't get package installation time for %s. (%s)", name, strerror(errno));
659 goto err_0;
661 setvbuf(fp, stream_buf1, _IOFBF, sizeof(stream_buf1));
663 /*XXX: better checks here (if NOTEX, or other error) */
664 tmpstr = g_strdup_printf("%s/%s", _db.scrdir, name);
665 fs = fopen(tmpstr, "r");
666 g_free(tmpstr);
667 if (fs)
668 setvbuf(fs, stream_buf2, _IOFBF, sizeof(stream_buf2));
670 p = db_alloc_pkg(name);
671 if (p == NULL)
672 goto err_1;
673 p->time = mtime;
675 /* parse main package file */
676 gint snl = strlen(p->shortname);
677 gint m[5] = { 0 }; /* if particular line was matched it can't
678 occur anymore, so we cache info about already matched lines */
680 gchar* line = NULL;
681 size_t size = 0;
682 gint linelen;
683 while ((linelen = getline(&line, &size, fp)) >= 0)
685 if (linelen > 0 && line[linelen-1] == '\n')
687 line[linelen-1] = '\0';
688 linelen--;
690 if (!m[0] && LINEMATCH("PACKAGE NAME:"))
692 gchar* name = g_strstrip(line + LINESIZE("PACKAGE NAME:"));
693 if (strcmp(name, p->name))
695 e_set(E_ERROR, "Package file name doesn't match with package name. (%s != %s)", p->name, name);
696 goto err_1;
698 /* skip whitespace */
699 m[0] = 1;
701 else if (!m[1] && LINEMATCH("COMPRESSED PACKAGE SIZE:"))
703 gchar* size = line + LINESIZE("COMPRESSED PACKAGE SIZE:");
704 if (sscanf(size, " %u ", &p->csize) != 1)
706 e_set(E_ERROR, "Can't parse compressed package size. (%s)", size);
707 goto err_1;
709 m[1] = 1;
711 else if (!m[2] && LINEMATCH("UNCOMPRESSED PACKAGE SIZE:"))
713 gchar* size = line + LINESIZE("UNCOMPRESSED PACKAGE SIZE:");
714 if (sscanf(size, " %u ", &p->usize) != 1)
716 e_set(E_ERROR, "Can't parse uncompressed package size. (%s)", size);
717 goto err_1;
719 m[2] = 1;
721 else if (!m[3] && LINEMATCH("PACKAGE LOCATION:"))
723 p->location = g_strdup(g_strstrip(line + LINESIZE("PACKAGE LOCATION:")));
724 m[3] = 1;
726 else if (!m[4] && LINEMATCH("PACKAGE DESCRIPTION:"))
728 m[4] = 1;
730 else if (strncmp(line, p->shortname, snl) == 0)
732 gchar* desc = g_strconcat(p->desc ? p->desc : "", line, "\n", NULL);
733 g_free(p->desc);
734 p->desc = desc;
736 else if (LINEMATCH("FILE LIST:"))
738 goto parse_files;
740 else
742 e_set(E_ERROR, "Corrupt package database entry. (%s)", p->name);
743 goto err_1;
746 goto err_1;
748 parse_files:
749 if (type == DB_GET_WITHOUT_FILES)
750 goto fini;
752 while ((linelen = getline(&line, &size, fp)) >= 0)
754 Word_t* ptype;
755 db_path_type type = DB_PATH_FILE;
756 if (linelen > 0 && line[linelen-1] == '\n')
757 line[linelen-1] = '\0', linelen--;
758 if (linelen > 0 && line[linelen-1] == '/')
759 line[linelen-1] = '\0', linelen--, type = DB_PATH_DIR;
760 /* check path size limit */
761 if (linelen >= MAXPATHLEN)
763 strcpy(line+100, "...");
764 e_set(E_ERROR, "Path too long in the package database file %s. (%s)", name, line);
765 goto err_1;
767 #if ASSUME_BROKEN_PKGDB == 1
768 gchar* sane_path = path_simplify(line);
769 if (sane_path[0] == '\0')
771 JSLI(ptype, p->paths, ".");
773 else
775 JSLI(ptype, p->paths, sane_path);
777 g_free(sane_path);
778 #else
779 JSLI(ptype, p->paths, line);
780 #endif
781 *ptype = type;
784 if (fs == NULL)
785 goto fini;
787 while ((linelen = getline(&line, &size, fs)) >= 0)
789 if (linelen > 0 && line[linelen-1] == '\n')
790 line[linelen-1] = '\0';
792 gchar *dir, *link, *target;
793 if (parse_createlink(line, &dir, &link, &target))
795 gchar* path = g_strdup_printf("%s/%s", dir, link);
796 gchar* sane_path = path_simplify(path);
797 g_free(path);
798 g_free(dir);
799 g_free(link);
800 g_free(target);
801 /* check path size limit */
802 if (strlen(sane_path) >= MAXPATHLEN)
804 strcpy(sane_path+100, "...");
805 e_set(E_ERROR, "Path too long in the package database script %s. (%s)", name, sane_path);
806 g_free(sane_path);
807 goto err_1;
809 /* add */
810 Word_t* ptype;
811 JSLI(ptype, p->paths, sane_path);
812 *ptype = DB_PATH_SYMLINK;
813 g_free(sane_path);
817 fseek(fs, 0, SEEK_END);
818 guint script_size = ftell(fs);
819 if (script_size > 4*1024*1024)
821 e_set(E_ERROR, "Script file is too big %s. (%u kB)", p->name, script_size / 1024);
822 goto err_1;
824 if (script_size)
826 p->doinst = g_malloc(script_size);
827 fseek(fs, 0, SEEK_SET);
828 if (fread(p->doinst, script_size, 1, fs) != 1)
830 e_set(E_ERROR, "Can't read script file %s. (%s)", p->name, strerror(errno));
831 goto err_1;
835 fini:
836 if (line)
837 free(line);
838 if (fs)
839 fclose(fs);
840 fclose(fp);
841 err_0:
842 return p;
843 err_1:
844 db_free_pkg(p);
845 p = NULL;
846 goto fini;
849 static gchar* _get_date()
851 static gchar buf[100];
852 time_t t = time(NULL);
853 struct tm* ts = localtime(&t);
854 #ifdef __WIN32__
855 strftime(buf, sizeof(buf), "%F-%T", ts);
856 #else
857 strftime(buf, sizeof(buf), "%F,%T", ts);
858 #endif
859 return buf;
862 gint db_rem_pkg(gchar* name)
864 _db_open_check(1)
866 gint ret = 1;
868 if (name == NULL)
870 e_set(E_BADARG, "Package name can't be NULL.");
871 goto err_0;
873 if (parse_pkgname(name, 6) != (gchar*)-1)
875 e_set(E_ERROR, "Invalid package name. (%s)", name);
876 goto err_0;
879 if (_db.readonly)
881 e_set(E_FATAL, "Can't remove packages from the database in the readonly mode.");
882 goto err_0;
885 gchar* p = g_strdup_printf("%s/%s", _db.pkgdir, name);
886 gchar* s = g_strdup_printf("%s/%s", _db.scrdir, name);
887 gchar* rp = g_strdup_printf("%s/removed_packages/%s-removed-%s", _db.topdir, name, _get_date());
888 gchar* rs = g_strdup_printf("%s/removed_scripts/%s-removed-%s", _db.topdir, name, _get_date());
890 if (sys_file_type(p, 1) != SYS_REG)
892 e_set(E_ERROR|DB_NOTEX, "Package is not in the database. (%s)", name);
893 goto err_1;
895 #ifdef __WIN32__
896 if (access(rp, 0) == 0)
897 remove(rp);
898 #endif
899 if (rename(p, rp) < 0)
901 e_set(E_ERROR, "Package file removal failed. (%s)", strerror(errno));
902 goto err_1;
904 if (sys_file_type(s, 1) == SYS_REG)
906 #ifdef __WIN32__
907 if (access(rs, 0) == 0)
908 remove(rs);
909 #endif
910 if (rename(s, rs) < 0)
912 e_set(E_ERROR, "Script file removal failed. (%s)", strerror(errno));
913 goto err_1;
917 ret = 0;
918 err_1:
919 g_free(p);
920 g_free(s);
921 g_free(rp);
922 g_free(rs);
923 err_0:
924 return ret;
927 /* public - generic database package queries
928 ************************************************************************/
930 static gint _query_compare(gconstpointer a, gconstpointer b, gpointer data)
932 db_query_type type = (db_query_type)data;
933 if (type == DB_QUERY_PKGS_WITH_FILES || type == DB_QUERY_PKGS_WITHOUT_FILES)
935 const struct db_pkg* apkg = a;
936 const struct db_pkg* bpkg = b;
937 return strcmp(apkg->name, bpkg->name);
939 else if (type == DB_QUERY_NAMES)
941 return strcmp(a, b);
943 return 0;
946 GSList* db_query(db_selector cb, void* data, db_query_type type)
948 GSList *pkgs = NULL;
950 _db_open_check(NULL)
952 if (type != DB_QUERY_PKGS_WITH_FILES &&
953 type != DB_QUERY_PKGS_WITHOUT_FILES &&
954 type != DB_QUERY_NAMES)
956 e_set(E_BADARG, "Invalid query type.");
957 goto err_0;
960 DIR* d = opendir(_db.pkgdir);
961 if (d == NULL)
963 e_set(E_FATAL, "Can't open package database directory. (%s)", strerror(errno));
964 goto err_0;
967 struct dirent* de;
968 while ((de = readdir(d)) != NULL)
970 if (de->d_name[0] == '.')
971 continue;
972 struct db_pkg* p;
973 gchar* name = de->d_name;
974 if (parse_pkgname(name, 6) == NULL)
975 continue;
976 /* if cb == NULL, then package matches */
977 if (cb != NULL)
979 /* otherwise get package from database ask the selector if it
980 likes this package */
981 p = db_get_pkg(name, DB_GET_WITHOUT_FILES);
982 if (p == NULL)
984 e_set(E_ERROR, "Can't get package from the database. (%s)", name);
985 goto err_1;
987 gint rs = cb(p, data);
988 if (rs != 0 && rs != 1)
990 db_free_pkg(p);
991 e_set(E_ERROR, "Package database query filter returned error. (%s)", name);
992 goto err_1;
994 else if (rs == 0)
996 db_free_pkg(p);
997 continue;
999 db_free_pkg(p);
1001 db_get_type get_type = DB_GET_WITHOUT_FILES;
1002 switch (type)
1004 case DB_QUERY_PKGS_WITH_FILES:
1005 get_type = DB_GET_FULL;
1006 case DB_QUERY_PKGS_WITHOUT_FILES:
1007 p = db_get_pkg(name, get_type);
1008 if (p == NULL)
1010 e_set(E_ERROR, "Can't get package from the database (%s).", name);
1011 goto err_1;
1013 pkgs = g_slist_prepend(pkgs, p);
1014 break;
1015 case DB_QUERY_NAMES:
1016 pkgs = g_slist_prepend(pkgs, g_strdup(name));
1017 break;
1021 closedir(d);
1022 return g_slist_sort_with_data(pkgs, _query_compare, (gpointer)type);
1023 err_1:
1024 db_free_query(pkgs, type);
1025 closedir(d);
1026 err_0:
1027 return NULL;
1030 void db_free_query(GSList* pkgs, db_query_type type)
1032 if (pkgs == NULL)
1033 return;
1035 void (*data_free_func)(void*) = g_free;
1036 if (type == DB_QUERY_PKGS_WITH_FILES ||
1037 type == DB_QUERY_PKGS_WITHOUT_FILES)
1038 data_free_func = (void (*)(void*))db_free_pkg;
1040 g_slist_foreach(pkgs, (GFunc)data_free_func, NULL);
1041 g_slist_free(pkgs);
1044 gchar* db_get_package_name(const gchar* namespec)
1046 _db_open_check(NULL)
1048 if (namespec == NULL)
1050 e_set(E_FATAL, "Namespec can't be NULL.");
1051 goto err_0;
1054 gchar* pkgname = NULL;
1055 DIR* d = opendir(_db.pkgdir);
1056 struct dirent* de;
1057 if (d == NULL)
1059 e_set(E_FATAL, "Can't open package database directory. (%s)", strerror(errno));
1060 goto err_0;
1063 /* first search for exact match if namespec looks like full name */
1064 gchar* searched_name = parse_pkgname(namespec, 5);
1065 if (searched_name)
1067 /* exact search */
1068 while ((de = readdir(d)) != NULL)
1070 if (de->d_name[0] == '.')
1071 continue;
1072 gchar* cur_name = de->d_name;
1073 if (parse_pkgname(cur_name, 6) == NULL)
1074 continue;
1075 if (!strcmp(searched_name, cur_name))
1077 pkgname = searched_name;
1078 goto done;
1081 g_free(searched_name);
1084 /* try to use namespec as shortname */
1085 rewinddir(d);
1086 while ((de = readdir(d)) != NULL)
1088 if (de->d_name[0] == '.')
1089 continue;
1090 gchar* cur_name = de->d_name;
1091 gchar* cur_shortname = parse_pkgname(cur_name, 1);
1092 if (cur_shortname == NULL)
1093 continue;
1094 if (!strcmp(namespec, cur_shortname))
1096 pkgname = g_strdup(cur_name);
1097 g_free(cur_shortname);
1098 goto done;
1100 g_free(cur_shortname);
1103 done:
1104 closedir(d);
1105 return pkgname;
1106 err_0:
1107 return NULL;