From 4d4bafc8891c456f27da5bb9f77f55413d398c5f Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Mar 29 2011 22:12:37 +0000 Subject: Move bind mount handling into a separate file. 2011-03-30 Miloslav Trmač * src/bind-mount.c (bind_mount_paths, bind_mount_paths_index) (last_path_mounted_mtime, bind_mount_paths_obstack) (bind_mount_paths_mark, rebuild_bind_mount_paths, is_bind_mount): Move from ... * src/updatedb.c: ... here. * src/bind-mount.c (bind_mount_init): Rename and move from ... * src/updatedb.c (init_bind_mount_paths): ... here, and move conf_prune_bind_mounts handling to the caller. * src/bind-mount.h: New file. * Makefile.am (src_updatedb_SOURCES): Add src/bind-mount.c and src/bind-mount.h. * src/lib.c (string_list_contains_dir_path): Rename and move from... * src/updatedb.c (path_is_in-list): ... here. All callers updated. * src/lib.h (string_list_contains_dir_path): New declaration. --- diff --git a/ChangeLog b/ChangeLog index 23b9a73..5bb00af 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2011-03-30 Miloslav Trmač + + * src/bind-mount.c (bind_mount_paths, bind_mount_paths_index) + (last_path_mounted_mtime, bind_mount_paths_obstack) + (bind_mount_paths_mark, rebuild_bind_mount_paths, is_bind_mount): Move + from ... + * src/updatedb.c: ... here. + * src/bind-mount.c (bind_mount_init): Rename and move from ... + * src/updatedb.c (init_bind_mount_paths): ... here, and move + conf_prune_bind_mounts handling to the caller. + * src/bind-mount.h: New file. + * Makefile.am (src_updatedb_SOURCES): Add src/bind-mount.c and + src/bind-mount.h. + + * src/lib.c (string_list_contains_dir_path): Rename and move from... + * src/updatedb.c (path_is_in-list): ... here. All callers updated. + * src/lib.h (string_list_contains_dir_path): New declaration. + 2011-03-10 Miloslav Trmač * doc/updatedb.8.in: Fix a typo. diff --git a/Makefile.am b/Makefile.am index 2b6adbc..022d52e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,7 +49,8 @@ src_liblib_a_SOURCES = src/db.h src/lib.c src/lib.h src_locate_CPPFLAGS = $(AM_CPPFLAGS) $(COMMON_CPPFLAGS) src_locate_LDADD = src/liblib.a gnulib/lib/libgnu.a $(LIBINTL) -src_updatedb_SOURCES = src/conf.c src/conf.h src/updatedb.c +src_updatedb_SOURCES = src/bind-mount.c src/bind-mount.h src/conf.c src/conf.h \ + src/updatedb.c src_updatedb_CPPFLAGS = $(AM_CPPFLAGS) $(COMMON_CPPFLAGS) $(CONF_CPPFLAGS) src_updatedb_LDADD = src/liblib.a gnulib/lib/libgnu.a $(LIBINTL) diff --git a/src/bind-mount.c b/src/bind-mount.c new file mode 100644 index 0000000..d8bd39f --- /dev/null +++ b/src/bind-mount.c @@ -0,0 +1,135 @@ +/* Bind mount detection. + +Copyright (C) 2005, 2007, 2008 Red Hat, Inc. All rights reserved. +This copyrighted material is made available to anyone wishing to use, modify, +copy, or redistribute it subject to the terms and conditions of the GNU General +Public License v.2. + +This program 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, write to the Free Software Foundation, Inc., 51 Franklin +Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Author: Miloslav Trmac */ +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "obstack.h" +#include "stat-time.h" +#include "timespec.h" + +#include "bind-mount.h" +#include "conf.h" +#include "lib.h" + +/* Known bind mount paths */ +static struct string_list bind_mount_paths; /* = { 0, }; */ + +/* Next bind_mount_paths entry */ +static size_t bind_mount_paths_index; /* = 0; */ + +/* _PATH_MOUNTED mtime at the time of last rebuild_bind_mount_paths () call */ +static struct timespec last_path_mounted_mtime; /* = { 0, }; */ + +static struct obstack bind_mount_paths_obstack; +static void *bind_mount_paths_mark; + +/* Rebuild bind_mount_paths */ +static void +rebuild_bind_mount_paths (void) +{ + FILE *f; + struct mntent *me; + + if (conf_debug_pruning != false) + /* This is debuging output, don't mark anything for translation */ + fprintf (stderr, "Rebuilding bind_mount_paths:\n"); + obstack_free (&bind_mount_paths_obstack, bind_mount_paths_mark); + bind_mount_paths_mark = obstack_alloc (&bind_mount_paths_obstack, 0); + bind_mount_paths.len = 0; + f = setmntent (_PATH_MOUNTED, "r"); + if (f == NULL) + goto err; + while ((me = getmntent (f)) != NULL) + { + if (conf_debug_pruning != false) + /* This is debuging output, don't mark anything for translation */ + fprintf (stderr, " `%s' on `%s', opts `%s'\n", me->mnt_fsname, + me->mnt_dir, me->mnt_opts); + /* Bind mounts "to self" can be used (e.g. by policycoreutils-sandbox) to + create another mount point to which Linux name space privacy flags can + be attached. Such a bind mount is not duplicating any part of the + directory tree, so it should not be excluded. */ + if (hasmntopt (me, "bind") != NULL + && strcmp (me->mnt_fsname, me->mnt_dir) != 0) + { + char dbuf[PATH_MAX], *dir; + + dir = realpath (me->mnt_dir, dbuf); + if (dir == NULL) + dir = me->mnt_dir; + if (conf_debug_pruning != false) + /* This is debuging output, don't mark anything for translation */ + fprintf (stderr, " => adding `%s'\n", dir); + dir = obstack_copy (&bind_mount_paths_obstack, dir, strlen (dir) + 1); + string_list_append (&bind_mount_paths, dir); + } + } + endmntent (f); + /* Fall through */ + err: + if (conf_debug_pruning != false) + /* This is debuging output, don't mark anything for translation */ + fprintf (stderr, "...done\n"); + string_list_dir_path_sort (&bind_mount_paths); +} + +/* Return true if PATH is a destination of a bind mount. + (Bind mounts "to self" are ignored.) */ +bool +is_bind_mount (const char *path) +{ + struct timespec path_mounted_mtime; + struct stat st; + + /* Unfortunately (mount --bind $path $path/subdir) would leave st_dev + unchanged between $path and $path/subdir, so we must keep reparsing + _PATH_MOUNTED (not PROC_MOUNTS_PATH) each time it changes. */ + if (stat (_PATH_MOUNTED, &st) != 0) + return false; + path_mounted_mtime = get_stat_mtime (&st); + if (timespec_cmp (last_path_mounted_mtime, path_mounted_mtime) < 0) + { + rebuild_bind_mount_paths (); + last_path_mounted_mtime = path_mounted_mtime; + bind_mount_paths_index = 0; + } + return string_list_contains_dir_path (&bind_mount_paths, + &bind_mount_paths_index, path); +} + +/* Initialize state for is_bind_mount(). */ +void +bind_mount_init (void) +{ + struct stat st; + + obstack_init (&bind_mount_paths_obstack); + obstack_alignment_mask (&bind_mount_paths_obstack) = 0; + bind_mount_paths_mark = obstack_alloc (&bind_mount_paths_obstack, 0); + if (stat (_PATH_MOUNTED, &st) != 0) + return; + rebuild_bind_mount_paths (); + last_path_mounted_mtime = get_stat_mtime (&st); +} diff --git a/src/bind-mount.h b/src/bind-mount.h new file mode 100644 index 0000000..19554ac --- /dev/null +++ b/src/bind-mount.h @@ -0,0 +1,32 @@ +/* Bind mount detection. + +Copyright (C) 2005, 2007, 2008 Red Hat, Inc. All rights reserved. +This copyrighted material is made available to anyone wishing to use, modify, +copy, or redistribute it subject to the terms and conditions of the GNU General +Public License v.2. + +This program 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, write to the Free Software Foundation, Inc., 51 Franklin +Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Author: Miloslav Trmac */ + +#ifndef BIND_MOUNT_H__ +#define BIND_MOUNT_H__ + +#include + +#include + +/* Return true if PATH is a destination of a bind mount. + (Bind mounts "to self" are ignored.) */ +extern bool is_bind_mount (const char *path); + +/* Initialize state for is_bind_mount(). */ +extern void bind_mount_init (void); + +#endif diff --git a/src/lib.c b/src/lib.c index 106df5e..5b11ade 100644 --- a/src/lib.c +++ b/src/lib.c @@ -143,6 +143,28 @@ string_list_dir_path_sort (struct string_list *list) cmp_dir_path_pointers); } +/* Is PATH included in LIST? Update *IDX to move within LIST. + + LIST is assumed to be sorted using dir_path_cmp (), successive calls to this + function are assumed to use PATH values increasing in dir_path_cmp (). */ +bool +string_list_contains_dir_path (const struct string_list *list, size_t *idx, + const char *path) +{ + int cmp; + + cmp = 0; + while (*idx < list->len + && (cmp = dir_path_cmp (list->entries[*idx], path)) < 0) + (*idx)++; + if (*idx < list->len && cmp == 0) + { + (*idx)++; + return true; + } + return false; +} + /* Reading of existing databases */ /* Open FILENAME (already open as FD), as DB, report error on failure if not diff --git a/src/lib.h b/src/lib.h index 9a8e538..e0707c7 100644 --- a/src/lib.h +++ b/src/lib.h @@ -84,6 +84,13 @@ extern void string_list_append (struct string_list *list, char *string); /* Sort LIST using dir_path_cmp () */ extern void string_list_dir_path_sort (struct string_list *list); +/* Is PATH included in LIST? Update *IDX to move within LIST. + + LIST is assumed to be sorted using dir_path_cmp (), successive calls to this + function are assumed to use PATH values increasing in dir_path_cmp (). */ +extern bool string_list_contains_dir_path (const struct string_list *list, + size_t *idx, const char *path); + /* An open database */ struct db { diff --git a/src/updatedb.c b/src/updatedb.c index 67f79c0..9010301 100644 --- a/src/updatedb.c +++ b/src/updatedb.c @@ -42,10 +42,10 @@ Author: Miloslav Trmac */ #include "obstack.h" #include "progname.h" #include "stat-time.h" -#include "timespec.h" #include "verify.h" #include "xalloc.h" +#include "bind-mount.h" #include "conf.h" #include "db.h" #include "lib.h" @@ -313,132 +313,6 @@ old_db_open (void) return fd; } - /* Path list handling */ - -/* Is PATH included in LIST? Update *IDX to move within LIST. - - LIST is assumed to be sorted using dir_path_cmp (), successive calls to this - function are assumed to use PATH values increasing in dir_path_cmp (). */ -static bool -path_is_in_list (const struct string_list *list, size_t *idx, const char *path) -{ - int cmp; - - cmp = 0; - while (*idx < list->len - && (cmp = dir_path_cmp (list->entries[*idx], path)) < 0) - (*idx)++; - if (*idx < list->len && cmp == 0) - { - (*idx)++; - return true; - } - return false; -} - - /* $PRUNE_BIND_MOUNTS handling */ - -/* Known bind mount paths */ -static struct string_list bind_mount_paths; /* = { 0, }; */ - -/* Next bind_mount_paths entry */ -static size_t bind_mount_paths_index; /* = 0; */ - -/* _PATH_MOUNTED mtime at the time of last rebuild_bind_mount_paths () call */ -static struct timespec last_path_mounted_mtime; /* = { 0, }; */ - -static struct obstack bind_mount_paths_obstack; -static void *bind_mount_paths_mark; - -/* Rebuild bind_mount_paths */ -static void -rebuild_bind_mount_paths (void) -{ - FILE *f; - struct mntent *me; - - if (conf_debug_pruning != false) - /* This is debuging output, don't mark anything for translation */ - fprintf (stderr, "Rebuilding bind_mount_paths:\n"); - obstack_free (&bind_mount_paths_obstack, bind_mount_paths_mark); - bind_mount_paths_mark = obstack_alloc (&bind_mount_paths_obstack, 0); - bind_mount_paths.len = 0; - f = setmntent (_PATH_MOUNTED, "r"); - if (f == NULL) - goto err; - while ((me = getmntent (f)) != NULL) - { - if (conf_debug_pruning != false) - /* This is debuging output, don't mark anything for translation */ - fprintf (stderr, " `%s' on `%s', opts `%s'\n", me->mnt_fsname, - me->mnt_dir, me->mnt_opts); - /* Bind mounts "to self" can be used (e.g. by policycoreutils-sandbox) to - create another mount point to which Linux name space privacy flags can - be attached. Such a bind mount is not duplicating any part of the - directory tree, so it should not be excluded. */ - if (hasmntopt (me, "bind") != NULL - && strcmp (me->mnt_fsname, me->mnt_dir) != 0) - { - char dbuf[PATH_MAX], *dir; - - dir = realpath (me->mnt_dir, dbuf); - if (dir == NULL) - dir = me->mnt_dir; - if (conf_debug_pruning != false) - /* This is debuging output, don't mark anything for translation */ - fprintf (stderr, " => adding `%s'\n", dir); - dir = obstack_copy (&bind_mount_paths_obstack, dir, strlen (dir) + 1); - string_list_append (&bind_mount_paths, dir); - } - } - endmntent (f); - /* Fall through */ - err: - if (conf_debug_pruning != false) - /* This is debuging output, don't mark anything for translation */ - fprintf (stderr, "...done\n"); - string_list_dir_path_sort (&bind_mount_paths); -} - -/* Return true if PATH is a destination of a bind mount. */ -static bool -is_bind_mount (const char *path) -{ - struct timespec path_mounted_mtime; - struct stat st; - - /* Unfortunately (mount --bind $path $path/subdir) would leave st_dev - unchanged between $path and $path/subdir, so we must keep reparsing - _PATH_MOUNTED (not PROC_MOUNTS_PATH) each time it changes. */ - if (stat (_PATH_MOUNTED, &st) != 0) - return false; - path_mounted_mtime = get_stat_mtime (&st); - if (timespec_cmp (last_path_mounted_mtime, path_mounted_mtime) < 0) - { - rebuild_bind_mount_paths (); - last_path_mounted_mtime = path_mounted_mtime; - bind_mount_paths_index = 0; - } - return path_is_in_list (&bind_mount_paths, &bind_mount_paths_index, path); -} - -/* Initialize $PRUNE_BIND_MOUNTS state */ -static void -init_bind_mount_paths (void) -{ - struct stat st; - - if (conf_prune_bind_mounts == false) - return; - obstack_init (&bind_mount_paths_obstack); - obstack_alignment_mask (&bind_mount_paths_obstack) = 0; - bind_mount_paths_mark = obstack_alloc (&bind_mount_paths_obstack, 0); - if (stat (_PATH_MOUNTED, &st) != 0) - return; - rebuild_bind_mount_paths (); - last_path_mounted_mtime = get_stat_mtime (&st); -} - /* $PRUNEFS handling */ static int @@ -829,7 +703,8 @@ scan (char *path, int *cwd_fd, const struct stat *st_parent, int cmp, res; bool have_subdir, did_chdir; - if (path_is_in_list (&conf_prunepaths, &conf_prunepaths_index, path)) + if (string_list_contains_dir_path (&conf_prunepaths, &conf_prunepaths_index, + path)) { if (conf_debug_pruning != false) /* This is debuging output, don't mark anything for translation */ @@ -1066,7 +941,8 @@ main (int argc, char *argv[]) bindtextdomain (PACKAGE_NAME, LOCALEDIR); textdomain (PACKAGE_NAME); conf_prepare (argc, argv); - init_bind_mount_paths (); + if (conf_prune_bind_mounts != false) + bind_mount_init (); lock_file_fd = old_db_open (); if (lock_file_fd != -1) {