Branch data Line data Source code
1 : : /* 2 : : * libdpkg - Debian packaging suite library routines 3 : : * db-fsys-divert.c - management of filesystem diverted files database 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 : : #include <dpkg/debug.h> 40 : : #include <dpkg/db-fsys.h> 41 : : 42 : : static struct fsys_diversion *diversions = NULL; 43 : : static char *diversionsname; 44 : : 45 : : void 46 : 74 : ensure_diversions(void) 47 : : { 48 : : static struct stat sb_prev; 49 : : struct stat sb_next; 50 : : char linebuf[MAXDIVERTFILENAME]; 51 : : static FILE *file_prev; 52 : : FILE *file; 53 : : struct fsys_diversion *ov, *oicontest, *oialtname; 54 : : 55 [ + - ]: 74 : if (diversionsname == NULL) 56 : 74 : diversionsname = dpkg_db_get_path(DIVERSIONSFILE); 57 : : 58 : 74 : onerr_abort++; 59 : : 60 : 74 : file = fopen(diversionsname, "r"); 61 [ + + ]: 74 : if (!file) { 62 [ + + ]: 2 : if (errno != ENOENT) 63 : 1 : ohshite(_("failed to open diversions file")); 64 : : } else { 65 : 72 : setcloexec(fileno(file), diversionsname); 66 : : 67 [ - + ]: 72 : if (fstat(fileno(file), &sb_next)) 68 : 0 : ohshite(_("failed to fstat diversions file")); 69 : : 70 : : /* 71 : : * We need to keep the database file open so that the 72 : : * filesystem cannot reuse the inode number (f.ex. during 73 : : * multiple dpkg-divert invocations in a maintainer script), 74 : : * otherwise the following check might turn true, and we 75 : : * would skip reloading a modified database. 76 : : */ 77 [ - + ]: 72 : if (file_prev && 78 [ # # ]: 0 : sb_prev.st_dev == sb_next.st_dev && 79 [ # # ]: 0 : sb_prev.st_ino == sb_next.st_ino) { 80 : 0 : fclose(file); 81 : 0 : onerr_abort--; 82 : 0 : debug(dbg_general, "%s: same, skipping", __func__); 83 : 1 : return; 84 : : } 85 : 72 : sb_prev = sb_next; 86 : : } 87 [ - + ]: 73 : if (file_prev) 88 : 0 : fclose(file_prev); 89 : 73 : file_prev = file; 90 : : 91 [ - + ]: 73 : for (ov = diversions; ov; ov = ov->next) { 92 : 0 : ov->useinstead->divert->camefrom->divert = NULL; 93 : 0 : ov->useinstead->divert = NULL; 94 : : } 95 : 73 : diversions = NULL; 96 [ + + ]: 73 : if (!file) { 97 : 1 : onerr_abort--; 98 : 1 : debug(dbg_general, "%s: none, resetting", __func__); 99 : 1 : return; 100 : : } 101 : 72 : debug(dbg_general, "%s: new, (re)loading", __func__); 102 : : 103 [ + + ]: 158 : while (fgets_checked(linebuf, sizeof(linebuf), file, diversionsname) >= 0) { 104 : 88 : oicontest = nfmalloc(sizeof(*oicontest)); 105 : 88 : oialtname = nfmalloc(sizeof(*oialtname)); 106 : : 107 : 88 : oialtname->camefrom = fsys_hash_find_node(linebuf, 0); 108 : 88 : oialtname->useinstead = NULL; 109 : : 110 : 88 : fgets_must(linebuf, sizeof(linebuf), file, diversionsname); 111 : 87 : oicontest->useinstead = fsys_hash_find_node(linebuf, 0); 112 : 87 : oicontest->camefrom = NULL; 113 : : 114 : 87 : fgets_must(linebuf, sizeof(linebuf), file, diversionsname); 115 : 172 : oicontest->pkgset = strcmp(linebuf, ":") ? 116 [ + + ]: 86 : pkg_hash_find_set(linebuf) : NULL; 117 : 86 : oialtname->pkgset = oicontest->pkgset; 118 : : 119 [ + - ]: 86 : if (oialtname->camefrom->divert || 120 [ - + ]: 86 : oicontest->useinstead->divert) 121 : 0 : ohshit(_("conflicting diversions involving '%.250s' or '%.250s'"), 122 : 0 : oialtname->camefrom->name, oicontest->useinstead->name); 123 : : 124 : 86 : oialtname->camefrom->divert = oicontest; 125 : 86 : oicontest->useinstead->divert = oialtname; 126 : : 127 : 86 : oicontest->next = diversions; 128 : 86 : diversions = oicontest; 129 : : } 130 : : 131 : 70 : onerr_abort--; 132 : : }