mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-22 13:33:56 +03:00
Merge pull request #25500 from DaanDeMeyer/mcopy-skip-symlinks
mkfs-util: Skip symlinks when calling mcopy
This commit is contained in:
commit
03288a3f28
@ -8,11 +8,11 @@
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
static int dirent_ensure_type(DIR *d, struct dirent *de) {
|
||||
int dirent_ensure_type(int dir_fd, struct dirent *de) {
|
||||
STRUCT_STATX_DEFINE(sx);
|
||||
int r;
|
||||
|
||||
assert(d);
|
||||
assert(dir_fd >= 0);
|
||||
assert(de);
|
||||
|
||||
if (de->d_type != DT_UNKNOWN)
|
||||
@ -24,7 +24,7 @@ static int dirent_ensure_type(DIR *d, struct dirent *de) {
|
||||
}
|
||||
|
||||
/* Let's ask only for the type, nothing else. */
|
||||
r = statx_fallback(dirfd(d), de->d_name, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT, STATX_TYPE, &sx);
|
||||
r = statx_fallback(dir_fd, de->d_name, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT, STATX_TYPE, &sx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -80,7 +80,7 @@ struct dirent *readdir_ensure_type(DIR *d) {
|
||||
if (!de)
|
||||
return NULL;
|
||||
|
||||
r = dirent_ensure_type(d, de);
|
||||
r = dirent_ensure_type(dirfd(d), de);
|
||||
if (r >= 0)
|
||||
return de;
|
||||
if (r != -ENOENT) {
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
bool dirent_is_file(const struct dirent *de) _pure_;
|
||||
bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_;
|
||||
int dirent_ensure_type(int dir_fd, struct dirent *de);
|
||||
|
||||
struct dirent *readdir_ensure_type(DIR *d);
|
||||
struct dirent *readdir_no_dot(DIR *dirp);
|
||||
|
@ -33,6 +33,7 @@ int readdir_all(int dir_fd,
|
||||
struct dirent *entry;
|
||||
DirectoryEntries *nde;
|
||||
size_t add, sz, j;
|
||||
int r;
|
||||
|
||||
assert(dir_fd >= 0);
|
||||
|
||||
@ -84,6 +85,15 @@ int readdir_all(int dir_fd,
|
||||
if (ignore_dirent(entry, flags))
|
||||
continue;
|
||||
|
||||
if (FLAGS_SET(flags, RECURSE_DIR_ENSURE_TYPE)) {
|
||||
r = dirent_ensure_type(dir_fd, entry);
|
||||
if (r == -ENOENT)
|
||||
/* dentry gone by now? no problem, let's just suppress it */
|
||||
continue;
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
de->n_entries++;
|
||||
}
|
||||
|
||||
@ -104,8 +114,14 @@ int readdir_all(int dir_fd,
|
||||
if (ignore_dirent(entry, flags))
|
||||
continue;
|
||||
|
||||
/* If d_type == DT_UNKNOWN that means we failed to ensure the type in the earlier loop and
|
||||
* didn't include the dentry in de->n_entries and as such should skip it here as well. */
|
||||
if (FLAGS_SET(flags, RECURSE_DIR_ENSURE_TYPE) && entry->d_type == DT_UNKNOWN)
|
||||
continue;
|
||||
|
||||
de->entries[j++] = entry;
|
||||
}
|
||||
assert(j == de->n_entries);
|
||||
|
||||
if (FLAGS_SET(flags, RECURSE_DIR_SORT))
|
||||
typesafe_qsort(de->entries, de->n_entries, sort_func);
|
||||
@ -160,7 +176,8 @@ int recurse_dir(
|
||||
return r;
|
||||
}
|
||||
|
||||
r = readdir_all(dir_fd, flags, &de);
|
||||
/* Mask out RECURSE_DIR_ENSURE_TYPE so we can do it ourselves and avoid an extra statx() call. */
|
||||
r = readdir_all(dir_fd, flags & ~RECURSE_DIR_ENSURE_TYPE, &de);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -130,7 +130,8 @@ static int setup_userns(uid_t uid, gid_t gid) {
|
||||
static int do_mcopy(const char *node, const char *root) {
|
||||
_cleanup_free_ char *mcopy = NULL;
|
||||
_cleanup_strv_free_ char **argv = NULL;
|
||||
_cleanup_closedir_ DIR *rootdir = NULL;
|
||||
_cleanup_close_ int rfd = -1;
|
||||
_cleanup_free_ DirectoryEntries *de = NULL;
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
@ -154,15 +155,24 @@ static int do_mcopy(const char *node, const char *root) {
|
||||
/* mcopy copies the top level directory instead of everything in it so we have to pass all
|
||||
* the subdirectories to mcopy instead to end up with the correct directory structure. */
|
||||
|
||||
rootdir = opendir(root);
|
||||
if (!rootdir)
|
||||
return log_error_errno(errno, "Failed to open directory '%s'", root);
|
||||
rfd = open(root, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
|
||||
if (rfd < 0)
|
||||
return log_error_errno(errno, "Failed to open directory '%s': %m", root);
|
||||
|
||||
FOREACH_DIRENT(de, rootdir, return -errno) {
|
||||
char *p = path_join(root, de->d_name);
|
||||
r = readdir_all(rfd, RECURSE_DIR_SORT|RECURSE_DIR_ENSURE_TYPE, &de);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read '%s' contents: %m", root);
|
||||
|
||||
for (size_t i = 0; i < de->n_entries; i++) {
|
||||
char *p = path_join(root, de->entries[i]->d_name);
|
||||
if (!p)
|
||||
return log_oom();
|
||||
|
||||
if (!IN_SET(de->entries[i]->d_type, DT_REG, DT_DIR)) {
|
||||
log_debug("%s is not a file/directory which are the only file types supported by vfat, ignoring", p);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = strv_consume(&argv, TAKE_PTR(p));
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
@ -172,7 +182,7 @@ static int do_mcopy(const char *node, const char *root) {
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
if (fstat(dirfd(rootdir), &st) < 0)
|
||||
if (fstat(rfd, &st) < 0)
|
||||
return log_error_errno(errno, "Failed to stat '%s': %m", root);
|
||||
|
||||
r = safe_fork("(mcopy)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR|FORK_NEW_USERNS|FORK_CLOSE_ALL_FDS, NULL);
|
||||
@ -269,7 +279,7 @@ static int make_protofile(const char *root, char **ret) {
|
||||
"0 0\n"
|
||||
"d--755 0 0\n", f);
|
||||
|
||||
r = recurse_dir_at(AT_FDCWD, root, STATX_TYPE|STATX_MODE, UINT_MAX, 0, protofile_print_item, f);
|
||||
r = recurse_dir_at(AT_FDCWD, root, STATX_TYPE|STATX_MODE, UINT_MAX, RECURSE_DIR_SORT, protofile_print_item, f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to recurse through %s: %m", root);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user