| /* |
| * dpkg - main program for package management |
| * statdb.c - management of database of ownership and mode of files |
| * |
| * Copyright © 1995 Ian Jackson <ian@chiark.greenend.org.uk> |
| * Copyright © 2000, 2001 Wichert Akkerman <wakkerma@debian.org> |
| * Copyright © 2008-2010 Guillem Jover <guillem@debian.org> |
| * |
| * This is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #include <config.h> |
| #include <compat.h> |
| |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| |
| #include <errno.h> |
| #include <string.h> |
| #include <pwd.h> |
| #include <grp.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| #include <stdlib.h> |
| |
| #include <dpkg/i18n.h> |
| #include <dpkg/dpkg.h> |
| #include <dpkg/dpkg-db.h> |
| #include <dpkg/fdio.h> |
| |
| #include "filesdb.h" |
| #include "main.h" |
| |
| static FILE *statoverridefile = NULL; |
| static char *statoverridename; |
| |
| uid_t |
| statdb_parse_uid(const char *str) |
| { |
| char* endptr; |
| uid_t uid; |
| |
| if (str[0] == '#') { |
| long int value; |
| |
| value = strtol(str + 1, &endptr, 10); |
| if (str + 1 == endptr || *endptr || value < 0) |
| ohshit(_("syntax error: invalid uid in statoverride file")); |
| uid = (uid_t)value; |
| } else { |
| struct passwd* pw = getpwnam(str); |
| if (pw == NULL) |
| ohshit(_("syntax error: unknown user '%s' in statoverride file"), |
| str); |
| uid = pw->pw_uid; |
| } |
| |
| return uid; |
| } |
| |
| gid_t |
| statdb_parse_gid(const char *str) |
| { |
| char* endptr; |
| gid_t gid; |
| |
| if (str[0] == '#') { |
| long int value; |
| |
| value = strtol(str + 1, &endptr, 10); |
| if (str + 1 == endptr || *endptr || value < 0) |
| ohshit(_("syntax error: invalid gid in statoverride file")); |
| gid = (gid_t)value; |
| } else { |
| struct group* gr = getgrnam(str); |
| if (gr == NULL) |
| ohshit(_("syntax error: unknown group '%s' in statoverride file"), |
| str); |
| gid = gr->gr_gid; |
| } |
| |
| return gid; |
| } |
| |
| mode_t |
| statdb_parse_mode(const char *str) |
| { |
| char* endptr; |
| long int mode; |
| |
| mode = strtol(str, &endptr, 8); |
| if (str == endptr || *endptr || mode < 0 || mode > 07777) |
| ohshit(_("syntax error: invalid mode in statoverride file")); |
| |
| return (mode_t)mode; |
| } |
| |
| void |
| ensure_statoverrides(void) |
| { |
| struct stat stab1, stab2; |
| FILE *file; |
| char *loaded_list, *loaded_list_end, *thisline, *nextline, *ptr; |
| struct file_stat *fso; |
| struct filenamenode *fnn; |
| |
| if (statoverridename != NULL) |
| free(statoverridename); |
| statoverridename = dpkg_db_get_path(STATOVERRIDEFILE); |
| |
| onerr_abort++; |
| |
| file = fopen(statoverridename, "r"); |
| if (!file) { |
| if (errno != ENOENT) |
| ohshite(_("failed to open statoverride file")); |
| if (!statoverridefile) { |
| onerr_abort--; |
| return; |
| } |
| } else { |
| if (fstat(fileno(file), &stab2)) |
| ohshite(_("failed to fstat statoverride file")); |
| if (statoverridefile) { |
| if (fstat(fileno(statoverridefile), &stab1)) |
| ohshite(_("failed to fstat previous statoverride file")); |
| if (stab1.st_dev == stab2.st_dev && |
| stab1.st_ino == stab2.st_ino) { |
| fclose(file); |
| onerr_abort--; |
| return; |
| } |
| } |
| } |
| if (statoverridefile) |
| fclose(statoverridefile); |
| statoverridefile = file; |
| setcloexec(fileno(statoverridefile), statoverridename); |
| |
| /* If the statoverride list is empty we don't need to bother |
| * reading it. */ |
| if (!stab2.st_size) { |
| onerr_abort--; |
| return; |
| } |
| |
| loaded_list = nfmalloc(stab2.st_size); |
| loaded_list_end = loaded_list + stab2.st_size; |
| |
| if (fd_read(fileno(file), loaded_list, stab2.st_size) < 0) |
| ohshite(_("reading statoverride file '%.250s'"), statoverridename); |
| |
| thisline = loaded_list; |
| while (thisline < loaded_list_end) { |
| fso = nfmalloc(sizeof(struct file_stat)); |
| |
| if (!(ptr = memchr(thisline, '\n', loaded_list_end - thisline))) |
| ohshit(_("statoverride file is missing final newline")); |
| /* Where to start next time around. */ |
| nextline = ptr + 1; |
| if (ptr == thisline) |
| ohshit(_("statoverride file contains empty line")); |
| *ptr = '\0'; |
| |
| /* Extract the uid. */ |
| if (!(ptr = memchr(thisline, ' ', nextline - thisline))) |
| ohshit(_("syntax error in statoverride file")); |
| *ptr = '\0'; |
| |
| fso->uid = statdb_parse_uid(thisline); |
| |
| /* Move to the next bit */ |
| thisline = ptr + 1; |
| if (thisline >= loaded_list_end) |
| ohshit(_("unexpected end of line in statoverride file")); |
| |
| /* Extract the gid */ |
| if (!(ptr = memchr(thisline, ' ', nextline - thisline))) |
| ohshit(_("syntax error in statoverride file")); |
| *ptr = '\0'; |
| |
| fso->gid = statdb_parse_gid(thisline); |
| |
| /* Move to the next bit */ |
| thisline = ptr + 1; |
| if (thisline >= loaded_list_end) |
| ohshit(_("unexpected end of line in statoverride file")); |
| |
| /* Extract the mode */ |
| if (!(ptr = memchr(thisline, ' ', nextline - thisline))) |
| ohshit(_("syntax error in statoverride file")); |
| *ptr = '\0'; |
| |
| fso->mode = statdb_parse_mode(thisline); |
| |
| /* Move to the next bit */ |
| thisline = ptr + 1; |
| if (thisline >= loaded_list_end) |
| ohshit(_("unexpected end of line in statoverride file")); |
| |
| fnn = findnamenode(thisline, 0); |
| if (fnn->statoverride) |
| ohshit(_("multiple statusoverrides present for file '%.250s'"), |
| thisline); |
| fnn->statoverride = fso; |
| |
| /* Moving on.. */ |
| thisline = nextline; |
| } |
| |
| onerr_abort--; |
| } |