forked from Mirrors/flatpak-builder
Use the new gs_dirfd_iterator api in symlink_tree
parent
206bf95fa3
commit
b8c29f18ae
130
xdg-app-utils.c
130
xdg-app-utils.c
|
@ -100,84 +100,77 @@ overlay_symlink_tree_dir (int source_parent_fd,
|
|||
{
|
||||
gboolean ret = FALSE;
|
||||
int res;
|
||||
int source_dfd = -1;
|
||||
int destination_dfd = -1;
|
||||
DIR *srcd = NULL;
|
||||
gs_dirfd_iterator_cleanup GSDirFdIterator source_iter;
|
||||
gs_fd_close int destination_dfd = -1;
|
||||
struct dirent *dent;
|
||||
|
||||
if (source_name == NULL)
|
||||
source_dfd = source_parent_fd; /* We take ownership of the passed fd and close it */
|
||||
else
|
||||
if (!gs_dirfd_iterator_init_at (source_parent_fd, source_name, FALSE, &source_iter, error))
|
||||
goto out;
|
||||
|
||||
do
|
||||
res = mkdirat (destination_parent_fd, destination_name, 0777);
|
||||
while (G_UNLIKELY (res == -1 && errno == EINTR));
|
||||
if (res == -1)
|
||||
{
|
||||
if (!gs_file_open_dir_fd_at (source_parent_fd, source_name,
|
||||
&source_dfd,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (destination_name == NULL)
|
||||
destination_dfd = destination_parent_fd; /* We take ownership of the passed fd and close it */
|
||||
else
|
||||
{
|
||||
do
|
||||
res = mkdirat (destination_parent_fd, destination_name, 0777);
|
||||
while (G_UNLIKELY (res == -1 && errno == EINTR));
|
||||
if (res == -1)
|
||||
{
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
gs_set_error_from_errno (error, errno);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!gs_file_open_dir_fd_at (destination_parent_fd, destination_name,
|
||||
&destination_dfd,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
srcd = fdopendir (source_dfd);
|
||||
if (!srcd)
|
||||
{
|
||||
gs_set_error_from_errno (error, errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
while ((dent = readdir (srcd)) != NULL)
|
||||
{
|
||||
const char *name = dent->d_name;
|
||||
struct stat child_stbuf;
|
||||
|
||||
if (strcmp (name, ".") == 0 ||
|
||||
strcmp (name, "..") == 0)
|
||||
continue;
|
||||
|
||||
if (fstatat (source_dfd, name, &child_stbuf,
|
||||
AT_SYMLINK_NOFOLLOW) != 0)
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
gs_set_error_from_errno (error, errno);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (S_ISDIR (child_stbuf.st_mode))
|
||||
if (!gs_file_open_dir_fd_at (destination_parent_fd, destination_name,
|
||||
&destination_dfd,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
gboolean is_dir = FALSE;
|
||||
|
||||
if (!gs_dirfd_iterator_next_dent (&source_iter, &dent, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (dent == NULL)
|
||||
break;
|
||||
|
||||
if (dent->d_type == DT_DIR)
|
||||
is_dir = TRUE;
|
||||
else if (dent->d_type == DT_UNKNOWN)
|
||||
{
|
||||
gs_free gchar *target = g_build_filename ("..", source_symlink_prefix, name, NULL);
|
||||
if (!overlay_symlink_tree_dir (source_dfd, name, target, destination_dfd, name,
|
||||
struct stat stbuf;
|
||||
if (fstatat (source_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW) == -1)
|
||||
{
|
||||
int errsv = errno;
|
||||
if (errsv == ENOENT)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
gs_set_error_from_errno (error, errsv);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
is_dir = S_ISDIR (stbuf.st_mode);
|
||||
}
|
||||
|
||||
if (is_dir)
|
||||
{
|
||||
gs_free gchar *target = g_build_filename ("..", source_symlink_prefix, dent->d_name, NULL);
|
||||
if (!overlay_symlink_tree_dir (source_iter.fd, dent->d_name, target, destination_dfd, dent->d_name,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
gs_free gchar *target = g_build_filename (source_symlink_prefix, name, NULL);
|
||||
gs_free gchar *target = g_build_filename (source_symlink_prefix, dent->d_name, NULL);
|
||||
|
||||
if (unlinkat (destination_dfd, name, 0) != 0 && errno != ENOENT)
|
||||
if (unlinkat (destination_dfd, dent->d_name, 0) != 0 && errno != ENOENT)
|
||||
{
|
||||
gs_set_error_from_errno (error, errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (symlinkat (target, destination_dfd, name) != 0)
|
||||
if (symlinkat (target, destination_dfd, dent->d_name) != 0)
|
||||
{
|
||||
gs_set_error_from_errno (error, errno);
|
||||
goto out;
|
||||
|
@ -187,12 +180,6 @@ overlay_symlink_tree_dir (int source_parent_fd,
|
|||
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (srcd != NULL)
|
||||
closedir (srcd); /* This closes source_dfd */
|
||||
else if (source_dfd != -1)
|
||||
close (source_dfd);
|
||||
if (destination_dfd != -1)
|
||||
close (destination_dfd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -205,23 +192,14 @@ xdg_app_overlay_symlink_tree (GFile *source,
|
|||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int source_dfd = -1;
|
||||
int destination_dfd = -1;
|
||||
|
||||
if (!gs_file_open_dir_fd (source, &source_dfd, cancellable, error))
|
||||
if (!gs_file_ensure_directory (destination, TRUE, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!gs_file_ensure_directory (destination, TRUE, cancellable, error) ||
|
||||
!gs_file_open_dir_fd (destination, &destination_dfd, cancellable, error))
|
||||
{
|
||||
close (source_dfd);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* The fds are closed by this call */
|
||||
if (!overlay_symlink_tree_dir (source_dfd, NULL,
|
||||
if (!overlay_symlink_tree_dir (AT_FDCWD, gs_file_get_path_cached (source),
|
||||
symlink_prefix,
|
||||
destination_dfd, NULL,
|
||||
AT_FDCWD, gs_file_get_path_cached (destination),
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
|
|
Loading…
Reference in New Issue