mirror of
https://github.com/flatpak/flatpak.git
synced 2026-03-27 19:33:06 -04:00
fdio: Open target dirname for glnx_file_copy_at()
Particularly if `AT_FDCWD` is used, we need to open in the target dir, otherwise we can get `EXDEV` when trying to do the final link. (Theoretically we can cross a mountpoint even with fd-relative though this is a lot less likely)
This commit is contained in:
13
glnx-fdio.c
13
glnx-fdio.c
@@ -930,11 +930,16 @@ glnx_file_copy_at (int src_dfd,
|
||||
if (!glnx_openat_rdonly (src_dfd, src_subpath, FALSE, &src_fd, error))
|
||||
return FALSE;
|
||||
|
||||
/* Open a tmpfile for dest */
|
||||
/* Open a tmpfile for dest. Particularly for AT_FDCWD calls, we really want to
|
||||
* open in the target directory, otherwise we may not be able to link.
|
||||
*/
|
||||
g_auto(GLnxTmpfile) tmp_dest = { 0, };
|
||||
if (!glnx_open_tmpfile_linkable_at (dest_dfd, ".", O_WRONLY | O_CLOEXEC,
|
||||
&tmp_dest, error))
|
||||
return FALSE;
|
||||
{ char *dnbuf = strdupa (dest_subpath);
|
||||
const char *dn = dirname (dnbuf);
|
||||
if (!glnx_open_tmpfile_linkable_at (dest_dfd, dn, O_WRONLY | O_CLOEXEC,
|
||||
&tmp_dest, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (glnx_regfile_copy_bytes (src_fd, tmp_dest.fd, (off_t) -1) < 0)
|
||||
return glnx_throw_errno_prefix (error, "regfile copy");
|
||||
|
||||
@@ -169,14 +169,24 @@ test_filecopy (void)
|
||||
_GLNX_TEST_DECLARE_ERROR(local_error, error);
|
||||
g_auto(GLnxTmpfile) tmpf = { 0, };
|
||||
const char foo[] = "foo";
|
||||
struct stat stbuf;
|
||||
|
||||
if (!glnx_ensure_dir (AT_FDCWD, "subdir", 0755, error))
|
||||
return;
|
||||
|
||||
if (!glnx_file_replace_contents_at (AT_FDCWD, foo, (guint8*)foo, sizeof (foo),
|
||||
GLNX_FILE_REPLACE_NODATASYNC, NULL, error))
|
||||
return;
|
||||
|
||||
/* Copy it into both the same dir and a subdir */
|
||||
if (!glnx_file_copy_at (AT_FDCWD, foo, NULL, AT_FDCWD, "bar",
|
||||
GLNX_FILE_COPY_NOXATTRS, NULL, error))
|
||||
return;
|
||||
if (!glnx_file_copy_at (AT_FDCWD, foo, NULL, AT_FDCWD, "subdir/bar",
|
||||
GLNX_FILE_COPY_NOXATTRS, NULL, error))
|
||||
return;
|
||||
if (!glnx_fstatat (AT_FDCWD, "subdir/bar", &stbuf, 0, error))
|
||||
return;
|
||||
|
||||
if (glnx_file_copy_at (AT_FDCWD, foo, NULL, AT_FDCWD, "bar",
|
||||
GLNX_FILE_COPY_NOXATTRS, NULL, error))
|
||||
@@ -206,7 +216,6 @@ test_filecopy (void)
|
||||
NULL, error))
|
||||
return;
|
||||
|
||||
struct stat stbuf;
|
||||
if (!glnx_fstatat_allow_noent (AT_FDCWD, "nosuchtarget", &stbuf, AT_SYMLINK_NOFOLLOW, error))
|
||||
return;
|
||||
g_assert_cmpint (errno, ==, ENOENT);
|
||||
|
||||
Reference in New Issue
Block a user