[ostree] core: Further unify API to create files
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree] core: Further unify API to create files
- Date: Fri, 2 Dec 2011 19:36:24 +0000 (UTC)
commit d1950da1a04f7f501bc9a3432f8732d681b858e5
Author: Colin Walters <walters verbum org>
Date: Fri Dec 2 11:22:32 2011 -0500
core: Further unify API to create files
We now have just one place which writes to the filesystem. Wrap a
temporary file allocation API on top of that.
src/libostree/ostree-core.c | 210 +++++++++++++++++++++++++++++++++++++++--
src/libostree/ostree-core.h | 21 ++++
src/libostree/ostree-repo.c | 12 +--
src/libotutil/ot-gio-utils.c | 129 --------------------------
src/libotutil/ot-gio-utils.h | 18 ----
5 files changed, 224 insertions(+), 166 deletions(-)
---
diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c
index da84fec..8e6b854 100644
--- a/src/libostree/ostree-core.c
+++ b/src/libostree/ostree-core.c
@@ -881,6 +881,7 @@ ostree_create_file_from_input (GFile *dest_file,
GFileInfo *finfo,
GVariant *xattrs,
GInputStream *input,
+ OstreeObjectType objtype,
GChecksum **out_checksum,
GCancellable *cancellable,
GError **error)
@@ -891,14 +892,22 @@ ostree_create_file_from_input (GFile *dest_file,
guint32 uid, gid, mode;
GChecksum *ret_checksum = NULL;
- uid = g_file_info_get_attribute_uint32 (finfo, "unix::uid");
- gid = g_file_info_get_attribute_uint32 (finfo, "unix::gid");
- mode = g_file_info_get_attribute_uint32 (finfo, "unix::mode");
+ 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 | 0666;
+ }
dest_path = ot_gfile_get_path_cached (dest_file);
if (S_ISREG (mode))
{
- out = g_file_replace (dest_file, NULL, FALSE, 0, NULL, error);
+ out = g_file_create (dest_file, 0, cancellable, error);
if (!out)
goto out;
@@ -913,6 +922,7 @@ ostree_create_file_from_input (GFile *dest_file,
else if (S_ISLNK (mode))
{
const char *target = g_file_info_get_attribute_byte_string (finfo, "standard::symlink-target");
+ g_assert (objtype == OSTREE_OBJECT_TYPE_FILE);
if (ret_checksum)
g_checksum_update (ret_checksum, (guint8*)target, strlen (target));
if (symlink (target, dest_path) < 0)
@@ -924,6 +934,7 @@ ostree_create_file_from_input (GFile *dest_file,
else if (S_ISCHR (mode) || S_ISBLK (mode))
{
guint32 dev = g_file_info_get_attribute_uint32 (finfo, "unix::rdev");
+ g_assert (objtype == OSTREE_OBJECT_TYPE_FILE);
if (ret_checksum)
g_checksum_update (ret_checksum, (guint8*)&dev, 4);
if (mknod (dest_path, mode, dev) < 0)
@@ -934,6 +945,7 @@ ostree_create_file_from_input (GFile *dest_file,
}
else if (S_ISFIFO (mode))
{
+ g_assert (objtype == OSTREE_OBJECT_TYPE_FILE);
if (mkfifo (dest_path, mode) < 0)
{
ot_util_set_error_from_errno (error, errno);
@@ -947,10 +959,21 @@ ostree_create_file_from_input (GFile *dest_file,
goto out;
}
- if (lchown (dest_path, uid, gid) < 0)
+ if (finfo != NULL)
{
- ot_util_set_error_from_errno (error, errno);
- goto out;
+ 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);
+ goto out;
+ }
+ }
+ else
+ {
+ uid = geteuid ();
+ gid = getegid ();
}
if (!S_ISLNK (mode))
@@ -962,13 +985,18 @@ ostree_create_file_from_input (GFile *dest_file,
}
}
- if (!ostree_set_xattrs (dest_file, xattrs, cancellable, error))
- goto out;
+ if (xattrs != NULL)
+ {
+ g_assert (objtype == OSTREE_OBJECT_TYPE_FILE);
+ if (!ostree_set_xattrs (dest_file, xattrs, cancellable, error))
+ goto out;
+ }
- if (ret_checksum)
+ if (ret_checksum && objtype == OSTREE_OBJECT_TYPE_FILE)
{
ostree_checksum_update_stat (ret_checksum, uid, gid, mode);
- g_checksum_update (ret_checksum, (guint8*)g_variant_get_data (xattrs), g_variant_get_size (xattrs));
+ if (xattrs)
+ g_checksum_update (ret_checksum, (guint8*)g_variant_get_data (xattrs), g_variant_get_size (xattrs));
}
ret = TRUE;
@@ -985,6 +1013,165 @@ ostree_create_file_from_input (GFile *dest_file,
return ret;
}
+static GString *
+create_tmp_string (const char *dirpath,
+ const char *prefix,
+ const char *suffix)
+{
+ GString *tmp_name = NULL;
+
+ if (!prefix)
+ prefix = "tmp-";
+ if (!suffix)
+ suffix = ".tmp";
+
+ tmp_name = g_string_new (dirpath);
+ g_string_append_c (tmp_name, '/');
+ g_string_append (tmp_name, prefix);
+ g_string_append (tmp_name, "XXXXXX");
+ g_string_append (tmp_name, suffix);
+
+ return tmp_name;
+}
+
+static char *
+subst_xxxxxx (GRand *rand,
+ const char *string)
+{
+ static const char table[] = "ABCEDEFGHIJKLMNOPQRSTUVWXYZabcedefghijklmnopqrstuvwxyz0123456789";
+ char *ret = g_strdup (string);
+ guint8 *xxxxxx = (guint8*)strstr (ret, "XXXXXX");
+
+ g_assert (xxxxxx != NULL);
+
+ while (*xxxxxx == 'X')
+ {
+ int offset = g_random_int_range (0, sizeof (table));
+ *xxxxxx = (guint8)table[offset];
+ xxxxxx++;
+ }
+
+ return ret;
+}
+
+gboolean
+ostree_create_temp_file_from_input (GFile *dir,
+ const char *prefix,
+ const char *suffix,
+ GFileInfo *finfo,
+ GVariant *xattrs,
+ GInputStream *input,
+ OstreeObjectType objtype,
+ GFile **out_file,
+ GChecksum **out_checksum,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ GChecksum *ret_checksum = NULL;
+ GRand *rand = NULL;
+ GString *tmp_name = NULL;
+ char *possible_name = NULL;
+ GFile *possible_file = NULL;
+ GError *temp_error = NULL;
+ int i = 0;
+
+ rand = g_rand_new ();
+
+ tmp_name = create_tmp_string (ot_gfile_get_path_cached (dir),
+ prefix, suffix);
+
+ /* 128 attempts seems reasonable... */
+ for (i = 0; i < 128; i++)
+ {
+ g_free (possible_name);
+ possible_name = subst_xxxxxx (rand, tmp_name->str);
+ g_clear_object (&possible_file);
+ possible_file = ot_gfile_new_for_path (possible_name);
+
+ if (!ostree_create_file_from_input (possible_file, finfo, xattrs, input,
+ objtype,
+ out_checksum ? &ret_checksum : NULL,
+ 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;
+ if (out_checksum)
+ {
+ *out_checksum = ret_checksum;
+ ret_checksum = NULL;
+ }
+ if (out_file)
+ {
+ *out_file = possible_file;
+ possible_file = NULL;
+ }
+ out:
+ if (rand)
+ g_rand_free (rand);
+ if (tmp_name)
+ g_string_free (tmp_name, TRUE);
+ g_free (possible_name);
+ g_clear_object (&possible_file);
+ ot_clear_checksum (&ret_checksum);
+ return ret;
+}
+
+gboolean
+ostree_create_temp_regular_file (GFile *dir,
+ const char *prefix,
+ const char *suffix,
+ GFile **out_file,
+ GOutputStream **out_stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ GFile *ret_file = NULL;
+ GOutputStream *ret_stream = NULL;
+
+ if (!ostree_create_temp_file_from_input (dir, prefix, suffix, NULL, NULL, NULL,
+ OSTREE_OBJECT_TYPE_FILE, &ret_file,
+ NULL, cancellable, error))
+ goto out;
+
+ ret_stream = (GOutputStream*)g_file_append_to (ret_file, 0, cancellable, error);
+ if (ret_stream == NULL)
+ goto out;
+
+ ret = TRUE;
+ *out_file = ret_file;
+ ret_file = NULL;
+ *out_stream = ret_stream;
+ ret_stream = NULL;
+ out:
+ g_clear_object (&ret_file);
+ g_clear_object (&ret_stream);
+ return ret;
+}
+
static gboolean
unpack_file (GFile *file,
GFile *dest_file,
@@ -1003,6 +1190,7 @@ unpack_file (GFile *file,
goto out;
if (!ostree_create_file_from_input (dest_file, finfo, xattrs, in,
+ OSTREE_OBJECT_TYPE_FILE,
out_checksum ? &ret_checksum : NULL,
cancellable, error))
goto out;
diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h
index 64bfca7..454889f 100644
--- a/src/libostree/ostree-core.h
+++ b/src/libostree/ostree-core.h
@@ -166,10 +166,31 @@ gboolean ostree_create_file_from_input (GFile *file,
GFileInfo *finfo,
GVariant *xattrs,
GInputStream *input,
+ OstreeObjectType objtype,
GChecksum **out_checksum,
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,
+ OstreeObjectType objtype,
+ GFile **out_file,
+ GChecksum **out_checksum,
+ GCancellable *cancellable,
+ GError **error);
+
+gboolean ostree_create_temp_regular_file (GFile *dir,
+ const char *prefix,
+ const char *suffix,
+ GFile **out_file,
+ GOutputStream **out_stream,
+ GCancellable *cancellable,
+ GError **error);
+
gboolean ostree_parse_packed_file (GFile *file,
GFileInfo **out_file_info,
GVariant **out_xattrs,
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index e4a6c92..0beef27 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -592,14 +592,10 @@ stage_and_checksum (OstreeRepo *self,
break;
}
- if (!ot_gfile_create_tmp (priv->tmp_dir, prefix, NULL, 0666,
- &tmp_f, &stream, cancellable, error))
- goto out;
-
- if (!ot_gio_splice_and_checksum (stream, input, &ret_checksum, cancellable, error))
- goto out;
-
- if (!g_output_stream_close ((GOutputStream*)stream, NULL, error))
+ if (!ostree_create_temp_file_from_input (priv->tmp_dir, prefix, NULL, NULL,
+ NULL, input, OSTREE_OBJECT_TYPE_META,
+ &tmp_f, &ret_checksum,
+ cancellable, error))
goto out;
ret_tmpname = g_file_get_child (priv->tmp_dir, g_checksum_get_string (ret_checksum));
diff --git a/src/libotutil/ot-gio-utils.c b/src/libotutil/ot-gio-utils.c
index 0e8f4c2..ed730e7 100644
--- a/src/libotutil/ot-gio-utils.c
+++ b/src/libotutil/ot-gio-utils.c
@@ -196,135 +196,6 @@ ot_gio_splice_and_checksum (GOutputStream *out,
return ret;
}
-static GString *
-create_tmp_string (const char *dirpath,
- const char *prefix,
- const char *suffix)
-{
- GString *tmp_name = NULL;
-
- if (!prefix)
- prefix = "tmp-";
- if (!suffix)
- suffix = ".tmp";
-
- tmp_name = g_string_new (dirpath);
- g_string_append_c (tmp_name, '/');
- g_string_append (tmp_name, prefix);
- g_string_append (tmp_name, "XXXXXX");
- g_string_append (tmp_name, suffix);
-
- return tmp_name;
-}
-
-gboolean
-ot_gfile_create_tmp (GFile *dir,
- const char *prefix,
- const char *suffix,
- int mode,
- GFile **out_file,
- GOutputStream **out_stream,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- GString *tmp_name = NULL;
- int tmpfd = -1;
- GFile *ret_file = NULL;
- GOutputStream *ret_stream = NULL;
-
- if (g_cancellable_set_error_if_cancelled (cancellable, error))
- return FALSE;
-
- tmp_name = create_tmp_string (ot_gfile_get_path_cached (dir), prefix, suffix);
-
- tmpfd = g_mkstemp_full (tmp_name->str, O_WRONLY | O_BINARY, mode);
- if (tmpfd == -1)
- {
- ot_util_set_error_from_errno (error, errno);
- goto out;
- }
-
- ret_file = ot_gfile_new_for_path (tmp_name->str);
- ret_stream = g_unix_output_stream_new (tmpfd, TRUE);
-
- ret = TRUE;
- if (out_file)
- {
- *out_file = ret_file;
- ret_file = NULL;
- }
- if (out_stream)
- {
- *out_stream = ret_stream;
- ret_stream = NULL;
- }
- out:
- g_clear_object (&ret_file);
- g_clear_object (&ret_stream);
- g_string_free (tmp_name, TRUE);
- return ret;
-}
-
-static char *
-subst_xxxxxx (GRand *rand,
- const char *string)
-{
- char *ret = g_strdup (string);
- guint8 *xxxxxx = (guint8*)strstr (ret, "XXXXXX");
-
- g_assert (xxxxxx != NULL);
-
- while (*xxxxxx == 'X')
- {
- *xxxxxx = (guint8)g_random_int_range (0, 255);
- xxxxxx++;
- }
-
- return ret;
-}
-
-gboolean
-ot_gfile_create_tmp_symlink (const char *target,
- GFile *dir,
- const char *prefix,
- const char *suffix,
- GFile **out_file,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- GRand *rand = NULL;
- GString *tmp_name = NULL;
- char *possible_name = NULL;
-
- rand = g_rand_new ();
-
- tmp_name = create_tmp_string (ot_gfile_get_path_cached (dir),
- prefix, suffix);
-
- while (TRUE)
- {
- g_free (possible_name);
- possible_name = subst_xxxxxx (rand, tmp_name->str);
- if (symlink (target, possible_name) < 0)
- {
- if (errno == EEXIST)
- continue;
- ot_util_set_error_from_errno (error, errno);
- goto out;
- }
- }
-
- *out_file = ot_gfile_new_for_path (possible_name);
- out:
- g_string_free (tmp_name, TRUE);
- g_free (possible_name);
- if (rand)
- g_rand_free (rand);
- return ret;
-}
-
gboolean
ot_gfile_merge_dirs (GFile *destination,
GFile *src,
diff --git a/src/libotutil/ot-gio-utils.h b/src/libotutil/ot-gio-utils.h
index de131df..a8cc080 100644
--- a/src/libotutil/ot-gio-utils.h
+++ b/src/libotutil/ot-gio-utils.h
@@ -51,24 +51,6 @@ gboolean ot_gio_splice_and_checksum (GOutputStream *out,
GCancellable *cancellable,
GError **error);
-
-gboolean ot_gfile_create_tmp (GFile *dir,
- const char *prefix,
- const char *suffix,
- int mode,
- GFile **out_file,
- GOutputStream **out_stream,
- GCancellable *cancellable,
- GError **error);
-
-gboolean ot_gfile_create_tmp_symlink (const char *target,
- GFile *dir,
- const char *prefix,
- const char *suffix,
- GFile **out_file,
- GCancellable *cancellable,
- GError **error);
-
gboolean ot_gfile_merge_dirs (GFile *destination,
GFile *src,
GCancellable *cancellable,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]