blob: 21eeb5f3a5a53a519cbac95cea5165b16ef5c5d8 [file] [log] [blame]
/*
* 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--;
}