2 * dpkg - main program for package management
3 * statdb.c - management of database of ownership and mode of files
5 * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 * Copyright © 2000, 2001 Wichert Akkerman <wakkerma@debian.org>
7 * Copyright © 2008-2012 Guillem Jover <guillem@debian.org>
9 * This is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
26 #include <sys/types.h>
37 #include <dpkg/i18n.h>
38 #include <dpkg/dpkg.h>
39 #include <dpkg/dpkg-db.h>
40 #include <dpkg/fdio.h>
45 static char *statoverridename;
48 statdb_parse_uid(const char *str)
57 value = strtol(str + 1, &endptr, 10);
58 if (str + 1 == endptr || *endptr || value < 0 || errno != 0)
59 ohshit(_("invalid statoverride uid %s"), str);
62 struct passwd *pw = getpwnam(str);
74 statdb_parse_gid(const char *str)
83 value = strtol(str + 1, &endptr, 10);
84 if (str + 1 == endptr || *endptr || value < 0 || errno != 0)
85 ohshit(_("invalid statoverride gid %s"), str);
88 struct group *gr = getgrnam(str);
100 statdb_parse_mode(const char *str)
105 mode = strtol(str, &endptr, 8);
106 if (str == endptr || *endptr || mode < 0 || mode > 07777)
107 ohshit(_("invalid statoverride mode %s"), str);
113 ensure_statoverrides(enum statdb_parse_flags flags)
115 static struct stat sb_prev;
117 static FILE *file_prev;
119 char *loaded_list, *loaded_list_end, *thisline, *nextline, *ptr;
120 struct file_stat *fso;
121 struct filenamenode *fnn;
122 struct fileiterator *iter;
124 if (statoverridename == NULL)
125 statoverridename = dpkg_db_get_path(STATOVERRIDEFILE);
129 file = fopen(statoverridename, "r");
132 ohshite(_("failed to open statoverride file"));
134 setcloexec(fileno(file), statoverridename);
136 if (fstat(fileno(file), &sb_next))
137 ohshite(_("failed to fstat statoverride file"));
140 * We need to keep the database file open so that the
141 * filesystem cannot reuse the inode number (f.ex. during
142 * multiple dpkg-statoverride invocations in a maintainer
143 * script), otherwise the following check might turn true,
144 * and we would skip reloading a modified database.
147 sb_prev.st_dev == sb_next.st_dev &&
148 sb_prev.st_ino == sb_next.st_ino) {
151 debug(dbg_general, "%s: same, skipping", __func__);
160 /* Reset statoverride information. */
161 iter = files_db_iter_new();
162 while ((fnn = files_db_iter_next(iter)))
163 fnn->statoverride = NULL;
164 files_db_iter_free(iter);
168 debug(dbg_general, "%s: none, resetting", __func__);
171 debug(dbg_general, "%s: new, (re)loading", __func__);
173 /* If the statoverride list is empty we don't need to bother
175 if (!sb_next.st_size) {
180 loaded_list = m_malloc(sb_next.st_size);
181 loaded_list_end = loaded_list + sb_next.st_size;
183 if (fd_read(fileno(file), loaded_list, sb_next.st_size) < 0)
184 ohshite(_("reading statoverride file '%.250s'"), statoverridename);
186 thisline = loaded_list;
187 while (thisline < loaded_list_end) {
188 fso = nfmalloc(sizeof(struct file_stat));
190 ptr = memchr(thisline, '\n', loaded_list_end - thisline);
192 ohshit(_("statoverride file is missing final newline"));
193 /* Where to start next time around. */
196 ohshit(_("statoverride file contains empty line"));
199 /* Extract the uid. */
200 ptr = memchr(thisline, ' ', nextline - thisline);
202 ohshit(_("syntax error in statoverride file"));
205 fso->uid = statdb_parse_uid(thisline);
206 if (fso->uid == (uid_t)-1)
207 fso->uname = nfstrsave(thisline);
211 if (fso->uid == (uid_t)-1 && !(flags & STATDB_PARSE_LAX))
212 ohshit(_("unknown user '%s' in statoverride file"),
215 /* Move to the next bit */
217 if (thisline >= loaded_list_end)
218 ohshit(_("unexpected end of line in statoverride file"));
220 /* Extract the gid */
221 ptr = memchr(thisline, ' ', nextline - thisline);
223 ohshit(_("syntax error in statoverride file"));
226 fso->gid = statdb_parse_gid(thisline);
227 if (fso->gid == (gid_t)-1)
228 fso->gname = nfstrsave(thisline);
232 if (fso->gid == (gid_t)-1 && !(flags & STATDB_PARSE_LAX))
233 ohshit(_("unknown group '%s' in statoverride file"),
236 /* Move to the next bit */
238 if (thisline >= loaded_list_end)
239 ohshit(_("unexpected end of line in statoverride file"));
241 /* Extract the mode */
242 ptr = memchr(thisline, ' ', nextline - thisline);
244 ohshit(_("syntax error in statoverride file"));
247 fso->mode = statdb_parse_mode(thisline);
249 /* Move to the next bit */
251 if (thisline >= loaded_list_end)
252 ohshit(_("unexpected end of line in statoverride file"));
254 fnn = findnamenode(thisline, 0);
255 if (fnn->statoverride)
256 ohshit(_("multiple statoverrides present for file '%.250s'"),
258 fnn->statoverride = fso;