chiark / gitweb /
lib/dpkg/tarfn.c: Kludge `tar_header_decode' to handle spurious `errno'.
[dpkg] / src / infodb-access.c
1 /*
2  * dpkg - main program for package management
3  * infodb.c - package control information database
4  *
5  * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6  * Copyright © 2011-2014 Guillem Jover <guillem@debian.org>
7  *
8  * This is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21
22 #include <config.h>
23 #include <compat.h>
24
25 #include <sys/types.h>
26 #include <sys/stat.h>
27
28 #include <errno.h>
29 #include <dirent.h>
30 #include <unistd.h>
31
32 #include <dpkg/i18n.h>
33 #include <dpkg/dpkg.h>
34 #include <dpkg/dpkg-db.h>
35 #include <dpkg/debug.h>
36
37 #include "filesdb.h"
38 #include "infodb.h"
39
40 bool
41 pkg_infodb_has_file(struct pkginfo *pkg, struct pkgbin *pkgbin,
42                     const char *name)
43 {
44         const char *filename;
45         struct stat stab;
46
47         filename = pkg_infodb_get_file(pkg, pkgbin, name);
48         if (lstat(filename, &stab) == 0)
49                 return true;
50         else if (errno == ENOENT)
51                 return false;
52         else
53                 ohshite(_("unable to check existence of '%.250s'"), filename);
54 }
55
56 void
57 pkg_infodb_foreach(struct pkginfo *pkg, struct pkgbin *pkgbin,
58                    pkg_infodb_file_func *func)
59 {
60         DIR *db_dir;
61         struct dirent *db_de;
62         struct varbuf_state db_path_state;
63         struct varbuf db_path = VARBUF_INIT;
64         const char *pkgname;
65         enum pkg_infodb_format db_format;
66
67         /* Make sure to always read and verify the format version. */
68         db_format = pkg_infodb_get_format();
69
70         if (pkgbin->multiarch == PKG_MULTIARCH_SAME &&
71             db_format == PKG_INFODB_FORMAT_MULTIARCH)
72                 pkgname = pkgbin_name(pkg, pkgbin, pnaw_always);
73         else
74                 pkgname = pkgbin_name(pkg, pkgbin, pnaw_never);
75
76         varbuf_add_str(&db_path, pkg_infodb_get_dir());
77         varbuf_add_char(&db_path, '/');
78         varbuf_end_str(&db_path);
79         varbuf_snapshot(&db_path, &db_path_state);
80
81         db_dir = opendir(db_path.buf);
82         if (!db_dir)
83                 ohshite(_("cannot read info directory"));
84
85         push_cleanup(cu_closedir, ~0, NULL, 0, 1, (void *)db_dir);
86         while ((db_de = readdir(db_dir)) != NULL) {
87                 const char *filename, *filetype, *dot;
88
89                 debug(dbg_veryverbose, "infodb foreach info file '%s'",
90                       db_de->d_name);
91
92                 /* Ignore dotfiles, including ‘.’ and ‘..’. */
93                 if (db_de->d_name[0] == '.')
94                         continue;
95
96                 /* Ignore anything odd. */
97                 dot = strrchr(db_de->d_name, '.');
98                 if (dot == NULL)
99                         continue;
100
101                 /* Ignore files from other packages. */
102                 if (strlen(pkgname) != (size_t)(dot - db_de->d_name) ||
103                     strncmp(db_de->d_name, pkgname, dot - db_de->d_name))
104                         continue;
105
106                 debug(dbg_stupidlyverbose, "infodb foreach file this pkg");
107
108                 /* Skip past the full stop. */
109                 filetype = dot + 1;
110
111                 varbuf_rollback(&db_path, &db_path_state);
112                 varbuf_add_str(&db_path, db_de->d_name);
113                 varbuf_end_str(&db_path);
114                 filename = db_path.buf;
115
116                 func(filename, filetype);
117         }
118         pop_cleanup(ehflag_normaltidy); /* closedir */
119
120         varbuf_destroy(&db_path);
121 }