Commit | Line | Data |
---|---|---|
1479465f GJ |
1 | /* |
2 | * dpkg - main program for package management | |
3 | * divertdb.c - management of database of diverted files | |
4 | * | |
5 | * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk> | |
6 | * Copyright © 2000, 2001 Wichert Akkerman <wakkerma@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 <string.h> | |
30 | #include <pwd.h> | |
31 | #include <grp.h> | |
32 | #include <fcntl.h> | |
33 | #include <unistd.h> | |
34 | #include <stdlib.h> | |
35 | ||
36 | #include <dpkg/i18n.h> | |
37 | #include <dpkg/dpkg.h> | |
38 | #include <dpkg/dpkg-db.h> | |
39 | ||
40 | #include "filesdb.h" | |
41 | #include "main.h" | |
42 | ||
43 | static struct diversion *diversions = NULL; | |
44 | static char *diversionsname; | |
45 | ||
46 | void | |
47 | ensure_diversions(void) | |
48 | { | |
49 | static struct stat sb_prev; | |
50 | struct stat sb_next; | |
51 | char linebuf[MAXDIVERTFILENAME]; | |
52 | static FILE *file_prev; | |
53 | FILE *file; | |
54 | struct diversion *ov, *oicontest, *oialtname; | |
55 | ||
56 | if (diversionsname == NULL) | |
57 | diversionsname = dpkg_db_get_path(DIVERSIONSFILE); | |
58 | ||
59 | onerr_abort++; | |
60 | ||
61 | file = fopen(diversionsname, "r"); | |
62 | if (!file) { | |
63 | if (errno != ENOENT) | |
64 | ohshite(_("failed to open diversions file")); | |
65 | } else { | |
66 | setcloexec(fileno(file), diversionsname); | |
67 | ||
68 | if (fstat(fileno(file), &sb_next)) | |
69 | ohshite(_("failed to fstat diversions file")); | |
70 | ||
71 | /* | |
72 | * We need to keep the database file open so that the | |
73 | * filesystem cannot reuse the inode number (f.ex. during | |
74 | * multiple dpkg-divert invocations in a maintainer script), | |
75 | * otherwise the following check might turn true, and we | |
76 | * would skip reloading a modified database. | |
77 | */ | |
78 | if (file_prev && | |
79 | sb_prev.st_dev == sb_next.st_dev && | |
80 | sb_prev.st_ino == sb_next.st_ino) { | |
81 | fclose(file); | |
82 | onerr_abort--; | |
83 | debug(dbg_general, "%s: same, skipping", __func__); | |
84 | return; | |
85 | } | |
86 | sb_prev = sb_next; | |
87 | } | |
88 | if (file_prev) | |
89 | fclose(file_prev); | |
90 | file_prev = file; | |
91 | ||
92 | for (ov = diversions; ov; ov = ov->next) { | |
93 | ov->useinstead->divert->camefrom->divert = NULL; | |
94 | ov->useinstead->divert = NULL; | |
95 | } | |
96 | diversions = NULL; | |
97 | if (!file) { | |
98 | onerr_abort--; | |
99 | debug(dbg_general, "%s: none, resetting", __func__); | |
100 | return; | |
101 | } | |
102 | debug(dbg_general, "%s: new, (re)loading", __func__); | |
103 | ||
104 | while (fgets_checked(linebuf, sizeof(linebuf), file, diversionsname) >= 0) { | |
105 | oicontest = nfmalloc(sizeof(struct diversion)); | |
106 | oialtname = nfmalloc(sizeof(struct diversion)); | |
107 | ||
108 | oialtname->camefrom = findnamenode(linebuf, 0); | |
109 | oialtname->useinstead = NULL; | |
110 | ||
111 | fgets_must(linebuf, sizeof(linebuf), file, diversionsname); | |
112 | oicontest->useinstead = findnamenode(linebuf, 0); | |
113 | oicontest->camefrom = NULL; | |
114 | ||
115 | fgets_must(linebuf, sizeof(linebuf), file, diversionsname); | |
116 | oicontest->pkgset = strcmp(linebuf, ":") ? | |
117 | pkg_db_find_set(linebuf) : NULL; | |
118 | oialtname->pkgset = oicontest->pkgset; | |
119 | ||
120 | if (oialtname->camefrom->divert || | |
121 | oicontest->useinstead->divert) | |
122 | ohshit(_("conflicting diversions involving '%.250s' or '%.250s'"), | |
123 | oialtname->camefrom->name, oicontest->useinstead->name); | |
124 | ||
125 | oialtname->camefrom->divert = oicontest; | |
126 | oicontest->useinstead->divert = oialtname; | |
127 | ||
128 | oicontest->next = diversions; | |
129 | diversions = oicontest; | |
130 | } | |
131 | ||
132 | onerr_abort--; | |
133 | } |