mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-02-20 14:22:26 +02:00
Now that Gnulib’s ‘error’ module does proper static checking for not returning, we need no longer use the ‘die’ macro. This makes code easier to read for people that are used to ‘error’. * cfg.mk (error_fns, exclude_file_name_regexp): Remove ‘die’. (sc_die_EXIT_FAILURE): Remove. * src/die.h: Remove. All includes removed. All calls to ‘die’ changed back to calls to ‘error’. * src/install.c (get_ids): Use quoteaf (problem found with make syntax-check). * src/system.h: Include error.h, since some of our macros call ‘error’. Stop including error.h elsewhere.
112 lines
3.3 KiB
C
112 lines
3.3 KiB
C
/* find-mount-point.c -- find the root mount point for a file.
|
|
Copyright (C) 2010-2023 Free Software Foundation, Inc.
|
|
|
|
This program 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 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
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, see <https://www.gnu.org/licenses/>. */
|
|
|
|
#include <config.h>
|
|
#include <sys/types.h>
|
|
|
|
#include "system.h"
|
|
#include "save-cwd.h"
|
|
#include "xgetcwd.h"
|
|
#include "find-mount-point.h"
|
|
|
|
/* Return the root mountpoint of the file system on which FILE exists, in
|
|
malloced storage. FILE_STAT should be the result of stating FILE.
|
|
Give a diagnostic and return nullptr if unable to determine the mount point.
|
|
Exit if unable to restore current working directory. */
|
|
extern char *
|
|
find_mount_point (char const *file, struct stat const *file_stat)
|
|
{
|
|
struct saved_cwd cwd;
|
|
struct stat last_stat;
|
|
char *mp = nullptr; /* The malloc'd mount point. */
|
|
|
|
if (save_cwd (&cwd) != 0)
|
|
{
|
|
error (0, errno, _("cannot get current directory"));
|
|
return nullptr;
|
|
}
|
|
|
|
if (S_ISDIR (file_stat->st_mode))
|
|
/* FILE is a directory, so just chdir there directly. */
|
|
{
|
|
last_stat = *file_stat;
|
|
if (chdir (file) < 0)
|
|
{
|
|
error (0, errno, _("cannot change to directory %s"), quoteaf (file));
|
|
return nullptr;
|
|
}
|
|
}
|
|
else
|
|
/* FILE is some other kind of file; use its directory. */
|
|
{
|
|
char *xdir = dir_name (file);
|
|
char *dir;
|
|
ASSIGN_STRDUPA (dir, xdir);
|
|
free (xdir);
|
|
|
|
if (chdir (dir) < 0)
|
|
{
|
|
error (0, errno, _("cannot change to directory %s"), quoteaf (dir));
|
|
return nullptr;
|
|
}
|
|
|
|
if (stat (".", &last_stat) < 0)
|
|
{
|
|
error (0, errno, _("cannot stat current directory (now %s)"),
|
|
quoteaf (dir));
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
/* Now walk up FILE's parents until we find another file system or /,
|
|
chdiring as we go. LAST_STAT holds stat information for the last place
|
|
we visited. */
|
|
while (true)
|
|
{
|
|
struct stat st;
|
|
if (stat ("..", &st) < 0)
|
|
{
|
|
error (0, errno, _("cannot stat %s"), quoteaf (".."));
|
|
goto done;
|
|
}
|
|
if (st.st_dev != last_stat.st_dev || st.st_ino == last_stat.st_ino)
|
|
/* cwd is the mount point. */
|
|
break;
|
|
if (chdir ("..") < 0)
|
|
{
|
|
error (0, errno, _("cannot change to directory %s"), quoteaf (".."));
|
|
goto done;
|
|
}
|
|
last_stat = st;
|
|
}
|
|
|
|
/* Finally reached a mount point, see what it's called. */
|
|
mp = xgetcwd ();
|
|
|
|
done:
|
|
/* Restore the original cwd. */
|
|
{
|
|
int save_errno = errno;
|
|
if (restore_cwd (&cwd) != 0)
|
|
error (EXIT_FAILURE, errno,
|
|
_("failed to return to initial working directory"));
|
|
free_cwd (&cwd);
|
|
errno = save_errno;
|
|
}
|
|
|
|
return mp;
|
|
}
|