Branch data Line data Source code
1 : : /*
2 : : * libdpkg - Debian packaging suite library routines
3 : : * db-fsys-override.c - management of filesystem stat overrides database
4 : : *
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>
8 : : *
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.
13 : : *
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.
18 : : *
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/>.
21 : : */
22 : :
23 : : #include <config.h>
24 : : #include <compat.h>
25 : :
26 : : #include <sys/types.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/fdio.h>
40 : : #include <dpkg/debug.h>
41 : : #include <dpkg/db-fsys.h>
42 : :
43 : : uid_t
44 : 0 : statdb_parse_uid(const char *str)
45 : : {
46 : : char *endptr;
47 : : uid_t uid;
48 : :
49 [ # # ]: 0 : if (str[0] == '#') {
50 : : long int value;
51 : :
52 : 0 : errno = 0;
53 : 0 : value = strtol(str + 1, &endptr, 10);
54 [ # # # # : 0 : if (str + 1 == endptr || *endptr || value < 0 || errno != 0)
# # # # ]
55 : 0 : ohshit(_("invalid statoverride uid %s"), str);
56 : 0 : uid = (uid_t)value;
57 : : } else {
58 : 0 : const struct passwd *pw = getpwnam(str);
59 : :
60 [ # # ]: 0 : if (pw == NULL)
61 : 0 : uid = (uid_t)-1;
62 : : else
63 : 0 : uid = pw->pw_uid;
64 : : }
65 : :
66 : 0 : return uid;
67 : : }
68 : :
69 : : gid_t
70 : 0 : statdb_parse_gid(const char *str)
71 : : {
72 : : char *endptr;
73 : : gid_t gid;
74 : :
75 [ # # ]: 0 : if (str[0] == '#') {
76 : : long int value;
77 : :
78 : 0 : errno = 0;
79 : 0 : value = strtol(str + 1, &endptr, 10);
80 [ # # # # : 0 : if (str + 1 == endptr || *endptr || value < 0 || errno != 0)
# # # # ]
81 : 0 : ohshit(_("invalid statoverride gid %s"), str);
82 : 0 : gid = (gid_t)value;
83 : : } else {
84 : 0 : const struct group *gr = getgrnam(str);
85 : :
86 [ # # ]: 0 : if (gr == NULL)
87 : 0 : gid = (gid_t)-1;
88 : : else
89 : 0 : gid = gr->gr_gid;
90 : : }
91 : :
92 : 0 : return gid;
93 : : }
94 : :
95 : : mode_t
96 : 0 : statdb_parse_mode(const char *str)
97 : : {
98 : : char *endptr;
99 : : long int mode;
100 : :
101 : 0 : mode = strtol(str, &endptr, 8);
102 [ # # # # : 0 : if (str == endptr || *endptr || mode < 0 || mode > 07777)
# # # # ]
103 : 0 : ohshit(_("invalid statoverride mode %s"), str);
104 : :
105 : 0 : return (mode_t)mode;
106 : : }
107 : :
108 : : void
109 : 0 : ensure_statoverrides(enum statdb_parse_flags flags)
110 : : {
111 : : static struct dpkg_db db = {
112 : : .name = STATOVERRIDEFILE,
113 : : };
114 : : enum dpkg_db_error rc;
115 : : char *loaded_list, *loaded_list_end, *thisline, *nextline, *ptr;
116 : : struct file_stat *fso;
117 : : struct fsys_namenode *fnn;
118 : : struct fsys_hash_iter *iter;
119 : :
120 : 0 : rc = dpkg_db_reopen(&db);
121 [ # # ]: 0 : if (rc == DPKG_DB_SAME)
122 : 0 : return;
123 : :
124 : 0 : onerr_abort++;
125 : :
126 : : /* Reset statoverride information. */
127 : 0 : iter = fsys_hash_iter_new();
128 [ # # ]: 0 : while ((fnn = fsys_hash_iter_next(iter)))
129 : 0 : fnn->statoverride = NULL;
130 : 0 : fsys_hash_iter_free(iter);
131 : :
132 : 0 : onerr_abort--;
133 : :
134 [ # # ]: 0 : if (rc == DPKG_DB_NONE)
135 : 0 : return;
136 : :
137 : : /* If the statoverride list is empty we don't need to bother
138 : : * reading it. */
139 [ # # ]: 0 : if (!db.st.st_size)
140 : 0 : return;
141 : :
142 : 0 : onerr_abort++;
143 : :
144 : 0 : loaded_list = m_malloc(db.st.st_size);
145 : 0 : loaded_list_end = loaded_list + db.st.st_size;
146 : :
147 [ # # ]: 0 : if (fd_read(fileno(db.file), loaded_list, db.st.st_size) < 0)
148 : 0 : ohshite(_("reading statoverride file '%.250s'"), db.pathname);
149 : :
150 : 0 : thisline = loaded_list;
151 [ # # ]: 0 : while (thisline < loaded_list_end) {
152 : 0 : fso = nfmalloc(sizeof(*fso));
153 : :
154 : 0 : ptr = memchr(thisline, '\n', loaded_list_end - thisline);
155 [ # # ]: 0 : if (ptr == NULL)
156 : 0 : ohshit(_("statoverride file is missing final newline"));
157 : : /* Where to start next time around. */
158 : 0 : nextline = ptr + 1;
159 [ # # ]: 0 : if (ptr == thisline)
160 : 0 : ohshit(_("statoverride file contains empty line"));
161 : 0 : *ptr = '\0';
162 : :
163 : : /* Extract the uid. */
164 : 0 : ptr = memchr(thisline, ' ', nextline - thisline);
165 [ # # ]: 0 : if (ptr == NULL)
166 : 0 : ohshit(_("syntax error in statoverride file"));
167 : 0 : *ptr = '\0';
168 : :
169 : 0 : fso->uid = statdb_parse_uid(thisline);
170 [ # # ]: 0 : if (fso->uid == (uid_t)-1)
171 : 0 : fso->uname = nfstrsave(thisline);
172 : : else
173 : 0 : fso->uname = NULL;
174 : :
175 [ # # # # ]: 0 : if (fso->uid == (uid_t)-1 && !(flags & STATDB_PARSE_LAX))
176 : 0 : ohshit(_("unknown system user '%s' in statoverride file; the system user got removed\n"
177 : : "before the override, which is most probably a packaging bug, to recover you\n"
178 : : "can remove the override manually with %s"), thisline, DPKGSTAT);
179 : :
180 : : /* Move to the next bit */
181 : 0 : thisline = ptr + 1;
182 [ # # ]: 0 : if (thisline >= loaded_list_end)
183 : 0 : ohshit(_("unexpected end of line in statoverride file"));
184 : :
185 : : /* Extract the gid */
186 : 0 : ptr = memchr(thisline, ' ', nextline - thisline);
187 [ # # ]: 0 : if (ptr == NULL)
188 : 0 : ohshit(_("syntax error in statoverride file"));
189 : 0 : *ptr = '\0';
190 : :
191 : 0 : fso->gid = statdb_parse_gid(thisline);
192 [ # # ]: 0 : if (fso->gid == (gid_t)-1)
193 : 0 : fso->gname = nfstrsave(thisline);
194 : : else
195 : 0 : fso->gname = NULL;
196 : :
197 [ # # # # ]: 0 : if (fso->gid == (gid_t)-1 && !(flags & STATDB_PARSE_LAX))
198 : 0 : ohshit(_("unknown system group '%s' in statoverride file; the system group got removed\n"
199 : : "before the override, which is most probably a packaging bug, to recover you\n"
200 : : "can remove the override manually with %s"), thisline, DPKGSTAT);
201 : :
202 : : /* Move to the next bit */
203 : 0 : thisline = ptr + 1;
204 [ # # ]: 0 : if (thisline >= loaded_list_end)
205 : 0 : ohshit(_("unexpected end of line in statoverride file"));
206 : :
207 : : /* Extract the mode */
208 : 0 : ptr = memchr(thisline, ' ', nextline - thisline);
209 [ # # ]: 0 : if (ptr == NULL)
210 : 0 : ohshit(_("syntax error in statoverride file"));
211 : 0 : *ptr = '\0';
212 : :
213 : 0 : fso->mode = statdb_parse_mode(thisline);
214 : :
215 : : /* Move to the next bit */
216 : 0 : thisline = ptr + 1;
217 [ # # ]: 0 : if (thisline >= loaded_list_end)
218 : 0 : ohshit(_("unexpected end of line in statoverride file"));
219 : :
220 : 0 : fnn = fsys_hash_find_node(thisline, FHFF_NONE);
221 [ # # ]: 0 : if (fnn->statoverride)
222 : 0 : ohshit(_("multiple statoverrides present for file '%.250s'"),
223 : : thisline);
224 : 0 : fnn->statoverride = fso;
225 : :
226 : : /* Moving on... */
227 : 0 : thisline = nextline;
228 : : }
229 : :
230 : 0 : free(loaded_list);
231 : :
232 : 0 : onerr_abort--;
233 : : }
|