New upstream version 2017.4

This commit is contained in:
Simon McVittie committed 2017-04-17 15:25:30 +01:00
commit 0b7290b235
168 files changed
+3573 -2254

No files matched your search

+11 -2
View File
@@ -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
+1 -5
View File
@@ -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
+1 -1
View File
@@ -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))
+9
View File
@@ -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
View File
@@ -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 (&regex_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 (&regex_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 (&regex_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);
}
+6 -1
View File
@@ -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
+57 -2
View File
@@ -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;
}
}
+36
View File
@@ -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,
+19
View File
@@ -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"))
+7 -6
View File
@@ -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);
}
+50 -9
View File
@@ -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;
File diff suppressed because it is too large. Load diff
+1
View File
@@ -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;
+52 -23
View File
@@ -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
View File
@@ -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
View File
@@ -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
+9 -1
View File
@@ -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;
/**
@@ -1,6 +1,6 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2011 Colin Walters <walters@verbum.org>.
* 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
@@ -16,18 +16,26 @@
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Colin Walters <walters@verbum.org>
*/
#pragma once
#include <gio/gio.h>
#include "ostree-types.h"
G_BEGIN_DECLS
GThreadPool * ot_thread_pool_new_nproc (GFunc func,
gpointer user_data);
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
View File
@@ -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);
}
+6
View File
@@ -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);
+17 -36
View File
@@ -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
+7 -20
View File
@@ -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
+14
View File
@@ -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
+24 -8
View File
@@ -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))
+14
View File
@@ -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,
+82
View File
@@ -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)))
+82
View File
@@ -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)))
+1
View File
@@ -33,3 +33,4 @@
#include <ostree-gpg-verify-result.h>
#include <ostree-autocleanups.h>
#include <ostree-version.h>
+195
View File
@@ -0,0 +1,195 @@
/* -*- 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.
*/
#include "config.h"
#include "ot-checksum-instream.h"
#include "ot-checksum-utils.h"
#ifdef HAVE_OPENSSL
#include <openssl/evp.h>
#endif
G_DEFINE_TYPE (OtChecksumInstream, ot_checksum_instream, G_TYPE_FILTER_INPUT_STREAM)
struct _OtChecksumInstreamPrivate {
#ifdef HAVE_OPENSSL
EVP_MD_CTX *checksum;
#else
GChecksumType checksum_type;
GChecksum *checksum;
#endif
};
static gssize ot_checksum_instream_read (GInputStream *stream,
void *buffer,
gsize count,
GCancellable *cancellable,
GError **error);
static void
ot_checksum_instream_finalize (GObject *object)
{
OtChecksumInstream *self = (OtChecksumInstream*)object;
#ifdef HAVE_OPENSSL
EVP_MD_CTX_destroy (self->priv->checksum);
#else
g_checksum_free (self->priv->checksum);
#endif
G_OBJECT_CLASS (ot_checksum_instream_parent_class)->finalize (object);
}
static void
ot_checksum_instream_class_init (OtChecksumInstreamClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
g_type_class_add_private (klass, sizeof (OtChecksumInstreamPrivate));
object_class->finalize = ot_checksum_instream_finalize;
stream_class->read_fn = ot_checksum_instream_read;
}
static void
ot_checksum_instream_init (OtChecksumInstream *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, OT_TYPE_CHECKSUM_INSTREAM, OtChecksumInstreamPrivate);
}
#ifdef HAVE_OPENSSL
static const EVP_MD *
gchecksum_type_to_openssl (GChecksumType checksum_type)
{
switch (checksum_type)
{
case G_CHECKSUM_SHA256:
return EVP_sha256 ();
default:
/* If there's something else, fill in here */
g_assert_not_reached ();
}
}
#endif
OtChecksumInstream *
ot_checksum_instream_new (GInputStream *base,
GChecksumType checksum_type)
{
OtChecksumInstream *stream;
g_return_val_if_fail (G_IS_INPUT_STREAM (base), NULL);
stream = g_object_new (OT_TYPE_CHECKSUM_INSTREAM,
"base-stream", base,
NULL);
/* For now */
g_assert (checksum_type == G_CHECKSUM_SHA256);
#ifdef HAVE_OPENSSL
stream->priv->checksum = EVP_MD_CTX_create ();
g_assert (stream->priv->checksum);
g_assert (EVP_DigestInit_ex (stream->priv->checksum, gchecksum_type_to_openssl (checksum_type), NULL));
#else
stream->priv->checksum = g_checksum_new (checksum_type);
stream->priv->checksum_type = checksum_type;
#endif
return (OtChecksumInstream*) (stream);
}
static gssize
ot_checksum_instream_read (GInputStream *stream,
void *buffer,
gsize count,
GCancellable *cancellable,
GError **error)
{
OtChecksumInstream *self = (OtChecksumInstream*) stream;
GFilterInputStream *fself = (GFilterInputStream*) self;
gssize res = -1;
res = g_input_stream_read (fself->base_stream,
buffer,
count,
cancellable,
error);
if (res > 0)
{
#ifdef HAVE_OPENSSL
g_assert (EVP_DigestUpdate (self->priv->checksum, buffer, res));
#else
g_checksum_update (self->priv->checksum, buffer, res);
#endif
}
return res;
}
void
ot_checksum_instream_get_digest (OtChecksumInstream *stream,
guint8 *buffer,
gsize *digest_len)
{
#ifdef HAVE_OPENSSL
unsigned len;
EVP_DigestFinal_ex (stream->priv->checksum, buffer, &len);
if (digest_len)
*digest_len = len;
#else
g_checksum_get_digest (stream->priv->checksum, buffer, digest_len);
#endif
}
guint8*
ot_checksum_instream_dup_digest (OtChecksumInstream *stream,
gsize *ret_len)
{
#ifdef HAVE_OPENSSL
guint len;
guchar *ret = g_malloc0 (EVP_MAX_MD_SIZE);
g_assert (EVP_DigestFinal_ex (stream->priv->checksum, ret, &len));
#else
gsize len = g_checksum_type_get_length (stream->priv->checksum_type);
guchar *ret = g_malloc (len);
g_checksum_get_digest (stream->priv->checksum, ret, &len);
#endif
if (ret_len)
*ret_len = len;
return ret;
}
char *
ot_checksum_instream_get_string (OtChecksumInstream *stream)
{
#ifdef HAVE_OPENSSL
unsigned len;
guint8 csum[EVP_MAX_MD_SIZE];
g_assert (EVP_DigestFinal_ex (stream->priv->checksum, csum, &len));
char *buf = g_malloc (len * 2 + 1);
ot_bin2hex (buf, (guint8*)csum, len);
return buf;
#else
return g_strdup (g_checksum_get_string (stream->priv->checksum));
#endif
}
+64
View File
@@ -0,0 +1,64 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2011 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 <gio/gio.h>
G_BEGIN_DECLS
#define OT_TYPE_CHECKSUM_INSTREAM (ot_checksum_instream_get_type ())
#define OT_CHECKSUM_INSTREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OT_TYPE_CHECKSUM_INPUT_STREAM, OtChecksumInstream))
#define OT_CHECKSUM_INSTREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), OT_TYPE_CHECKSUM_INPUT_STREAM, OtChecksumInstreamClass))
#define OT_IS_CHECKSUM_INSTREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OT_TYPE_CHECKSUM_INPUT_STREAM))
#define OT_IS_CHECKSUM_INSTREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OT_TYPE_CHECKSUM_INPUT_STREAM))
#define OT_CHECKSUM_INSTREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OT_TYPE_CHECKSUM_INPUT_STREAM, OtChecksumInstreamClass))
typedef struct _OtChecksumInstream OtChecksumInstream;
typedef struct _OtChecksumInstreamClass OtChecksumInstreamClass;
typedef struct _OtChecksumInstreamPrivate OtChecksumInstreamPrivate;
struct _OtChecksumInstream
{
GFilterInputStream parent_instance;
/*< private >*/
OtChecksumInstreamPrivate *priv;
};
struct _OtChecksumInstreamClass
{
GFilterInputStreamClass parent_class;
};
GType ot_checksum_instream_get_type (void) G_GNUC_CONST;
OtChecksumInstream * ot_checksum_instream_new (GInputStream *stream, GChecksumType checksum);
void ot_checksum_instream_get_digest (OtChecksumInstream *stream,
guint8 *buffer,
gsize *digest_len);
guint8* ot_checksum_instream_dup_digest (OtChecksumInstream *stream,
gsize *ret_len);
char * ot_checksum_instream_get_string (OtChecksumInstream *stream);
G_END_DECLS
+16 -43
View File
@@ -26,6 +26,22 @@
#include <string.h>
void
ot_bin2hex (char *out_buf, const guint8 *inbuf, gsize len)
{
static const gchar hexchars[] = "0123456789abcdef";
guint i, j;
for (i = 0, j = 0; i < len; i++, j += 2)
{
guchar byte = inbuf[i];
out_buf[j] = hexchars[byte >> 4];
out_buf[j+1] = hexchars[byte & 0xF];
}
out_buf[j] = '\0';
}
guchar *
ot_csum_from_gchecksum (GChecksum *checksum)
{
@@ -164,46 +180,3 @@ ot_checksum_file_at (int dfd,
return ret;
}
static void
checksum_stream_thread (GSimpleAsyncResult *result,
GObject *object,
GCancellable *cancellable)
{
GError *error = NULL;
guchar *csum;
if (!ot_gio_checksum_stream ((GInputStream*)object, &csum,
cancellable, &error))
g_simple_async_result_take_error (result, error);
else
g_simple_async_result_set_op_res_gpointer (result, csum, g_free);
}
void
ot_gio_checksum_stream_async (GInputStream *in,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSimpleAsyncResult *result;
result = g_simple_async_result_new ((GObject*) in,
callback, user_data,
ot_gio_checksum_stream_async);
g_simple_async_result_run_in_thread (result, checksum_stream_thread, io_priority, cancellable);
g_object_unref (result);
}
guchar *
ot_gio_checksum_stream_finish (GInputStream *in,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == ot_gio_checksum_stream_async);
return g_memdup (g_simple_async_result_get_op_res_gpointer (simple), 32);
}
+2 -10
View File
@@ -26,6 +26,8 @@
G_BEGIN_DECLS
void ot_bin2hex (char *out_buf, const guint8 *inbuf, gsize len);
guchar *ot_csum_from_gchecksum (GChecksum *checksum);
gboolean ot_gio_write_update_checksum (GOutputStream *out,
@@ -59,14 +61,4 @@ char * ot_checksum_file_at (int dfd,
GCancellable *cancellable,
GError **error);
void ot_gio_checksum_stream_async (GInputStream *in,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
guchar * ot_gio_checksum_stream_finish (GInputStream *in,
GAsyncResult *result,
GError **error);
G_END_DECLS
+34
View File
@@ -25,6 +25,16 @@
#include <sys/xattr.h>
#include <gio/gunixinputstream.h>
/* Convert a fd-relative path to a GFile* - use
* for legacy code.
*/
GFile *
ot_fdrel_to_gfile (int dfd, const char *path)
{
g_autofree char *abspath = glnx_fdrel_abspath (dfd, path);
return g_file_new_for_path (abspath);
}
int
ot_opendirat (int dfd, const char *path, gboolean follow)
{
@@ -205,6 +215,30 @@ ot_ensure_unlinked_at (int dfd,
return TRUE;
}
gboolean
ot_query_exists_at (int dfd, const char *path,
gboolean *out_exists,
GError **error)
{
struct stat stbuf;
gboolean ret_exists;
if (fstatat (dfd, path, &stbuf, AT_SYMLINK_NOFOLLOW) < 0)
{
if (errno != ENOENT)
{
glnx_set_error_from_errno (error);
return FALSE;
}
ret_exists = FALSE;
}
else
ret_exists = TRUE;
*out_exists = ret_exists;
return TRUE;
}
gboolean
ot_openat_ignore_enoent (int dfd,
const char *path,
+7
View File
@@ -24,6 +24,8 @@
G_BEGIN_DECLS
GFile * ot_fdrel_to_gfile (int dfd, const char *path);
int ot_opendirat (int dfd, const char *path, gboolean follow);
gboolean ot_gopendirat (int dfd,
const char *path,
@@ -57,6 +59,11 @@ gboolean ot_openat_read_stream (int dfd,
GCancellable *cancellable,
GError **error);
gboolean ot_query_exists_at (int dfd, const char *path,
gboolean *out_exists,
GError **error);
gboolean ot_ensure_unlinked_at (int dfd,
const char *path,
GError **error);
-209
View File
@@ -51,91 +51,6 @@ ot_gfile_type_for_mode (guint32 mode)
}
GFile *
ot_gfile_from_build_path (const char *first, ...)
{
va_list args;
const char *arg;
g_autofree char *path = NULL;
g_autoptr(GPtrArray) components = NULL;
va_start (args, first);
components = g_ptr_array_new ();
arg = first;
while (arg != NULL)
{
g_ptr_array_add (components, (char*)arg);
arg = va_arg (args, const char *);
}
va_end (args);
g_ptr_array_add (components, NULL);
path = g_build_filenamev ((char**)components->pdata);
return g_file_new_for_path (path);
}
GFile *
ot_gfile_get_child_strconcat (GFile *parent,
const char *first,
...)
{
va_list args;
GFile *ret;
GString *buf;
const char *arg;
g_return_val_if_fail (first != NULL, NULL);
va_start (args, first);
buf = g_string_new (first);
while ((arg = va_arg (args, const char *)) != NULL)
g_string_append (buf, arg);
va_end (args);
ret = g_file_get_child (parent, buf->str);
g_string_free (buf, TRUE);
return ret;
}
GFile *
ot_gfile_get_child_build_path (GFile *parent,
const char *first, ...)
{
va_list args;
const char *arg;
g_autofree char *path = NULL;
g_autoptr(GPtrArray) components = NULL;
va_start (args, first);
components = g_ptr_array_new ();
arg = first;
while (arg != NULL)
{
g_ptr_array_add (components, (char*)arg);
arg = va_arg (args, const char *);
}
va_end (args);
g_ptr_array_add (components, NULL);
path = g_build_filenamev ((char**)components->pdata);
return g_file_resolve_relative_path (parent, path);
}
GFile *
ot_gfile_resolve_path_printf (GFile *path,
const char *format,
@@ -151,130 +66,6 @@ ot_gfile_resolve_path_printf (GFile *path,
return g_file_resolve_relative_path (path, relpath);
}
gboolean
ot_gfile_get_symlink_target_from_info (GFile *path,
GFileInfo *file_info,
GFile **out_target,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
const char *target;
g_autoptr(GFile) path_parent = NULL;
g_autoptr(GFile) ret_target = NULL;
if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_SYMBOLIC_LINK)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Not a symbolic link");
goto out;
}
path_parent = g_file_get_parent (path);
target = g_file_info_get_symlink_target (file_info);
g_assert (target);
ret_target = g_file_resolve_relative_path (path_parent, target);
ret = TRUE;
out:
ot_transfer_out_value (out_target, &ret_target);
return ret;
}
gboolean
ot_gfile_query_info_allow_noent (GFile *path,
const char *queryopts,
GFileQueryInfoFlags flags,
GFileInfo **out_info,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GFileInfo) ret_file_info = NULL;
GError *temp_error = NULL;
ret_file_info = g_file_query_info (path, queryopts, flags,
cancellable, &temp_error);
if (!ret_file_info)
{
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
g_clear_error (&temp_error);
}
else
{
g_propagate_error (error, temp_error);
goto out;
}
}
ret = TRUE;
ot_transfer_out_value (out_info, &ret_file_info);
out:
return ret;
}
gboolean
ot_gfile_query_symlink_target_allow_noent (GFile *path,
GFile **out_target,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GFileInfo) file_info = NULL;
g_autoptr(GFile) ret_target = NULL;
if (!ot_gfile_query_info_allow_noent (path, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
&file_info,
cancellable, error))
goto out;
if (file_info != NULL)
{
if (!ot_gfile_get_symlink_target_from_info (path, file_info, &ret_target,
cancellable, error))
goto out;
}
ret = TRUE;
ot_transfer_out_value (out_target, &ret_target);
out:
return ret;
}
gboolean
ot_gfile_load_contents_utf8_allow_noent (GFile *path,
char **out_contents,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
GError *temp_error = NULL;
g_autofree char *ret_contents = NULL;
ret_contents = glnx_file_get_contents_utf8_at (AT_FDCWD, gs_file_get_path_cached (path), NULL,
cancellable, &temp_error);
if (!ret_contents)
{
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
g_clear_error (&temp_error);
}
else
{
g_propagate_error (error, temp_error);
goto out;
}
}
ret = TRUE;
ot_transfer_out_value (out_contents, &ret_contents);
out:
return ret;
}
/**
* ot_gfile_replace_contents_fsync:
*
-37
View File
@@ -35,47 +35,10 @@ G_BEGIN_DECLS
GFileType ot_gfile_type_for_mode (guint32 mode);
GFile *ot_gfile_from_build_path (const char *first, ...) G_GNUC_NULL_TERMINATED;
GFile *ot_gfile_get_child_strconcat (GFile *parent, const char *first, ...) G_GNUC_NULL_TERMINATED;
GFile *ot_gfile_get_child_build_path (GFile *parent, const char *first, ...) G_GNUC_NULL_TERMINATED;
GFile * ot_gfile_resolve_path_printf (GFile *path,
const char *format,
...) G_GNUC_PRINTF(2, 3);
gboolean ot_gfile_get_symlink_target_from_info (GFile *path,
GFileInfo *file_info,
GFile **out_target,
GCancellable *cancellable,
GError **error);
gboolean ot_gfile_query_info_allow_noent (GFile *path,
const char *queryopts,
GFileQueryInfoFlags flags,
GFileInfo **out_info,
GCancellable *cancellable,
GError **error);
gboolean ot_gfile_query_symlink_target_allow_noent (GFile *path,
GFile **out_target,
GCancellable *cancellable,
GError **error);
gboolean ot_gfile_load_contents_utf8_allow_noent (GFile *path,
char **out_contents,
GCancellable *cancellable,
GError **error);
gboolean ot_file_replace_contents_at (int dfd,
const char *path,
GBytes *contents,
gboolean datasync,
GCancellable *cancellable,
GError **error);
gboolean ot_gfile_replace_contents_fsync (GFile *path,
GBytes *contents,
GCancellable *cancellable,
-49
View File
@@ -1,49 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2011 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.
*
* Author: Colin Walters <walters@verbum.org>
*/
#include "config.h"
#include "otutil.h"
#include <string.h>
/**
* ot_thread_pool_new_nproc:
*
* Like g_thread_pool_new (), but choose number of threads appropriate
* for CPU bound workers automatically. Also aborts on error.
*/
GThreadPool *
ot_thread_pool_new_nproc (GFunc func,
gpointer user_data)
{
long nproc_onln;
GThreadPool *ret;
GError *local_error = NULL;
nproc_onln = sysconf (_SC_NPROCESSORS_ONLN);
if (G_UNLIKELY (nproc_onln == -1 && errno == EINVAL))
nproc_onln = 2;
ret = g_thread_pool_new (func, user_data, (int)nproc_onln, FALSE, &local_error);
g_assert_no_error (local_error);
return ret;
}
-14
View File
@@ -121,17 +121,3 @@ ot_util_path_split_validate (const char *path,
out:
return ret;
}
void
ot_util_fatal_literal (const char *msg)
{
g_printerr ("%s\n", msg);
exit (EXIT_FAILURE);
}
void
ot_util_fatal_gerror (GError *error)
{
g_assert (error != NULL);
ot_util_fatal_literal (error->message);
}
-4
View File
@@ -36,10 +36,6 @@
G_BEGIN_DECLS
void ot_util_fatal_literal (const char *msg) G_GNUC_NORETURN;
void ot_util_fatal_gerror (GError *error) G_GNUC_NORETURN;
gboolean ot_util_filename_validate (const char *name, GError **error);
gboolean ot_util_path_split_validate (const char *path, GPtrArray **out_components, GError **error);
-67
View File
@@ -80,36 +80,6 @@ ot_util_variant_asv_to_hash_table (GVariant *variant)
return ret;
}
gboolean
ot_util_variant_save (GFile *dest,
GVariant *variant,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GOutputStream) out = NULL;
gsize bytes_written;
out = (GOutputStream*)g_file_replace (dest, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION,
cancellable, error);
if (!out)
goto out;
if (!g_output_stream_write_all (out,
g_variant_get_data (variant),
g_variant_get_size (variant),
&bytes_written,
cancellable,
error))
goto out;
if (!g_output_stream_close (out, cancellable, error))
goto out;
ret = TRUE;
out:
return ret;
}
GVariant *
ot_util_variant_take_ref (GVariant *variant)
{
@@ -198,43 +168,6 @@ ot_util_variant_map_fd (int fd,
return ret;
}
/**
* Read all input from @src, allocating a new #GVariant from it into
* output variable @out_variant. @src will be closed as a result.
*
* Note the returned @out_variant is not floating.
*/
gboolean
ot_util_variant_from_stream (GInputStream *src,
const GVariantType *type,
gboolean trusted,
GVariant **out_variant,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GMemoryOutputStream) data_stream = NULL;
g_autoptr(GVariant) ret_variant = NULL;
data_stream = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
if (g_output_stream_splice ((GOutputStream*)data_stream, src,
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
cancellable, error) < 0)
goto out;
ret_variant = g_variant_new_from_data (type, g_memory_output_stream_get_data (data_stream),
g_memory_output_stream_get_data_size (data_stream),
trusted, (GDestroyNotify) g_object_unref, data_stream);
data_stream = NULL; /* Transfer ownership */
g_variant_ref_sink (ret_variant);
ret = TRUE;
ot_transfer_out_value (out_variant, &ret_variant);
out:
return ret;
}
GInputStream *
ot_variant_read (GVariant *variant)
{
-12
View File
@@ -37,11 +37,6 @@ GHashTable *ot_util_variant_asv_to_hash_table (GVariant *variant);
GVariant * ot_util_variant_take_ref (GVariant *variant);
gboolean ot_util_variant_save (GFile *dest,
GVariant *variant,
GCancellable *cancellable,
GError **error);
typedef enum {
OT_VARIANT_MAP_TRUSTED = (1 << 0),
OT_VARIANT_MAP_ALLOW_NOENT = (1 << 1)
@@ -61,13 +56,6 @@ gboolean ot_util_variant_map_fd (int fd,
GVariant **out_variant,
GError **error);
gboolean ot_util_variant_from_stream (GInputStream *src,
const GVariantType *type,
gboolean trusted,
GVariant **out_variant,
GCancellable *cancellable,
GError **error);
GInputStream *ot_variant_read (GVariant *variant);
GVariantBuilder *ot_util_variant_builder_from_variant (GVariant *variant,
+1 -1
View File
@@ -49,9 +49,9 @@
#include <ot-opt-utils.h>
#include <ot-unix-utils.h>
#include <ot-variant-utils.h>
#include <ot-spawn-utils.h>
#include <ot-checksum-utils.h>
#include <ot-gpg-utils.h>
#include <ot-log-utils.h>
#include <ot-checksum-instream.h>
void ot_ptrarray_add_many (GPtrArray *a, ...) G_GNUC_NULL_TERMINATED;
+2 -3
View File
@@ -58,7 +58,7 @@ static OstreeCommand commands[] = {
{ "show", ostree_builtin_show },
{ "static-delta", ostree_builtin_static_delta },
{ "summary", ostree_builtin_summary },
#ifdef HAVE_LIBSOUP
#if defined(HAVE_LIBSOUP) && defined(BUILDOPT_ENABLE_TRIVIAL_HTTPD_CMDLINE)
{ "trivial-httpd", ostree_builtin_trivial_httpd },
#endif
{ NULL }
@@ -68,7 +68,7 @@ int
main (int argc,
char **argv)
{
GError *error = NULL;
g_autoptr(GError) error = NULL;
int ret;
setlocale (LC_ALL, "");
@@ -88,7 +88,6 @@ main (int argc,
suffix = "\x1b[22m\x1b[0m"; /* bold off, color reset */
}
g_printerr ("%serror: %s%s\n", prefix, suffix, error->message);
g_error_free (error);
}
return ret;
+4
View File
@@ -45,6 +45,7 @@ static gboolean opt_link_checkout_speedup;
static gboolean opt_skip_if_unchanged;
static gboolean opt_tar_autocreate_parents;
static gboolean opt_no_xattrs;
static gboolean opt_canonical_permissions;
static char **opt_trees;
static gint opt_owner_uid = -1;
static gint opt_owner_gid = -1;
@@ -84,6 +85,7 @@ static GOptionEntry options[] = {
{ "add-detached-metadata-string", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_detached_metadata_strings, "Add a key/value pair to detached metadata", "KEY=VALUE" },
{ "owner-uid", 0, 0, G_OPTION_ARG_INT, &opt_owner_uid, "Set file ownership user id", "UID" },
{ "owner-gid", 0, 0, G_OPTION_ARG_INT, &opt_owner_gid, "Set file ownership group id", "GID" },
{ "canonical-permissions", 0, 0, G_OPTION_ARG_NONE, &opt_canonical_permissions, "Canonicalize permissions in the same way bare-user does for hardlinked files", NULL },
{ "no-xattrs", 0, 0, G_OPTION_ARG_NONE, &opt_no_xattrs, "Do not import extended attributes", NULL },
{ "link-checkout-speedup", 0, 0, G_OPTION_ARG_NONE, &opt_link_checkout_speedup, "Optimize for commits of trees composed of hardlinks into the repository", NULL },
{ "tar-autocreate-parents", 0, 0, G_OPTION_ARG_NONE, &opt_tar_autocreate_parents, "When loading tar archives, automatically create parent directories as needed", NULL },
@@ -399,6 +401,8 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
if (opt_no_xattrs)
flags |= OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS;
if (opt_canonical_permissions)
flags |= OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS;
if (opt_generate_sizes)
flags |= OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES;
if (opt_disable_fsync)
+8 -2
View File
@@ -30,11 +30,15 @@
static gboolean opt_stats;
static gboolean opt_fs_diff;
static gboolean opt_no_xattrs;
static gint opt_owner_uid = -1;
static gint opt_owner_gid = -1;
static GOptionEntry options[] = {
{ "stats", 0, 0, G_OPTION_ARG_NONE, &opt_stats, "Print various statistics", NULL },
{ "fs-diff", 0, 0, G_OPTION_ARG_NONE, &opt_fs_diff, "Print filesystem diff", NULL },
{ "no-xattrs", 0, 0, G_OPTION_ARG_NONE, &opt_no_xattrs, "Skip output of extended attributes", NULL },
{ "owner-uid", 0, 0, G_OPTION_ARG_INT, &opt_owner_uid, "Use file ownership user id for local files", "UID" },
{ "owner-gid", 0, 0, G_OPTION_ARG_INT, &opt_owner_gid, "Use file ownership group id for local files", "GID" },
{ NULL }
};
@@ -177,8 +181,10 @@ ostree_builtin_diff (int argc, char **argv, GCancellable *cancellable, GError **
modified = g_ptr_array_new_with_free_func ((GDestroyNotify)ostree_diff_item_unref);
removed = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);
added = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);
if (!ostree_diff_dirs (diff_flags, srcf, targetf, modified, removed, added, cancellable, error))
OstreeDiffDirsOptions diff_opts = { opt_owner_uid, opt_owner_gid };
if (!ostree_diff_dirs_with_options (diff_flags, srcf, targetf, modified, removed,
added, &diff_opts, cancellable, error))
goto out;
ostree_diff_print (srcf, targetf, modified, removed, added);
+52 -90
View File
@@ -52,17 +52,13 @@ do_print_variant_generic (const GVariantType *type,
const char *filename,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GVariant) variant = NULL;
if (!ot_util_variant_map_at (AT_FDCWD, filename, type, TRUE, &variant, error))
goto out;
return FALSE;
ot_dump_variant (variant);
ret = TRUE;
out:
return ret;
return TRUE;
}
static gboolean
@@ -71,34 +67,23 @@ do_print_related (OstreeRepo *repo,
const char *resolved_rev,
GError **error)
{
gboolean ret = FALSE;
const char *name;
g_autoptr(GVariant) csum_v = NULL;
g_autoptr(GVariant) variant = NULL;
g_autoptr(GVariant) related = NULL;
GVariantIter *viter = NULL;
if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT,
resolved_rev, &variant, error))
goto out;
/* PARSE OSTREE_SERIALIZED_COMMIT_VARIANT */
related = g_variant_get_child_value (variant, 2);
viter = g_variant_iter_new (related);
return FALSE;
/* PARSE OSTREE_SERIALIZED_COMMIT_VARIANT */
g_autoptr(GVariant) related = g_variant_get_child_value (variant, 2);
g_autoptr(GVariantIter) viter = g_variant_iter_new (related);
const char *name;
GVariant* csum_v;
while (g_variant_iter_loop (viter, "(&s@ay)", &name, &csum_v))
{
g_autofree char *checksum = ostree_checksum_from_bytes_v (csum_v);
g_print ("%s %s\n", name, checksum);
}
csum_v = NULL;
ret = TRUE;
out:
if (viter)
g_variant_iter_free (viter);
return ret;
return TRUE;
}
static gboolean
@@ -108,8 +93,6 @@ do_print_metadata_key (OstreeRepo *repo,
const char *key,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GVariant) value = NULL;
g_autoptr(GVariant) commit = NULL;
g_autoptr(GVariant) metadata = NULL;
@@ -117,7 +100,7 @@ do_print_metadata_key (OstreeRepo *repo,
{
if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT,
resolved_rev, &commit, error))
goto out;
return FALSE;
/* PARSE OSTREE_SERIALIZED_COMMIT_VARIANT */
metadata = g_variant_get_child_value (commit, 0);
}
@@ -125,28 +108,25 @@ do_print_metadata_key (OstreeRepo *repo,
{
if (!ostree_repo_read_commit_detached_metadata (repo, resolved_rev, &metadata,
NULL, error))
goto out;
return FALSE;
if (metadata == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"No detached metadata for commit %s", resolved_rev);
goto out;
return FALSE;
}
}
value = g_variant_lookup_value (metadata, key, NULL);
g_autoptr(GVariant) value = g_variant_lookup_value (metadata, key, NULL);
if (!value)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"No such metadata key '%s'", key);
goto out;
return FALSE;
}
ot_dump_variant (value);
ret = TRUE;
out:
return ret;
return TRUE;
}
static gboolean
@@ -155,13 +135,12 @@ print_object (OstreeRepo *repo,
const char *checksum,
GError **error)
{
g_autoptr(GVariant) variant = NULL;
OstreeDumpFlags flags = OSTREE_DUMP_NONE;
gboolean ret = FALSE;
g_autoptr(GVariant) variant = NULL;
if (!ostree_repo_load_variant (repo, objtype, checksum,
&variant, error))
goto out;
return FALSE;
if (opt_raw)
flags |= OSTREE_DUMP_RAW;
ot_dump_object (objtype, checksum, variant, flags);
@@ -169,7 +148,7 @@ print_object (OstreeRepo *repo,
if (objtype == OSTREE_OBJECT_TYPE_COMMIT)
{
glnx_unref_object OstreeGpgVerifyResult *result = NULL;
GError *local_error = NULL;
g_autoptr(GError) local_error = NULL;
g_autoptr(GFile) gpg_homedir = opt_gpg_homedir ? g_file_new_for_path (opt_gpg_homedir) : NULL;
if (opt_gpg_verify_remote)
@@ -186,24 +165,20 @@ print_object (OstreeRepo *repo,
if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
g_clear_error (&local_error);
/* Ignore */
}
else if (local_error != NULL)
{
g_propagate_error (error, local_error);
goto out;
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
else
{
GString *buffer;
guint n_sigs, ii;
n_sigs = ostree_gpg_verify_result_count_all (result);
guint n_sigs = ostree_gpg_verify_result_count_all (result);
g_print ("Found %u signature%s:\n", n_sigs, n_sigs == 1 ? "" : "s");
buffer = g_string_sized_new (256);
for (ii = 0; ii < n_sigs; ii++)
g_autoptr(GString) buffer = g_string_sized_new (256);
for (guint ii = 0; ii < n_sigs; ii++)
{
g_string_append_c (buffer, '\n');
ostree_gpg_verify_result_describe (result, ii, buffer, " ",
@@ -211,13 +186,10 @@ print_object (OstreeRepo *repo,
}
g_print ("%s", buffer->str);
g_string_free (buffer, TRUE);
}
}
ret = TRUE;
out:
return ret;
return TRUE;
}
static gboolean
@@ -228,7 +200,6 @@ print_if_found (OstreeRepo *repo,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gboolean have_object = FALSE;
if (*inout_was_found)
@@ -236,62 +207,56 @@ print_if_found (OstreeRepo *repo,
if (!ostree_repo_has_object (repo, objtype, checksum, &have_object,
cancellable, error))
goto out;
return FALSE;
if (have_object)
{
if (!print_object (repo, objtype, checksum, error))
goto out;
return FALSE;
*inout_was_found = TRUE;
}
ret = TRUE;
out:
return ret;
return TRUE;
}
gboolean
ostree_builtin_show (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GOptionContext) context = g_option_context_new ("OBJECT - Output a metadata object");
glnx_unref_object OstreeRepo *repo = NULL;
gboolean ret = FALSE;
const char *rev;
g_autofree char *resolved_rev = NULL;
context = g_option_context_new ("OBJECT - Output a metadata object");
if (!ostree_option_context_parse (context, options, &argc, &argv, OSTREE_BUILTIN_FLAG_NONE, &repo, cancellable, error))
goto out;
return FALSE;
if (argc <= 1)
{
ot_util_usage_error (context, "An object argument is required", error);
goto out;
return FALSE;
}
rev = argv[1];
const char *rev = argv[1];
g_autofree char *resolved_rev = NULL;
if (opt_print_metadata_key || opt_print_detached_metadata_key)
{
gboolean detached = opt_print_detached_metadata_key != NULL;
const char *key = detached ? opt_print_detached_metadata_key : opt_print_metadata_key;
if (!ostree_repo_resolve_rev (repo, rev, FALSE, &resolved_rev, error))
goto out;
return FALSE;
if (!do_print_metadata_key (repo, resolved_rev, detached, key, error))
goto out;
return FALSE;
}
else if (opt_print_related)
{
if (!ostree_repo_resolve_rev (repo, rev, FALSE, &resolved_rev, error))
goto out;
return FALSE;
if (!do_print_related (repo, rev, resolved_rev, error))
goto out;
return FALSE;
}
else if (opt_print_variant_type)
{
if (!do_print_variant_generic (G_VARIANT_TYPE (opt_print_variant_type), rev, error))
goto out;
return FALSE;
}
else
{
@@ -299,33 +264,32 @@ ostree_builtin_show (int argc, char **argv, GCancellable *cancellable, GError **
if (!ostree_validate_checksum_string (rev, NULL))
{
if (!ostree_repo_resolve_rev (repo, rev, FALSE, &resolved_rev, error))
goto out;
return FALSE;
if (!print_object (repo, OSTREE_OBJECT_TYPE_COMMIT, resolved_rev, error))
goto out;
return FALSE;
}
else
{
if (!print_if_found (repo, OSTREE_OBJECT_TYPE_COMMIT, rev,
&found, cancellable, error))
goto out;
return FALSE;
if (!print_if_found (repo, OSTREE_OBJECT_TYPE_DIR_META, rev,
&found, cancellable, error))
goto out;
return FALSE;
if (!print_if_found (repo, OSTREE_OBJECT_TYPE_DIR_TREE, rev,
&found, cancellable, error))
goto out;
return FALSE;
if (!found)
{
g_autoptr(GFileInfo) finfo = NULL;
g_autoptr(GVariant) xattrs = NULL;
GFileType filetype;
if (!ostree_repo_load_file (repo, rev, NULL, &finfo, &xattrs,
cancellable, error))
goto out;
return FALSE;
g_print ("Object: %s\nType: %s\n", rev, ostree_object_type_to_string (OSTREE_OBJECT_TYPE_FILE));
filetype = g_file_info_get_file_type (finfo);
GFileType filetype = g_file_info_get_file_type (finfo);
g_print ("File Type: ");
switch (filetype)
{
@@ -358,8 +322,6 @@ ostree_builtin_show (int argc, char **argv, GCancellable *cancellable, GError **
}
}
}
ret = TRUE;
out:
return ret;
return TRUE;
}
+2 -3
View File
@@ -259,7 +259,7 @@ ostree_option_context_parse (GOptionContext *context,
if (opt_repo == NULL && !(flags & OSTREE_BUILTIN_FLAG_NO_REPO))
{
GError *local_error = NULL;
g_autoptr(GError) local_error = NULL;
repo = ostree_repo_new_default ();
if (!ostree_repo_open (repo, cancellable, &local_error))
@@ -270,14 +270,13 @@ ostree_option_context_parse (GOptionContext *context,
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Command requires a --repo argument");
g_error_free (local_error);
help = g_option_context_get_help (context, FALSE, NULL);
g_printerr ("%s", help);
}
else
{
g_propagate_error (error, local_error);
g_propagate_error (error, g_steal_pointer (&local_error));
}
goto out;
}
+1 -1
View File
@@ -37,7 +37,7 @@ gboolean
ot_remote_builtin_add_cookie (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
glnx_unref_object OstreeRepo *repo = NULL;
g_autoptr(OstreeRepo) repo = NULL;
const char *remote_name;
const char *domain;
const char *path;
+1 -1
View File
@@ -45,7 +45,7 @@ gboolean
ot_remote_builtin_add (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
glnx_unref_object OstreeRepo *repo = NULL;
g_autoptr(OstreeRepo) repo = NULL;
const char *remote_name;
const char *remote_url;
char **iter;
+1 -1
View File
@@ -37,7 +37,7 @@ gboolean
ot_remote_builtin_delete_cookie (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
glnx_unref_object OstreeRepo *repo = NULL;
g_autoptr(OstreeRepo) repo = NULL;
const char *remote_name;
const char *domain;
const char *path;
+1 -1
View File
@@ -36,7 +36,7 @@ gboolean
ot_remote_builtin_delete (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
glnx_unref_object OstreeRepo *repo = NULL;
g_autoptr(OstreeRepo) repo = NULL;
const char *remote_name;
gboolean ret = FALSE;
+1 -1
View File
@@ -94,7 +94,7 @@ gboolean
ot_remote_builtin_gpg_import (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
glnx_unref_object OstreeRepo *repo = NULL;
g_autoptr(OstreeRepo) repo = NULL;
g_autoptr(GInputStream) source_stream = NULL;
const char *remote_name;
const char * const *key_ids;
+1 -1
View File
@@ -36,7 +36,7 @@ gboolean
ot_remote_builtin_list_cookies (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
glnx_unref_object OstreeRepo *repo = NULL;
g_autoptr(OstreeRepo) repo = NULL;
const char *remote_name;
g_autofree char *jar_path = NULL;
g_autofree char *cookie_file = NULL;
+1 -1
View File
@@ -34,7 +34,7 @@ gboolean
ot_remote_builtin_list (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
glnx_unref_object OstreeRepo *repo = NULL;
g_autoptr(OstreeRepo) repo = NULL;
g_auto(GStrv) remotes = NULL;
guint ii, n_remotes = 0;
gboolean ret = FALSE;
+1 -1
View File
@@ -36,7 +36,7 @@ gboolean
ot_remote_builtin_refs (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
glnx_unref_object OstreeRepo *repo = NULL;
g_autoptr(OstreeRepo) repo = NULL;
const char *remote_name;
gboolean ret = FALSE;
g_autoptr(GHashTable) refs = NULL;
+1 -1
View File
@@ -33,7 +33,7 @@ gboolean
ot_remote_builtin_show_url (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
glnx_unref_object OstreeRepo *repo = NULL;
g_autoptr(OstreeRepo) repo = NULL;
const char *remote_name;
g_autofree char *remote_url = NULL;
gboolean ret = FALSE;
+1 -1
View File
@@ -40,7 +40,7 @@ gboolean
ot_remote_builtin_summary (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
glnx_unref_object OstreeRepo *repo = NULL;
g_autoptr(OstreeRepo) repo = NULL;
const char *remote_name;
g_autoptr(GBytes) summary_bytes = NULL;
g_autoptr(GBytes) signature_bytes = NULL;