New upstream version 2017.4
This commit is contained in:
commit
0b7290b235
168 files changed
+3573
-2254
No files matched your search
@@ -381,16 +381,25 @@ global:
|
||||
ostree_raw_file_to_archive_z2_stream_with_options;
|
||||
} LIBOSTREE_2017.2;
|
||||
|
||||
LIBOSTREE_2017.4 {
|
||||
global:
|
||||
ostree_check_version;
|
||||
ostree_diff_dirs_with_options;
|
||||
ostree_sepolicy_new_at;
|
||||
ostree_sysroot_write_deployments_with_options;
|
||||
} LIBOSTREE_2017.3;
|
||||
|
||||
/* NOTE NOTE NOTE
|
||||
* Versions above here are released. Only add symbols below this line.
|
||||
* NOTE NOTE NOTE
|
||||
*/
|
||||
|
||||
/* Stub section for new version, uncomment when the first symbol is added
|
||||
/* Uncomment when adding the first new symbol */
|
||||
/*
|
||||
LIBOSTREE_2017.$NEWVERSION {
|
||||
global:
|
||||
someostree_symbol_deleteme;
|
||||
} LIBOSTREE_2017.2;
|
||||
} LIBOSTREE_2017.4;
|
||||
*/
|
||||
|
||||
/* Stub section for the stable release *after* this development one; don't
|
||||
|
||||
@@ -26,14 +26,10 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifndef OSTREE_WITH_AUTOCLEANUPS
|
||||
#define OSTREE_WITH_AUTOCLEANUPS 0
|
||||
#endif
|
||||
|
||||
/* ostree can use g_autoptr backports from libglnx when glib is too
|
||||
* old, but still avoid exposing them to users that also have an old
|
||||
* glib */
|
||||
#if defined(OSTREE_COMPILATION) || (OSTREE_WITH_AUTOCLEANUPS && GLIB_CHECK_VERSION(2, 44, 0))
|
||||
#if defined(OSTREE_COMPILATION) || GLIB_CHECK_VERSION(2, 44, 0)
|
||||
|
||||
/*
|
||||
* The following types have no specific clear/free/unref functions, so
|
||||
|
||||
@@ -353,7 +353,7 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader,
|
||||
use_system_grub2_mkconfig = FALSE;
|
||||
}
|
||||
else
|
||||
grub_exec = use_system_grub2_mkconfig ? GRUB2_MKCONFIG_PATH : "/usr/lib/ostree/ostree-grub-generator";
|
||||
grub_exec = use_system_grub2_mkconfig ? GRUB2_MKCONFIG_PATH : TARGET_PREFIX "/lib/ostree/ostree-grub-generator";
|
||||
|
||||
if (use_system_grub2_mkconfig && ostree_sysroot_get_booted_deployment (self->sysroot) == NULL
|
||||
&& g_file_has_parent (self->sysroot->path, NULL))
|
||||
|
||||
@@ -139,6 +139,15 @@ _ostree_loose_path (char *buf,
|
||||
#define _OSTREE_METADATA_GPGSIGS_NAME "ostree.gpgsigs"
|
||||
#define _OSTREE_METADATA_GPGSIGS_TYPE G_VARIANT_TYPE ("aay")
|
||||
|
||||
static inline gboolean
|
||||
_ostree_repo_mode_is_bare (OstreeRepoMode mode)
|
||||
{
|
||||
return
|
||||
mode == OSTREE_REPO_MODE_BARE ||
|
||||
mode == OSTREE_REPO_MODE_BARE_USER ||
|
||||
mode == OSTREE_REPO_MODE_BARE_USER_ONLY;
|
||||
}
|
||||
|
||||
GVariant *
|
||||
_ostree_detached_metadata_append_gpg_sig (GVariant *existing_metadata,
|
||||
GBytes *signature_bytes);
|
||||
|
||||
+56
-117
@@ -121,13 +121,8 @@ ostree_parse_refspec (const char *refspec,
|
||||
char **out_ref,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GMatchInfo *match = NULL;
|
||||
g_autofree char *remote = NULL;
|
||||
|
||||
static gsize regex_initialized;
|
||||
static GRegex *regex;
|
||||
|
||||
static gsize regex_initialized;
|
||||
if (g_once_init_enter (®ex_initialized))
|
||||
{
|
||||
regex = g_regex_new ("^(" OSTREE_REF_FRAGMENT_REGEXP ":)?(" OSTREE_REF_REGEXP ")$", 0, 0, NULL);
|
||||
@@ -135,14 +130,11 @@ ostree_parse_refspec (const char *refspec,
|
||||
g_once_init_leave (®ex_initialized, 1);
|
||||
}
|
||||
|
||||
g_autoptr(GMatchInfo) match = NULL;
|
||||
if (!g_regex_match (regex, refspec, 0, &match))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Invalid refspec %s", refspec);
|
||||
goto out;
|
||||
}
|
||||
return glnx_throw (error, "Invalid refspec %s", refspec);
|
||||
|
||||
remote = g_match_info_fetch (match, 1);
|
||||
g_autofree char *remote = g_match_info_fetch (match, 1);
|
||||
if (*remote == '\0')
|
||||
{
|
||||
g_clear_pointer (&remote, g_free);
|
||||
@@ -153,16 +145,11 @@ ostree_parse_refspec (const char *refspec,
|
||||
remote[strlen(remote)-1] = '\0';
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
if (out_remote)
|
||||
*out_remote = g_steal_pointer (&remote);
|
||||
if (out_ref != NULL)
|
||||
*out_ref = g_match_info_fetch (match, 2);
|
||||
out:
|
||||
if (match)
|
||||
g_match_info_unref (match);
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,12 +163,10 @@ gboolean
|
||||
ostree_validate_rev (const char *rev,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GMatchInfo *match = NULL;
|
||||
g_autoptr(GMatchInfo) match = NULL;
|
||||
|
||||
static gsize regex_initialized;
|
||||
static GRegex *regex;
|
||||
|
||||
if (g_once_init_enter (®ex_initialized))
|
||||
{
|
||||
regex = g_regex_new ("^" OSTREE_REF_REGEXP "$", 0, 0, NULL);
|
||||
@@ -190,17 +175,9 @@ ostree_validate_rev (const char *rev,
|
||||
}
|
||||
|
||||
if (!g_regex_match (regex, rev, 0, &match))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Invalid ref name %s", rev);
|
||||
goto out;
|
||||
}
|
||||
return glnx_throw (error, "Invalid ref name %s", rev);
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (match)
|
||||
g_match_info_unref (match);
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GVariant *
|
||||
@@ -282,7 +259,6 @@ write_padding (GOutputStream *output,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
guint bits;
|
||||
guint padding_len;
|
||||
guchar padding_nuls[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
@@ -298,12 +274,10 @@ write_padding (GOutputStream *output,
|
||||
if (!ot_gio_write_update_checksum (output, (guchar*)padding_nuls, padding_len,
|
||||
out_bytes_written, checksum,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -330,7 +304,6 @@ _ostree_write_variant_with_size (GOutputStream *output,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
guint64 variant_size;
|
||||
guint32 variant_size_u32_be;
|
||||
gsize bytes_written;
|
||||
@@ -345,7 +318,7 @@ _ostree_write_variant_with_size (GOutputStream *output,
|
||||
if (!ot_gio_write_update_checksum (output, &variant_size_u32_be, 4,
|
||||
&bytes_written, checksum,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
ret_bytes_written += bytes_written;
|
||||
alignment_offset += bytes_written;
|
||||
|
||||
@@ -353,21 +326,19 @@ _ostree_write_variant_with_size (GOutputStream *output,
|
||||
/* Pad to offset of 8, write variant */
|
||||
if (!write_padding (output, 8, alignment_offset, &bytes_written, checksum,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
ret_bytes_written += bytes_written;
|
||||
|
||||
bytes_written = 0;
|
||||
if (!ot_gio_write_update_checksum (output, g_variant_get_data (variant),
|
||||
variant_size, &bytes_written, checksum,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
ret_bytes_written += bytes_written;
|
||||
|
||||
ret = TRUE;
|
||||
if (out_bytes_written)
|
||||
*out_bytes_written = ret_bytes_written;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -388,16 +359,13 @@ write_file_header_update_checksum (GOutputStream *out,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
gsize bytes_written;
|
||||
|
||||
if (!_ostree_write_variant_with_size (out, header, 0, &bytes_written, checksum,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -724,32 +692,28 @@ ostree_content_file_parse_at (gboolean compressed,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
struct stat stbuf;
|
||||
g_autoptr(GInputStream) file_input = NULL;
|
||||
g_autoptr(GInputStream) ret_input = NULL;
|
||||
g_autoptr(GFileInfo) ret_file_info = NULL;
|
||||
g_autoptr(GVariant) ret_xattrs = NULL;
|
||||
|
||||
if (!ot_openat_read_stream (parent_dfd, path, TRUE, &file_input,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
return FALSE;
|
||||
|
||||
struct stat stbuf;
|
||||
if (!glnx_stream_fstat ((GFileDescriptorBased*)file_input, &stbuf, error))
|
||||
goto out;
|
||||
|
||||
return FALSE;
|
||||
|
||||
g_autoptr(GFileInfo) ret_file_info = NULL;
|
||||
g_autoptr(GVariant) ret_xattrs = NULL;
|
||||
g_autoptr(GInputStream) ret_input = NULL;
|
||||
if (!ostree_content_stream_parse (compressed, file_input, stbuf.st_size, trusted,
|
||||
out_input ? &ret_input : NULL,
|
||||
&ret_file_info, &ret_xattrs,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
ret = TRUE;
|
||||
return FALSE;
|
||||
|
||||
ot_transfer_out_value (out_input, &ret_input);
|
||||
ot_transfer_out_value (out_file_info, &ret_file_info);
|
||||
ot_transfer_out_value (out_xattrs, &ret_xattrs);
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -804,23 +768,19 @@ ostree_checksum_file_from_input (GFileInfo *file_info,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autofree guchar *ret_csum = NULL;
|
||||
GChecksum *checksum = NULL;
|
||||
|
||||
checksum = g_checksum_new (G_CHECKSUM_SHA256);
|
||||
g_autoptr(GChecksum) checksum = g_checksum_new (G_CHECKSUM_SHA256);
|
||||
|
||||
if (OSTREE_OBJECT_TYPE_IS_META (objtype))
|
||||
{
|
||||
if (!ot_gio_splice_update_checksum (NULL, in, checksum, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
|
||||
{
|
||||
g_autoptr(GVariant) dirmeta = ostree_create_directory_metadata (file_info, xattrs);
|
||||
g_checksum_update (checksum, g_variant_get_data (dirmeta),
|
||||
g_variant_get_size (dirmeta));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -830,22 +790,17 @@ ostree_checksum_file_from_input (GFileInfo *file_info,
|
||||
|
||||
if (!write_file_header_update_checksum (NULL, file_header, checksum,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
|
||||
{
|
||||
if (!ot_gio_splice_update_checksum (NULL, in, checksum, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
ret_csum = ot_csum_from_gchecksum (checksum);
|
||||
|
||||
ret = TRUE;
|
||||
ot_transfer_out_value (out_csum, &ret_csum);
|
||||
out:
|
||||
g_clear_pointer (&checksum, (GDestroyNotify)g_checksum_free);
|
||||
return ret;
|
||||
*out_csum = ot_csum_from_gchecksum (checksum);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1042,10 +997,9 @@ _ostree_make_temporary_symlink_at (int tmp_dirfd,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
char *tmpname = g_strdup ("tmplink.XXXXXX");
|
||||
guint i;
|
||||
g_autofree char *tmpname = g_strdup ("tmplink.XXXXXX");
|
||||
const int max_attempts = 128;
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < max_attempts; i++)
|
||||
{
|
||||
@@ -1055,28 +1009,17 @@ _ostree_make_temporary_symlink_at (int tmp_dirfd,
|
||||
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;
|
||||
}
|
||||
return glnx_throw_errno (error);
|
||||
}
|
||||
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;
|
||||
}
|
||||
return glnx_throw (error, "Exhausted attempts to open temporary file");
|
||||
|
||||
ret = TRUE;
|
||||
if (out_name)
|
||||
*out_name = g_steal_pointer (&tmpname);
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -1351,16 +1294,7 @@ void
|
||||
ostree_checksum_inplace_from_bytes (const guchar *csum,
|
||||
char *buf)
|
||||
{
|
||||
static const gchar hexchars[] = "0123456789abcdef";
|
||||
guint i, j;
|
||||
|
||||
for (i = 0, j = 0; i < OSTREE_SHA256_DIGEST_LEN; i++, j += 2)
|
||||
{
|
||||
guchar byte = csum[i];
|
||||
buf[j] = hexchars[byte >> 4];
|
||||
buf[j+1] = hexchars[byte & 0xF];
|
||||
}
|
||||
buf[j] = '\0';
|
||||
ot_bin2hex (buf, csum, OSTREE_SHA256_DIGEST_LEN);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1807,13 +1741,9 @@ ostree_validate_structureof_objtype (guchar objtype,
|
||||
GError **error)
|
||||
{
|
||||
OstreeObjectType objtype_v = (OstreeObjectType) objtype;
|
||||
if (objtype_v < OSTREE_OBJECT_TYPE_FILE
|
||||
if (objtype_v < OSTREE_OBJECT_TYPE_FILE
|
||||
|| objtype_v > OSTREE_OBJECT_TYPE_COMMIT)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Invalid object type '%u'", objtype);
|
||||
return FALSE;
|
||||
}
|
||||
return glnx_throw (error, "Invalid object type '%u'", objtype);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1846,11 +1776,7 @@ ostree_validate_structureof_checksum_string (const char *checksum,
|
||||
size_t len = strlen (checksum);
|
||||
|
||||
if (len != OSTREE_SHA256_STRING_LEN)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Invalid rev '%s'", checksum);
|
||||
return FALSE;
|
||||
}
|
||||
return glnx_throw (error, "Invalid rev '%s'", checksum);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
@@ -2153,3 +2079,16 @@ _ostree_get_default_sysroot_path (void)
|
||||
|
||||
return default_sysroot_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_check_version:
|
||||
* @required_year: Major/year required
|
||||
* @required_release: Release version required
|
||||
*
|
||||
* Returns: %TRUE if current libostree has at least the requested version, %FALSE otherwise
|
||||
*/
|
||||
gboolean
|
||||
ostree_check_version (guint required_year, guint required_release)
|
||||
{
|
||||
return OSTREE_CHECK_VERSION(required_year, required_release);
|
||||
}
|
||||
@@ -179,6 +179,7 @@ typedef enum {
|
||||
* @OSTREE_REPO_MODE_BARE: Files are stored as themselves; checkouts are hardlinks; can only be written as root
|
||||
* @OSTREE_REPO_MODE_ARCHIVE_Z2: Files are compressed, should be owned by non-root. Can be served via HTTP
|
||||
* @OSTREE_REPO_MODE_BARE_USER: Files are stored as themselves, except ownership; can be written by user. Hardlinks work only in user checkouts.
|
||||
* @OSTREE_REPO_MODE_BARE_USER_ONLY: Same as BARE_USER, but all metadata is not stored, so it can only be used for user checkouts. Does not need xattrs.
|
||||
*
|
||||
* See the documentation of #OstreeRepo for more information about the
|
||||
* possible modes.
|
||||
@@ -186,7 +187,8 @@ typedef enum {
|
||||
typedef enum {
|
||||
OSTREE_REPO_MODE_BARE,
|
||||
OSTREE_REPO_MODE_ARCHIVE_Z2,
|
||||
OSTREE_REPO_MODE_BARE_USER
|
||||
OSTREE_REPO_MODE_BARE_USER,
|
||||
OSTREE_REPO_MODE_BARE_USER_ONLY,
|
||||
} OstreeRepoMode;
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
@@ -399,4 +401,7 @@ gchar * ostree_commit_get_parent (GVariant *commit_variant);
|
||||
_OSTREE_PUBLIC
|
||||
guint64 ostree_commit_get_timestamp (GVariant *commit_variant);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
gboolean ostree_check_version (guint required_year, guint required_release);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "libglnx.h"
|
||||
#include "ostree.h"
|
||||
#include "ostree-repo-private.h"
|
||||
#include "otutil.h"
|
||||
|
||||
static gboolean
|
||||
@@ -225,6 +226,37 @@ ostree_diff_dirs (OstreeDiffFlags flags,
|
||||
GPtrArray *added,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
return ostree_diff_dirs_with_options (flags, a, b, modified,
|
||||
removed, added, NULL,
|
||||
cancellable, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_diff_dirs_with_options:
|
||||
* @flags: Flags
|
||||
* @a: First directory path, or %NULL
|
||||
* @b: First directory path
|
||||
* @modified: (element-type OstreeDiffItem): Modified files
|
||||
* @removed: (element-type Gio.File): Removed files
|
||||
* @added: (element-type Gio.File): Added files
|
||||
* @cancellable: Cancellable
|
||||
* @options: (allow-none): Options
|
||||
* @error: Error
|
||||
*
|
||||
* Compute the difference between directory @a and @b as 3 separate
|
||||
* sets of #OstreeDiffItem in @modified, @removed, and @added.
|
||||
*/
|
||||
gboolean
|
||||
ostree_diff_dirs_with_options (OstreeDiffFlags flags,
|
||||
GFile *a,
|
||||
GFile *b,
|
||||
GPtrArray *modified,
|
||||
GPtrArray *removed,
|
||||
GPtrArray *added,
|
||||
OstreeDiffDirsOptions *options,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GError *temp_error = NULL;
|
||||
@@ -233,6 +265,23 @@ ostree_diff_dirs (OstreeDiffFlags flags,
|
||||
g_autoptr(GFile) child_b = NULL;
|
||||
g_autoptr(GFileInfo) child_a_info = NULL;
|
||||
g_autoptr(GFileInfo) child_b_info = NULL;
|
||||
OstreeDiffDirsOptions default_opts = OSTREE_DIFF_DIRS_OPTIONS_INIT;
|
||||
|
||||
if (!options)
|
||||
options = &default_opts;
|
||||
|
||||
/* If we're diffing versus a repo, and either of them have xattrs disabled,
|
||||
* then disable for both.
|
||||
*/
|
||||
OstreeRepo *repo;
|
||||
if (OSTREE_IS_REPO_FILE (a))
|
||||
repo = ostree_repo_file_get_repo ((OstreeRepoFile*)a);
|
||||
else if (OSTREE_IS_REPO_FILE (b))
|
||||
repo = ostree_repo_file_get_repo ((OstreeRepoFile*)b);
|
||||
else
|
||||
repo = NULL;
|
||||
if (repo != NULL && repo->disable_xattrs)
|
||||
flags |= OSTREE_DIFF_FLAGS_IGNORE_XATTRS;
|
||||
|
||||
if (a == NULL)
|
||||
{
|
||||
@@ -316,6 +365,11 @@ ostree_diff_dirs (OstreeDiffFlags flags,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (options->owner_uid >= 0)
|
||||
g_file_info_set_attribute_uint32 (child_b_info, "unix::uid", options->owner_uid);
|
||||
if (options->owner_gid >= 0)
|
||||
g_file_info_set_attribute_uint32 (child_b_info, "unix::gid", options->owner_gid);
|
||||
|
||||
child_b_type = g_file_info_get_file_type (child_b_info);
|
||||
if (child_a_type != child_b_type)
|
||||
{
|
||||
@@ -337,8 +391,9 @@ ostree_diff_dirs (OstreeDiffFlags flags,
|
||||
|
||||
if (child_a_type == G_FILE_TYPE_DIRECTORY)
|
||||
{
|
||||
if (!ostree_diff_dirs (flags, child_a, child_b, modified,
|
||||
removed, added, cancellable, error))
|
||||
if (!ostree_diff_dirs_with_options (flags, child_a, child_b, modified,
|
||||
removed, added, options,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,42 @@ gboolean ostree_diff_dirs (OstreeDiffFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
/**
|
||||
* OstreeDiffDirsOptions:
|
||||
*
|
||||
* An extensible options structure controlling diff dirs. Make sure
|
||||
* that owner_uid/gid is set to -1 when not used. This is used by
|
||||
* ostree_diff_dirs_with_options().
|
||||
*/
|
||||
typedef struct {
|
||||
gint owner_uid;
|
||||
gint owner_gid;
|
||||
|
||||
OstreeRepoDevInoCache *devino_to_csum_cache;
|
||||
|
||||
gboolean unused_bools[7];
|
||||
int unused_ints[6];
|
||||
gpointer unused_ptrs[7];
|
||||
} OstreeDiffDirsOptions;
|
||||
|
||||
/**
|
||||
* OSTREE_DIFF_DIRS_OPTIONS_INIT:
|
||||
*
|
||||
* Use this to initialize an `OstreeDiffDirsOptions` structure.
|
||||
*/
|
||||
#define OSTREE_DIFF_DIRS_OPTIONS_INIT { .owner_uid = -1, .owner_gid = -1, }
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
gboolean ostree_diff_dirs_with_options (OstreeDiffFlags flags,
|
||||
GFile *a,
|
||||
GFile *b,
|
||||
GPtrArray *modified,
|
||||
GPtrArray *removed,
|
||||
GPtrArray *added,
|
||||
OstreeDiffDirsOptions *options,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
void ostree_diff_print (GFile *a,
|
||||
GFile *b,
|
||||
|
||||
@@ -36,6 +36,14 @@
|
||||
#define CURL_AT_LEAST_VERSION(x,y,z) (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
|
||||
#endif
|
||||
|
||||
/* Cargo culted from https://github.com/curl/curl/blob/curl-7_53_0/docs/examples/http2-download.c */
|
||||
#ifndef CURLPIPE_MULTIPLEX
|
||||
/* This little trick will just make sure that we don't enable pipelining for
|
||||
libcurls old enough to not have this symbol. It is _not_ defined to zero in
|
||||
a recent libcurl header. */
|
||||
#define CURLPIPE_MULTIPLEX 0
|
||||
#endif
|
||||
|
||||
#include "ostree-fetcher.h"
|
||||
#include "ostree-fetcher-util.h"
|
||||
#include "ostree-enumtypes.h"
|
||||
@@ -219,6 +227,12 @@ _ostree_fetcher_init (OstreeFetcher *self)
|
||||
#if CURL_AT_LEAST_VERSION(7, 30, 0)
|
||||
/* Let's do something reasonable here. */
|
||||
curl_multi_setopt (self->multi, CURLMOPT_MAX_TOTAL_CONNECTIONS, 8);
|
||||
#endif
|
||||
/* This version mirrors the version at which we're enabling HTTP2 support.
|
||||
* See also https://github.com/curl/curl/blob/curl-7_53_0/docs/examples/http2-download.c
|
||||
*/
|
||||
#if CURL_AT_LEAST_VERSION(7, 51, 0)
|
||||
curl_multi_setopt (self->multi, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -764,6 +778,11 @@ initiate_next_curl_request (FetcherRequest *req,
|
||||
*/
|
||||
#if CURL_AT_LEAST_VERSION(7, 51, 0)
|
||||
curl_easy_setopt (req->easy, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
|
||||
#endif
|
||||
/* https://github.com/curl/curl/blob/curl-7_53_0/docs/examples/http2-download.c */
|
||||
#if (CURLPIPE_MULTIPLEX > 0)
|
||||
/* wait for pipe connection to confirm */
|
||||
curl_easy_setopt (req->easy, CURLOPT_PIPEWAIT, 1L);
|
||||
#endif
|
||||
curl_easy_setopt (req->easy, CURLOPT_WRITEFUNCTION, write_cb);
|
||||
if (g_getenv ("OSTREE_DEBUG_HTTP"))
|
||||
|
||||
@@ -1040,21 +1040,21 @@ on_request_sent (GObject *object,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task = G_TASK (user_data);
|
||||
OstreeFetcherPendingURI *pending;
|
||||
GCancellable *cancellable;
|
||||
/* Hold a ref to the pending across this function, since we remove
|
||||
* it from the hash early in some cases, not in others. */
|
||||
OstreeFetcherPendingURI *pending = pending_uri_ref (g_task_get_task_data (task));
|
||||
GCancellable *cancellable = g_task_get_cancellable (task);
|
||||
GError *local_error = NULL;
|
||||
glnx_unref_object SoupMessage *msg = NULL;
|
||||
|
||||
pending = g_task_get_task_data (task);
|
||||
cancellable = g_task_get_cancellable (task);
|
||||
|
||||
pending->state = OSTREE_FETCHER_STATE_COMPLETE;
|
||||
pending->request_body = soup_request_send_finish ((SoupRequest*) object,
|
||||
result, &local_error);
|
||||
|
||||
if (!pending->request_body)
|
||||
goto out;
|
||||
|
||||
g_assert_no_error (local_error);
|
||||
|
||||
if (SOUP_IS_REQUEST_HTTP (object))
|
||||
{
|
||||
msg = soup_request_http_get_message ((SoupRequestHTTP*) object);
|
||||
@@ -1183,6 +1183,7 @@ on_request_sent (GObject *object,
|
||||
remove_pending (pending);
|
||||
}
|
||||
|
||||
pending_uri_unref (pending);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
|
||||
@@ -363,7 +363,7 @@ checkout_file_hardlink (OstreeRepo *self,
|
||||
GError **error)
|
||||
{
|
||||
HardlinkResult ret_result = HARDLINK_RESULT_NOT_SUPPORTED;
|
||||
int srcfd = (self->mode == OSTREE_REPO_MODE_BARE || self->mode == OSTREE_REPO_MODE_BARE_USER) ?
|
||||
int srcfd = _ostree_repo_mode_is_bare (self->mode) ?
|
||||
self->objects_dir_fd : self->uncompressed_objects_dir_fd;
|
||||
|
||||
again:
|
||||
@@ -423,6 +423,7 @@ checkout_one_file_at (OstreeRepo *repo,
|
||||
gboolean ret = FALSE;
|
||||
const char *checksum;
|
||||
gboolean is_symlink;
|
||||
gboolean is_bare_user_symlink = FALSE;
|
||||
gboolean can_cache;
|
||||
gboolean need_copy = TRUE;
|
||||
char loose_path_buf[_OSTREE_LOOSE_PATH_MAX];
|
||||
@@ -431,7 +432,6 @@ checkout_one_file_at (OstreeRepo *repo,
|
||||
gboolean is_whiteout;
|
||||
|
||||
is_symlink = g_file_info_get_file_type (source_info) == G_FILE_TYPE_SYMBOLIC_LINK;
|
||||
|
||||
checksum = ostree_repo_file_get_checksum ((OstreeRepoFile*)source);
|
||||
|
||||
is_whiteout = !is_symlink && options->process_whiteouts &&
|
||||
@@ -468,18 +468,42 @@ checkout_one_file_at (OstreeRepo *repo,
|
||||
|
||||
while (current_repo)
|
||||
{
|
||||
gboolean is_bare = ((current_repo->mode == OSTREE_REPO_MODE_BARE
|
||||
&& options->mode == OSTREE_REPO_CHECKOUT_MODE_NONE) ||
|
||||
(current_repo->mode == OSTREE_REPO_MODE_BARE_USER
|
||||
&& options->mode == OSTREE_REPO_CHECKOUT_MODE_USER
|
||||
/* NOTE: bare-user symlinks are not stored as symlinks */
|
||||
&& !is_symlink));
|
||||
/* TODO - Hoist this up to the toplevel at least for checking out from
|
||||
* !parent; don't need to compute it for each file.
|
||||
*/
|
||||
gboolean repo_is_usermode =
|
||||
current_repo->mode == OSTREE_REPO_MODE_BARE_USER ||
|
||||
current_repo->mode == OSTREE_REPO_MODE_BARE_USER_ONLY;
|
||||
/* We're hardlinkable if the checkout mode matches the repo mode */
|
||||
gboolean is_hardlinkable =
|
||||
(current_repo->mode == OSTREE_REPO_MODE_BARE
|
||||
&& options->mode == OSTREE_REPO_CHECKOUT_MODE_NONE) ||
|
||||
(repo_is_usermode && options->mode == OSTREE_REPO_CHECKOUT_MODE_USER);
|
||||
gboolean is_bare = is_hardlinkable && !is_bare_user_symlink;
|
||||
gboolean current_can_cache = (options->enable_uncompressed_cache
|
||||
&& current_repo->enable_uncompressed_cache);
|
||||
gboolean is_archive_z2_with_cache = (current_repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2
|
||||
&& options->mode == OSTREE_REPO_CHECKOUT_MODE_USER
|
||||
&& current_can_cache);
|
||||
|
||||
/* NOTE: bare-user symlinks are not stored as symlinks; see
|
||||
* https://github.com/ostreedev/ostree/commit/47c612e5a0688c3452a125655a245e8f4f01b2b0
|
||||
* as well as write_object().
|
||||
*/
|
||||
is_bare_user_symlink = (repo_is_usermode && is_symlink);
|
||||
|
||||
/* Verify if no_copy_fallback is set that we can hardlink, with a
|
||||
* special exception for bare-user symlinks.
|
||||
*/
|
||||
if (options->no_copy_fallback && !is_hardlinkable && !is_bare_user_symlink)
|
||||
{
|
||||
glnx_throw (error,
|
||||
repo_is_usermode ?
|
||||
"User repository mode requires user checkout mode to hardlink" :
|
||||
"Bare repository mode cannot hardlink in user checkout mode");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* But only under these conditions */
|
||||
if (is_bare || is_archive_z2_with_cache)
|
||||
{
|
||||
@@ -594,7 +618,13 @@ checkout_one_file_at (OstreeRepo *repo,
|
||||
/* Fall back to copy if we couldn't hardlink */
|
||||
if (need_copy)
|
||||
{
|
||||
g_assert (!options->no_copy_fallback);
|
||||
/* Bare user mode can't hardlink symlinks, so we need to do a copy for
|
||||
* those. (Although in the future we could hardlink inside checkouts) This
|
||||
* assertion is intended to ensure that for regular files at least, we
|
||||
* succeeded at hardlinking above.
|
||||
*/
|
||||
if (options->no_copy_fallback)
|
||||
g_assert (is_bare_user_symlink);
|
||||
if (!ostree_repo_load_file (repo, checksum, &input, NULL, &xattrs,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
@@ -862,6 +892,9 @@ ostree_repo_checkout_tree (OstreeRepo *self,
|
||||
{
|
||||
OstreeRepoCheckoutAtOptions options = { 0, };
|
||||
|
||||
if (ostree_repo_get_mode (self) == OSTREE_REPO_MODE_BARE_USER_ONLY)
|
||||
mode = OSTREE_REPO_CHECKOUT_MODE_USER;
|
||||
|
||||
options.mode = mode;
|
||||
options.overwrite_mode = overwrite_mode;
|
||||
/* Backwards compatibility */
|
||||
@@ -948,6 +981,7 @@ ostree_repo_checkout_at (OstreeRepo *self,
|
||||
GError **error)
|
||||
{
|
||||
OstreeRepoCheckoutAtOptions default_options = { 0, };
|
||||
OstreeRepoCheckoutAtOptions real_options;
|
||||
|
||||
if (!options)
|
||||
{
|
||||
@@ -955,6 +989,13 @@ ostree_repo_checkout_at (OstreeRepo *self,
|
||||
options = &default_options;
|
||||
}
|
||||
|
||||
/* Make a copy so we can modify the options */
|
||||
real_options = *options;
|
||||
options = &real_options;
|
||||
|
||||
if (ostree_repo_get_mode (self) == OSTREE_REPO_MODE_BARE_USER_ONLY)
|
||||
options->mode = OSTREE_REPO_CHECKOUT_MODE_USER;
|
||||
|
||||
g_autoptr(GFile) commit_root = (GFile*) _ostree_repo_file_new_for_commit (self, commit, error);
|
||||
if (!commit_root)
|
||||
return FALSE;
|
||||
|
||||
+187
-263
File diff suppressed because it is too large.
Load diff
@@ -100,6 +100,7 @@ struct OstreeRepo {
|
||||
GError *writable_error;
|
||||
gboolean in_transaction;
|
||||
gboolean disable_fsync;
|
||||
gboolean disable_xattrs;
|
||||
guint zlib_compression_level;
|
||||
GHashTable *loose_object_devino_hash;
|
||||
GHashTable *updated_uncompressed_dirs;
|
||||
|
||||
@@ -279,18 +279,21 @@ pull_termination_condition (OtPullData *pull_data)
|
||||
|
||||
static void
|
||||
check_outstanding_requests_handle_error (OtPullData *pull_data,
|
||||
GError *error)
|
||||
GError **errorp)
|
||||
{
|
||||
g_assert (errorp);
|
||||
|
||||
GError *error = *errorp;
|
||||
if (error)
|
||||
{
|
||||
if (!pull_data->caught_error)
|
||||
{
|
||||
pull_data->caught_error = TRUE;
|
||||
g_propagate_error (pull_data->async_error, error);
|
||||
g_propagate_error (pull_data->async_error, g_steal_pointer (errorp));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_error_free (error);
|
||||
g_clear_error (errorp);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -382,7 +385,7 @@ idle_worker (gpointer user_data)
|
||||
{
|
||||
OtPullData *pull_data = user_data;
|
||||
ScanObjectQueueData *scan_data;
|
||||
GError *error = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
scan_data = g_queue_pop_head (&pull_data->scan_object_queue);
|
||||
if (!scan_data)
|
||||
@@ -398,7 +401,7 @@ idle_worker (gpointer user_data)
|
||||
scan_data->recursion_depth,
|
||||
pull_data->cancellable,
|
||||
&error);
|
||||
check_outstanding_requests_handle_error (pull_data, error);
|
||||
check_outstanding_requests_handle_error (pull_data, &error);
|
||||
|
||||
g_free (scan_data->path);
|
||||
g_free (scan_data);
|
||||
@@ -760,7 +763,7 @@ content_fetch_on_write_complete (GObject *object,
|
||||
{
|
||||
FetchObjectData *fetch_data = user_data;
|
||||
OtPullData *pull_data = fetch_data->pull_data;
|
||||
GError *local_error = NULL;
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
GError **error = &local_error;
|
||||
OstreeObjectType objtype;
|
||||
const char *expected_checksum;
|
||||
@@ -794,7 +797,7 @@ content_fetch_on_write_complete (GObject *object,
|
||||
pull_data->n_fetched_deltapart_fallbacks++;
|
||||
out:
|
||||
pull_data->n_outstanding_content_write_requests--;
|
||||
check_outstanding_requests_handle_error (pull_data, local_error);
|
||||
check_outstanding_requests_handle_error (pull_data, &local_error);
|
||||
fetch_object_data_free (fetch_data);
|
||||
}
|
||||
|
||||
@@ -806,7 +809,7 @@ content_fetch_on_complete (GObject *object,
|
||||
OstreeFetcher *fetcher = (OstreeFetcher *)object;
|
||||
FetchObjectData *fetch_data = user_data;
|
||||
OtPullData *pull_data = fetch_data->pull_data;
|
||||
GError *local_error = NULL;
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
GError **error = &local_error;
|
||||
GCancellable *cancellable = NULL;
|
||||
guint64 length;
|
||||
@@ -881,7 +884,7 @@ content_fetch_on_complete (GObject *object,
|
||||
|
||||
out:
|
||||
pull_data->n_outstanding_content_fetches--;
|
||||
check_outstanding_requests_handle_error (pull_data, local_error);
|
||||
check_outstanding_requests_handle_error (pull_data, &local_error);
|
||||
if (free_fetch_data)
|
||||
fetch_object_data_free (fetch_data);
|
||||
}
|
||||
@@ -893,7 +896,7 @@ on_metadata_written (GObject *object,
|
||||
{
|
||||
FetchObjectData *fetch_data = user_data;
|
||||
OtPullData *pull_data = fetch_data->pull_data;
|
||||
GError *local_error = NULL;
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
GError **error = &local_error;
|
||||
const char *expected_checksum;
|
||||
OstreeObjectType objtype;
|
||||
@@ -927,7 +930,7 @@ on_metadata_written (GObject *object,
|
||||
pull_data->n_outstanding_metadata_write_requests--;
|
||||
fetch_object_data_free (fetch_data);
|
||||
|
||||
check_outstanding_requests_handle_error (pull_data, local_error);
|
||||
check_outstanding_requests_handle_error (pull_data, &local_error);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -943,7 +946,7 @@ meta_fetch_on_complete (GObject *object,
|
||||
const char *checksum;
|
||||
g_autofree char *checksum_obj = NULL;
|
||||
OstreeObjectType objtype;
|
||||
GError *local_error = NULL;
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
GError **error = &local_error;
|
||||
glnx_fd_close int fd = -1;
|
||||
gboolean free_fetch_data = TRUE;
|
||||
@@ -1038,7 +1041,7 @@ meta_fetch_on_complete (GObject *object,
|
||||
g_assert (pull_data->n_outstanding_metadata_fetches > 0);
|
||||
pull_data->n_outstanding_metadata_fetches--;
|
||||
pull_data->n_fetched_metadata++;
|
||||
check_outstanding_requests_handle_error (pull_data, local_error);
|
||||
check_outstanding_requests_handle_error (pull_data, &local_error);
|
||||
if (free_fetch_data)
|
||||
fetch_object_data_free (fetch_data);
|
||||
}
|
||||
@@ -1061,7 +1064,7 @@ on_static_delta_written (GObject *object,
|
||||
{
|
||||
FetchStaticDeltaData *fetch_data = user_data;
|
||||
OtPullData *pull_data = fetch_data->pull_data;
|
||||
GError *local_error = NULL;
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
GError **error = &local_error;
|
||||
|
||||
g_debug ("execute static delta part %s complete", fetch_data->expected_checksum);
|
||||
@@ -1072,7 +1075,7 @@ on_static_delta_written (GObject *object,
|
||||
out:
|
||||
g_assert (pull_data->n_outstanding_deltapart_write_requests > 0);
|
||||
pull_data->n_outstanding_deltapart_write_requests--;
|
||||
check_outstanding_requests_handle_error (pull_data, local_error);
|
||||
check_outstanding_requests_handle_error (pull_data, &local_error);
|
||||
/* Always free state */
|
||||
fetch_static_delta_data_free (fetch_data);
|
||||
}
|
||||
@@ -1088,7 +1091,7 @@ static_deltapart_fetch_on_complete (GObject *object,
|
||||
g_autofree char *temp_path = NULL;
|
||||
g_autoptr(GInputStream) in = NULL;
|
||||
g_autoptr(GVariant) part = NULL;
|
||||
GError *local_error = NULL;
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
GError **error = &local_error;
|
||||
glnx_fd_close int fd = -1;
|
||||
gboolean free_fetch_data = TRUE;
|
||||
@@ -1132,7 +1135,7 @@ static_deltapart_fetch_on_complete (GObject *object,
|
||||
g_assert (pull_data->n_outstanding_deltapart_fetches > 0);
|
||||
pull_data->n_outstanding_deltapart_fetches--;
|
||||
pull_data->n_fetched_deltaparts++;
|
||||
check_outstanding_requests_handle_error (pull_data, local_error);
|
||||
check_outstanding_requests_handle_error (pull_data, &local_error);
|
||||
if (free_fetch_data)
|
||||
fetch_static_delta_data_free (fetch_data);
|
||||
}
|
||||
@@ -1197,6 +1200,14 @@ gpg_verify_unwritten_commit (OtPullData *pull_data,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
commitstate_is_partial (OtPullData *pull_data,
|
||||
OstreeRepoCommitState commitstate)
|
||||
{
|
||||
return pull_data->legacy_transaction_resuming
|
||||
|| (commitstate & OSTREE_REPO_COMMIT_STATE_PARTIAL) > 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
scan_commit_object (OtPullData *pull_data,
|
||||
const char *checksum,
|
||||
@@ -1253,8 +1264,7 @@ scan_commit_object (OtPullData *pull_data,
|
||||
goto out;
|
||||
|
||||
/* If we found a legacy transaction flag, assume all commits are partial */
|
||||
is_partial = pull_data->legacy_transaction_resuming
|
||||
|| (commitstate & OSTREE_REPO_COMMIT_STATE_PARTIAL) > 0;
|
||||
is_partial = commitstate_is_partial (pull_data, commitstate);
|
||||
|
||||
/* PARSE OSTREE_SERIALIZED_COMMIT_VARIANT */
|
||||
g_variant_get_child (commit, 1, "@ay", &parent_csum);
|
||||
@@ -1882,7 +1892,7 @@ get_best_static_delta_start_for (OtPullData *pull_data,
|
||||
/* Array<char*> of possible from checksums */
|
||||
g_autoptr(GPtrArray) candidates = g_ptr_array_new_with_free_func (g_free);
|
||||
const char *newest_candidate = NULL;
|
||||
guint64 newest_candidate_timestamp;
|
||||
guint64 newest_candidate_timestamp = 0;
|
||||
|
||||
g_assert (pull_data->summary_deltas_checksums != NULL);
|
||||
g_hash_table_iter_init (&hiter, pull_data->summary_deltas_checksums);
|
||||
@@ -1911,7 +1921,7 @@ get_best_static_delta_start_for (OtPullData *pull_data,
|
||||
for (guint i = 0; i < candidates->len; i++)
|
||||
{
|
||||
const char *candidate = candidates->pdata[i];
|
||||
guint64 candidate_ts;
|
||||
guint64 candidate_ts = 0;
|
||||
g_autoptr(GVariant) commit = NULL;
|
||||
OstreeRepoCommitState state;
|
||||
gboolean have_candidate;
|
||||
@@ -1961,7 +1971,7 @@ on_superblock_fetched (GObject *src,
|
||||
{
|
||||
FetchDeltaSuperData *fdata = data;
|
||||
OtPullData *pull_data = fdata->pull_data;
|
||||
GError *local_error = NULL;
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
GError **error = &local_error;
|
||||
g_autoptr(GBytes) delta_superblock_data = NULL;
|
||||
const char *from_revision = fdata->from_revision;
|
||||
@@ -2038,7 +2048,7 @@ on_superblock_fetched (GObject *src,
|
||||
g_assert (pull_data->n_outstanding_metadata_fetches > 0);
|
||||
pull_data->n_outstanding_metadata_fetches--;
|
||||
pull_data->n_fetched_metadata++;
|
||||
check_outstanding_requests_handle_error (pull_data, local_error);
|
||||
check_outstanding_requests_handle_error (pull_data, &local_error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -3242,6 +3252,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||
g_autofree char *from_revision = NULL;
|
||||
const char *ref = key;
|
||||
const char *to_revision = value;
|
||||
gboolean have_valid_from_commit = TRUE;
|
||||
|
||||
/* If we have a summary, find the latest local commit we have
|
||||
* to use as a from revision for static deltas.
|
||||
@@ -3257,9 +3268,27 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||
if (!ostree_repo_resolve_rev (pull_data->repo, ref, TRUE,
|
||||
&from_revision, error))
|
||||
goto out;
|
||||
|
||||
/* Determine whether the from revision we have is partial; this
|
||||
* can happen if e.g. one uses `ostree pull --commit-metadata-only`.
|
||||
* This mirrors the logic in get_best_static_delta_start_for().
|
||||
*/
|
||||
if (from_revision)
|
||||
{
|
||||
OstreeRepoCommitState from_commitstate;
|
||||
|
||||
if (!ostree_repo_load_commit (pull_data->repo, from_revision, NULL,
|
||||
&from_commitstate, error))
|
||||
goto out;
|
||||
|
||||
/* Was it partial? OK, we can't use it. */
|
||||
if (commitstate_is_partial (pull_data, from_commitstate))
|
||||
have_valid_from_commit = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!disable_static_deltas &&
|
||||
have_valid_from_commit &&
|
||||
(from_revision == NULL || g_strcmp0 (from_revision, to_revision) != 0))
|
||||
{
|
||||
g_autofree char *delta_name =
|
||||
|
||||
+100
-184
@@ -32,30 +32,23 @@ add_ref_to_set (const char *remote,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
char *contents;
|
||||
gsize len;
|
||||
GString *refname;
|
||||
|
||||
contents = glnx_file_get_contents_utf8_at (base_fd, path, &len, cancellable, error);
|
||||
char *contents = glnx_file_get_contents_utf8_at (base_fd, path, &len, cancellable, error);
|
||||
if (!contents)
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
g_strchomp (contents);
|
||||
|
||||
refname = g_string_new ("");
|
||||
g_autoptr(GString) refname = g_string_new ("");
|
||||
if (remote)
|
||||
{
|
||||
g_string_append (refname, remote);
|
||||
g_string_append_c (refname, ':');
|
||||
}
|
||||
g_string_append (refname, path);
|
||||
|
||||
g_hash_table_insert (refs, g_string_free (refname, FALSE), contents);
|
||||
g_hash_table_insert (refs, g_string_free (g_steal_pointer (&refname), FALSE), contents);
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -66,27 +59,16 @@ write_checksum_file_at (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
const char *lastslash;
|
||||
|
||||
if (!ostree_validate_checksum_string (sha256, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (ostree_validate_checksum_string (name, NULL))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Rev name '%s' looks like a checksum", name);
|
||||
goto out;
|
||||
}
|
||||
return glnx_throw (error, "Rev name '%s' looks like a checksum", name);
|
||||
|
||||
if (!*name)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Invalid empty ref name");
|
||||
goto out;
|
||||
}
|
||||
return glnx_throw (error, "Invalid empty ref name");
|
||||
|
||||
lastslash = strrchr (name, '/');
|
||||
const char *lastslash = strrchr (name, '/');
|
||||
|
||||
if (lastslash)
|
||||
{
|
||||
@@ -94,7 +76,7 @@ write_checksum_file_at (OstreeRepo *self,
|
||||
parent[lastslash - name] = '\0';
|
||||
|
||||
if (!glnx_shutil_mkdir_p_at (dfd, parent, 0777, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
{
|
||||
@@ -118,38 +100,32 @@ write_checksum_file_at (OstreeRepo *self,
|
||||
g_clear_error (&temp_error);
|
||||
|
||||
if (!ostree_repo_list_refs (self, name, &refs, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_iter_init (&hashiter, refs);
|
||||
|
||||
while ((g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue)))
|
||||
{
|
||||
if (strcmp (name, (char *)hashkey) != 0)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Conflict: %s exists under %s when attempting write", (char*)hashkey, name);
|
||||
goto out;
|
||||
}
|
||||
return glnx_throw (error, "Conflict: %s exists under %s when attempting write", (char*)hashkey, name);
|
||||
}
|
||||
|
||||
if (!glnx_shutil_rm_rf_at (dfd, name, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (!_ostree_repo_file_replace_contents (self, dfd, name, (guint8*)bufnl, l + 1,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_propagate_error (error, g_steal_pointer (&temp_error));
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -158,12 +134,11 @@ find_ref_in_remotes (OstreeRepo *self,
|
||||
int *out_fd,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
|
||||
glnx_fd_close int ret_fd = -1;
|
||||
|
||||
if (!glnx_dirfd_iterator_init_at (self->repo_dir_fd, "refs/remotes", TRUE, &dfd_iter, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
@@ -171,7 +146,7 @@ find_ref_in_remotes (OstreeRepo *self,
|
||||
glnx_fd_close int remote_dfd = -1;
|
||||
|
||||
if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, NULL, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
if (dent == NULL)
|
||||
break;
|
||||
|
||||
@@ -179,19 +154,17 @@ find_ref_in_remotes (OstreeRepo *self,
|
||||
continue;
|
||||
|
||||
if (!glnx_opendirat (dfd_iter.fd, dent->d_name, TRUE, &remote_dfd, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (!ot_openat_ignore_enoent (remote_dfd, rev, &ret_fd, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (ret_fd != -1)
|
||||
break;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
*out_fd = ret_fd; ret_fd = -1;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -213,14 +186,13 @@ resolve_refspec_fallback (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autofree char *ret_rev = NULL;
|
||||
|
||||
if (self->parent_repo)
|
||||
{
|
||||
if (!resolve_refspec (self->parent_repo, remote, ref, allow_noent,
|
||||
fallback_remote, &ret_rev, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
else if (!allow_noent)
|
||||
{
|
||||
@@ -229,13 +201,11 @@ resolve_refspec_fallback (OstreeRepo *self,
|
||||
remote ? remote : "",
|
||||
remote ? ":" : "",
|
||||
ref);
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
ot_transfer_out_value (out_rev, &ret_rev);
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -247,11 +217,10 @@ resolve_refspec (OstreeRepo *self,
|
||||
char **out_rev,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
__attribute__((unused)) GCancellable *cancellable = NULL;
|
||||
g_autofree char *ret_rev = NULL;
|
||||
glnx_fd_close int target_fd = -1;
|
||||
|
||||
|
||||
g_return_val_if_fail (ref != NULL, FALSE);
|
||||
|
||||
/* We intentionally don't allow a ref that looks like a checksum */
|
||||
@@ -264,26 +233,26 @@ resolve_refspec (OstreeRepo *self,
|
||||
const char *remote_ref = glnx_strjoina ("refs/remotes/", remote, "/", ref);
|
||||
|
||||
if (!ot_openat_ignore_enoent (self->repo_dir_fd, remote_ref, &target_fd, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *local_ref = glnx_strjoina ("refs/heads/", ref);
|
||||
|
||||
if (!ot_openat_ignore_enoent (self->repo_dir_fd, local_ref, &target_fd, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (target_fd == -1 && fallback_remote)
|
||||
{
|
||||
local_ref = glnx_strjoina ("refs/remotes/", ref);
|
||||
|
||||
if (!ot_openat_ignore_enoent (self->repo_dir_fd, local_ref, &target_fd, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (target_fd == -1)
|
||||
{
|
||||
if (!find_ref_in_remotes (self, ref, &target_fd, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -294,24 +263,22 @@ resolve_refspec (OstreeRepo *self,
|
||||
if (!ret_rev)
|
||||
{
|
||||
g_prefix_error (error, "Couldn't open ref '%s': ", ref);
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
g_strchomp (ret_rev);
|
||||
if (!ostree_validate_checksum_string (ret_rev, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!resolve_refspec_fallback (self, remote, ref, allow_noent, fallback_remote,
|
||||
&ret_rev, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ot_transfer_out_value (out_rev, &ret_rev);
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -330,65 +297,51 @@ ostree_repo_resolve_partial_checksum (OstreeRepo *self,
|
||||
char **full_checksum,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
static const char hexchars[] = "0123456789abcdef";
|
||||
gsize off;
|
||||
g_autoptr(GHashTable) ref_list = NULL;
|
||||
g_autofree char *ret_rev = NULL;
|
||||
guint length;
|
||||
const char *checksum = NULL;
|
||||
OstreeObjectType objtype;
|
||||
GHashTableIter hashiter;
|
||||
gpointer key, value;
|
||||
GVariant *first_commit;
|
||||
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
/* If the input is longer than OSTREE_SHA256_STRING_LEN chars or contains non-hex chars,
|
||||
don't bother looking for it as an object */
|
||||
off = strspn (refspec, hexchars);
|
||||
const gsize off = strspn (refspec, hexchars);
|
||||
if (off > OSTREE_SHA256_STRING_LEN || refspec[off] != '\0')
|
||||
return TRUE;
|
||||
|
||||
/* this looks through all objects and adds them to the ref_list if:
|
||||
a) they are a commit object AND
|
||||
b) the obj checksum starts with the partual checksum defined by "refspec" */
|
||||
g_autoptr(GHashTable) ref_list = NULL;
|
||||
if (!ostree_repo_list_commit_objects_starting_with (self, refspec, &ref_list, NULL, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
length = g_hash_table_size (ref_list);
|
||||
guint length = g_hash_table_size (ref_list);
|
||||
|
||||
GHashTableIter hashiter;
|
||||
gpointer key, value;
|
||||
GVariant *first_commit = NULL;
|
||||
g_hash_table_iter_init (&hashiter, ref_list);
|
||||
if (g_hash_table_iter_next (&hashiter, &key, &value))
|
||||
first_commit = (GVariant*) key;
|
||||
else
|
||||
first_commit = NULL;
|
||||
|
||||
if (first_commit)
|
||||
OstreeObjectType objtype;
|
||||
const char *checksum = NULL;
|
||||
if (first_commit)
|
||||
ostree_object_name_deserialize (first_commit, &checksum, &objtype);
|
||||
|
||||
/* length more than one - multiple commits match partial refspec: is not unique */
|
||||
if (length > 1)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Refspec %s not unique", refspec);
|
||||
goto out;
|
||||
}
|
||||
|
||||
return glnx_throw (error, "Refspec %s not unique", refspec);
|
||||
/* length is 1 - a single matching commit gives us our revision */
|
||||
else if (length == 1)
|
||||
{
|
||||
ret_rev = g_strdup (checksum);
|
||||
}
|
||||
ret_rev = g_strdup (checksum);
|
||||
|
||||
/* Note: if length is 0, then code will return TRUE
|
||||
because there is no error, but it will return full_checksum = NULL
|
||||
to signal to continue parsing */
|
||||
|
||||
ret = TRUE;
|
||||
ot_transfer_out_value (full_checksum, &ret_rev);
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -399,7 +352,6 @@ _ostree_repo_resolve_rev_internal (OstreeRepo *self,
|
||||
char **out_rev,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autofree char *ret_rev = NULL;
|
||||
|
||||
g_return_val_if_fail (refspec != NULL, FALSE);
|
||||
@@ -410,12 +362,12 @@ _ostree_repo_resolve_rev_internal (OstreeRepo *self,
|
||||
}
|
||||
|
||||
else if (!ostree_repo_resolve_partial_checksum (self, refspec, &ret_rev, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (!ret_rev)
|
||||
{
|
||||
if (error != NULL && *error != NULL)
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (g_str_has_suffix (refspec, "^"))
|
||||
{
|
||||
@@ -427,18 +379,14 @@ _ostree_repo_resolve_rev_internal (OstreeRepo *self,
|
||||
parent_refspec[strlen(parent_refspec) - 1] = '\0';
|
||||
|
||||
if (!ostree_repo_resolve_rev (self, parent_refspec, allow_noent, &parent_rev, error))
|
||||
goto out;
|
||||
|
||||
return FALSE;
|
||||
|
||||
if (!ostree_repo_load_variant (self, OSTREE_OBJECT_TYPE_COMMIT, parent_rev,
|
||||
&commit, error))
|
||||
goto out;
|
||||
|
||||
return FALSE;
|
||||
|
||||
if (!(ret_rev = ostree_commit_get_parent (commit)))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Commit %s has no parent", parent_rev);
|
||||
goto out;
|
||||
}
|
||||
return glnx_throw (error, "Commit %s has no parent", parent_rev);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -446,18 +394,16 @@ _ostree_repo_resolve_rev_internal (OstreeRepo *self,
|
||||
g_autofree char *ref = NULL;
|
||||
|
||||
if (!ostree_parse_refspec (refspec, &remote, &ref, error))
|
||||
goto out;
|
||||
|
||||
return FALSE;
|
||||
|
||||
if (!resolve_refspec (self, remote, ref, allow_noent,
|
||||
fallback_remote, &ret_rev, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
ot_transfer_out_value (out_rev, &ret_rev);
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -518,11 +464,10 @@ enumerate_refs_recurse (OstreeRepo *repo,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
|
||||
|
||||
if (!glnx_dirfd_iterator_init_at (child_dfd, path, FALSE, &dfd_iter, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
@@ -530,7 +475,7 @@ enumerate_refs_recurse (OstreeRepo *repo,
|
||||
struct dirent *dent = NULL;
|
||||
|
||||
if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
if (dent == NULL)
|
||||
break;
|
||||
|
||||
@@ -543,22 +488,19 @@ enumerate_refs_recurse (OstreeRepo *repo,
|
||||
if (!enumerate_refs_recurse (repo, remote, base_dfd, base_path,
|
||||
dfd_iter.fd, dent->d_name,
|
||||
refs, cancellable, error))
|
||||
goto out;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else if (dent->d_type == DT_REG)
|
||||
{
|
||||
if (!add_ref_to_set (remote, base_dfd, base_path->str, refs,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_string_truncate (base_path, len);
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -569,7 +511,6 @@ _ostree_repo_list_refs_internal (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autoptr(GHashTable) ret_all_refs = NULL;
|
||||
g_autofree char *remote = NULL;
|
||||
g_autofree char *ref_prefix = NULL;
|
||||
@@ -583,7 +524,7 @@ _ostree_repo_list_refs_internal (OstreeRepo *self,
|
||||
const char *path;
|
||||
|
||||
if (!ostree_parse_refspec (refspec_prefix, &remote, &ref_prefix, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (remote)
|
||||
{
|
||||
@@ -599,10 +540,7 @@ _ostree_repo_list_refs_internal (OstreeRepo *self,
|
||||
if (fstatat (self->repo_dir_fd, path, &stbuf, 0) < 0)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
}
|
||||
return glnx_throw_errno (error);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -614,23 +552,23 @@ _ostree_repo_list_refs_internal (OstreeRepo *self,
|
||||
g_string_printf (base_path, "%s/", ref_prefix);
|
||||
|
||||
if (!glnx_opendirat (self->repo_dir_fd, cut_prefix ? path : prefix_path, TRUE, &base_fd, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (!enumerate_refs_recurse (self, remote, base_fd, base_path,
|
||||
base_fd, cut_prefix ? "." : ref_prefix,
|
||||
ret_all_refs, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
glnx_fd_close int prefix_dfd = -1;
|
||||
|
||||
|
||||
if (!glnx_opendirat (self->repo_dir_fd, prefix_path, TRUE, &prefix_dfd, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (!add_ref_to_set (remote, prefix_dfd, ref_prefix, ret_all_refs,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -639,19 +577,19 @@ _ostree_repo_list_refs_internal (OstreeRepo *self,
|
||||
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
|
||||
g_autoptr(GString) base_path = g_string_new ("");
|
||||
glnx_fd_close int refs_heads_dfd = -1;
|
||||
|
||||
|
||||
if (!glnx_opendirat (self->repo_dir_fd, "refs/heads", TRUE, &refs_heads_dfd, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (!enumerate_refs_recurse (self, NULL, refs_heads_dfd, base_path,
|
||||
refs_heads_dfd, ".",
|
||||
ret_all_refs, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
g_string_truncate (base_path, 0);
|
||||
|
||||
if (!glnx_dirfd_iterator_init_at (self->repo_dir_fd, "refs/remotes", TRUE, &dfd_iter, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
@@ -659,7 +597,7 @@ _ostree_repo_list_refs_internal (OstreeRepo *self,
|
||||
glnx_fd_close int remote_dfd = -1;
|
||||
|
||||
if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
if (!dent)
|
||||
break;
|
||||
|
||||
@@ -667,20 +605,18 @@ _ostree_repo_list_refs_internal (OstreeRepo *self,
|
||||
continue;
|
||||
|
||||
if (!glnx_opendirat (dfd_iter.fd, dent->d_name, TRUE, &remote_dfd, error))
|
||||
goto out;
|
||||
|
||||
return FALSE;
|
||||
|
||||
if (!enumerate_refs_recurse (self, dent->d_name, remote_dfd, base_path,
|
||||
remote_dfd, ".",
|
||||
ret_all_refs,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
ot_transfer_out_value (out_all_refs, &ret_all_refs);
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -748,19 +684,16 @@ ostree_repo_remote_list_refs (OstreeRepo *self,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GBytes) summary_bytes = NULL;
|
||||
gboolean ret = FALSE;
|
||||
g_autoptr(GHashTable) ret_all_refs = NULL;
|
||||
|
||||
if (!ostree_repo_remote_fetch_summary (self, remote_name,
|
||||
&summary_bytes, NULL,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (summary_bytes == NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Remote refs not available; server has no summary file\n");
|
||||
goto out;
|
||||
return glnx_throw (error, "Remote refs not available; server has no summary file");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -786,12 +719,11 @@ ostree_repo_remote_list_refs (OstreeRepo *self,
|
||||
|
||||
if (ref_name != NULL)
|
||||
{
|
||||
const guchar *csum_bytes;
|
||||
|
||||
g_variant_get_child (child, 1, "(t@aya{sv})", NULL, &csum_v, NULL);
|
||||
csum_bytes = ostree_checksum_bytes_peek_validate (csum_v, error);
|
||||
|
||||
const guchar *csum_bytes = ostree_checksum_bytes_peek_validate (csum_v, error);
|
||||
if (csum_bytes == NULL)
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
ostree_checksum_inplace_from_bytes (csum_bytes, tmp_checksum);
|
||||
|
||||
@@ -804,14 +736,11 @@ ostree_repo_remote_list_refs (OstreeRepo *self,
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
ot_transfer_out_value (out_all_refs, &ret_all_refs);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gboolean
|
||||
_ostree_repo_write_ref (OstreeRepo *self,
|
||||
const char *remote,
|
||||
const char *ref,
|
||||
@@ -819,7 +748,6 @@ _ostree_repo_write_ref (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
glnx_fd_close int dfd = -1;
|
||||
|
||||
if (remote == NULL)
|
||||
@@ -828,7 +756,7 @@ _ostree_repo_write_ref (OstreeRepo *self,
|
||||
&dfd, error))
|
||||
{
|
||||
g_prefix_error (error, "Opening %s: ", "refs/heads");
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -839,23 +767,19 @@ _ostree_repo_write_ref (OstreeRepo *self,
|
||||
&refs_remotes_dfd, error))
|
||||
{
|
||||
g_prefix_error (error, "Opening %s: ", "refs/remotes");
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (rev != NULL)
|
||||
{
|
||||
/* Ensure we have a dir for the remote */
|
||||
if (!glnx_shutil_mkdir_p_at (refs_remotes_dfd, remote, 0777, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dfd = glnx_opendirat_with_errno (refs_remotes_dfd, remote, TRUE);
|
||||
if (dfd < 0 && (errno != ENOENT || rev != NULL))
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
g_prefix_error (error, "Opening remotes/ dir %s: ", remote);
|
||||
goto out;
|
||||
}
|
||||
return glnx_throw_errno_prefix (error, "Opening remotes/ dir %s", remote);
|
||||
}
|
||||
|
||||
if (rev == NULL)
|
||||
@@ -863,27 +787,22 @@ _ostree_repo_write_ref (OstreeRepo *self,
|
||||
if (dfd >= 0)
|
||||
{
|
||||
if (unlinkat (dfd, ref, 0) != 0)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
return glnx_throw_errno (error);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!write_checksum_file_at (self, dfd, ref, rev, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!_ostree_repo_update_mtime (self, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -892,7 +811,6 @@ _ostree_repo_update_refs (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GHashTableIter hash_iter;
|
||||
gpointer key, value;
|
||||
|
||||
@@ -905,14 +823,12 @@ _ostree_repo_update_refs (OstreeRepo *self,
|
||||
g_autofree char *ref = NULL;
|
||||
|
||||
if (!ostree_parse_refspec (refspec, &remote, &ref, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (!_ostree_repo_write_ref (self, remote, ref, rev,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
+171
-239
@@ -42,6 +42,7 @@
|
||||
|
||||
#include <locale.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
/**
|
||||
* SECTION:ostree-repo
|
||||
@@ -891,26 +892,21 @@ ostree_repo_write_config (OstreeRepo *self,
|
||||
GKeyFile *new_config,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autofree char *data = NULL;
|
||||
gsize len;
|
||||
|
||||
g_return_val_if_fail (self->inited, FALSE);
|
||||
|
||||
data = g_key_file_to_data (new_config, &len, error);
|
||||
gsize len;
|
||||
g_autofree char *data = g_key_file_to_data (new_config, &len, error);
|
||||
if (!glnx_file_replace_contents_at (self->repo_dir_fd, "config",
|
||||
(guint8*)data, len, 0,
|
||||
NULL, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
g_key_file_free (self->config);
|
||||
self->config = g_key_file_new ();
|
||||
if (!g_key_file_load_from_data (self->config, data, len, 0, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Bind a subset of an a{sv} to options in a given GKeyfile section */
|
||||
@@ -953,34 +949,24 @@ impl_repo_remote_add (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(OstreeRemote) remote = NULL;
|
||||
gboolean different_sysroot = FALSE;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
g_return_val_if_fail (name != NULL, FALSE);
|
||||
g_return_val_if_fail (url != NULL, FALSE);
|
||||
g_return_val_if_fail (options == NULL || g_variant_is_of_type (options, G_VARIANT_TYPE ("a{sv}")), FALSE);
|
||||
|
||||
if (strchr (name, '/') != NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Invalid character '/' in remote name: %s",
|
||||
name);
|
||||
goto out;
|
||||
}
|
||||
return glnx_throw (error, "Invalid character '/' in remote name: %s", name);
|
||||
|
||||
remote = ost_repo_get_remote (self, name, NULL);
|
||||
g_autoptr(OstreeRemote) remote = ost_repo_get_remote (self, name, NULL);
|
||||
if (remote != NULL && if_not_exists)
|
||||
{
|
||||
ret = TRUE;
|
||||
goto out;
|
||||
/* Note early return */
|
||||
return TRUE;
|
||||
}
|
||||
else if (remote != NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Remote configuration for \"%s\" already exists: %s",
|
||||
name, remote->file ? gs_file_get_path_cached (remote->file) : "(in config)");
|
||||
goto out;
|
||||
return glnx_throw (error,
|
||||
"Remote configuration for \"%s\" already exists: %s",
|
||||
name, remote->file ? gs_file_get_path_cached (remote->file) : "(in config)");
|
||||
}
|
||||
|
||||
remote = ost_remote_new ();
|
||||
@@ -994,20 +980,18 @@ impl_repo_remote_add (OstreeRepo *self,
|
||||
*
|
||||
* XXX Having API regret about the "sysroot" argument now.
|
||||
*/
|
||||
gboolean different_sysroot = FALSE;
|
||||
if (sysroot != NULL)
|
||||
different_sysroot = !g_file_equal (sysroot, self->sysroot_dir);
|
||||
|
||||
if (different_sysroot || ostree_repo_is_system (self))
|
||||
{
|
||||
g_autofree char *basename = g_strconcat (name, ".conf", NULL);
|
||||
g_autoptr(GFile) etc_ostree_remotes_d = NULL;
|
||||
GError *local_error = NULL;
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
|
||||
if (sysroot == NULL)
|
||||
sysroot = self->sysroot_dir;
|
||||
|
||||
etc_ostree_remotes_d = g_file_resolve_relative_path (sysroot, SYSCONF_REMOTES);
|
||||
|
||||
g_autoptr(GFile) etc_ostree_remotes_d = g_file_resolve_relative_path (sysroot, SYSCONF_REMOTES);
|
||||
if (!g_file_make_directory_with_parents (etc_ostree_remotes_d,
|
||||
cancellable, &local_error))
|
||||
{
|
||||
@@ -1017,11 +1001,12 @@ impl_repo_remote_add (OstreeRepo *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
g_propagate_error (error, local_error);
|
||||
goto out;
|
||||
g_propagate_error (error, g_steal_pointer (&local_error));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
g_autofree char *basename = g_strconcat (name, ".conf", NULL);
|
||||
remote->file = g_file_get_child (etc_ostree_remotes_d, basename);
|
||||
}
|
||||
|
||||
@@ -1035,16 +1020,14 @@ impl_repo_remote_add (OstreeRepo *self,
|
||||
|
||||
if (remote->file != NULL)
|
||||
{
|
||||
g_autofree char *data = NULL;
|
||||
gsize length;
|
||||
|
||||
data = g_key_file_to_data (remote->options, &length, NULL);
|
||||
g_autofree char *data = g_key_file_to_data (remote->options, &length, NULL);
|
||||
|
||||
if (!g_file_replace_contents (remote->file,
|
||||
data, length,
|
||||
NULL, FALSE, 0, NULL,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1054,15 +1037,12 @@ impl_repo_remote_add (OstreeRepo *self,
|
||||
ot_keyfile_copy_group (remote->options, config, remote->group);
|
||||
|
||||
if (!ostree_repo_write_config (self, config, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ost_repo_add_remote (self, remote);
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1103,67 +1083,52 @@ impl_repo_remote_delete (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(OstreeRemote) remote = NULL;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
g_return_val_if_fail (name != NULL, FALSE);
|
||||
|
||||
if (strchr (name, '/') != NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Invalid character '/' in remote name: %s",
|
||||
name);
|
||||
goto out;
|
||||
}
|
||||
return glnx_throw (error, "Invalid character '/' in remote name: %s", name);
|
||||
|
||||
g_autoptr(OstreeRemote) remote = NULL;
|
||||
if (if_exists)
|
||||
{
|
||||
remote = ost_repo_get_remote (self, name, NULL);
|
||||
if (!remote)
|
||||
{
|
||||
ret = TRUE;
|
||||
goto out;
|
||||
/* Note early return */
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
remote = ost_repo_get_remote (self, name, error);
|
||||
|
||||
if (remote == NULL)
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (remote->file != NULL)
|
||||
{
|
||||
if (unlink (gs_file_get_path_cached (remote->file)) != 0)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
}
|
||||
return glnx_throw_errno (error);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_autoptr(GKeyFile) config = NULL;
|
||||
|
||||
config = ostree_repo_copy_config (self);
|
||||
g_autoptr(GKeyFile) config = ostree_repo_copy_config (self);
|
||||
|
||||
/* XXX Not sure it's worth failing if the group to remove
|
||||
* isn't found. It's the end result we want, after all. */
|
||||
if (g_key_file_remove_group (config, remote->group, NULL))
|
||||
{
|
||||
if (!ostree_repo_write_config (self, config, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete the remote's keyring file, if it exists. */
|
||||
if (!ot_ensure_unlinked_at (self->repo_dir_fd, remote->keyring, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
ost_repo_remove_remote (self, remote);
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1319,11 +1284,9 @@ ostree_repo_remote_get_url (OstreeRepo *self,
|
||||
char **out_url,
|
||||
GError **error)
|
||||
{
|
||||
g_autofree char *url = NULL;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
g_return_val_if_fail (name != NULL, FALSE);
|
||||
|
||||
g_autofree char *url = NULL;
|
||||
if (_ostree_repo_remote_name_is_file (name))
|
||||
{
|
||||
url = g_strdup (name);
|
||||
@@ -1331,23 +1294,19 @@ ostree_repo_remote_get_url (OstreeRepo *self,
|
||||
else
|
||||
{
|
||||
if (!ostree_repo_get_remote_option (self, name, "url", NULL, &url, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (url == NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
|
||||
"No \"url\" option in remote \"%s\"", name);
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (out_url != NULL)
|
||||
*out_url = g_steal_pointer (&url);
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1583,8 +1542,9 @@ ostree_repo_remote_gpg_import (OstreeRepo *self,
|
||||
|
||||
if (fstatat (self->repo_dir_fd, remote->keyring, &stbuf, AT_SYMLINK_NOFOLLOW) == 0)
|
||||
{
|
||||
GLnxFileCopyFlags copyflags = self->disable_xattrs ? GLNX_FILE_COPY_NOXATTRS : 0;
|
||||
if (!glnx_file_copy_at (self->repo_dir_fd, remote->keyring,
|
||||
&stbuf, target_temp_fd, "pubring.gpg", 0,
|
||||
&stbuf, target_temp_fd, "pubring.gpg", copyflags,
|
||||
cancellable, error))
|
||||
{
|
||||
g_prefix_error (error, "Unable to copy remote's keyring: ");
|
||||
@@ -1741,7 +1701,6 @@ ostree_repo_mode_to_string (OstreeRepoMode mode,
|
||||
const char **out_mode,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
const char *ret_mode;
|
||||
|
||||
switch (mode)
|
||||
@@ -1752,19 +1711,18 @@ ostree_repo_mode_to_string (OstreeRepoMode mode,
|
||||
case OSTREE_REPO_MODE_BARE_USER:
|
||||
ret_mode = "bare-user";
|
||||
break;
|
||||
case OSTREE_REPO_MODE_BARE_USER_ONLY:
|
||||
ret_mode = "bare-user-only";
|
||||
break;
|
||||
case OSTREE_REPO_MODE_ARCHIVE_Z2:
|
||||
ret_mode ="archive-z2";
|
||||
break;
|
||||
default:
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Invalid mode '%d'", mode);
|
||||
goto out;
|
||||
return glnx_throw (error, "Invalid mode '%d'", mode);
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
*out_mode = ret_mode;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -1772,27 +1730,22 @@ ostree_repo_mode_from_string (const char *mode,
|
||||
OstreeRepoMode *out_mode,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
OstreeRepoMode ret_mode;
|
||||
|
||||
if (strcmp (mode, "bare") == 0)
|
||||
ret_mode = OSTREE_REPO_MODE_BARE;
|
||||
else if (strcmp (mode, "bare-user") == 0)
|
||||
ret_mode = OSTREE_REPO_MODE_BARE_USER;
|
||||
else if (strcmp (mode, "bare-user-only") == 0)
|
||||
ret_mode = OSTREE_REPO_MODE_BARE_USER_ONLY;
|
||||
else if (strcmp (mode, "archive-z2") == 0 ||
|
||||
strcmp (mode, "archive") == 0)
|
||||
ret_mode = OSTREE_REPO_MODE_ARCHIVE_Z2;
|
||||
else
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Invalid mode '%s' in repository configuration", mode);
|
||||
goto out;
|
||||
}
|
||||
return glnx_throw (error, "Invalid mode '%s' in repository configuration", mode);
|
||||
|
||||
ret = TRUE;
|
||||
*out_mode = ret_mode;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define DEFAULT_CONFIG_CONTENTS ("[core]\n" \
|
||||
@@ -1830,10 +1783,7 @@ ostree_repo_create (OstreeRepo *self,
|
||||
if (mkdir (repopath, 0755) != 0)
|
||||
{
|
||||
if (G_UNLIKELY (errno != EEXIST))
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
return FALSE;
|
||||
}
|
||||
return glnx_throw_errno (error);
|
||||
}
|
||||
|
||||
if (!glnx_opendirat (AT_FDCWD, repopath, TRUE, &dfd, error))
|
||||
@@ -1843,11 +1793,12 @@ ostree_repo_create (OstreeRepo *self,
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
{
|
||||
const char *mode_str;
|
||||
const char *mode_str = NULL;
|
||||
g_autoptr(GString) config_data = g_string_new (DEFAULT_CONFIG_CONTENTS);
|
||||
|
||||
if (!ostree_repo_mode_to_string (mode, &mode_str, error))
|
||||
return FALSE;
|
||||
g_assert (mode_str);
|
||||
|
||||
g_string_append_printf (config_data, "mode=%s\n", mode_str);
|
||||
|
||||
@@ -1857,10 +1808,7 @@ ostree_repo_create (OstreeRepo *self,
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
return FALSE;
|
||||
}
|
||||
return glnx_throw_errno (error);
|
||||
}
|
||||
|
||||
for (guint i = 0; i < G_N_ELEMENTS (state_dirs); i++)
|
||||
@@ -1869,10 +1817,7 @@ ostree_repo_create (OstreeRepo *self,
|
||||
if (mkdirat (dfd, elt, 0755) == -1)
|
||||
{
|
||||
if (G_UNLIKELY (errno != EEXIST))
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
return FALSE;
|
||||
}
|
||||
return glnx_throw_errno (error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1890,8 +1835,7 @@ enumerate_directory_allow_noent (GFile *dirpath,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GError *temp_error = NULL;
|
||||
g_autoptr(GError) temp_error = NULL;
|
||||
g_autoptr(GFileEnumerator) ret_direnum = NULL;
|
||||
|
||||
ret_direnum = g_file_enumerate_children (dirpath, queryargs, queryflags,
|
||||
@@ -1899,21 +1843,17 @@ enumerate_directory_allow_noent (GFile *dirpath,
|
||||
if (!ret_direnum)
|
||||
{
|
||||
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||
{
|
||||
g_clear_error (&temp_error);
|
||||
ret = TRUE;
|
||||
}
|
||||
g_clear_error (&temp_error);
|
||||
else
|
||||
g_propagate_error (error, temp_error);
|
||||
|
||||
goto out;
|
||||
{
|
||||
g_propagate_error (error, g_steal_pointer (&temp_error));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
if (out_direnum)
|
||||
*out_direnum = g_steal_pointer (&ret_direnum);
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1979,17 +1919,12 @@ append_one_remote_config (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autoptr(GKeyFile) remotedata = g_key_file_new ();
|
||||
|
||||
if (!g_key_file_load_from_file (remotedata, gs_file_get_path_cached (path),
|
||||
0, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
ret = add_remotes_from_keyfile (self, remotedata, path, error);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return add_remotes_from_keyfile (self, remotedata, path, error);
|
||||
}
|
||||
|
||||
static GFile *
|
||||
@@ -2033,11 +1968,7 @@ reload_core_config (OstreeRepo *self,
|
||||
return FALSE;
|
||||
|
||||
if (strcmp (version, "1") != 0)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Invalid repository version '%s'", version);
|
||||
return FALSE;
|
||||
}
|
||||
return glnx_throw (error, "Invalid repository version '%s'", version);
|
||||
|
||||
if (!ot_keyfile_get_boolean_with_default (self->config, "core", "archive",
|
||||
FALSE, &is_archive, error))
|
||||
@@ -2075,6 +2006,11 @@ reload_core_config (OstreeRepo *self,
|
||||
ostree_repo_set_disable_fsync (self, TRUE);
|
||||
}
|
||||
|
||||
/* See https://github.com/ostreedev/ostree/issues/758 */
|
||||
if (!ot_keyfile_get_boolean_with_default (self->config, "core", "disable-xattrs",
|
||||
FALSE, &self->disable_xattrs, error))
|
||||
return FALSE;
|
||||
|
||||
{ g_autofree char *tmp_expiry_seconds = NULL;
|
||||
|
||||
/* 86400 secs = one day */
|
||||
@@ -2125,25 +2061,23 @@ reload_remote_config (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autoptr(GFile) remotes_d = NULL;
|
||||
g_autoptr(GFileEnumerator) direnum = NULL;
|
||||
|
||||
g_mutex_lock (&self->remotes_lock);
|
||||
g_hash_table_remove_all (self->remotes);
|
||||
g_mutex_unlock (&self->remotes_lock);
|
||||
|
||||
if (!add_remotes_from_keyfile (self, self->config, NULL, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
remotes_d = get_remotes_d_dir (self);
|
||||
g_autoptr(GFile) remotes_d = get_remotes_d_dir (self);
|
||||
if (remotes_d == NULL)
|
||||
return TRUE;
|
||||
|
||||
g_autoptr(GFileEnumerator) direnum = NULL;
|
||||
if (!enumerate_directory_allow_noent (remotes_d, OSTREE_GIO_FAST_QUERYINFO, 0,
|
||||
&direnum,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
if (direnum)
|
||||
{
|
||||
while (TRUE)
|
||||
@@ -2155,7 +2089,7 @@ reload_remote_config (OstreeRepo *self,
|
||||
|
||||
if (!g_file_enumerator_iterate (direnum, &file_info, &path,
|
||||
NULL, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
if (file_info == NULL)
|
||||
break;
|
||||
|
||||
@@ -2166,14 +2100,12 @@ reload_remote_config (OstreeRepo *self,
|
||||
g_str_has_suffix (name, ".conf"))
|
||||
{
|
||||
if (!append_one_remote_config (self, path, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2202,7 +2134,6 @@ ostree_repo_open (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
struct stat stbuf;
|
||||
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
@@ -2225,7 +2156,7 @@ ostree_repo_open (OstreeRepo *self,
|
||||
&boot_id,
|
||||
NULL,
|
||||
error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
g_strdelimit (boot_id, "\n", '\0');
|
||||
}
|
||||
|
||||
@@ -2236,14 +2167,14 @@ ostree_repo_open (OstreeRepo *self,
|
||||
&self->repo_dir_fd, error))
|
||||
{
|
||||
g_prefix_error (error, "%s: ", gs_file_get_path_cached (self->repodir));
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!glnx_opendirat (self->repo_dir_fd, "objects", TRUE,
|
||||
&self->objects_dir_fd, error))
|
||||
{
|
||||
g_prefix_error (error, "Opening objects/ directory: ");
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
self->writable = faccessat (self->objects_dir_fd, ".", W_OK, 0) == 0;
|
||||
@@ -2251,13 +2182,11 @@ ostree_repo_open (OstreeRepo *self,
|
||||
{
|
||||
/* This is returned through ostree_repo_is_writable(). */
|
||||
glnx_set_error_from_errno (&self->writable_error);
|
||||
/* Note - we don't return this error yet! */
|
||||
}
|
||||
|
||||
if (fstat (self->objects_dir_fd, &stbuf) != 0)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
}
|
||||
return glnx_throw_errno (error);
|
||||
|
||||
if (stbuf.st_uid != getuid () || stbuf.st_gid != getgid ())
|
||||
{
|
||||
@@ -2270,37 +2199,34 @@ ostree_repo_open (OstreeRepo *self,
|
||||
}
|
||||
|
||||
if (!glnx_opendirat (self->repo_dir_fd, "tmp", TRUE, &self->tmp_dir_fd, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (self->writable)
|
||||
{
|
||||
if (!glnx_shutil_mkdir_p_at (self->tmp_dir_fd, _OSTREE_CACHE_DIR, 0775, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (!glnx_opendirat (self->tmp_dir_fd, _OSTREE_CACHE_DIR, TRUE, &self->cache_dir_fd, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!ostree_repo_reload_config (self, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
/* TODO - delete this */
|
||||
if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 && self->enable_uncompressed_cache)
|
||||
{
|
||||
if (!glnx_shutil_mkdir_p_at (self->repo_dir_fd, "uncompressed-objects-cache", 0755,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
if (!glnx_opendirat (self->repo_dir_fd, "uncompressed-objects-cache", TRUE,
|
||||
&self->uncompressed_objects_dir_fd,
|
||||
error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
self->inited = TRUE;
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2368,8 +2294,8 @@ ostree_repo_get_disable_fsync (OstreeRepo *self)
|
||||
|
||||
/* Replace the contents of a file, honoring the repository's fsync
|
||||
* policy.
|
||||
*/
|
||||
gboolean
|
||||
*/
|
||||
gboolean
|
||||
_ostree_repo_file_replace_contents (OstreeRepo *self,
|
||||
int dfd,
|
||||
const char *path,
|
||||
@@ -2474,7 +2400,7 @@ list_loose_objects_at (OstreeRepo *self,
|
||||
|
||||
if ((self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2
|
||||
&& strcmp (dot, ".filez") == 0) ||
|
||||
((self->mode == OSTREE_REPO_MODE_BARE || self->mode == OSTREE_REPO_MODE_BARE_USER)
|
||||
((_ostree_repo_mode_is_bare (self->mode))
|
||||
&& strcmp (dot, ".file") == 0))
|
||||
objtype = OSTREE_OBJECT_TYPE_FILE;
|
||||
else if (strcmp (dot, ".dirtree") == 0)
|
||||
@@ -2529,7 +2455,6 @@ list_loose_objects (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
guint c;
|
||||
int dfd = -1;
|
||||
static const gchar hexchars[] = "0123456789abcdef";
|
||||
@@ -2546,21 +2471,16 @@ list_loose_objects (OstreeRepo *self,
|
||||
if (errno == ENOENT)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
}
|
||||
return glnx_throw_errno (error);
|
||||
}
|
||||
/* Takes ownership of dfd */
|
||||
if (!list_loose_objects_at (self, inout_objects, buf, dfd,
|
||||
commit_starting_with,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -2574,7 +2494,6 @@ load_metadata_internal (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
char loose_path_buf[_OSTREE_LOOSE_PATH_MAX];
|
||||
struct stat stbuf;
|
||||
glnx_fd_close int fd = -1;
|
||||
@@ -2587,22 +2506,19 @@ load_metadata_internal (OstreeRepo *self,
|
||||
|
||||
if (!ot_openat_ignore_enoent (self->objects_dir_fd, loose_path_buf, &fd,
|
||||
error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (fd < 0 && self->commit_stagedir_fd != -1)
|
||||
{
|
||||
if (!ot_openat_ignore_enoent (self->commit_stagedir_fd, loose_path_buf, &fd,
|
||||
error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (fd != -1)
|
||||
{
|
||||
if (fstat (fd, &stbuf) < 0)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
}
|
||||
return glnx_throw_errno (error);
|
||||
|
||||
if (out_variant)
|
||||
{
|
||||
@@ -2613,7 +2529,7 @@ load_metadata_internal (OstreeRepo *self,
|
||||
|
||||
mfile = g_mapped_file_new_from_fd (fd, FALSE, error);
|
||||
if (!mfile)
|
||||
goto out;
|
||||
return FALSE;
|
||||
ret_variant = g_variant_new_from_data (ostree_metadata_variant_type (objtype),
|
||||
g_mapped_file_get_contents (mfile),
|
||||
g_mapped_file_get_length (mfile),
|
||||
@@ -2626,7 +2542,7 @@ load_metadata_internal (OstreeRepo *self,
|
||||
{
|
||||
g_autoptr(GBytes) data = glnx_fd_readall_bytes (fd, cancellable, error);
|
||||
if (!data)
|
||||
goto out;
|
||||
return FALSE;
|
||||
ret_variant = g_variant_new_from_bytes (ostree_metadata_variant_type (objtype),
|
||||
data, TRUE);
|
||||
g_variant_ref_sink (ret_variant);
|
||||
@@ -2636,7 +2552,7 @@ load_metadata_internal (OstreeRepo *self,
|
||||
{
|
||||
ret_stream = g_unix_input_stream_new (fd, TRUE);
|
||||
if (!ret_stream)
|
||||
goto out;
|
||||
return FALSE;
|
||||
fd = -1; /* Transfer ownership */
|
||||
}
|
||||
|
||||
@@ -2646,21 +2562,19 @@ load_metadata_internal (OstreeRepo *self,
|
||||
else if (self->parent_repo)
|
||||
{
|
||||
if (!ostree_repo_load_variant (self->parent_repo, objtype, sha256, &ret_variant, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
else if (error_if_not_found)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
|
||||
"No such metadata object %s.%s",
|
||||
sha256, ostree_object_type_to_string (objtype));
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
ot_transfer_out_value (out_variant, &ret_variant);
|
||||
ot_transfer_out_value (out_stream, &ret_stream);
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -2745,8 +2659,7 @@ _ostree_repo_read_bare_fd (OstreeRepo *self,
|
||||
{
|
||||
char loose_path_buf[_OSTREE_LOOSE_PATH_MAX];
|
||||
|
||||
g_assert (self->mode == OSTREE_REPO_MODE_BARE ||
|
||||
self->mode == OSTREE_REPO_MODE_BARE_USER);
|
||||
g_assert (_ostree_repo_mode_is_bare (self->mode));
|
||||
|
||||
_ostree_loose_path (loose_path_buf, checksum, OSTREE_OBJECT_TYPE_FILE, self->mode);
|
||||
|
||||
@@ -2910,6 +2823,37 @@ ostree_repo_load_file (OstreeRepo *self,
|
||||
g_file_info_set_symlink_target (ret_file_info, targetbuf);
|
||||
}
|
||||
}
|
||||
else if (repo_mode == OSTREE_REPO_MODE_BARE_USER_ONLY)
|
||||
{
|
||||
glnx_fd_close int fd = -1;
|
||||
|
||||
/* Canonical info is: uid/gid is 0 and no xattrs, which
|
||||
might be wrong and thus not validate correctly, but
|
||||
at least we report something consistent. */
|
||||
g_file_info_set_attribute_uint32 (ret_file_info, "unix::uid", 0);
|
||||
g_file_info_set_attribute_uint32 (ret_file_info, "unix::gid", 0);
|
||||
|
||||
if (g_file_info_get_file_type (ret_file_info) == G_FILE_TYPE_REGULAR &&
|
||||
out_input)
|
||||
{
|
||||
fd = openat (self->objects_dir_fd, loose_path_buf, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_input = g_unix_input_stream_new (fd, TRUE);
|
||||
fd = -1; /* Transfer ownership */
|
||||
}
|
||||
|
||||
if (out_xattrs)
|
||||
{
|
||||
GVariantBuilder builder;
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ayay)"));
|
||||
ret_xattrs = g_variant_ref_sink (g_variant_builder_end (&builder));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert (repo_mode == OSTREE_REPO_MODE_BARE);
|
||||
@@ -2928,8 +2872,10 @@ ostree_repo_load_file (OstreeRepo *self,
|
||||
|
||||
if (out_xattrs)
|
||||
{
|
||||
if (!glnx_fd_get_all_xattrs (fd, &ret_xattrs,
|
||||
cancellable, error))
|
||||
if (self->disable_xattrs)
|
||||
ret_xattrs = g_variant_ref_sink (g_variant_new_array (G_VARIANT_TYPE ("(ayay)"), NULL, 0));
|
||||
else if (!glnx_fd_get_all_xattrs (fd, &ret_xattrs,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -2942,15 +2888,17 @@ ostree_repo_load_file (OstreeRepo *self,
|
||||
else if (g_file_info_get_file_type (ret_file_info) == G_FILE_TYPE_SYMBOLIC_LINK
|
||||
&& out_xattrs)
|
||||
{
|
||||
if (!glnx_dfd_name_get_all_xattrs (self->objects_dir_fd, loose_path_buf,
|
||||
&ret_xattrs,
|
||||
cancellable, error))
|
||||
if (self->disable_xattrs)
|
||||
ret_xattrs = g_variant_ref_sink (g_variant_new_array (G_VARIANT_TYPE ("(ayay)"), NULL, 0));
|
||||
else if (!glnx_dfd_name_get_all_xattrs (self->objects_dir_fd, loose_path_buf,
|
||||
&ret_xattrs,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!found)
|
||||
{
|
||||
if (self->parent_repo)
|
||||
@@ -3476,26 +3424,20 @@ ostree_repo_query_object_storage_size (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
char loose_path[_OSTREE_LOOSE_PATH_MAX];
|
||||
int res;
|
||||
struct stat stbuf;
|
||||
|
||||
_ostree_loose_path (loose_path, sha256, objtype, self->mode);
|
||||
|
||||
do
|
||||
do
|
||||
res = fstatat (self->objects_dir_fd, loose_path, &stbuf, AT_SYMLINK_NOFOLLOW);
|
||||
while (G_UNLIKELY (res == -1 && errno == EINTR));
|
||||
if (G_UNLIKELY (res == -1))
|
||||
{
|
||||
glnx_set_prefix_error_from_errno (error, "Querying object %s.%s", sha256, ostree_object_type_to_string (objtype));
|
||||
goto out;
|
||||
}
|
||||
return glnx_throw_errno_prefix (error, "Querying object %s.%s", sha256, ostree_object_type_to_string (objtype));
|
||||
|
||||
*out_size = stbuf.st_size;
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3563,13 +3505,11 @@ ostree_repo_load_commit (OstreeRepo *self,
|
||||
OstreeRepoCommitState *out_state,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
|
||||
if (out_variant)
|
||||
{
|
||||
if (!load_metadata_internal (self, OSTREE_OBJECT_TYPE_COMMIT, checksum, TRUE,
|
||||
out_variant, NULL, NULL, NULL, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (out_state)
|
||||
@@ -3585,14 +3525,11 @@ ostree_repo_load_commit (OstreeRepo *self,
|
||||
}
|
||||
else if (errno != ENOENT)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
return glnx_throw_errno (error);
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3618,15 +3555,13 @@ ostree_repo_list_objects (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autoptr(GHashTable) ret_objects = NULL;
|
||||
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
g_return_val_if_fail (self->inited, FALSE);
|
||||
|
||||
ret_objects = g_hash_table_new_full (ostree_hash_object_name, g_variant_equal,
|
||||
(GDestroyNotify) g_variant_unref,
|
||||
(GDestroyNotify) g_variant_unref);
|
||||
g_autoptr(GHashTable) ret_objects =
|
||||
g_hash_table_new_full (ostree_hash_object_name, g_variant_equal,
|
||||
(GDestroyNotify) g_variant_unref,
|
||||
(GDestroyNotify) g_variant_unref);
|
||||
|
||||
if (flags & OSTREE_REPO_LIST_OBJECTS_ALL)
|
||||
flags |= (OSTREE_REPO_LIST_OBJECTS_LOOSE | OSTREE_REPO_LIST_OBJECTS_PACKED);
|
||||
@@ -3634,11 +3569,11 @@ ostree_repo_list_objects (OstreeRepo *self,
|
||||
if (flags & OSTREE_REPO_LIST_OBJECTS_LOOSE)
|
||||
{
|
||||
if (!list_loose_objects (self, ret_objects, NULL, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
if ((flags & OSTREE_REPO_LIST_OBJECTS_NO_PARENTS) == 0 && self->parent_repo)
|
||||
{
|
||||
if (!list_loose_objects (self->parent_repo, ret_objects, NULL, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3647,10 +3582,8 @@ ostree_repo_list_objects (OstreeRepo *self,
|
||||
/* Nothing for now... */
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
ot_transfer_out_value (out_objects, &ret_objects);
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3720,25 +3653,20 @@ ostree_repo_read_commit (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autoptr(GFile) ret_root = NULL;
|
||||
g_autofree char *resolved_commit = NULL;
|
||||
|
||||
if (!ostree_repo_resolve_rev (self, ref, FALSE, &resolved_commit, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
ret_root = (GFile*) _ostree_repo_file_new_for_commit (self, resolved_commit, error);
|
||||
g_autoptr(GFile) ret_root = (GFile*) _ostree_repo_file_new_for_commit (self, resolved_commit, error);
|
||||
if (!ret_root)
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (!ostree_repo_file_ensure_resolved ((OstreeRepoFile*)ret_root, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
ret = TRUE;
|
||||
ot_transfer_out_value(out_root, &ret_root);
|
||||
ot_transfer_out_value(out_commit, &resolved_commit);
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4225,6 +4153,13 @@ out:
|
||||
|
||||
/**
|
||||
* ostree_repo_sign_delta:
|
||||
* @self: Self
|
||||
* @from_commit: From commit
|
||||
* @to_commit: To commit
|
||||
* @key_id: key id
|
||||
* @homedir: homedir
|
||||
* @cancellable: cancellable
|
||||
* @error: error
|
||||
*
|
||||
* This function is deprecated, sign the summary file instead.
|
||||
* Add a GPG signature to a static delta.
|
||||
@@ -4859,7 +4794,6 @@ _ostree_repo_try_lock_tmpdir (int tmpdir_dfd,
|
||||
gboolean *out_did_lock,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autofree char *lock_name = g_strconcat (tmpdir_name, "-lock", NULL);
|
||||
gboolean did_lock = FALSE;
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
@@ -4876,7 +4810,7 @@ _ostree_repo_try_lock_tmpdir (int tmpdir_dfd,
|
||||
else
|
||||
{
|
||||
g_propagate_error (error, g_steal_pointer (&local_error));
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -4884,10 +4818,8 @@ _ostree_repo_try_lock_tmpdir (int tmpdir_dfd,
|
||||
did_lock = TRUE;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
*out_did_lock = did_lock;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* This allocates and locks a subdir of the repo tmp dir, using an existing
|
||||
|
||||
@@ -123,6 +123,10 @@ gboolean ostree_repo_remote_delete (OstreeRepo *self,
|
||||
/**
|
||||
* OstreeRepoRemoteChange:
|
||||
* The remote change operation.
|
||||
* @OSTREE_REPO_REMOTE_CHANGE_ADD: Add a remote
|
||||
* @OSTREE_REPO_REMOTE_CHANGE_ADD_IF_NOT_EXISTS: Like above, but do nothing if the remote exists
|
||||
* @OSTREE_REPO_REMOTE_CHANGE_DELETE: Delete a remote
|
||||
* @OSTREE_REPO_REMOTE_CHANGE_DELETE_IF_EXISTS: Delete a remote, do nothing if the remote does not exist
|
||||
*/
|
||||
typedef enum {
|
||||
OSTREE_REPO_REMOTE_CHANGE_ADD,
|
||||
@@ -536,11 +540,15 @@ typedef OstreeRepoCommitFilterResult (*OstreeRepoCommitFilter) (OstreeRepo *r
|
||||
* @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_NONE: No special flags
|
||||
* @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS: Do not process extended attributes
|
||||
* @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES: Generate size information.
|
||||
* @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS: Canonicalize permissions for bare-user-only mode.
|
||||
* @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_ERROR_ON_UNLABELED: Emit an error if configured SELinux policy does not provide a label
|
||||
*/
|
||||
typedef enum {
|
||||
OSTREE_REPO_COMMIT_MODIFIER_FLAGS_NONE = 0,
|
||||
OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS = (1 << 0),
|
||||
OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES = (1 << 1)
|
||||
OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES = (1 << 1),
|
||||
OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS = (1 << 2),
|
||||
OSTREE_REPO_COMMIT_MODIFIER_FLAGS_ERROR_ON_UNLABELED = (1 << 3),
|
||||
} OstreeRepoCommitModifierFlags;
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2017 Colin Walters <walters@verbum.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ostree-types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct {
|
||||
gboolean initialized;
|
||||
} OstreeSepolicyFsCreatecon;
|
||||
|
||||
void _ostree_sepolicy_fscreatecon_clear (OstreeSepolicyFsCreatecon *con);
|
||||
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(OstreeSepolicyFsCreatecon, _ostree_sepolicy_fscreatecon_clear)
|
||||
|
||||
gboolean _ostree_sepolicy_preparefscreatecon (OstreeSepolicyFsCreatecon *con,
|
||||
OstreeSePolicy *self,
|
||||
const char *path,
|
||||
guint32 mode,
|
||||
GError **error);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
+128
-29
@@ -28,6 +28,7 @@
|
||||
#include "otutil.h"
|
||||
|
||||
#include "ostree-sepolicy.h"
|
||||
#include "ostree-sepolicy-private.h"
|
||||
#include "ostree-bootloader-uboot.h"
|
||||
#include "ostree-bootloader-syslinux.h"
|
||||
|
||||
@@ -42,6 +43,8 @@
|
||||
struct OstreeSePolicy {
|
||||
GObject parent;
|
||||
|
||||
int rootfs_dfd;
|
||||
int rootfs_dfd_owned;
|
||||
GFile *path;
|
||||
|
||||
gboolean runtime_enabled;
|
||||
@@ -63,7 +66,8 @@ static void initable_iface_init (GInitableIface *initable_iface);
|
||||
enum {
|
||||
PROP_0,
|
||||
|
||||
PROP_PATH
|
||||
PROP_PATH,
|
||||
PROP_ROOTFS_DFD
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (OstreeSePolicy, ostree_sepolicy, G_TYPE_OBJECT,
|
||||
@@ -75,6 +79,8 @@ ostree_sepolicy_finalize (GObject *object)
|
||||
OstreeSePolicy *self = OSTREE_SEPOLICY (object);
|
||||
|
||||
g_clear_object (&self->path);
|
||||
if (self->rootfs_dfd_owned != -1)
|
||||
(void) close (self->rootfs_dfd_owned);
|
||||
#ifdef HAVE_SELINUX
|
||||
g_clear_object (&self->selinux_policy_root);
|
||||
g_clear_pointer (&self->selinux_policy_name, g_free);
|
||||
@@ -100,8 +106,25 @@ ostree_sepolicy_set_property(GObject *object,
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PATH:
|
||||
/* Canonicalize */
|
||||
self->path = g_file_new_for_path (gs_file_get_path_cached (g_value_get_object (value)));
|
||||
{
|
||||
GFile *path = g_value_get_object (value);
|
||||
if (path)
|
||||
{
|
||||
/* Canonicalize */
|
||||
self->path = g_file_new_for_path (gs_file_get_path_cached (path));
|
||||
g_assert_cmpint (self->rootfs_dfd, ==, -1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PROP_ROOTFS_DFD:
|
||||
{
|
||||
int fd = g_value_get_int (value);
|
||||
if (fd != -1)
|
||||
{
|
||||
g_assert (self->path == NULL);
|
||||
self->rootfs_dfd = fd;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
@@ -122,6 +145,9 @@ ostree_sepolicy_get_property(GObject *object,
|
||||
case PROP_PATH:
|
||||
g_value_set_object (value, self->path);
|
||||
break;
|
||||
case PROP_ROOTFS_DFD:
|
||||
g_value_set_int (value, self->rootfs_dfd);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -133,7 +159,7 @@ ostree_sepolicy_constructed (GObject *object)
|
||||
{
|
||||
OstreeSePolicy *self = OSTREE_SEPOLICY (object);
|
||||
|
||||
g_assert (self->path != NULL);
|
||||
g_assert (self->path != NULL || self->rootfs_dfd != -1);
|
||||
|
||||
G_OBJECT_CLASS (ostree_sepolicy_parent_class)->constructed (object);
|
||||
}
|
||||
@@ -155,6 +181,13 @@ ostree_sepolicy_class_init (OstreeSePolicyClass *klass)
|
||||
"",
|
||||
G_TYPE_FILE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_ROOTFS_DFD,
|
||||
g_param_spec_int ("rootfs-dfd",
|
||||
"", "",
|
||||
-1, G_MAXINT, -1,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
}
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
@@ -252,6 +285,7 @@ initable_init (GInitable *initable,
|
||||
#ifdef HAVE_SELINUX
|
||||
gboolean ret = FALSE;
|
||||
OstreeSePolicy *self = OSTREE_SEPOLICY (initable);
|
||||
g_autoptr(GFile) path = NULL;
|
||||
g_autoptr(GFile) etc_selinux_dir = NULL;
|
||||
g_autoptr(GFile) policy_config_path = NULL;
|
||||
g_autoptr(GFile) policy_root = NULL;
|
||||
@@ -262,11 +296,28 @@ initable_init (GInitable *initable,
|
||||
const char *selinux_prefix = "SELINUX=";
|
||||
const char *selinuxtype_prefix = "SELINUXTYPE=";
|
||||
|
||||
etc_selinux_dir = g_file_resolve_relative_path (self->path, "etc/selinux");
|
||||
/* TODO - use this below */
|
||||
if (self->rootfs_dfd != -1)
|
||||
path = ot_fdrel_to_gfile (self->rootfs_dfd, ".");
|
||||
else if (self->path)
|
||||
{
|
||||
path = g_object_ref (self->path);
|
||||
#if 0
|
||||
/* TODO - use this below */
|
||||
if (!glnx_opendirat (AT_FDCWD, gs_file_get_path_cached (self->path), TRUE,
|
||||
&self->rootfs_dfd_owned, error))
|
||||
goto out;
|
||||
self->rootfs_dfd = self->rootfs_dfd_owned;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
|
||||
etc_selinux_dir = g_file_resolve_relative_path (path, "etc/selinux");
|
||||
if (!g_file_query_exists (etc_selinux_dir, NULL))
|
||||
{
|
||||
g_object_unref (etc_selinux_dir);
|
||||
etc_selinux_dir = g_file_resolve_relative_path (self->path, "usr/etc/selinux");
|
||||
etc_selinux_dir = g_file_resolve_relative_path (path, "usr/etc/selinux");
|
||||
}
|
||||
policy_config_path = g_file_get_child (etc_selinux_dir, "config");
|
||||
|
||||
@@ -367,6 +418,8 @@ initable_init (GInitable *initable,
|
||||
static void
|
||||
ostree_sepolicy_init (OstreeSePolicy *self)
|
||||
{
|
||||
self->rootfs_dfd = -1;
|
||||
self->rootfs_dfd_owned = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -378,6 +431,8 @@ initable_iface_init (GInitableIface *initable_iface)
|
||||
/**
|
||||
* ostree_sepolicy_new:
|
||||
* @path: Path to a root directory
|
||||
* @cancellable: Cancellable
|
||||
* @error: Error
|
||||
*
|
||||
* Returns: (transfer full): An accessor object for SELinux policy in root located at @path
|
||||
*/
|
||||
@@ -389,6 +444,22 @@ ostree_sepolicy_new (GFile *path,
|
||||
return g_initable_new (OSTREE_TYPE_SEPOLICY, cancellable, error, "path", path, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_sepolicy_new_at:
|
||||
* @rootfs_dfd: Directory fd for rootfs (will not be cloned)
|
||||
* @cancellable: Cancellable
|
||||
* @error: Error
|
||||
*
|
||||
* Returns: (transfer full): An accessor object for SELinux policy in root located at @rootfs_dfd
|
||||
*/
|
||||
OstreeSePolicy*
|
||||
ostree_sepolicy_new_at (int rootfs_dfd,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
return g_initable_new (OSTREE_TYPE_SEPOLICY, cancellable, error, "rootfs-dfd", rootfs_dfd, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_sepolicy_get_path:
|
||||
* @self:
|
||||
@@ -455,35 +526,34 @@ ostree_sepolicy_get_label (OstreeSePolicy *self,
|
||||
GError **error)
|
||||
{
|
||||
#ifdef HAVE_SELINUX
|
||||
gboolean ret = FALSE;
|
||||
int res;
|
||||
char *con = NULL;
|
||||
/* Early return if no policy */
|
||||
if (!self->selinux_hnd)
|
||||
return TRUE;
|
||||
|
||||
if (self->selinux_hnd)
|
||||
/* http://marc.info/?l=selinux&m=149082134430052&w=2
|
||||
* https://github.com/ostreedev/ostree/pull/768
|
||||
*/
|
||||
if (strcmp (relpath, "/proc") == 0)
|
||||
relpath = "/mnt";
|
||||
|
||||
char *con = NULL;
|
||||
int res = selabel_lookup_raw (self->selinux_hnd, &con, relpath, unix_mode);
|
||||
if (res != 0)
|
||||
{
|
||||
res = selabel_lookup_raw (self->selinux_hnd, &con, relpath, unix_mode);
|
||||
if (res != 0)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (errno == ENOENT)
|
||||
*out_label = NULL;
|
||||
else
|
||||
{
|
||||
/* Ensure we consistently allocate with g_malloc */
|
||||
*out_label = g_strdup (con);
|
||||
freecon (con);
|
||||
}
|
||||
return glnx_throw_errno (error);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Ensure we consistently allocate with g_malloc */
|
||||
*out_label = g_strdup (con);
|
||||
freecon (con);
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
#else
|
||||
return TRUE;
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -621,6 +691,7 @@ ostree_sepolicy_setfscreatecon (OstreeSePolicy *self,
|
||||
|
||||
/**
|
||||
* ostree_sepolicy_fscreatecon_cleanup:
|
||||
* @unused: Not used, just in case you didn't infer that from the parameter name
|
||||
*
|
||||
* Cleanup function for ostree_sepolicy_setfscreatecon().
|
||||
*/
|
||||
@@ -631,3 +702,31 @@ ostree_sepolicy_fscreatecon_cleanup (void **unused)
|
||||
setfscreatecon (NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Currently private copy of the older sepolicy/fscreatecon API with a nicer
|
||||
* g_auto() cleanup. May be made public later.
|
||||
*/
|
||||
gboolean
|
||||
_ostree_sepolicy_preparefscreatecon (OstreeSepolicyFsCreatecon *con,
|
||||
OstreeSePolicy *self,
|
||||
const char *path,
|
||||
guint32 mode,
|
||||
GError **error)
|
||||
{
|
||||
if (!self || ostree_sepolicy_get_name (self) == NULL)
|
||||
return TRUE;
|
||||
|
||||
if (!ostree_sepolicy_setfscreatecon (self, path, mode, error))
|
||||
return FALSE;
|
||||
|
||||
con->initialized = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_ostree_sepolicy_fscreatecon_clear (OstreeSepolicyFsCreatecon *con)
|
||||
{
|
||||
if (!con->initialized)
|
||||
return;
|
||||
ostree_sepolicy_fscreatecon_cleanup (NULL);
|
||||
}
|
||||
@@ -38,6 +38,12 @@ OstreeSePolicy* ostree_sepolicy_new (GFile *path,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
OstreeSePolicy* ostree_sepolicy_new_at (int rootfs_dfd,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
GFile * ostree_sepolicy_get_path (OstreeSePolicy *self);
|
||||
|
||||
|
||||
@@ -515,12 +515,7 @@ ostree_sysroot_cleanup (OstreeSysroot *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
OstreeSysrootCleanupFlags flags;
|
||||
|
||||
/* Do everything. */
|
||||
flags = OSTREE_SYSROOT_CLEANUP_ALL;
|
||||
|
||||
return _ostree_sysroot_piecemeal_cleanup (self, flags, cancellable, error);
|
||||
return _ostree_sysroot_cleanup_internal (self, TRUE, cancellable, error);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -537,55 +532,41 @@ ostree_sysroot_prepare_cleanup (OstreeSysroot *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
OstreeSysrootCleanupFlags flags;
|
||||
|
||||
/* Do everything EXCEPT pruning the repository. */
|
||||
flags = OSTREE_SYSROOT_CLEANUP_ALL & ~OSTREE_SYSROOT_CLEANUP_PRUNE_REPO;
|
||||
|
||||
return _ostree_sysroot_piecemeal_cleanup (self, flags, cancellable, error);
|
||||
return _ostree_sysroot_cleanup_internal (self, FALSE, cancellable, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_ostree_sysroot_piecemeal_cleanup (OstreeSysroot *self,
|
||||
OstreeSysrootCleanupFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
_ostree_sysroot_cleanup_internal (OstreeSysroot *self,
|
||||
gboolean do_prune_repo,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
glnx_unref_object OstreeRepo *repo = NULL;
|
||||
|
||||
g_return_val_if_fail (OSTREE_IS_SYSROOT (self), FALSE);
|
||||
g_return_val_if_fail (self->loaded, FALSE);
|
||||
|
||||
if (flags & OSTREE_SYSROOT_CLEANUP_BOOTVERSIONS)
|
||||
{
|
||||
if (!cleanup_other_bootversions (self, cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
if (!cleanup_other_bootversions (self, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
if (flags & OSTREE_SYSROOT_CLEANUP_DEPLOYMENTS)
|
||||
{
|
||||
if (!cleanup_old_deployments (self, cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
if (!cleanup_old_deployments (self, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
if (!ostree_sysroot_get_repo (self, &repo, cancellable, error))
|
||||
goto out;
|
||||
|
||||
return FALSE;
|
||||
|
||||
if (!generate_deployment_refs (self, repo,
|
||||
self->bootversion,
|
||||
self->subbootversion,
|
||||
self->deployments,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (flags & OSTREE_SYSROOT_CLEANUP_PRUNE_REPO)
|
||||
return FALSE;
|
||||
|
||||
if (do_prune_repo)
|
||||
{
|
||||
if (!prune_repo (repo, cancellable, error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -30,7 +30,9 @@ G_BEGIN_DECLS
|
||||
typedef enum {
|
||||
|
||||
/* Don't flag deployments as immutable. */
|
||||
OSTREE_SYSROOT_DEBUG_MUTABLE_DEPLOYMENTS = 1 << 0
|
||||
OSTREE_SYSROOT_DEBUG_MUTABLE_DEPLOYMENTS = 1 << 0,
|
||||
/* See https://github.com/ostreedev/ostree/pull/759 */
|
||||
OSTREE_SYSROOT_DEBUG_NO_XATTRS = 1 << 1,
|
||||
|
||||
} OstreeSysrootDebugFlags;
|
||||
|
||||
@@ -47,8 +49,6 @@ struct OstreeSysroot {
|
||||
|
||||
gboolean loaded;
|
||||
|
||||
OstreeSePolicy *sepolicy;
|
||||
|
||||
GPtrArray *deployments;
|
||||
int bootversion;
|
||||
int subbootversion;
|
||||
@@ -109,22 +109,9 @@ gboolean _ostree_sysroot_query_bootloader (OstreeSysroot *sysroot,
|
||||
gboolean _ostree_sysroot_bump_mtime (OstreeSysroot *sysroot,
|
||||
GError **error);
|
||||
|
||||
typedef enum {
|
||||
OSTREE_SYSROOT_CLEANUP_BOOTVERSIONS = 1 << 0,
|
||||
OSTREE_SYSROOT_CLEANUP_DEPLOYMENTS = 1 << 1,
|
||||
OSTREE_SYSROOT_CLEANUP_PRUNE_REPO = 1 << 2,
|
||||
OSTREE_SYSROOT_CLEANUP_ALL = 0xffff
|
||||
} OstreeSysrootCleanupFlags;
|
||||
|
||||
gboolean _ostree_sysroot_piecemeal_cleanup (OstreeSysroot *sysroot,
|
||||
OstreeSysrootCleanupFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
gboolean _ostree_sysroot_write_deployments_internal (OstreeSysroot *self,
|
||||
GPtrArray *new_deployments,
|
||||
OstreeSysrootCleanupFlags cleanup_flags,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
gboolean _ostree_sysroot_cleanup_internal (OstreeSysroot *sysroot,
|
||||
gboolean prune_repo,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -293,6 +293,8 @@ ostree_sysroot_upgrader_init (OstreeSysrootUpgrader *self)
|
||||
/**
|
||||
* ostree_sysroot_upgrader_new:
|
||||
* @sysroot: An #OstreeSysroot
|
||||
* @cancellable: Cancellable
|
||||
* @error: Error
|
||||
*
|
||||
* Returns: (transfer full): An upgrader
|
||||
*/
|
||||
@@ -309,6 +311,8 @@ ostree_sysroot_upgrader_new (OstreeSysroot *sysroot,
|
||||
* ostree_sysroot_upgrader_new_for_os:
|
||||
* @sysroot: An #OstreeSysroot
|
||||
* @osname: (allow-none): Operating system name
|
||||
* @cancellable: Cancellable
|
||||
* @error: Error
|
||||
*
|
||||
* Returns: (transfer full): An upgrader
|
||||
*/
|
||||
@@ -327,6 +331,8 @@ ostree_sysroot_upgrader_new_for_os (OstreeSysroot *sysroot,
|
||||
* @sysroot: An #OstreeSysroot
|
||||
* @osname: (allow-none): Operating system name
|
||||
* @flags: Flags
|
||||
* @cancellable: Cancellable
|
||||
* @error: Error
|
||||
*
|
||||
* Returns: (transfer full): An upgrader
|
||||
*/
|
||||
@@ -514,6 +520,14 @@ ostree_sysroot_upgrader_pull (OstreeSysrootUpgrader *self,
|
||||
|
||||
/**
|
||||
* ostree_sysroot_upgrader_pull_one_dir:
|
||||
* @self: Upgrader
|
||||
* @dir_to_pull: Subdirectory path (should include a leading /)
|
||||
* @flags: Flags controlling pull behavior
|
||||
* @upgrader_flags: Flags controlling upgrader behavior
|
||||
* @progress: (allow-none): Progress
|
||||
* @out_changed: (out): Whether or not the origin changed
|
||||
* @cancellable: Cancellable
|
||||
* @error: Error
|
||||
*
|
||||
* Like ostree_sysroot_upgrader_pull(), but allows retrieving just a
|
||||
* subpath of the tree. This can be used to download metadata files
|
||||
|
||||
@@ -21,10 +21,12 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "otutil.h"
|
||||
#include <sys/file.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "ostree-core-private.h"
|
||||
#include "ostree-sepolicy-private.h"
|
||||
#include "ostree-sysroot-private.h"
|
||||
#include "ostree-deployment-private.h"
|
||||
#include "ostree-bootloader-uboot.h"
|
||||
@@ -70,7 +72,6 @@ ostree_sysroot_finalize (GObject *object)
|
||||
OstreeSysroot *self = OSTREE_SYSROOT (object);
|
||||
|
||||
g_clear_object (&self->path);
|
||||
g_clear_object (&self->sepolicy);
|
||||
g_clear_object (&self->repo);
|
||||
g_clear_pointer (&self->deployments, g_ptr_array_unref);
|
||||
g_clear_object (&self->booted_deployment);
|
||||
@@ -160,9 +161,10 @@ ostree_sysroot_init (OstreeSysroot *self)
|
||||
{
|
||||
const GDebugKey keys[] = {
|
||||
{ "mutable-deployments", OSTREE_SYSROOT_DEBUG_MUTABLE_DEPLOYMENTS },
|
||||
{ "no-xattrs", OSTREE_SYSROOT_DEBUG_NO_XATTRS },
|
||||
};
|
||||
|
||||
self->debug_flags = g_parse_debug_string (g_getenv("OSTREE_SYSROOT_DEBUG"),
|
||||
self->debug_flags = g_parse_debug_string (g_getenv ("OSTREE_SYSROOT_DEBUG"),
|
||||
keys, G_N_ELEMENTS (keys));
|
||||
|
||||
self->sysroot_fd = -1;
|
||||
@@ -1268,12 +1270,13 @@ ostree_sysroot_get_merge_deployment (OstreeSysroot *self,
|
||||
|
||||
/**
|
||||
* ostree_sysroot_origin_new_from_refspec:
|
||||
* @self: Sysroot
|
||||
* @refspec: A refspec
|
||||
*
|
||||
* Returns: (transfer full): A new config file which sets @refspec as an origin
|
||||
*/
|
||||
GKeyFile *
|
||||
ostree_sysroot_origin_new_from_refspec (OstreeSysroot *sysroot,
|
||||
ostree_sysroot_origin_new_from_refspec (OstreeSysroot *self,
|
||||
const char *refspec)
|
||||
{
|
||||
GKeyFile *ret = g_key_file_new ();
|
||||
@@ -1551,6 +1554,7 @@ ostree_sysroot_simple_write_deployment (OstreeSysroot *sysroot,
|
||||
g_autoptr(GPtrArray) deployments = NULL;
|
||||
g_autoptr(GPtrArray) new_deployments = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
const gboolean postclean = (flags & OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_NO_CLEAN) == 0;
|
||||
OstreeSysrootWriteDeploymentsOpts write_opts = { .do_postclean = postclean };
|
||||
gboolean retain = (flags & OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN) > 0;
|
||||
const gboolean make_default = !((flags & OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_NOT_DEFAULT) > 0);
|
||||
gboolean added_new = FALSE;
|
||||
@@ -1601,9 +1605,8 @@ ostree_sysroot_simple_write_deployment (OstreeSysroot *sysroot,
|
||||
added_new = TRUE;
|
||||
}
|
||||
|
||||
if (!_ostree_sysroot_write_deployments_internal (sysroot, new_deployments,
|
||||
postclean ? OSTREE_SYSROOT_CLEANUP_ALL : 0,
|
||||
cancellable, error))
|
||||
if (!ostree_sysroot_write_deployments_with_options (sysroot, new_deployments, &write_opts,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
ret = TRUE;
|
||||
@@ -1688,6 +1691,7 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
glnx_unref_object OstreeSePolicy *sepolicy = NULL;
|
||||
OstreeDeploymentUnlockedState current_unlocked =
|
||||
ostree_deployment_get_unlocked (deployment);
|
||||
glnx_unref_object OstreeDeployment *deployment_clone =
|
||||
@@ -1735,6 +1739,10 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self,
|
||||
if (!glnx_opendirat (self->sysroot_fd, deployment_path, TRUE, &deployment_dfd, error))
|
||||
goto out;
|
||||
|
||||
sepolicy = ostree_sepolicy_new_at (deployment_dfd, cancellable, error);
|
||||
if (!sepolicy)
|
||||
goto out;
|
||||
|
||||
switch (unlocked_state)
|
||||
{
|
||||
case OSTREE_DEPLOYMENT_UNLOCKED_NONE:
|
||||
@@ -1762,8 +1770,16 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self,
|
||||
const char *development_ovl_upper;
|
||||
const char *development_ovl_work;
|
||||
|
||||
if (!glnx_mkdtempat (AT_FDCWD, development_ovldir, 0700, error))
|
||||
goto out;
|
||||
/* Ensure that the directory is created with the same label as `/usr` */
|
||||
{ g_auto(OstreeSepolicyFsCreatecon) con = { 0, };
|
||||
|
||||
if (!_ostree_sepolicy_preparefscreatecon (&con, sepolicy,
|
||||
"/usr", 0755, error))
|
||||
goto out;
|
||||
|
||||
if (!glnx_mkdtempat (AT_FDCWD, development_ovldir, 0755, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
development_ovl_upper = glnx_strjoina (development_ovldir, "/upper");
|
||||
if (!glnx_shutil_mkdir_p_at (AT_FDCWD, development_ovl_upper, 0755, cancellable, error))
|
||||
|
||||
@@ -145,6 +145,20 @@ gboolean ostree_sysroot_write_deployments (OstreeSysroot *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
typedef struct {
|
||||
gboolean do_postclean;
|
||||
gboolean unused_bools[7];
|
||||
int unused_ints[7];
|
||||
gpointer unused_ptrs[7];
|
||||
} OstreeSysrootWriteDeploymentsOpts;
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
gboolean ostree_sysroot_write_deployments_with_options (OstreeSysroot *self,
|
||||
GPtrArray *new_deployments,
|
||||
OstreeSysrootWriteDeploymentsOpts *opts,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
gboolean ostree_sysroot_deploy_tree (OstreeSysroot *self,
|
||||
const char *osname,
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2017 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the licence or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* SECTION:ostree-version
|
||||
* @short_description: ostree version checking
|
||||
*
|
||||
* ostree provides macros to check the version of the library
|
||||
* at compile-time
|
||||
*/
|
||||
|
||||
/**
|
||||
* OSTREE_YEAR_VERSION:
|
||||
*
|
||||
* ostree year version component (e.g. 2017 if %OSTREE_VERSION is 2017.2)
|
||||
*/
|
||||
#define OSTREE_YEAR_VERSION (2017)
|
||||
|
||||
/**
|
||||
* OSTREE_RELEASE_VERSION:
|
||||
*
|
||||
* ostree release version component (e.g. 2 if %OSTREE_VERSION is 2017.2)
|
||||
*/
|
||||
#define OSTREE_RELEASE_VERSION (4)
|
||||
|
||||
/**
|
||||
* OSTREE_VERSION
|
||||
*
|
||||
* ostree version.
|
||||
*/
|
||||
#define OSTREE_VERSION (2017.4)
|
||||
|
||||
/**
|
||||
* OSTREE_VERSION_S:
|
||||
*
|
||||
* ostree version, encoded as a string, useful for printing and
|
||||
* concatenation.
|
||||
*/
|
||||
#define OSTREE_VERSION_S "2017.4"
|
||||
|
||||
#define OSTREE_ENCODE_VERSION(year,release) \
|
||||
((year) << 16 | (release))
|
||||
|
||||
/**
|
||||
* OSTREE_VERSION_HEX:
|
||||
*
|
||||
* ostree version, encoded as an hexadecimal number, useful for
|
||||
* integer comparisons.
|
||||
*/
|
||||
#define OSTREE_VERSION_HEX \
|
||||
(OSTREE_ENCODE_VERSION (OSTREE_YEAR_VERSION, OSTREE_RELEASE_VERSION))
|
||||
|
||||
/**
|
||||
* OSTREE_CHECK_VERSION:
|
||||
* @year: required year version
|
||||
* @release: required release version
|
||||
*
|
||||
* Compile-time version checking. Evaluates to %TRUE if the version
|
||||
* of ostree is equal or greater than the required one.
|
||||
*/
|
||||
#define OSTREE_CHECK_VERSION(year,release) \
|
||||
(OSTREE_YEAR_VERSION > (year) || \
|
||||
(OSTREE_YEAR_VERSION == (year) && OSTREE_RELEASE_VERSION >= (release)))
|
||||
@@ -0,0 +1,82 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2017 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the licence or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* SECTION:ostree-version
|
||||
* @short_description: ostree version checking
|
||||
*
|
||||
* ostree provides macros to check the version of the library
|
||||
* at compile-time
|
||||
*/
|
||||
|
||||
/**
|
||||
* OSTREE_YEAR_VERSION:
|
||||
*
|
||||
* ostree year version component (e.g. 2017 if %OSTREE_VERSION is 2017.2)
|
||||
*/
|
||||
#define OSTREE_YEAR_VERSION (@YEAR_VERSION@)
|
||||
|
||||
/**
|
||||
* OSTREE_RELEASE_VERSION:
|
||||
*
|
||||
* ostree release version component (e.g. 2 if %OSTREE_VERSION is 2017.2)
|
||||
*/
|
||||
#define OSTREE_RELEASE_VERSION (@RELEASE_VERSION@)
|
||||
|
||||
/**
|
||||
* OSTREE_VERSION
|
||||
*
|
||||
* ostree version.
|
||||
*/
|
||||
#define OSTREE_VERSION (@VERSION@)
|
||||
|
||||
/**
|
||||
* OSTREE_VERSION_S:
|
||||
*
|
||||
* ostree version, encoded as a string, useful for printing and
|
||||
* concatenation.
|
||||
*/
|
||||
#define OSTREE_VERSION_S "@VERSION@"
|
||||
|
||||
#define OSTREE_ENCODE_VERSION(year,release) \
|
||||
((year) << 16 | (release))
|
||||
|
||||
/**
|
||||
* OSTREE_VERSION_HEX:
|
||||
*
|
||||
* ostree version, encoded as an hexadecimal number, useful for
|
||||
* integer comparisons.
|
||||
*/
|
||||
#define OSTREE_VERSION_HEX \
|
||||
(OSTREE_ENCODE_VERSION (OSTREE_YEAR_VERSION, OSTREE_RELEASE_VERSION))
|
||||
|
||||
/**
|
||||
* OSTREE_CHECK_VERSION:
|
||||
* @year: required year version
|
||||
* @release: required release version
|
||||
*
|
||||
* Compile-time version checking. Evaluates to %TRUE if the version
|
||||
* of ostree is equal or greater than the required one.
|
||||
*/
|
||||
#define OSTREE_CHECK_VERSION(year,release) \
|
||||
(OSTREE_YEAR_VERSION > (year) || \
|
||||
(OSTREE_YEAR_VERSION == (year) && OSTREE_RELEASE_VERSION >= (release)))
|
||||
@@ -33,3 +33,4 @@
|
||||
#include <ostree-gpg-verify-result.h>
|
||||
|
||||
#include <ostree-autocleanups.h>
|
||||
#include <ostree-version.h>
|
||||
Reference in new issue
Block a user