libostree: Move file creation APIs out of core, into checkout.c
Since this was the only user, let's not have generic code to go from OSTree representation -> filesystem here. It should live in checkout.
This commit is contained in:
parent
79c922a00b
commit
36815f52b5
|
|
@ -40,8 +40,6 @@ ostree_checksum_file
|
||||||
ostree_checksum_file_async
|
ostree_checksum_file_async
|
||||||
ostree_checksum_file_async_finish
|
ostree_checksum_file_async_finish
|
||||||
ostree_create_directory_metadata
|
ostree_create_directory_metadata
|
||||||
ostree_create_file_from_input
|
|
||||||
ostree_create_temp_file_from_input
|
|
||||||
ostree_create_temp_dir
|
ostree_create_temp_dir
|
||||||
ostree_validate_structureof_objtype
|
ostree_validate_structureof_objtype
|
||||||
ostree_validate_structureof_csum_v
|
ostree_validate_structureof_csum_v
|
||||||
|
|
|
||||||
|
|
@ -1511,214 +1511,6 @@ zlib_file_header_parse (GVariant *metadata,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* ostree_create_file_from_input:
|
|
||||||
* @dest_file: Destination; must not exist
|
|
||||||
* @finfo: File information
|
|
||||||
* @xattrs: (allow-none): Optional extended attributes
|
|
||||||
* @input: (allow-none): Optional file content, must be %NULL for symbolic links
|
|
||||||
* @cancellable: Cancellable
|
|
||||||
* @error: Error
|
|
||||||
*
|
|
||||||
* Create a directory, regular file, or symbolic link, based on
|
|
||||||
* @finfo. Append extended attributes from @xattrs if provided. For
|
|
||||||
* %G_FILE_TYPE_REGULAR, set content based on @input.
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
ostree_create_file_from_input (GFile *dest_file,
|
|
||||||
GFileInfo *finfo,
|
|
||||||
GVariant *xattrs,
|
|
||||||
GInputStream *input,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
gboolean ret = FALSE;
|
|
||||||
const char *dest_path;
|
|
||||||
guint32 uid, gid, mode;
|
|
||||||
gs_unref_object GOutputStream *out = NULL;
|
|
||||||
|
|
||||||
if (g_cancellable_set_error_if_cancelled (cancellable, error))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (finfo != NULL)
|
|
||||||
{
|
|
||||||
mode = g_file_info_get_attribute_uint32 (finfo, "unix::mode");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mode = S_IFREG | 0664;
|
|
||||||
}
|
|
||||||
dest_path = gs_file_get_path_cached (dest_file);
|
|
||||||
|
|
||||||
if (S_ISDIR (mode))
|
|
||||||
{
|
|
||||||
if (mkdir (gs_file_get_path_cached (dest_file), mode) < 0)
|
|
||||||
{
|
|
||||||
ot_util_set_error_from_errno (error, errno);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (S_ISREG (mode))
|
|
||||||
{
|
|
||||||
if (finfo != NULL)
|
|
||||||
{
|
|
||||||
uid = g_file_info_get_attribute_uint32 (finfo, "unix::uid");
|
|
||||||
gid = g_file_info_get_attribute_uint32 (finfo, "unix::gid");
|
|
||||||
|
|
||||||
if (!gs_file_create_with_uidgid (dest_file, mode, uid, gid, &out,
|
|
||||||
cancellable, error))
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!gs_file_create (dest_file, mode, &out,
|
|
||||||
cancellable, error))
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input)
|
|
||||||
{
|
|
||||||
if (g_output_stream_splice ((GOutputStream*)out, input, 0,
|
|
||||||
cancellable, error) < 0)
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!g_output_stream_close ((GOutputStream*)out, NULL, error))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* Work around libguestfs/FUSE bug */
|
|
||||||
if (mode & (S_ISUID|S_ISGID))
|
|
||||||
{
|
|
||||||
if (chmod (dest_path, mode) == -1)
|
|
||||||
{
|
|
||||||
ot_util_set_error_from_errno (error, errno);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (S_ISLNK (mode))
|
|
||||||
{
|
|
||||||
const char *target = g_file_info_get_attribute_byte_string (finfo, "standard::symlink-target");
|
|
||||||
if (symlink (target, dest_path) < 0)
|
|
||||||
{
|
|
||||||
ot_util_set_error_from_errno (error, errno);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
||||||
"Invalid mode %u", mode);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We only need to chown for directories and symlinks; we already
|
|
||||||
* did a chown for files above via fchown().
|
|
||||||
*/
|
|
||||||
if (finfo != NULL && !S_ISREG (mode))
|
|
||||||
{
|
|
||||||
uid = g_file_info_get_attribute_uint32 (finfo, "unix::uid");
|
|
||||||
gid = g_file_info_get_attribute_uint32 (finfo, "unix::gid");
|
|
||||||
|
|
||||||
if (lchown (dest_path, uid, gid) < 0)
|
|
||||||
{
|
|
||||||
ot_util_set_error_from_errno (error, errno);
|
|
||||||
g_prefix_error (error, "lchown(%u, %u) failed: ", uid, gid);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xattrs != NULL)
|
|
||||||
{
|
|
||||||
if (!ostree_set_xattrs (dest_file, xattrs, cancellable, error))
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = TRUE;
|
|
||||||
out:
|
|
||||||
if (!ret && !S_ISDIR(mode))
|
|
||||||
{
|
|
||||||
(void) unlink (dest_path);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ostree_create_temp_file_from_input:
|
|
||||||
* @dir: Target directory
|
|
||||||
* @prefix: Optional prefix
|
|
||||||
* @suffix: Optional suffix
|
|
||||||
* @finfo: File information
|
|
||||||
* @xattrs: (allow-none): Optional extended attributes
|
|
||||||
* @input: (allow-none): Optional file content, must be %NULL for symbolic links
|
|
||||||
* @out_file: (out): Path for newly created directory, file, or symbolic link
|
|
||||||
* @cancellable: Cancellable
|
|
||||||
* @error: Error
|
|
||||||
*
|
|
||||||
* Like ostree_create_file_from_input(), but securely allocates a
|
|
||||||
* randomly-named target in @dir. This is a unified version of
|
|
||||||
* mkstemp()/mkdtemp() that also supports symbolic links.
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
ostree_create_temp_file_from_input (GFile *dir,
|
|
||||||
const char *prefix,
|
|
||||||
const char *suffix,
|
|
||||||
GFileInfo *finfo,
|
|
||||||
GVariant *xattrs,
|
|
||||||
GInputStream *input,
|
|
||||||
GFile **out_file,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
gboolean ret = FALSE;
|
|
||||||
GError *temp_error = NULL;
|
|
||||||
int i = 0;
|
|
||||||
gs_unref_object GFile *possible_file = NULL;
|
|
||||||
|
|
||||||
/* 128 attempts seems reasonable... */
|
|
||||||
for (i = 0; i < 128; i++)
|
|
||||||
{
|
|
||||||
gs_free char *possible_name = NULL;
|
|
||||||
|
|
||||||
if (g_cancellable_set_error_if_cancelled (cancellable, error))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
possible_name = gsystem_fileutil_gen_tmp_name (prefix, suffix);
|
|
||||||
g_clear_object (&possible_file);
|
|
||||||
possible_file = g_file_get_child (dir, possible_name);
|
|
||||||
|
|
||||||
if (!ostree_create_file_from_input (possible_file, finfo, xattrs, input,
|
|
||||||
cancellable, &temp_error))
|
|
||||||
{
|
|
||||||
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
|
|
||||||
{
|
|
||||||
g_clear_error (&temp_error);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_propagate_error (error, temp_error);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i >= 128)
|
|
||||||
{
|
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
||||||
"Exhausted 128 attempts to create a temporary file");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = TRUE;
|
|
||||||
ot_transfer_out_value(out_file, &possible_file);
|
|
||||||
out:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ostree_create_temp_dir:
|
* ostree_create_temp_dir:
|
||||||
* @dir: Use this as temporary base
|
* @dir: Use this as temporary base
|
||||||
|
|
|
||||||
|
|
@ -228,23 +228,6 @@ gboolean ostree_checksum_file_async_finish (GFile *f,
|
||||||
GVariant *ostree_create_directory_metadata (GFileInfo *dir_info,
|
GVariant *ostree_create_directory_metadata (GFileInfo *dir_info,
|
||||||
GVariant *xattrs);
|
GVariant *xattrs);
|
||||||
|
|
||||||
gboolean ostree_create_file_from_input (GFile *dest_file,
|
|
||||||
GFileInfo *finfo,
|
|
||||||
GVariant *xattrs,
|
|
||||||
GInputStream *input,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
gboolean ostree_create_temp_file_from_input (GFile *dir,
|
|
||||||
const char *prefix,
|
|
||||||
const char *suffix,
|
|
||||||
GFileInfo *finfo,
|
|
||||||
GVariant *xattrs,
|
|
||||||
GInputStream *input,
|
|
||||||
GFile **out_file,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
gboolean ostree_create_temp_dir (GFile *dir,
|
gboolean ostree_create_temp_dir (GFile *dir,
|
||||||
const char *prefix,
|
const char *prefix,
|
||||||
const char *suffix,
|
const char *suffix,
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,214 @@
|
||||||
#include "ostree-repo-file.h"
|
#include "ostree-repo-file.h"
|
||||||
#include "ostree-repo-private.h"
|
#include "ostree-repo-private.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* create_file_from_input:
|
||||||
|
* @dest_file: Destination; must not exist
|
||||||
|
* @finfo: File information
|
||||||
|
* @xattrs: (allow-none): Optional extended attributes
|
||||||
|
* @input: (allow-none): Optional file content, must be %NULL for symbolic links
|
||||||
|
* @cancellable: Cancellable
|
||||||
|
* @error: Error
|
||||||
|
*
|
||||||
|
* Create a directory, regular file, or symbolic link, based on
|
||||||
|
* @finfo. Append extended attributes from @xattrs if provided. For
|
||||||
|
* %G_FILE_TYPE_REGULAR, set content based on @input.
|
||||||
|
*/
|
||||||
|
static gboolean
|
||||||
|
create_file_from_input (GFile *dest_file,
|
||||||
|
GFileInfo *finfo,
|
||||||
|
GVariant *xattrs,
|
||||||
|
GInputStream *input,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
const char *dest_path;
|
||||||
|
guint32 uid, gid, mode;
|
||||||
|
gs_unref_object GOutputStream *out = NULL;
|
||||||
|
|
||||||
|
if (g_cancellable_set_error_if_cancelled (cancellable, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (finfo != NULL)
|
||||||
|
{
|
||||||
|
mode = g_file_info_get_attribute_uint32 (finfo, "unix::mode");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mode = S_IFREG | 0664;
|
||||||
|
}
|
||||||
|
dest_path = gs_file_get_path_cached (dest_file);
|
||||||
|
|
||||||
|
if (S_ISDIR (mode))
|
||||||
|
{
|
||||||
|
if (mkdir (gs_file_get_path_cached (dest_file), mode) < 0)
|
||||||
|
{
|
||||||
|
ot_util_set_error_from_errno (error, errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (S_ISREG (mode))
|
||||||
|
{
|
||||||
|
if (finfo != NULL)
|
||||||
|
{
|
||||||
|
uid = g_file_info_get_attribute_uint32 (finfo, "unix::uid");
|
||||||
|
gid = g_file_info_get_attribute_uint32 (finfo, "unix::gid");
|
||||||
|
|
||||||
|
if (!gs_file_create_with_uidgid (dest_file, mode, uid, gid, &out,
|
||||||
|
cancellable, error))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!gs_file_create (dest_file, mode, &out,
|
||||||
|
cancellable, error))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input)
|
||||||
|
{
|
||||||
|
if (g_output_stream_splice ((GOutputStream*)out, input, 0,
|
||||||
|
cancellable, error) < 0)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_output_stream_close ((GOutputStream*)out, NULL, error))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Work around libguestfs/FUSE bug */
|
||||||
|
if (mode & (S_ISUID|S_ISGID))
|
||||||
|
{
|
||||||
|
if (chmod (dest_path, mode) == -1)
|
||||||
|
{
|
||||||
|
ot_util_set_error_from_errno (error, errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (S_ISLNK (mode))
|
||||||
|
{
|
||||||
|
const char *target = g_file_info_get_attribute_byte_string (finfo, "standard::symlink-target");
|
||||||
|
if (symlink (target, dest_path) < 0)
|
||||||
|
{
|
||||||
|
ot_util_set_error_from_errno (error, errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"Invalid mode %u", mode);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We only need to chown for directories and symlinks; we already
|
||||||
|
* did a chown for files above via fchown().
|
||||||
|
*/
|
||||||
|
if (finfo != NULL && !S_ISREG (mode))
|
||||||
|
{
|
||||||
|
uid = g_file_info_get_attribute_uint32 (finfo, "unix::uid");
|
||||||
|
gid = g_file_info_get_attribute_uint32 (finfo, "unix::gid");
|
||||||
|
|
||||||
|
if (lchown (dest_path, uid, gid) < 0)
|
||||||
|
{
|
||||||
|
ot_util_set_error_from_errno (error, errno);
|
||||||
|
g_prefix_error (error, "lchown(%u, %u) failed: ", uid, gid);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xattrs != NULL)
|
||||||
|
{
|
||||||
|
if (!ostree_set_xattrs (dest_file, xattrs, cancellable, error))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
out:
|
||||||
|
if (!ret && !S_ISDIR(mode))
|
||||||
|
{
|
||||||
|
(void) unlink (dest_path);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* create_temp_file_from_input:
|
||||||
|
* @dir: Target directory
|
||||||
|
* @prefix: Optional prefix
|
||||||
|
* @suffix: Optional suffix
|
||||||
|
* @finfo: File information
|
||||||
|
* @xattrs: (allow-none): Optional extended attributes
|
||||||
|
* @input: (allow-none): Optional file content, must be %NULL for symbolic links
|
||||||
|
* @out_file: (out): Path for newly created directory, file, or symbolic link
|
||||||
|
* @cancellable: Cancellable
|
||||||
|
* @error: Error
|
||||||
|
*
|
||||||
|
* Like create_file_from_input(), but securely allocates a
|
||||||
|
* randomly-named target in @dir. This is a unified version of
|
||||||
|
* mkstemp()/mkdtemp() that also supports symbolic links.
|
||||||
|
*/
|
||||||
|
static gboolean
|
||||||
|
create_temp_file_from_input (GFile *dir,
|
||||||
|
const char *prefix,
|
||||||
|
const char *suffix,
|
||||||
|
GFileInfo *finfo,
|
||||||
|
GVariant *xattrs,
|
||||||
|
GInputStream *input,
|
||||||
|
GFile **out_file,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
GError *temp_error = NULL;
|
||||||
|
int i = 0;
|
||||||
|
gs_unref_object GFile *possible_file = NULL;
|
||||||
|
|
||||||
|
/* 128 attempts seems reasonable... */
|
||||||
|
for (i = 0; i < 128; i++)
|
||||||
|
{
|
||||||
|
gs_free char *possible_name = NULL;
|
||||||
|
|
||||||
|
if (g_cancellable_set_error_if_cancelled (cancellable, error))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
possible_name = gsystem_fileutil_gen_tmp_name (prefix, suffix);
|
||||||
|
g_clear_object (&possible_file);
|
||||||
|
possible_file = g_file_get_child (dir, possible_name);
|
||||||
|
|
||||||
|
if (!create_file_from_input (possible_file, finfo, xattrs, input,
|
||||||
|
cancellable, &temp_error))
|
||||||
|
{
|
||||||
|
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
|
||||||
|
{
|
||||||
|
g_clear_error (&temp_error);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_propagate_error (error, temp_error);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i >= 128)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"Exhausted 128 attempts to create a temporary file");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
ot_transfer_out_value(out_file, &possible_file);
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
checkout_file_from_input (GFile *file,
|
checkout_file_from_input (GFile *file,
|
||||||
OstreeRepoCheckoutMode mode,
|
OstreeRepoCheckoutMode mode,
|
||||||
|
|
@ -60,7 +268,7 @@ checkout_file_from_input (GFile *file,
|
||||||
{
|
{
|
||||||
if (g_file_info_get_file_type (temp_info) == G_FILE_TYPE_DIRECTORY)
|
if (g_file_info_get_file_type (temp_info) == G_FILE_TYPE_DIRECTORY)
|
||||||
{
|
{
|
||||||
if (!ostree_create_file_from_input (file, temp_info,
|
if (!create_file_from_input (file, temp_info,
|
||||||
xattrs, input,
|
xattrs, input,
|
||||||
cancellable, &temp_error))
|
cancellable, &temp_error))
|
||||||
{
|
{
|
||||||
|
|
@ -78,7 +286,7 @@ checkout_file_from_input (GFile *file,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dir = g_file_get_parent (file);
|
dir = g_file_get_parent (file);
|
||||||
if (!ostree_create_temp_file_from_input (dir, NULL, "checkout",
|
if (!create_temp_file_from_input (dir, NULL, "checkout",
|
||||||
temp_info, xattrs, input, &temp_file,
|
temp_info, xattrs, input, &temp_file,
|
||||||
cancellable, error))
|
cancellable, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
@ -98,7 +306,7 @@ checkout_file_from_input (GFile *file,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!ostree_create_file_from_input (file, temp_info,
|
if (!create_file_from_input (file, temp_info,
|
||||||
xattrs, input, cancellable, error))
|
xattrs, input, cancellable, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue