core: Use at-relative functions for checking out tree copies too

For the cases where we can't hardlink, use at-relative walking of the
path where possible.  We still don't have lsetxattrat, so we also need
to deal with pathnames, but that is now only for symlinks.

Again, the advantages of this are a lot less malloc() of pathnames in
ostree, and much less time spent traversing paths inside the kernel.

https://bugzilla.gnome.org/show_bug.cgi?id=707733
This commit is contained in:
Colin Walters committed 2013-09-08 14:42:50 -04:00
1 parent 0c2ea54e68
commit 33e589c018
4 files changed
+374 -390

No files matched your search

+4 -56
View File
@@ -170,58 +170,6 @@ commit_loose_object_trusted (OstreeRepo *self,
return ret;
}
/* Create a randomly-named symbolic link in @tempdir which points to
* @target. The filename will be returned in @out_file.
*
* The reason this odd function exists is that the repo should only
* contain objects in their final state. For bare repositories, we
* need to first create the symlink, then chown it, and apply all
* extended attributes, before finally rename()ing it into place.
*/
static gboolean
make_temporary_symlink_at (int tmp_dirfd,
const char *target,
char **out_name,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gs_free char *tmpname = NULL;
guint i;
const int max_attempts = 128;
for (i = 0; i < max_attempts; i++)
{
g_free (tmpname);
tmpname = gsystem_fileutil_gen_tmp_name (NULL, NULL);
if (symlinkat (target, tmp_dirfd, tmpname) < 0)
{
if (errno == EEXIST)
continue;
else
{
int errsv = errno;
g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errsv),
g_strerror (errsv));
goto out;
}
}
else
break;
}
if (i == max_attempts)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Exhausted attempts to open temporary file");
goto out;
}
ret = TRUE;
gs_transfer_out_value (out_name, &tmpname);
out:
return ret;
}
static gboolean
write_object (OstreeRepo *self,
OstreeObjectType objtype,
@@ -317,10 +265,10 @@ write_object (OstreeRepo *self,
}
else if (repo_mode == OSTREE_REPO_MODE_BARE && is_symlink)
{
if (!make_temporary_symlink_at (self->tmp_dir_fd,
g_file_info_get_symlink_target (file_info),
&temp_filename,
cancellable, error))
if (!_ostree_make_temporary_symlink_at (self->tmp_dir_fd,
g_file_info_get_symlink_target (file_info),
&temp_filename,
cancellable, error))
goto out;
temp_file = g_file_get_child (self->tmp_dir, temp_filename);
}