New upstream version 2017.14

This commit is contained in:
Simon McVittie committed 2017-12-10 19:02:31 +00:00
commit 84beec3c14
77 files changed
+1754 -1343

No files matched your search

+6 -1
View File
@@ -61,7 +61,12 @@ read_config()
populate_menu()
{
boot_prefix="${OSTREE_BOOT_PARTITION}"
# Default to /boot if OSTREE_BOOT_PARTITION is not set and /boot is on the same device than ostree/repo
if [ -z ${OSTREE_BOOT_PARTITION+x} ] && [ -d /boot/ostree ] && [ -d /ostree/repo ] && [ $(stat -c '%d' /boot/ostree) -eq $(stat -c '%d' /ostree/repo) ]; then
boot_prefix="/boot"
else
boot_prefix="${OSTREE_BOOT_PARTITION}"
fi
for config in $(ls ${entries_path}); do
read_config ${config}
menu="${menu}menuentry '${title}' {\n"
+3 -2
View File
@@ -18,8 +18,9 @@
***/
/* Add new symbols here. Release commits should copy this section into -released.sym. */
LIBOSTREE_2017.14 {
} LIBOSTREE_2017.13;
LIBOSTREE_2017.15 {
} LIBOSTREE_2017.14;
/* Stub section for the stable release *after* this development one; don't
* edit this other than to update the last number. This is just a copy/paste
+6
View File
@@ -89,3 +89,9 @@ global:
ostree_repo_finder_override_get_type;
ostree_repo_finder_override_new;
} LIBOSTREE_2017.12_EXPERIMENTAL;
LIBOSTREE_2017.14_EXPERIMENTAL {
global:
ostree_remote_get_type;
ostree_remote_get_url;
} LIBOSTREE_2017.13_EXPERIMENTAL;
+3
View File
@@ -442,6 +442,9 @@ global:
ostree_repo_checkout_at_options_set_devino;
} LIBOSTREE_2017.12;
LIBOSTREE_2017.14 {
} LIBOSTREE_2017.13;
/* NOTE: Only add more content here in release commits! See the
* comments at the top of this file.
*/
+2 -2
View File
@@ -278,7 +278,7 @@ ostree_validate_remote_name (const char *remote_name,
/**
* ostree_validate_collection_id:
* @rev: (nullable): A collection ID
* @collection_id: (nullable): A collection ID
* @error: Error
*
* Check whether the given @collection_id is valid. Return an error if it is
@@ -2204,7 +2204,7 @@ _ostree_compare_timestamps (const char *current_rev,
g_autofree char *current_ts_str = g_date_time_format (current_dt, "%c");
g_autofree char *new_ts_str = g_date_time_format (new_dt, "%c");
return glnx_throw (error, "Upgrade target revision '%s' with timestamp '%s' is chronologically older than current revision '%s' with timestamp '%s'",
return glnx_throw (error, "Upgrade target revision '%s' with timestamp '%s' is chronologically older than current revision '%s' with timestamp '%s'; use --allow-downgrade to permit",
new_rev, new_ts_str, current_rev, current_ts_str);
}
+1 -3
View File
@@ -18,9 +18,7 @@
* Boston, MA 02111-1307, USA.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include "config.h"
#include <string.h>
#include "ostree-enumtypes.h"
+8 -3
View File
@@ -167,6 +167,7 @@ _ostree_fetcher_finalize (GObject *object)
{
OstreeFetcher *self = OSTREE_FETCHER (object);
curl_multi_cleanup (self->multi);
g_free (self->remote_name);
g_free (self->cookie_jar_path);
g_free (self->proxy);
@@ -177,7 +178,6 @@ _ostree_fetcher_finalize (GObject *object)
g_clear_pointer (&self->timer_event, (GDestroyNotify)destroy_and_unref_source);
if (self->mainctx)
g_main_context_unref (self->mainctx);
curl_multi_cleanup (self->multi);
G_OBJECT_CLASS (_ostree_fetcher_parent_class)->finalize (object);
}
@@ -788,8 +788,13 @@ initiate_next_curl_request (FetcherRequest *req,
curl_easy_setopt (req->easy, CURLOPT_PROGRESSFUNCTION, prog_cb);
curl_easy_setopt (req->easy, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt (req->easy, CURLOPT_CONNECTTIMEOUT, 30L);
curl_easy_setopt (req->easy, CURLOPT_LOW_SPEED_LIMIT, 1L);
curl_easy_setopt (req->easy, CURLOPT_LOW_SPEED_TIME, 30L);
/* We used to set CURLOPT_LOW_SPEED_LIMIT and CURLOPT_LOW_SPEED_TIME
* here, but see https://github.com/ostreedev/ostree/issues/878#issuecomment-347228854
* basically those options don't play well with HTTP2 at the moment
* where we can have lots of outstanding requests. Further,
* we could implement that functionality at a higher level
* more consistently too.
*/
/* closure bindings -> task */
curl_easy_setopt (req->easy, CURLOPT_PRIVATE, task);
-2
View File
@@ -48,7 +48,6 @@ typedef struct
gchar *ref_name; /* (not nullable) */
} OstreeCollectionRef;
#ifndef __GI_SCANNER__
_OSTREE_PUBLIC
GType ostree_collection_ref_get_type (void);
@@ -59,7 +58,6 @@ _OSTREE_PUBLIC
OstreeCollectionRef *ostree_collection_ref_dup (const OstreeCollectionRef *ref);
_OSTREE_PUBLIC
void ostree_collection_ref_free (OstreeCollectionRef *ref);
#endif
_OSTREE_PUBLIC
guint ostree_collection_ref_hash (gconstpointer ref);
+18
View File
@@ -180,3 +180,21 @@ ostree_remote_get_name (OstreeRemote *remote)
return remote->name;
}
/**
* ostree_remote_get_url:
* @remote: an #OstreeRemote
*
* Get the URL from the remote.
*
* Returns: (transfer full): the remote's URL
* Since: 2017.14
*/
gchar *
ostree_remote_get_url (OstreeRemote *remote)
{
g_return_val_if_fail (remote != NULL, NULL);
g_return_val_if_fail (remote->ref_count > 0, NULL);
return g_key_file_get_string (remote->options, remote->group, "url", NULL);
}
+3 -2
View File
@@ -47,16 +47,17 @@ G_BEGIN_DECLS
typedef struct OstreeRemote OstreeRemote;
#endif
#ifndef __GI_SCANNER__
_OSTREE_PUBLIC
GType ostree_remote_get_type (void) G_GNUC_CONST;
_OSTREE_PUBLIC
OstreeRemote *ostree_remote_ref (OstreeRemote *remote);
_OSTREE_PUBLIC
void ostree_remote_unref (OstreeRemote *remote);
#endif /* GI_SCANNER */
_OSTREE_PUBLIC
const gchar *ostree_remote_get_name (OstreeRemote *remote);
_OSTREE_PUBLIC
gchar *ostree_remote_get_url (OstreeRemote *remote);
G_END_DECLS
+237 -116
View File
@@ -38,18 +38,33 @@
#include "ostree-checksum-input-stream.h"
#include "ostree-varint.h"
/* In most cases, we write into a staging dir for commit, but we also allow
* direct writes into objects/ for e.g. hardlink imports.
/* If fsync is enabled and we're in a txn, we write into a staging dir for
* commit, but we also allow direct writes into objects/ for e.g. hardlink
* imports.
*/
static int
commit_dest_dfd (OstreeRepo *self)
{
if (self->in_transaction)
if (self->in_transaction && !self->disable_fsync)
return self->commit_stagedir.fd;
else
return self->objects_dir_fd;
}
/* If we don't have O_TMPFILE, or for symlinks we'll create temporary
* files. If we have a txn, use the staging dir to ensure that
* things are consistently locked against concurrent cleanup, and
* in general we have all of our data in one place.
*/
static int
commit_tmp_dfd (OstreeRepo *self)
{
if (self->in_transaction)
return self->commit_stagedir.fd;
else
return self->tmp_dir_fd;
}
/* The objects/ directory has a two-character directory prefix for checksums
* to avoid putting lots of files in a single directory. This technique
* is quite old, but Git also uses it for example.
@@ -404,46 +419,116 @@ add_size_index_to_metadata (OstreeRepo *self,
return g_variant_ref_sink (g_variant_builder_end (builder));
}
typedef struct {
gboolean initialized;
GLnxTmpfile tmpf;
char *expected_checksum;
OtChecksum checksum;
guint64 content_len;
guint64 bytes_written;
guint uid;
guint gid;
guint mode;
GVariant *xattrs;
} OstreeRealRepoBareContent;
G_STATIC_ASSERT (sizeof (OstreeRepoBareContent) >= sizeof (OstreeRealRepoBareContent));
/* Create a tmpfile for writing a bare file. Currently just used
* by the static delta code, but will likely later be extended
* to be used also by the dfd_iter commit path.
*/
gboolean
_ostree_repo_open_content_bare (OstreeRepo *self,
const char *checksum,
guint64 content_len,
GLnxTmpfile *out_tmpf,
GCancellable *cancellable,
GError **error)
_ostree_repo_bare_content_open (OstreeRepo *self,
const char *expected_checksum,
guint64 content_len,
guint uid,
guint gid,
guint mode,
GVariant *xattrs,
OstreeRepoBareContent *out_regwrite,
GCancellable *cancellable,
GError **error)
{
return glnx_open_tmpfile_linkable_at (self->tmp_dir_fd, ".", O_WRONLY|O_CLOEXEC,
out_tmpf, error);
OstreeRealRepoBareContent *real = (OstreeRealRepoBareContent*) out_regwrite;
g_assert (!real->initialized);
real->initialized = TRUE;
g_assert (S_ISREG (mode));
if (!glnx_open_tmpfile_linkable_at (commit_tmp_dfd (self), ".", O_WRONLY|O_CLOEXEC,
&real->tmpf, error))
return FALSE;
ot_checksum_init (&real->checksum);
real->expected_checksum = g_strdup (expected_checksum);
real->content_len = content_len;
real->bytes_written = 0;
real->uid = uid;
real->gid = gid;
real->mode = mode;
real->xattrs = xattrs ? g_variant_ref (xattrs) : NULL;
/* Initialize the checksum with the header info */
g_autoptr(GFileInfo) finfo = _ostree_mode_uidgid_to_gfileinfo (mode, uid, gid);
g_autoptr(GBytes) header = _ostree_file_header_new (finfo, xattrs);
ot_checksum_update_bytes (&real->checksum, header);
return TRUE;
}
/* Used by static deltas, which have a separate "push" flow for
* regfile objects distinct from the "pull" model used by
* write_content_object().
*/
gboolean
_ostree_repo_commit_trusted_content_bare (OstreeRepo *self,
const char *checksum,
GLnxTmpfile *tmpf,
guint32 uid,
guint32 gid,
guint32 mode,
GVariant *xattrs,
GCancellable *cancellable,
GError **error)
_ostree_repo_bare_content_write (OstreeRepo *repo,
OstreeRepoBareContent *barewrite,
const guint8 *buf,
size_t len,
GCancellable *cancellable,
GError **error)
{
/* I don't think this is necessary, but a similar check was here previously,
* keeping it for extra redundancy.
*/
if (!tmpf->initialized || tmpf->fd == -1)
return TRUE;
OstreeRealRepoBareContent *real = (OstreeRealRepoBareContent*) barewrite;
g_assert (real->initialized);
ot_checksum_update (&real->checksum, buf, len);
if (glnx_loop_write (real->tmpf.fd, buf, len) < 0)
return glnx_throw_errno_prefix (error, "write");
return TRUE;
}
return commit_loose_regfile_object (self, checksum,
tmpf, uid, gid, mode, xattrs,
cancellable, error);
gboolean
_ostree_repo_bare_content_commit (OstreeRepo *self,
OstreeRepoBareContent *barewrite,
char *checksum_buf,
size_t buflen,
GCancellable *cancellable,
GError **error)
{
OstreeRealRepoBareContent *real = (OstreeRealRepoBareContent*) barewrite;
g_assert (real->initialized);
ot_checksum_get_hexdigest (&real->checksum, checksum_buf, buflen);
if (real->expected_checksum &&
!_ostree_compare_object_checksum (OSTREE_OBJECT_TYPE_FILE,
real->expected_checksum, checksum_buf,
error))
return FALSE;
if (!commit_loose_regfile_object (self, checksum_buf,
&real->tmpf, real->uid, real->gid,
real->mode, real->xattrs,
cancellable, error))
return FALSE;
/* Let's have a guarantee that after commit the object is cleaned up */
_ostree_repo_bare_content_cleanup (barewrite);
return TRUE;
}
void
_ostree_repo_bare_content_cleanup (OstreeRepoBareContent *regwrite)
{
OstreeRealRepoBareContent *real = (OstreeRealRepoBareContent*) regwrite;
if (!real->initialized)
return;
glnx_tmpfile_clear (&real->tmpf);
ot_checksum_clear (&real->checksum);
g_clear_pointer (&real->expected_checksum, (GDestroyNotify)g_free);
g_clear_pointer (&real->xattrs, (GDestroyNotify)g_variant_unref);
real->initialized = FALSE;
}
/* Allocate an O_TMPFILE, write everything from @input to it, but
@@ -459,7 +544,7 @@ create_regular_tmpfile_linkable_with_content (OstreeRepo *self,
GError **error)
{
g_auto(GLnxTmpfile) tmpf = { 0, };
if (!glnx_open_tmpfile_linkable_at (self->tmp_dir_fd, ".", O_WRONLY|O_CLOEXEC,
if (!glnx_open_tmpfile_linkable_at (commit_tmp_dfd (self), ".", O_WRONLY|O_CLOEXEC,
&tmpf, error))
return FALSE;
@@ -597,7 +682,7 @@ write_content_object (OstreeRepo *self,
*
* We use GLnxTmpfile for regular files, and OtCleanupUnlinkat for symlinks.
*/
g_auto(OtCleanupUnlinkat) tmp_unlinker = { self->tmp_dir_fd, NULL };
g_auto(OtCleanupUnlinkat) tmp_unlinker = { commit_tmp_dfd (self), NULL };
g_auto(GLnxTmpfile) tmpf = { 0, };
goffset unpacked_size = 0;
gboolean indexable = FALSE;
@@ -606,7 +691,7 @@ write_content_object (OstreeRepo *self,
{
/* This will not be hit for bare-user or archive */
g_assert (self->mode == OSTREE_REPO_MODE_BARE || self->mode == OSTREE_REPO_MODE_BARE_USER_ONLY);
if (!_ostree_make_temporary_symlink_at (self->tmp_dir_fd,
if (!_ostree_make_temporary_symlink_at (commit_tmp_dfd (self),
g_file_info_get_symlink_target (file_info),
&tmp_unlinker.path,
cancellable, error))
@@ -629,7 +714,7 @@ write_content_object (OstreeRepo *self,
if (self->generate_sizes)
indexable = TRUE;
if (!glnx_open_tmpfile_linkable_at (self->tmp_dir_fd, ".", O_WRONLY|O_CLOEXEC,
if (!glnx_open_tmpfile_linkable_at (commit_tmp_dfd (self), ".", O_WRONLY|O_CLOEXEC,
&tmpf, error))
return FALSE;
temp_out = g_unix_output_stream_new (tmpf.fd, FALSE);
@@ -719,14 +804,14 @@ write_content_object (OstreeRepo *self,
* Note, this does not apply for bare-user repos, as they store symlinks
* as regular files.
*/
if (G_UNLIKELY (fchownat (self->tmp_dir_fd, tmp_unlinker.path,
if (G_UNLIKELY (fchownat (tmp_unlinker.dfd, tmp_unlinker.path,
uid, gid, AT_SYMLINK_NOFOLLOW) == -1))
return glnx_throw_errno_prefix (error, "fchownat");
if (xattrs != NULL)
{
ot_security_smack_reset_dfd_name (self->tmp_dir_fd, tmp_unlinker.path);
if (!glnx_dfd_name_set_all_xattrs (self->tmp_dir_fd, tmp_unlinker.path,
ot_security_smack_reset_dfd_name (tmp_unlinker.dfd, tmp_unlinker.path);
if (!glnx_dfd_name_set_all_xattrs (tmp_unlinker.dfd, tmp_unlinker.path,
xattrs, cancellable, error))
return FALSE;
}
@@ -968,7 +1053,7 @@ write_metadata_object (OstreeRepo *self,
/* Write the metadata to a temporary file */
g_auto(GLnxTmpfile) tmpf = { 0, };
if (!glnx_open_tmpfile_linkable_at (self->tmp_dir_fd, ".", O_WRONLY|O_CLOEXEC,
if (!glnx_open_tmpfile_linkable_at (commit_tmp_dfd (self), ".", O_WRONLY|O_CLOEXEC,
&tmpf, error))
return FALSE;
if (!glnx_try_fallocate (tmpf.fd, 0, len, error))
@@ -1350,8 +1435,40 @@ rename_pending_loose_objects (OstreeRepo *self,
return glnx_throw_errno_prefix (error, "fsync");
}
if (!glnx_tmpdir_delete (&self->commit_stagedir, cancellable, error))
return TRUE;
}
/* Try to lock a transaction stage directory created by
* ostree_repo_prepare_transaction().
*/
static gboolean
cleanup_txn_dir (OstreeRepo *self,
int dfd,
const char *path,
GCancellable *cancellable,
GError **error)
{
g_auto(GLnxLockFile) lockfile = { 0, };
gboolean did_lock;
/* Try to lock, but if we don't get it, move on */
if (!_ostree_repo_try_lock_tmpdir (dfd, path, &lockfile, &did_lock, error))
return FALSE;
if (!did_lock)
return TRUE; /* Note early return */
/* If however this is the staging directory for the *current*
* boot, then don't delete it now - we may end up reusing it, as
* is the point.
*/
if (g_str_has_prefix (path, self->stagedir_prefix))
return TRUE; /* Note early return */
/* But, crucially we can now clean up staging directories
* from *other* boots.
*/
if (!glnx_shutil_rm_rf_at (dfd, path, cancellable, error))
return glnx_prefix_error (error, "Removing %s", path);
return TRUE;
}
@@ -1376,15 +1493,9 @@ cleanup_tmpdir (OstreeRepo *self,
while (TRUE)
{
guint64 delta;
struct dirent *dent;
struct stat stbuf;
g_auto(GLnxLockFile) lockfile = { 0, };
gboolean did_lock;
if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error))
return FALSE;
if (dent == NULL)
break;
@@ -1394,56 +1505,40 @@ cleanup_tmpdir (OstreeRepo *self,
if (strcmp (dent->d_name, "cache") == 0)
continue;
struct stat stbuf;
if (!glnx_fstatat_allow_noent (dfd_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW, error))
return FALSE;
if (errno == ENOENT) /* Did another cleanup win? */
continue;
/* First, if it's a directory which needs locking, but it's
* busy, skip it.
*/
/* Handle transaction tmpdirs */
if (_ostree_repo_is_locked_tmpdir (dent->d_name))
{
if (!_ostree_repo_try_lock_tmpdir (dfd_iter.fd, dent->d_name,
&lockfile, &did_lock, error))
if (!cleanup_txn_dir (self, dfd_iter.fd, dent->d_name, cancellable, error))
return FALSE;
if (!did_lock)
continue;
continue; /* We've handled this, move on */
}
/* If however this is the staging directory for the *current*
* boot, then don't delete it now - we may end up reusing it, as
* is the point.
/* At this point we're looking at an unknown-origin file or directory in
* the tmpdir. This could be something like a temporary checkout dir (used
* by rpm-ostree), or (from older versions of libostree) a tempfile if we
* don't have O_TMPFILE for commits.
*/
if (g_str_has_prefix (dent->d_name, self->stagedir_prefix))
/* Ignore files from the future */
if (stbuf.st_mtime > curtime_secs)
continue;
else if (g_str_has_prefix (dent->d_name, OSTREE_REPO_TMPDIR_STAGING))
/* We're pruning content based on the expiry, which
* defaults to a day. That's what we were doing before we
* had locking...but in future we can be smarter here.
*/
guint64 delta = curtime_secs - stbuf.st_mtime;
if (delta > self->tmp_expiry_seconds)
{
/* But, crucially we can now clean up staging directories
* from *other* boots
*/
if (!glnx_shutil_rm_rf_at (dfd_iter.fd, dent->d_name, cancellable, error))
return glnx_prefix_error (error, "Removing %s", dent->d_name);
}
else
{
/* Now we do time-based cleanup. Ignore it if it's somehow
* in the future...
*/
if (stbuf.st_mtime > curtime_secs)
continue;
/* Now, we're pruning content based on the expiry, which
* defaults to a day. That's what we were doing before we
* had locking...but in future we can be smarter here.
*/
delta = curtime_secs - stbuf.st_mtime;
if (delta > self->tmp_expiry_seconds)
{
if (!glnx_shutil_rm_rf_at (dfd_iter.fd, dent->d_name, cancellable, error))
return glnx_prefix_error (error, "Removing %s", dent->d_name);
}
}
}
return TRUE;
@@ -1675,6 +1770,12 @@ ostree_repo_commit_transaction (OstreeRepo *self,
if (!rename_pending_loose_objects (self, cancellable, error))
return FALSE;
g_debug ("txn commit %s", glnx_basename (self->commit_stagedir.path));
if (!glnx_tmpdir_delete (&self->commit_stagedir, cancellable, error))
return FALSE;
glnx_release_lock_file (&self->commit_stagedir_lock);
/* This performs a global cleanup */
if (!cleanup_tmpdir (self, cancellable, error))
return FALSE;
@@ -1691,9 +1792,6 @@ ostree_repo_commit_transaction (OstreeRepo *self,
return FALSE;
g_clear_pointer (&self->txn_collection_refs, g_hash_table_destroy);
glnx_tmpdir_unset (&self->commit_stagedir);
glnx_release_lock_file (&self->commit_stagedir_lock);
self->in_transaction = FALSE;
if (!ot_ensure_unlinked_at (self->repo_dir_fd, "transaction", 0))
@@ -2695,47 +2793,70 @@ write_directory_content_to_mtree_internal (OstreeRepo *self,
g_assert (dir_enum != NULL || dfd_iter != NULL);
GFileType file_type = g_file_info_get_file_type (child_info);
const char *name = g_file_info_get_name (child_info);
g_ptr_array_add (path, (char*)name);
g_autofree char *child_relpath = ptrarray_path_join (path);
/* See if we have a devino hit; this is used below. Further, for bare-user
* repos we'll reload our file info from the object (specifically the
* ostreemeta xattr). The on-disk state is not normally what we want to
* commit. Basically we're making sure that we pick up "real" uid/gid and any
* xattrs there.
/* Load flags into boolean constants for ease of readability (we also need to
* NULL-check modifier)
*/
const char *loose_checksum = NULL;
g_autoptr(GVariant) source_xattrs = NULL;
if (dfd_iter != NULL && (file_type != G_FILE_TYPE_DIRECTORY))
{
guint32 dev = g_file_info_get_attribute_uint32 (child_info, "unix::device");
guint64 inode = g_file_info_get_attribute_uint64 (child_info, "unix::inode");
loose_checksum = devino_cache_lookup (self, modifier, dev, inode);
if (loose_checksum && self->mode == OSTREE_REPO_MODE_BARE_USER)
{
child_info = NULL;
if (!ostree_repo_load_file (self, loose_checksum, NULL, &child_info, &source_xattrs,
cancellable, error))
return FALSE;
}
}
g_autoptr(GFileInfo) modified_info = NULL;
OstreeRepoCommitFilterResult filter_result =
_ostree_repo_commit_modifier_apply (self, modifier, child_relpath, child_info, &modified_info);
const gboolean child_info_was_modified = !_ostree_gfileinfo_equal (child_info, modified_info);
const gboolean canonical_permissions = modifier &&
(modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS);
const gboolean devino_canonical = modifier &&
(modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_DEVINO_CANONICAL);
/* We currently only honor the CONSUME flag in the dfd_iter case to avoid even
* more complexity in this function, and it'd mostly only be useful when
* operating on local filesystems anyways.
*/
const gboolean delete_after_commit = dfd_iter && modifier &&
(modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CONSUME);
const gboolean canonical_permissions = modifier &&
(modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS);
/* See if we have a devino hit; this is used below in a few places. */
const char *loose_checksum = NULL;
if (dfd_iter != NULL && (file_type != G_FILE_TYPE_DIRECTORY))
{
guint32 dev = g_file_info_get_attribute_uint32 (child_info, "unix::device");
guint64 inode = g_file_info_get_attribute_uint64 (child_info, "unix::inode");
loose_checksum = devino_cache_lookup (self, modifier, dev, inode);
if (loose_checksum && devino_canonical)
{
/* Go directly to checksum, do not pass Go, do not collect $200.
* In this mode the app is required to break hardlinks for any
* files it wants to modify.
*/
if (!ostree_mutable_tree_replace_file (mtree, name, loose_checksum, error))
return FALSE;
if (delete_after_commit)
{
if (!glnx_shutil_rm_rf_at (dfd_iter->fd, name, cancellable, error))
return FALSE;
}
return TRUE; /* Early return */
}
}
/* Build the full path which we need for callbacks */
g_ptr_array_add (path, (char*)name);
g_autofree char *child_relpath = ptrarray_path_join (path);
/* For bare-user repos we'll reload our file info from the object
* (specifically the ostreemeta xattr), if it was checked out that way (via
* hardlink). The on-disk state is not normally what we want to commit.
* Basically we're making sure that we pick up "real" uid/gid and any xattrs
* there.
*/
g_autoptr(GVariant) source_xattrs = NULL;
if (loose_checksum && self->mode == OSTREE_REPO_MODE_BARE_USER)
{
child_info = NULL;
if (!ostree_repo_load_file (self, loose_checksum, NULL, &child_info, &source_xattrs,
cancellable, error))
return FALSE;
}
/* Call the filter */
g_autoptr(GFileInfo) modified_info = NULL;
OstreeRepoCommitFilterResult filter_result =
_ostree_repo_commit_modifier_apply (self, modifier, child_relpath, child_info, &modified_info);
const gboolean child_info_was_modified = !_ostree_gfileinfo_equal (child_info, modified_info);
if (filter_result != OSTREE_REPO_COMMIT_FILTER_ALLOW)
{
+2 -2
View File
@@ -432,8 +432,8 @@ G_DEFINE_BOXED_TYPE (OstreeRepoFinderResult, ostree_repo_finder_result,
* result
* @priority: static priority of the result, where higher numbers indicate lower
* priority
* @ref_to_checksum: (element-type OstreeCollectionRef utf8): map of collection–ref pairs
* to checksums provided by this result
* @ref_to_checksum: (element-type OstreeCollectionRef utf8) (transfer none):
* map of collection–ref pairs to checksums provided by this result
* @summary_last_modified: Unix timestamp (seconds since the epoch, UTC) when
* the summary file for the result was last modified, or `0` if this is unknown
*
+30 -13
View File
@@ -365,24 +365,41 @@ _ostree_repo_commit_tmpf_final (OstreeRepo *self,
GCancellable *cancellable,
GError **error);
typedef struct {
gboolean initialized;
gpointer opaque0[10];
guint opaque1[10];
} OstreeRepoBareContent;
void _ostree_repo_bare_content_cleanup (OstreeRepoBareContent *regwrite);
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(OstreeRepoBareContent, _ostree_repo_bare_content_cleanup)
gboolean
_ostree_repo_open_content_bare (OstreeRepo *self,
const char *checksum,
guint64 content_len,
GLnxTmpfile *out_tmpf,
_ostree_repo_bare_content_open (OstreeRepo *self,
const char *checksum,
guint64 content_len,
guint uid,
guint gid,
guint mode,
GVariant *xattrs,
OstreeRepoBareContent *out_regwrite,
GCancellable *cancellable,
GError **error);
gboolean
_ostree_repo_commit_trusted_content_bare (OstreeRepo *self,
const char *checksum,
GLnxTmpfile *tmpf,
guint32 uid,
guint32 gid,
guint32 mode,
GVariant *xattrs,
GCancellable *cancellable,
GError **error);
_ostree_repo_bare_content_write (OstreeRepo *repo,
OstreeRepoBareContent *barewrite,
const guint8 *buf,
size_t len,
GCancellable *cancellable,
GError **error);
gboolean
_ostree_repo_bare_content_commit (OstreeRepo *self,
OstreeRepoBareContent *barewrite,
char *checksum_buf,
size_t buflen,
GCancellable *cancellable,
GError **error);
gboolean
_ostree_repo_load_file_bare (OstreeRepo *self,
+96 -23
View File
@@ -2325,19 +2325,39 @@ process_one_static_delta (OtPullData *pull_data,
return ret;
}
/* Loop over the static delta data we got from the summary,
* and find the newest commit for @out_from_revision that
* goes to @to_revision.
/*
* DELTA_SEARCH_RESULT_UNCHANGED:
* We already have the commit.
*
* Additionally, @out_have_scratch_delta will be set to %TRUE
* if there is a %NULL → @to_revision delta, also known as
* DELTA_SEARCH_RESULT_NO_MATCH:
* No deltas were found.
*
* DELTA_SEARCH_RESULT_FROM:
* A regular delta was found, and the "from" revision will be
* set in `from_revision`.
*
* DELTA_SEARCH_RESULT_SCRATCH:
* There is a %NULL → @to_revision delta, also known as
* a "from scratch" delta.
*/
typedef struct {
enum {
DELTA_SEARCH_RESULT_UNCHANGED,
DELTA_SEARCH_RESULT_NO_MATCH,
DELTA_SEARCH_RESULT_FROM,
DELTA_SEARCH_RESULT_SCRATCH,
} result;
char from_revision[OSTREE_SHA256_STRING_LEN+1];
} DeltaSearchResult;
/* Loop over the static delta data we got from the summary,
* and find the a delta path (if available) that goes to @to_revision.
* See the enum in `DeltaSearchResult` for available result types.
*/
static gboolean
get_best_static_delta_start_for (OtPullData *pull_data,
const char *to_revision,
gboolean *out_have_scratch_delta,
char **out_from_revision,
DeltaSearchResult *out_result,
GCancellable *cancellable,
GError **error)
{
@@ -2348,7 +2368,28 @@ get_best_static_delta_start_for (OtPullData *pull_data,
g_assert (pull_data->summary_deltas_checksums != NULL);
*out_have_scratch_delta = FALSE;
out_result->result = DELTA_SEARCH_RESULT_NO_MATCH;
out_result->from_revision[0] = '\0';
/* First, do we already have this commit completely downloaded? */
gboolean have_to_rev;
if (!ostree_repo_has_object (pull_data->repo, OSTREE_OBJECT_TYPE_COMMIT,
to_revision, &have_to_rev,
cancellable, error))
return FALSE;
if (have_to_rev)
{
OstreeRepoCommitState to_rev_state;
if (!ostree_repo_load_commit (pull_data->repo, to_revision,
NULL, &to_rev_state, error))
return FALSE;
if (!(to_rev_state & OSTREE_REPO_COMMIT_STATE_PARTIAL))
{
/* We already have this commit, we're done! */
out_result->result = DELTA_SEARCH_RESULT_UNCHANGED;
return TRUE; /* Early return */
}
}
/* Loop over all deltas known from the summary file,
* finding ones which go to to_revision */
@@ -2366,9 +2407,17 @@ get_best_static_delta_start_for (OtPullData *pull_data,
continue;
if (cur_from_rev)
g_ptr_array_add (candidates, g_steal_pointer (&cur_from_rev));
{
g_ptr_array_add (candidates, g_steal_pointer (&cur_from_rev));
}
else
*out_have_scratch_delta = TRUE;
{
/* We note that we have a _SCRATCH delta here, but we'll prefer using
* "from" deltas (obviously, they'll be smaller) where possible if we
* find one below.
*/
out_result->result = DELTA_SEARCH_RESULT_SCRATCH;
}
}
/* Loop over our candidates, find the newest one */
@@ -2407,7 +2456,11 @@ get_best_static_delta_start_for (OtPullData *pull_data,
}
}
*out_from_revision = g_strdup (newest_candidate);
if (newest_candidate)
{
out_result->result = DELTA_SEARCH_RESULT_FROM;
memcpy (out_result->from_revision, newest_candidate, OSTREE_SHA256_STRING_LEN+1);
}
return TRUE;
}
@@ -3082,25 +3135,45 @@ initiate_request (OtPullData *pull_data,
/* If we have a summary, we can use the newer logic */
if (pull_data->summary)
{
gboolean have_scratch_delta = FALSE;
DeltaSearchResult deltares;
/* Look for a delta to @to_revision in the summary data */
if (!get_best_static_delta_start_for (pull_data, to_revision,
&have_scratch_delta, &delta_from_revision,
if (!get_best_static_delta_start_for (pull_data, to_revision, &deltares,
pull_data->cancellable, error))
return FALSE;
if (delta_from_revision) /* Did we find a delta FROM commit? */
initiate_delta_request (pull_data, delta_from_revision, to_revision, ref);
else if (have_scratch_delta) /* No delta FROM, do we have a scratch? */
initiate_delta_request (pull_data, NULL, to_revision, ref);
else if (pull_data->require_static_deltas) /* No deltas found; are they required? */
switch (deltares.result)
{
set_required_deltas_error (error, (ref != NULL) ? ref->ref_name : "", to_revision);
return FALSE;
case DELTA_SEARCH_RESULT_NO_MATCH:
{
if (pull_data->require_static_deltas) /* No deltas found; are they required? */
{
set_required_deltas_error (error, (ref != NULL) ? ref->ref_name : "", to_revision);
return FALSE;
}
else /* No deltas, fall back to object fetches. */
queue_scan_one_metadata_object (pull_data, to_revision, OSTREE_OBJECT_TYPE_COMMIT, NULL, 0, ref);
}
break;
case DELTA_SEARCH_RESULT_FROM:
initiate_delta_request (pull_data, deltares.from_revision, to_revision, ref);
break;
case DELTA_SEARCH_RESULT_SCRATCH:
initiate_delta_request (pull_data, NULL, to_revision, ref);
break;
case DELTA_SEARCH_RESULT_UNCHANGED:
{
/* If we already have the commit, here things get a little special; we've historically
* fetched detached metadata, so let's keep doing that. But in the --require-static-deltas
* path, we don't, under the assumption the user wants as little network traffic as
* possible.
*/
if (pull_data->require_static_deltas)
break;
else
queue_scan_one_metadata_object (pull_data, to_revision, OSTREE_OBJECT_TYPE_COMMIT, NULL, 0, ref);
}
}
else /* No deltas, fall back to object fetches. */
queue_scan_one_metadata_object (pull_data, to_revision, OSTREE_OBJECT_TYPE_COMMIT, NULL, 0, ref);
}
else if (ref != NULL)
{
+10 -5
View File
@@ -725,7 +725,8 @@ _ostree_repo_list_refs_internal (OstreeRepo *self,
* ostree_repo_list_refs:
* @self: Repo
* @refspec_prefix: (allow-none): Only list refs which match this prefix
* @out_all_refs: (out) (element-type utf8 utf8): Mapping from ref to checksum
* @out_all_refs: (out) (element-type utf8 utf8) (transfer container):
* Mapping from ref to checksum
* @cancellable: Cancellable
* @error: Error
*
@@ -750,7 +751,8 @@ ostree_repo_list_refs (OstreeRepo *self,
* ostree_repo_list_refs_ext:
* @self: Repo
* @refspec_prefix: (allow-none): Only list refs which match this prefix
* @out_all_refs: (out) (element-type utf8 utf8): Mapping from ref to checksum
* @out_all_refs: (out) (element-type utf8 utf8) (transfer container):
* Mapping from ref to checksum
* @flags: Options controlling listing behavior
* @cancellable: Cancellable
* @error: Error
@@ -778,7 +780,8 @@ ostree_repo_list_refs_ext (OstreeRepo *self,
* ostree_repo_remote_list_refs:
* @self: Repo
* @remote_name: Name of the remote.
* @out_all_refs: (out) (element-type utf8 utf8): Mapping from ref to checksum
* @out_all_refs: (out) (element-type utf8 utf8) (transfer container):
* Mapping from ref to checksum
* @cancellable: Cancellable
* @error: Error
*
@@ -893,7 +896,8 @@ remote_list_collection_refs_process_refs (OstreeRepo *self,
* ostree_repo_remote_list_collection_refs:
* @self: Repo
* @remote_name: Name of the remote.
* @out_all_refs: (out) (element-type OstreeCollectionRef utf8): Mapping from collection–ref to checksum
* @out_all_refs: (out) (element-type OstreeCollectionRef utf8) (transfer container):
* Mapping from collection–ref to checksum
* @cancellable: Cancellable
* @error: Error
*
@@ -1165,7 +1169,8 @@ _ostree_repo_update_collection_refs (OstreeRepo *self,
* ostree_repo_list_collection_refs:
* @self: Repo
* @match_collection_id: (nullable): If non-%NULL, only list refs from this collection
* @out_all_refs: (out) (element-type OstreeCollectionRef utf8): Mapping from collection–ref to checksum
* @out_all_refs: (out) (element-type OstreeCollectionRef utf8) (transfer container):
* Mapping from collection–ref to checksum
* @flags: Options controlling listing behavior
* @cancellable: Cancellable
* @error: Error
@@ -217,6 +217,37 @@ string_array_nonempty_intersection (GPtrArray *a,
return FALSE;
}
static gboolean
sizename_is_delta_candidate (OstreeDeltaContentSizeNames *sizename)
{
/* Don't build candidates for the empty object */
if (sizename->size == 0)
return FALSE;
/* Look for known non-delta-able files (currently just compression like xz) */
for (guint i = 0; i < sizename->basenames->len; i++)
{
const char *name = sizename->basenames->pdata[i];
/* We could replace this down the line with g_content_type_guess() or so,
* but it's not clear to me that's a major win; we'd still need to
* maintain a list of compression formats, and this doesn't require
* allocation.
* NB: We explicitly don't have .gz here in case someone might be
* using --rsyncable for that.
*/
const char *dot = strrchr (name, '.');
if (!dot)
continue;
const char *extension = dot+1;
/* Don't add .gz here, see above */
if (g_str_equal (extension, "xz") || g_str_equal (extension, "bz2"))
return FALSE;
}
/* Let's try it */
return TRUE;
}
/*
* Build up a map of files with matching basenames and similar size,
* and use it to find apparently similar objects.
@@ -258,7 +289,7 @@ _ostree_delta_compute_similar_objects (OstreeRepo *repo,
&to_sizes,
cancellable, error))
goto out;
/* Iterate over all newly added objects, find objects which have
* similar basename and sizes.
*
@@ -277,8 +308,7 @@ _ostree_delta_compute_similar_objects (OstreeRepo *repo,
const guint64 max_threshold = to_sizenames->size *
(1.0+similarity_percent_threshold/100.0);
/* Don't build candidates for the empty object */
if (to_sizenames->size == 0)
if (!sizename_is_delta_candidate (to_sizenames))
continue;
for (fuzzy = 0; fuzzy < 2 && !found; fuzzy++)
@@ -286,12 +316,8 @@ _ostree_delta_compute_similar_objects (OstreeRepo *repo,
for (j = lower; j < upper; j++)
{
OstreeDeltaContentSizeNames *from_sizenames = from_sizes->pdata[j];
/* Don't build candidates for the empty object */
if (from_sizenames->size == 0)
{
continue;
}
if (!sizename_is_delta_candidate (from_sizenames))
continue;
if (from_sizenames->size < min_threshold)
{
@@ -55,11 +55,9 @@ typedef struct {
GError **async_error;
OstreeObjectType output_objtype;
GLnxTmpfile tmpf;
guint64 content_size;
GOutputStream *content_out;
OtChecksum content_checksum;
char checksum[OSTREE_SHA256_STRING_LEN+1];
OstreeRepoBareContent content_out;
char *read_source_object;
int read_source_fd;
gboolean have_obj;
@@ -278,9 +276,7 @@ _ostree_static_delta_part_execute (OstreeRepo *repo,
ret = TRUE;
out:
glnx_tmpfile_clear (&state->tmpf);
g_clear_object (&state->content_out);
ot_checksum_clear (&state->content_checksum);
_ostree_repo_bare_content_cleanup (&state->content_out);
return ret;
}
@@ -378,29 +374,6 @@ validate_ofs (StaticDeltaExecutionState *state,
return TRUE;
}
static gboolean
content_out_write (OstreeRepo *repo,
StaticDeltaExecutionState *state,
const guint8* buf,
gsize len,
GCancellable *cancellable,
GError **error)
{
gsize bytes_written;
if (state->content_checksum.initialized)
ot_checksum_update (&state->content_checksum, buf, len);
/* Ignore bytes_written since we discard partial content */
if (!g_output_stream_write_all (state->content_out,
buf, len,
&bytes_written,
cancellable, error))
return FALSE;
return TRUE;
}
static gboolean
do_content_open_generic (OstreeRepo *repo,
StaticDeltaExecutionState *state,
@@ -485,33 +458,15 @@ dispatch_bspatch (OstreeRepo *repo,
&stream) < 0)
return FALSE;
if (!content_out_write (repo, state, buf, state->content_size,
cancellable, error))
if (!_ostree_repo_bare_content_write (repo, &state->content_out,
buf, state->content_size,
cancellable, error))
return FALSE;
}
return TRUE;
}
/* Before, we had a distinction between "trusted" and "untrusted" deltas
* which we've decided wasn't a good idea. Now, we always checksum the content.
* Compare with what ostree_checksum_file_from_input() is doing too.
*/
static gboolean
handle_untrusted_content_checksum (OstreeRepo *repo,
StaticDeltaExecutionState *state,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GFileInfo) finfo = _ostree_mode_uidgid_to_gfileinfo (state->mode, state->uid, state->gid);
g_autoptr(GBytes) header = _ostree_file_header_new (finfo, state->xattrs);
ot_checksum_init (&state->content_checksum);
ot_checksum_update_bytes (&state->content_checksum, header);
return TRUE;
}
static gboolean
dispatch_open_splice_and_close (OstreeRepo *repo,
StaticDeltaExecutionState *state,
@@ -589,20 +544,18 @@ dispatch_open_splice_and_close (OstreeRepo *repo,
if (!state->have_obj)
{
if (!_ostree_repo_open_content_bare (repo, state->checksum,
if (!_ostree_repo_bare_content_open (repo, state->checksum,
state->content_size,
&state->tmpf,
state->uid, state->gid, state->mode,
state->xattrs,
&state->content_out,
cancellable, error))
goto out;
state->content_out = g_unix_output_stream_new (state->tmpf.fd, FALSE);
if (!handle_untrusted_content_checksum (repo, state, cancellable, error))
goto out;
if (!content_out_write (repo, state,
state->payload_data + content_offset,
state->content_size,
cancellable, error))
if (!_ostree_repo_bare_content_write (repo, &state->content_out,
state->payload_data + content_offset,
state->content_size,
cancellable, error))
goto out;
}
}
@@ -691,17 +644,15 @@ dispatch_open (OstreeRepo *repo,
if (!state->have_obj)
{
if (!_ostree_repo_open_content_bare (repo, state->checksum,
if (!_ostree_repo_bare_content_open (repo, state->checksum,
state->content_size,
&state->tmpf,
state->uid, state->gid, state->mode,
state->xattrs,
&state->content_out,
cancellable, error))
return FALSE;
state->content_out = g_unix_output_stream_new (state->tmpf.fd, FALSE);
}
if (!handle_untrusted_content_checksum (repo, state, cancellable, error))
return FALSE;
return TRUE;
}
@@ -740,8 +691,9 @@ dispatch_write (OstreeRepo *repo,
if (G_UNLIKELY (bytes_read == 0))
return glnx_throw (error, "Unexpected EOF reading object %s", state->read_source_object);
if (!content_out_write (repo, state, (guint8*)buf, bytes_read,
cancellable, error))
if (!_ostree_repo_bare_content_write (repo, &state->content_out,
(guint8*)buf, bytes_read,
cancellable, error))
return FALSE;
content_size -= bytes_read;
@@ -753,8 +705,9 @@ dispatch_write (OstreeRepo *repo,
if (!validate_ofs (state, content_offset, content_size, error))
return FALSE;
if (!content_out_write (repo, state, state->payload_data + content_offset, content_size,
cancellable, error))
if (!_ostree_repo_bare_content_write (repo, &state->content_out,
state->payload_data + content_offset, content_size,
cancellable, error))
return FALSE;
}
}
@@ -818,34 +771,22 @@ dispatch_close (OstreeRepo *repo,
{
GLNX_AUTO_PREFIX_ERROR("opcode close", error);
if (state->content_out)
if (state->content_out.initialized)
{
if (!g_output_stream_flush (state->content_out, cancellable, error))
char actual_checksum[OSTREE_SHA256_STRING_LEN+1];
if (!_ostree_repo_bare_content_commit (repo, &state->content_out, actual_checksum,
sizeof (actual_checksum),
cancellable, error))
return FALSE;
if (state->content_checksum.initialized)
{
char actual_checksum[OSTREE_SHA256_STRING_LEN+1];
ot_checksum_get_hexdigest (&state->content_checksum, actual_checksum, sizeof (actual_checksum));
if (strcmp (actual_checksum, state->checksum) != 0)
return glnx_throw (error, "Corrupted object %s (actual checksum is %s)",
state->checksum, actual_checksum);
}
if (!_ostree_repo_commit_trusted_content_bare (repo, state->checksum, &state->tmpf,
state->uid, state->gid, state->mode,
state->xattrs,
cancellable, error))
return FALSE;
g_clear_object (&state->content_out);
g_assert_cmpstr (state->checksum, ==, actual_checksum);
}
if (!dispatch_unset_read_source (repo, state, cancellable, error))
return FALSE;
g_clear_pointer (&state->xattrs, g_variant_unref);
ot_checksum_clear (&state->content_checksum);
_ostree_repo_bare_content_cleanup (&state->content_out);
state->checksum_index++;
state->output_target = NULL;
+36 -58
View File
@@ -56,10 +56,6 @@ ostree_repo_commit_traverse_iter_init_commit (OstreeRepoCommitTraverseIter *it
{
struct _OstreeRepoRealCommitTraverseIter *real =
(struct _OstreeRepoRealCommitTraverseIter*)iter;
gboolean ret = FALSE;
const guchar *csum;
g_autoptr(GVariant) meta_csum_bytes = NULL;
g_autoptr(GVariant) content_csum_bytes = NULL;
memset (real, 0, sizeof (*real));
real->initialized = TRUE;
@@ -68,21 +64,21 @@ ostree_repo_commit_traverse_iter_init_commit (OstreeRepoCommitTraverseIter *it
real->current_dir = NULL;
real->idx = 0;
g_autoptr(GVariant) content_csum_bytes = NULL;
g_variant_get_child (commit, 6, "@ay", &content_csum_bytes);
csum = ostree_checksum_bytes_peek_validate (content_csum_bytes, error);
const guchar *csum = ostree_checksum_bytes_peek_validate (content_csum_bytes, error);
if (!csum)
goto out;
return FALSE;
ostree_checksum_inplace_from_bytes (csum, real->checksum_content);
g_autoptr(GVariant) meta_csum_bytes = NULL;
g_variant_get_child (commit, 7, "@ay", &meta_csum_bytes);
csum = ostree_checksum_bytes_peek_validate (meta_csum_bytes, error);
if (!csum)
goto out;
return FALSE;
ostree_checksum_inplace_from_bytes (csum, real->checksum_meta);
ret = TRUE;
out:
return ret;
return TRUE;
}
/**
@@ -312,8 +308,6 @@ traverse_iter (OstreeRepo *repo,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
while (TRUE)
{
g_autoptr(GVariant) key = NULL;
@@ -330,12 +324,11 @@ traverse_iter (OstreeRepo *repo,
g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
g_debug ("Ignoring not-found dirmeta");
ret = TRUE;
return TRUE; /* Note early return */
}
else
g_propagate_error (error, g_steal_pointer (&local_error));
goto out;
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
else if (iterres == OSTREE_REPO_COMMIT_ITER_RESULT_END)
break;
@@ -371,16 +364,14 @@ traverse_iter (OstreeRepo *repo,
if (!traverse_dirtree (repo, content_checksum, inout_reachable,
ignore_missing_dirs, cancellable, error))
goto out;
return FALSE;
}
}
else
g_assert_not_reached ();
}
ret = TRUE;
out:
return ret;
return TRUE;
}
static gboolean
@@ -391,12 +382,9 @@ traverse_dirtree (OstreeRepo *repo,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GVariant) dirtree = NULL;
ostree_cleanup_repo_commit_traverse_iter
OstreeRepoCommitTraverseIter iter = { 0, };
g_autoptr(GError) local_error = NULL;
g_autoptr(GVariant) dirtree = NULL;
if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_DIR_TREE, checksum,
&dirtree, &local_error))
{
@@ -404,26 +392,25 @@ traverse_dirtree (OstreeRepo *repo,
g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
g_debug ("Ignoring not-found dirmeta %s", checksum);
ret = TRUE;
return TRUE; /* Early return */
}
else
g_propagate_error (error, g_steal_pointer (&local_error));
goto out;
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
g_debug ("Traversing dirtree %s", checksum);
ostree_cleanup_repo_commit_traverse_iter
OstreeRepoCommitTraverseIter iter = { 0, };
if (!ostree_repo_commit_traverse_iter_init_dirtree (&iter, repo, dirtree,
OSTREE_REPO_COMMIT_TRAVERSE_FLAG_NONE,
error))
goto out;
return FALSE;
if (!traverse_iter (repo, &iter, inout_reachable, ignore_missing_dirs, cancellable, error))
goto out;
return FALSE;
ret = TRUE;
out:
return ret;
return TRUE;
}
/**
@@ -446,28 +433,21 @@ ostree_repo_traverse_commit_union (OstreeRepo *repo,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
g_autofree char *tmp_checksum = NULL;
while (TRUE)
{
gboolean recurse = FALSE;
g_autoptr(GVariant) key = NULL;
g_autoptr(GVariant) commit = NULL;
ostree_cleanup_repo_commit_traverse_iter
OstreeRepoCommitTraverseIter iter = { 0, };
OstreeRepoCommitState commitstate;
gboolean ignore_missing_dirs = FALSE;
key = g_variant_ref_sink (ostree_object_name_serialize (commit_checksum, OSTREE_OBJECT_TYPE_COMMIT));
g_autoptr(GVariant) key =
g_variant_ref_sink (ostree_object_name_serialize (commit_checksum, OSTREE_OBJECT_TYPE_COMMIT));
if (g_hash_table_contains (inout_reachable, key))
break;
g_autoptr(GVariant) commit = NULL;
if (!ostree_repo_load_variant_if_exists (repo, OSTREE_OBJECT_TYPE_COMMIT,
commit_checksum, &commit,
error))
goto out;
return FALSE;
/* Just return if the parent isn't found; we do expect most
* people to have partial repositories.
@@ -476,10 +456,12 @@ ostree_repo_traverse_commit_union (OstreeRepo *repo,
break;
/* See if the commit is partial, if so it's not an error to lack objects */
OstreeRepoCommitState commitstate;
if (!ostree_repo_load_commit (repo, commit_checksum, NULL, &commitstate,
error))
goto out;
return FALSE;
gboolean ignore_missing_dirs = FALSE;
if ((commitstate & OSTREE_REPO_COMMIT_STATE_PARTIAL) != 0)
ignore_missing_dirs = TRUE;
@@ -487,14 +469,17 @@ ostree_repo_traverse_commit_union (OstreeRepo *repo,
key = NULL;
g_debug ("Traversing commit %s", commit_checksum);
ostree_cleanup_repo_commit_traverse_iter
OstreeRepoCommitTraverseIter iter = { 0, };
if (!ostree_repo_commit_traverse_iter_init_commit (&iter, repo, commit,
OSTREE_REPO_COMMIT_TRAVERSE_FLAG_NONE,
error))
goto out;
return FALSE;
if (!traverse_iter (repo, &iter, inout_reachable, ignore_missing_dirs, cancellable, error))
goto out;
return FALSE;
gboolean recurse = FALSE;
if (maxdepth == -1 || maxdepth > 0)
{
g_free (tmp_checksum);
@@ -511,9 +496,7 @@ ostree_repo_traverse_commit_union (OstreeRepo *repo,
break;
}
ret = TRUE;
out:
return ret;
return TRUE;
}
/**
@@ -536,17 +519,12 @@ ostree_repo_traverse_commit (OstreeRepo *repo,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GHashTable) ret_reachable =
ostree_repo_traverse_new_reachable ();
g_autoptr(GHashTable) ret_reachable = ostree_repo_traverse_new_reachable ();
if (!ostree_repo_traverse_commit_union (repo, commit_checksum, maxdepth,
ret_reachable, cancellable, error))
goto out;
return FALSE;
ret = TRUE;
if (out_reachable)
*out_reachable = g_steal_pointer (&ret_reachable);
out:
return ret;
return TRUE;
}
+27 -4
View File
@@ -1918,8 +1918,9 @@ ostree_repo_create (OstreeRepo *self,
g_variant_new_variant (g_variant_new_string (self->collection_id)));
glnx_autofd int repo_dir_fd = -1;
g_autoptr(GVariant) options = g_variant_ref_sink (g_variant_builder_end (builder));
if (!repo_create_at_internal (AT_FDCWD, repopath, mode,
g_variant_builder_end (builder),
options,
&repo_dir_fd,
cancellable, error))
return FALSE;
@@ -4903,7 +4904,16 @@ _ostree_repo_try_lock_tmpdir (int tmpdir_dfd,
}
else
{
did_lock = TRUE;
/* It's possible that we got a lock after seeing the directory, but
* another process deleted the tmpdir, so verify it still exists.
*/
struct stat stbuf;
if (!glnx_fstatat_allow_noent (tmpdir_dfd, tmpdir_name, &stbuf, AT_SYMLINK_NOFOLLOW, error))
return FALSE;
if (errno == 0 && S_ISDIR (stbuf.st_mode))
did_lock = TRUE;
else
glnx_release_lock_file (file_lock_out);
}
*out_did_lock = did_lock;
@@ -4954,7 +4964,8 @@ _ostree_repo_allocate_tmpdir (int tmpdir_dfd,
if (!glnx_opendirat (dfd_iter.fd, dent->d_name, FALSE,
&target_dfd, &local_error))
{
if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY))
if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY) ||
g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
continue;
else
{
@@ -4978,6 +4989,8 @@ _ostree_repo_allocate_tmpdir (int tmpdir_dfd,
(void)futimens (target_dfd, NULL);
/* We found an existing tmpdir which we managed to lock */
g_debug ("Reusing tmpdir %s", dent->d_name);
reusing_dir = TRUE;
ret_tmpdir.src_dfd = tmpdir_dfd;
ret_tmpdir.fd = glnx_steal_fd (&target_dfd);
ret_tmpdir.path = g_strdup (dent->d_name);
@@ -5000,8 +5013,18 @@ _ostree_repo_allocate_tmpdir (int tmpdir_dfd,
error))
return FALSE;
if (!did_lock)
continue;
{
/* We raced and someone else already locked the newly created
* directory. Free the resources here and then mark it as
* uninitialized so glnx_tmpdir_cleanup doesn't delete the directory
* when new_tmpdir goes out of scope.
*/
glnx_tmpdir_unset (&new_tmpdir);
new_tmpdir.initialized = FALSE;
continue;
}
g_debug ("Using new tmpdir %s", new_tmpdir.path);
ret_tmpdir = new_tmpdir; /* Transfer ownership */
new_tmpdir.initialized = FALSE;
}
+15
View File
@@ -539,7 +539,20 @@ gboolean ostree_repo_load_variant_if_exists (OstreeRepo *self,
GVariant **out_variant,
GError **error);
/**
* OstreeRepoCommitState:
* @OSTREE_REPO_COMMIT_STATE_NORMAL: Commit is complete. This is the default.
* (Since: 2017.14.)
* @OSTREE_REPO_COMMIT_STATE_PARTIAL: One or more objects are missing from the
* local copy of the commit, but metadata is present. (Since: 2015.7.)
*
* Flags representing the state of a commit in the local repository, as returned
* by ostree_repo_load_commit().
*
* Since: 2015.7
*/
typedef enum {
OSTREE_REPO_COMMIT_STATE_NORMAL = 0,
OSTREE_REPO_COMMIT_STATE_PARTIAL = (1 << 0),
} OstreeRepoCommitState;
@@ -631,6 +644,7 @@ typedef OstreeRepoCommitFilterResult (*OstreeRepoCommitFilter) (OstreeRepo *r
* @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
* @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CONSUME: Delete added files/directories after commit; Since: 2017.13
* @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_DEVINO_CANONICAL: If a devino cache hit is found, skip modifier filters (non-directories only); Since: 2017.14
*/
typedef enum {
OSTREE_REPO_COMMIT_MODIFIER_FLAGS_NONE = 0,
@@ -639,6 +653,7 @@ typedef enum {
OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS = (1 << 2),
OSTREE_REPO_COMMIT_MODIFIER_FLAGS_ERROR_ON_UNLABELED = (1 << 3),
OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CONSUME = (1 << 4),
OSTREE_REPO_COMMIT_MODIFIER_FLAGS_DEVINO_CANONICAL = (1 << 5),
} OstreeRepoCommitModifierFlags;
/**
+1 -1
View File
@@ -82,7 +82,7 @@ encode_pair (GString *str, const char *name, const char *value)
/**
* soup_form_encode_hash:
* @form_data_set: (element-type utf8 utf8): a hash table containing
* @form_data_set: (element-type utf8 utf8) (transfer none): a hash table containing
* name/value pairs (as strings)
*
* Encodes @form_data_set into a value of type
+1 -1
View File
@@ -1281,7 +1281,7 @@ soup_uri_set_query (SoupURI *uri, const char *query)
/**
* soup_uri_set_query_from_form:
* @uri: a #SoupURI
* @form: (element-type utf8 utf8): a #GHashTable containing HTML form
* @form: (element-type utf8 utf8) (transfer none): a #GHashTable containing HTML form
* information
*
* Sets @uri's query to the result of encoding @form according to the
+3 -3
View File
@@ -43,7 +43,7 @@
*
* Since: 2017.4
*/
#define OSTREE_RELEASE_VERSION (13)
#define OSTREE_RELEASE_VERSION (14)
/**
* OSTREE_VERSION
@@ -52,7 +52,7 @@
*
* Since: 2017.4
*/
#define OSTREE_VERSION (2017.13)
#define OSTREE_VERSION (2017.14)
/**
* OSTREE_VERSION_S:
@@ -62,7 +62,7 @@
*
* Since: 2017.4
*/
#define OSTREE_VERSION_S "2017.13"
#define OSTREE_VERSION_S "2017.14"
#define OSTREE_ENCODE_VERSION(year,release) \
((year) << 16 | (release))
+15 -28
View File
@@ -43,29 +43,20 @@ static GOptionEntry options[] = {
gboolean
ot_admin_builtin_diff (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(OstreeSysroot) sysroot = NULL;
gboolean ret = FALSE;
g_autoptr(OstreeDeployment) deployment = NULL;
g_autoptr(GFile) deployment_dir = NULL;
g_autoptr(GPtrArray) modified = NULL;
g_autoptr(GPtrArray) removed = NULL;
g_autoptr(GPtrArray) added = NULL;
g_autoptr(GFile) orig_etc_path = NULL;
g_autoptr(GFile) new_etc_path = NULL;
context = g_option_context_new ("");
g_autoptr(GOptionContext) context = g_option_context_new ("");
g_option_context_add_main_entries (context, options, NULL);
g_autoptr(OstreeSysroot) sysroot = NULL;
if (!ostree_admin_option_context_parse (context, options, &argc, &argv,
OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER | OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED,
invocation, &sysroot, cancellable, error))
goto out;
return FALSE;
if (!ot_admin_require_booted_deployment_or_osname (sysroot, opt_osname,
cancellable, error))
goto out;
return FALSE;
g_autoptr(OstreeDeployment) deployment = NULL;
if (opt_osname != NULL)
{
deployment = ostree_sysroot_get_merge_deployment (sysroot, opt_osname);
@@ -73,28 +64,24 @@ ot_admin_builtin_diff (int argc, char **argv, OstreeCommandInvocation *invocatio
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"No deployment for OS '%s'", opt_osname);
goto out;
return FALSE;
}
}
else
deployment = g_object_ref (ostree_sysroot_get_booted_deployment (sysroot));
deployment_dir = ostree_sysroot_get_deployment_directory (sysroot, deployment);
orig_etc_path = g_file_resolve_relative_path (deployment_dir, "usr/etc");
new_etc_path = g_file_resolve_relative_path (deployment_dir, "etc");
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);
g_autoptr(GFile) deployment_dir = ostree_sysroot_get_deployment_directory (sysroot, deployment);
g_autoptr(GFile) orig_etc_path = g_file_resolve_relative_path (deployment_dir, "usr/etc");
g_autoptr(GFile) new_etc_path = g_file_resolve_relative_path (deployment_dir, "etc");
g_autoptr(GPtrArray) modified = g_ptr_array_new_with_free_func ((GDestroyNotify) ostree_diff_item_unref);
g_autoptr(GPtrArray) removed = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
g_autoptr(GPtrArray) added = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
if (!ostree_diff_dirs (OSTREE_DIFF_FLAGS_IGNORE_XATTRS,
orig_etc_path, new_etc_path, modified, removed, added,
cancellable, error))
goto out;
return FALSE;
ostree_diff_print (orig_etc_path, new_etc_path, modified, removed, added);
ret = TRUE;
out:
return ret;
return TRUE;
}
+7
View File
@@ -51,6 +51,7 @@ static gboolean opt_no_xattrs;
static char *opt_selinux_policy;
static gboolean opt_canonical_permissions;
static gboolean opt_consume;
static gboolean opt_devino_canonical;
static char **opt_trees;
static gint opt_owner_uid = -1;
static gint opt_owner_gid = -1;
@@ -98,6 +99,7 @@ static GOptionEntry options[] = {
{ "no-xattrs", 0, 0, G_OPTION_ARG_NONE, &opt_no_xattrs, "Do not import extended attributes", NULL },
{ "selinux-policy", 0, 0, G_OPTION_ARG_FILENAME, &opt_selinux_policy, "Set SELinux labels based on policy in root filesystem PATH (may be /)", "PATH" },
{ "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 },
{ "devino-canonical", 'I', 0, G_OPTION_ARG_NONE, &opt_devino_canonical, "Assume hardlinked objects are unmodified. Implies --link-checkout-speedup", 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 },
{ "tar-pathname-filter", 0, 0, G_OPTION_ARG_STRING, &opt_tar_pathname_filter, "When loading tar archives, use REGEX,REPLACEMENT against path names", "REGEX,REPLACEMENT" },
{ "skip-if-unchanged", 0, 0, G_OPTION_ARG_NONE, &opt_skip_if_unchanged, "If the contents are unchanged from previous commit, do nothing", NULL },
@@ -480,6 +482,11 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio
flags |= OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS;
if (opt_consume)
flags |= OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CONSUME;
if (opt_devino_canonical)
{
opt_link_checkout_speedup = TRUE; /* Imply this */
flags |= OSTREE_REPO_COMMIT_MODIFIER_FLAGS_DEVINO_CANONICAL;
}
if (opt_canonical_permissions)
flags |= OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS;
if (opt_generate_sizes)
+6 -13
View File
@@ -86,12 +86,8 @@ remote_option_context_new_with_commands (void)
gboolean
ostree_builtin_remote (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
{
OstreeCommand *subcommand;
const char *subcommand_name = NULL;
g_autofree char *prgname = NULL;
gboolean ret = FALSE;
int in, out;
int in,out;
for (in = 1, out = 1; in < argc; in++, out++)
{
/* The non-option is the command, take it out of the arguments */
@@ -115,7 +111,7 @@ ostree_builtin_remote (int argc, char **argv, OstreeCommandInvocation *invocatio
argc = out;
subcommand = remote_subcommands;
OstreeCommand *subcommand = remote_subcommands;
while (subcommand->name)
{
if (g_strcmp0 (subcommand_name, subcommand->name) == 0)
@@ -150,18 +146,15 @@ ostree_builtin_remote (int argc, char **argv, OstreeCommandInvocation *invocatio
help = g_option_context_get_help (context, FALSE, NULL);
g_printerr ("%s", help);
goto out;
return FALSE;
}
prgname = g_strdup_printf ("%s %s", g_get_prgname (), subcommand_name);
g_autofree char *prgname = g_strdup_printf ("%s %s", g_get_prgname (), subcommand_name);
g_set_prgname (prgname);
OstreeCommandInvocation sub_invocation = { .command = subcommand };
if (!subcommand->fn (argc, argv, &sub_invocation, cancellable, error))
goto out;
return FALSE;
ret = TRUE;
out:
return ret;
return TRUE;
}
+39 -61
View File
@@ -149,77 +149,63 @@ ot_static_delta_builtin_list (int argc, char **argv, OstreeCommandInvocation *in
static gboolean
ot_static_delta_builtin_show (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
{
gboolean ret = FALSE;
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GOptionContext) context = g_option_context_new ("");
g_autoptr(OstreeRepo) repo = NULL;
const char *delta_id = NULL;
context = g_option_context_new ("");
if (!ostree_option_context_parse (context, list_options, &argc, &argv, invocation, &repo, cancellable, error))
goto out;
return FALSE;
if (argc < 3)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"DELTA must be specified");
goto out;
return FALSE;
}
delta_id = argv[2];
const char *delta_id = argv[2];
if (!ostree_cmd__private__ ()->ostree_static_delta_dump (repo, delta_id, cancellable, error))
goto out;
ret = TRUE;
out:
return ret;
return FALSE;
return TRUE;
}
static gboolean
ot_static_delta_builtin_delete (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
{
gboolean ret = FALSE;
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GOptionContext) context = g_option_context_new ("");
g_autoptr(OstreeRepo) repo = NULL;
const char *delta_id = NULL;
context = g_option_context_new ("");
if (!ostree_option_context_parse (context, list_options, &argc, &argv, invocation, &repo, cancellable, error))
goto out;
return FALSE;
if (argc < 3)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"DELTA must be specified");
goto out;
return FALSE;
}
delta_id = argv[2];
const char *delta_id = argv[2];
if (!ostree_cmd__private__ ()->ostree_static_delta_delete (repo, delta_id, cancellable, error))
goto out;
return FALSE;
ret = TRUE;
out:
return ret;
return TRUE;
}
static gboolean
ot_static_delta_builtin_generate (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
{
gboolean ret = FALSE;
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GOptionContext) context = g_option_context_new ("[TO]");
g_autoptr(OstreeRepo) repo = NULL;
context = g_option_context_new ("[TO]");
if (!ostree_option_context_parse (context, generate_options, &argc, &argv, invocation, &repo, cancellable, error))
goto out;
return FALSE;
if (!ostree_ensure_repo_writable (repo, error))
goto out;
return FALSE;
if (argc >= 3 && opt_to_rev == NULL)
opt_to_rev = argv[2];
@@ -228,7 +214,7 @@ ot_static_delta_builtin_generate (int argc, char **argv, OstreeCommandInvocation
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"TO revision must be specified");
goto out;
return FALSE;
}
else
{
@@ -247,7 +233,7 @@ ot_static_delta_builtin_generate (int argc, char **argv, OstreeCommandInvocation
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Cannot specify both --empty and --from=REV");
goto out;
return FALSE;
}
from_source = NULL;
}
@@ -264,25 +250,24 @@ ot_static_delta_builtin_generate (int argc, char **argv, OstreeCommandInvocation
if (from_source)
{
if (!ostree_repo_resolve_rev (repo, from_source, FALSE, &from_resolved, error))
goto out;
return FALSE;
}
if (!ostree_repo_resolve_rev (repo, opt_to_rev, FALSE, &to_resolved, error))
goto out;
return FALSE;
if (opt_if_not_exists)
{
gboolean does_exist;
g_autofree char *delta_id = from_resolved ? g_strconcat (from_resolved, "-", to_resolved, NULL) : g_strdup (to_resolved);
if (!ostree_cmd__private__ ()->ostree_static_delta_query_exists (repo, delta_id, &does_exist, cancellable, error))
goto out;
return FALSE;
if (does_exist)
{
g_print ("Delta %s already exists.\n", delta_id);
ret = TRUE;
goto out;
return TRUE;
}
}
if (opt_endianness)
{
if (strcmp (opt_endianness, "l") == 0)
@@ -293,12 +278,12 @@ ot_static_delta_builtin_generate (int argc, char **argv, OstreeCommandInvocation
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid endianness '%s'", opt_endianness);
goto out;
return FALSE;
}
}
else
endianness = G_BYTE_ORDER;
if (opt_swap_endianness)
{
switch (endianness)
@@ -346,54 +331,47 @@ ot_static_delta_builtin_generate (int argc, char **argv, OstreeCommandInvocation
from_resolved, to_resolved, NULL,
params,
cancellable, error))
goto out;
return FALSE;
}
}
ret = TRUE;
out:
return ret;
return TRUE;
}
static gboolean
ot_static_delta_builtin_apply_offline (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
{
gboolean ret = FALSE;
const char *patharg;
g_autoptr(GFile) path = NULL;
g_autoptr(GOptionContext) context = NULL;
g_autoptr(OstreeRepo) repo = NULL;
context = g_option_context_new ("");
if (!ostree_option_context_parse (context, apply_offline_options, &argc, &argv, invocation, &repo, cancellable, error))
goto out;
return FALSE;
if (!ostree_ensure_repo_writable (repo, error))
goto out;
return FALSE;
if (argc < 3)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"PATH must be specified");
goto out;
return FALSE;
}
patharg = argv[2];
path = g_file_new_for_path (patharg);
const char *patharg = argv[2];
g_autoptr(GFile) path = g_file_new_for_path (patharg);
if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error))
goto out;
return FALSE;
if (!ostree_repo_static_delta_execute_offline (repo, path, FALSE, cancellable, error))
goto out;
return FALSE;
if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error))
goto out;
return FALSE;
ret = TRUE;
out:
return ret;
return TRUE;
}
gboolean
+1 -1
View File
@@ -210,7 +210,7 @@ ostree_builtin_summary (int argc, char **argv, OstreeCommandInvocation *invocati
return FALSE;
}
}
else if (opt_view)
else if (opt_view || opt_raw)
{
g_autoptr(GBytes) summary_data = NULL;
+171 -216
View File
@@ -103,6 +103,7 @@
#include <stdlib.h>
#include <sys/time.h>
#include <glib.h>
#include <stdint.h>
/* There's no need to extend the stack, so there's no need to involve
alloca. */
@@ -119,11 +120,11 @@ xmemdup (void const *p, size_t s)
static void
gettime (struct timespec *ts)
{
#if HAVE_NANOTIME
#ifdef HAVE_NANOTIME
nanotime (ts);
#else
# if defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME
# if defined(CLOCK_REALTIME) && defined(HAVE_CLOCK_GETTIME)
if (clock_gettime (CLOCK_REALTIME, ts) == 0)
return;
# endif
@@ -199,13 +200,6 @@ gettime (struct timespec *ts)
#define HOUR(x) ((x) * 60)
/* long_time_t is a signed integer type that contains all time_t values. */
#if TIME_T_FITS_IN_LONG_INT
typedef long int long_time_t;
#else
typedef time_t long_time_t;
#endif
/* Convert a possibly-signed character to an unsigned character. This is
a bit safer than casting to unsigned char, since it catches some type
errors that the cast doesn't. */
@@ -245,15 +239,11 @@ typedef struct
long int day;
long int hour;
long int minutes;
long_time_t seconds;
long int ns;
intmax_t seconds;
int ns;
} relative_time;
#if HAVE_COMPOUND_LITERALS
# define RELATIVE_TIME_0 ((relative_time) { 0, 0, 0, 0, 0, 0, 0 })
#else
static relative_time const RELATIVE_TIME_0;
#endif
#define RELATIVE_TIME_0 ((relative_time) { 0, 0, 0, 0, 0, 0, 0 })
/* Information passed to and from the parser. */
typedef struct
@@ -371,7 +361,7 @@ set_hhmmss (parser_control *pc, long int hour, long int minutes,
}
#line 375 "src/ostree/parse-datetime.c" /* yacc.c:339 */
#line 365 "src/ostree/parse-datetime.c" /* yacc.c:339 */
# ifndef YY_NULLPTR
# if defined __cplusplus && 201103L <= __cplusplus
@@ -452,14 +442,14 @@ extern int yydebug;
union YYSTYPE
{
#line 320 "src/ostree/parse-datetime.y" /* yacc.c:355 */
#line 310 "src/ostree/parse-datetime.y" /* yacc.c:355 */
long int intval;
textint textintval;
struct timespec timespec;
relative_time rel;
#line 463 "src/ostree/parse-datetime.c" /* yacc.c:355 */
#line 453 "src/ostree/parse-datetime.c" /* yacc.c:355 */
};
typedef union YYSTYPE YYSTYPE;
@@ -475,7 +465,7 @@ int yyparse (parser_control *pc);
/* Copy the second part of user declarations. */
#line 479 "src/ostree/parse-datetime.c" /* yacc.c:358 */
#line 469 "src/ostree/parse-datetime.c" /* yacc.c:358 */
#ifdef short
# undef short
@@ -774,16 +764,16 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
0, 347, 347, 348, 352, 359, 361, 365, 367, 369,
371, 373, 375, 377, 378, 379, 383, 387, 391, 396,
401, 406, 410, 415, 420, 427, 429, 433, 441, 446,
456, 458, 460, 463, 466, 468, 470, 475, 480, 485,
490, 498, 503, 523, 531, 539, 544, 550, 555, 561,
565, 575, 577, 579, 584, 586, 588, 590, 592, 594,
596, 598, 600, 602, 604, 606, 608, 610, 612, 614,
616, 618, 620, 622, 624, 628, 630, 632, 634, 636,
638, 643, 647, 647, 650, 651, 656, 657, 662, 667,
678, 679
0, 337, 337, 338, 342, 349, 351, 355, 357, 359,
361, 363, 365, 367, 368, 369, 373, 377, 381, 386,
391, 396, 400, 405, 410, 417, 419, 423, 431, 436,
446, 448, 450, 453, 456, 458, 460, 465, 470, 475,
480, 488, 493, 513, 521, 529, 534, 540, 545, 551,
555, 565, 567, 569, 574, 576, 578, 580, 582, 584,
586, 588, 590, 592, 594, 596, 598, 600, 602, 604,
606, 608, 610, 612, 614, 618, 620, 622, 624, 626,
628, 633, 637, 637, 640, 641, 646, 647, 652, 657,
668, 669
};
#endif
@@ -1642,222 +1632,222 @@ yyreduce:
switch (yyn)
{
case 4:
#line 353 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 343 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
pc->seconds = (yyvsp[0].timespec);
pc->timespec_seen = true;
}
#line 1651 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1641 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 7:
#line 366 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 356 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ pc->times_seen++; pc->dates_seen++; }
#line 1657 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1647 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 8:
#line 368 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 358 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ pc->times_seen++; }
#line 1663 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1653 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 9:
#line 370 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 360 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ pc->local_zones_seen++; }
#line 1669 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1659 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 10:
#line 372 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 362 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ pc->zones_seen++; }
#line 1675 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1665 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 11:
#line 374 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 364 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ pc->dates_seen++; }
#line 1681 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1671 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 12:
#line 376 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 366 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ pc->days_seen++; }
#line 1687 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1677 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 18:
#line 392 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 382 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
set_hhmmss (pc, (yyvsp[-1].textintval).value, 0, 0, 0);
pc->meridian = (yyvsp[0].intval);
}
#line 1696 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1686 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 19:
#line 397 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 387 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
set_hhmmss (pc, (yyvsp[-3].textintval).value, (yyvsp[-1].textintval).value, 0, 0);
pc->meridian = (yyvsp[0].intval);
}
#line 1705 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1695 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 20:
#line 402 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 392 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
set_hhmmss (pc, (yyvsp[-5].textintval).value, (yyvsp[-3].textintval).value, (yyvsp[-1].timespec).tv_sec, (yyvsp[-1].timespec).tv_nsec);
pc->meridian = (yyvsp[0].intval);
}
#line 1714 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1704 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 22:
#line 411 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 401 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
set_hhmmss (pc, (yyvsp[-1].textintval).value, 0, 0, 0);
pc->meridian = MER24;
}
#line 1723 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1713 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 23:
#line 416 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 406 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
set_hhmmss (pc, (yyvsp[-3].textintval).value, (yyvsp[-1].textintval).value, 0, 0);
pc->meridian = MER24;
}
#line 1732 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1722 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 24:
#line 421 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 411 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
set_hhmmss (pc, (yyvsp[-5].textintval).value, (yyvsp[-3].textintval).value, (yyvsp[-1].timespec).tv_sec, (yyvsp[-1].timespec).tv_nsec);
pc->meridian = MER24;
}
#line 1741 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1731 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 27:
#line 434 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 424 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
pc->zones_seen++;
pc->time_zone = time_zone_hhmm (pc, (yyvsp[-1].textintval), (yyvsp[0].intval));
}
#line 1750 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1740 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 28:
#line 442 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 432 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
pc->local_isdst = (yyvsp[0].intval);
pc->dsts_seen += (0 < (yyvsp[0].intval));
}
#line 1759 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1749 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 29:
#line 447 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 437 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
pc->local_isdst = 1;
pc->dsts_seen += (0 < (yyvsp[-1].intval)) + 1;
}
#line 1768 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1758 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 30:
#line 457 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 447 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ pc->time_zone = (yyvsp[0].intval); }
#line 1774 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1764 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 31:
#line 459 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 449 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ pc->time_zone = HOUR(7); }
#line 1780 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1770 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 32:
#line 461 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 451 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ pc->time_zone = (yyvsp[-1].intval);
apply_relative_time (pc, (yyvsp[0].rel), 1); }
#line 1787 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1777 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 33:
#line 464 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 454 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ pc->time_zone = HOUR(7);
apply_relative_time (pc, (yyvsp[0].rel), 1); }
#line 1794 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1784 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 34:
#line 467 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 457 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ pc->time_zone = (yyvsp[-2].intval) + time_zone_hhmm (pc, (yyvsp[-1].textintval), (yyvsp[0].intval)); }
#line 1800 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1790 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 35:
#line 469 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 459 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ pc->time_zone = (yyvsp[0].intval) + 60; }
#line 1806 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1796 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 36:
#line 471 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 461 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ pc->time_zone = (yyvsp[-1].intval) + 60; }
#line 1812 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1802 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 37:
#line 476 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 466 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
pc->day_ordinal = 0;
pc->day_number = (yyvsp[0].intval);
}
#line 1821 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1811 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 38:
#line 481 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 471 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
pc->day_ordinal = 0;
pc->day_number = (yyvsp[-1].intval);
}
#line 1830 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1820 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 39:
#line 486 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 476 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
pc->day_ordinal = (yyvsp[-1].intval);
pc->day_number = (yyvsp[0].intval);
}
#line 1839 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1829 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 40:
#line 491 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 481 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
pc->day_ordinal = (yyvsp[-1].textintval).value;
pc->day_number = (yyvsp[0].intval);
}
#line 1848 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1838 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 41:
#line 499 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 489 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
pc->month = (yyvsp[-2].textintval).value;
pc->day = (yyvsp[0].textintval).value;
}
#line 1857 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1847 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 42:
#line 504 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 494 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
/* Interpret as YYYY/MM/DD if the first value has 4 or more digits,
otherwise as MM/DD/YY.
@@ -1877,11 +1867,11 @@ yyreduce:
pc->year = (yyvsp[0].textintval);
}
}
#line 1881 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1871 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 43:
#line 524 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 514 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
/* e.g. 17-JUN-1992. */
pc->day = (yyvsp[-2].textintval).value;
@@ -1889,11 +1879,11 @@ yyreduce:
pc->year.value = -(yyvsp[0].textintval).value;
pc->year.digits = (yyvsp[0].textintval).digits;
}
#line 1893 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1883 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 44:
#line 532 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 522 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
/* e.g. JUN-17-1992. */
pc->month = (yyvsp[-2].intval);
@@ -1901,281 +1891,281 @@ yyreduce:
pc->year.value = -(yyvsp[0].textintval).value;
pc->year.digits = (yyvsp[0].textintval).digits;
}
#line 1905 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1895 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 45:
#line 540 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 530 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
pc->month = (yyvsp[-1].intval);
pc->day = (yyvsp[0].textintval).value;
}
#line 1914 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1904 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 46:
#line 545 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 535 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
pc->month = (yyvsp[-3].intval);
pc->day = (yyvsp[-2].textintval).value;
pc->year = (yyvsp[0].textintval);
}
#line 1924 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1914 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 47:
#line 551 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 541 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
pc->day = (yyvsp[-1].textintval).value;
pc->month = (yyvsp[0].intval);
}
#line 1933 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1923 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 48:
#line 556 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 546 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
pc->day = (yyvsp[-2].textintval).value;
pc->month = (yyvsp[-1].intval);
pc->year = (yyvsp[0].textintval);
}
#line 1943 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1933 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 50:
#line 566 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 556 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
/* ISO 8601 format. YYYY-MM-DD. */
pc->year = (yyvsp[-2].textintval);
pc->month = -(yyvsp[-1].textintval).value;
pc->day = -(yyvsp[0].textintval).value;
}
#line 1954 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1944 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 51:
#line 576 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 566 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ apply_relative_time (pc, (yyvsp[-1].rel), (yyvsp[0].intval)); }
#line 1960 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1950 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 52:
#line 578 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 568 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ apply_relative_time (pc, (yyvsp[0].rel), 1); }
#line 1966 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1956 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 53:
#line 580 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 570 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ apply_relative_time (pc, (yyvsp[0].rel), 1); }
#line 1972 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1962 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 54:
#line 585 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 575 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).year = (yyvsp[-1].intval); }
#line 1978 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1968 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 55:
#line 587 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 577 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).year = (yyvsp[-1].textintval).value; }
#line 1984 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1974 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 56:
#line 589 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 579 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).year = 1; }
#line 1990 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1980 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 57:
#line 591 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 581 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).month = (yyvsp[-1].intval); }
#line 1996 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1986 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 58:
#line 593 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 583 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).month = (yyvsp[-1].textintval).value; }
#line 2002 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1992 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 59:
#line 595 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 585 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).month = 1; }
#line 2008 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 1998 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 60:
#line 597 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 587 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[-1].intval) * (yyvsp[0].intval); }
#line 2014 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2004 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 61:
#line 599 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 589 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[-1].textintval).value * (yyvsp[0].intval); }
#line 2020 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2010 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 62:
#line 601 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 591 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[0].intval); }
#line 2026 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2016 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 63:
#line 603 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 593 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).hour = (yyvsp[-1].intval); }
#line 2032 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2022 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 64:
#line 605 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 595 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).hour = (yyvsp[-1].textintval).value; }
#line 2038 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2028 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 65:
#line 607 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 597 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).hour = 1; }
#line 2044 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2034 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 66:
#line 609 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 599 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).minutes = (yyvsp[-1].intval); }
#line 2050 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2040 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 67:
#line 611 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 601 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).minutes = (yyvsp[-1].textintval).value; }
#line 2056 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2046 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 68:
#line 613 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 603 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).minutes = 1; }
#line 2062 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2052 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 69:
#line 615 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 605 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[-1].intval); }
#line 2068 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2058 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 70:
#line 617 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 607 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[-1].textintval).value; }
#line 2074 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2064 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 71:
#line 619 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 609 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[-1].timespec).tv_sec; (yyval.rel).ns = (yyvsp[-1].timespec).tv_nsec; }
#line 2080 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2070 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 72:
#line 621 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 611 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[-1].timespec).tv_sec; (yyval.rel).ns = (yyvsp[-1].timespec).tv_nsec; }
#line 2086 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2076 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 73:
#line 623 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 613 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = 1; }
#line 2092 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2082 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 75:
#line 629 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 619 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).year = (yyvsp[-1].textintval).value; }
#line 2098 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2088 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 76:
#line 631 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 621 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).month = (yyvsp[-1].textintval).value; }
#line 2104 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2094 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 77:
#line 633 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 623 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[-1].textintval).value * (yyvsp[0].intval); }
#line 2110 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2100 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 78:
#line 635 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 625 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).hour = (yyvsp[-1].textintval).value; }
#line 2116 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2106 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 79:
#line 637 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 627 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).minutes = (yyvsp[-1].textintval).value; }
#line 2122 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2112 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 80:
#line 639 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 629 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[-1].textintval).value; }
#line 2128 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2118 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 81:
#line 644 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 634 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[0].intval); }
#line 2134 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2124 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 85:
#line 652 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 642 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.timespec).tv_sec = (yyvsp[0].textintval).value; (yyval.timespec).tv_nsec = 0; }
#line 2140 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2130 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 87:
#line 658 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 648 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.timespec).tv_sec = (yyvsp[0].textintval).value; (yyval.timespec).tv_nsec = 0; }
#line 2146 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2136 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 88:
#line 663 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 653 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ digits_to_date_time (pc, (yyvsp[0].textintval)); }
#line 2152 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2142 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 89:
#line 668 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 658 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{
/* Hybrid all-digit and relative offset, so that we accept e.g.,
"YYYYMMDD +N days" as well as "YYYYMMDD N days". */
digits_to_date_time (pc, (yyvsp[-1].textintval));
apply_relative_time (pc, (yyvsp[0].rel), 1);
}
#line 2163 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2153 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 90:
#line 678 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 668 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.intval) = -1; }
#line 2169 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2159 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
case 91:
#line 680 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
#line 670 "src/ostree/parse-datetime.y" /* yacc.c:1646 */
{ (yyval.intval) = (yyvsp[0].textintval).value; }
#line 2175 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2165 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
break;
#line 2179 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
#line 2169 "src/ostree/parse-datetime.c" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -2403,7 +2393,7 @@ yyreturn:
#endif
return yyresult;
}
#line 683 "src/ostree/parse-datetime.y" /* yacc.c:1906 */
#line 673 "src/ostree/parse-datetime.y" /* yacc.c:1906 */
static table const meridian_table[] =
@@ -2679,7 +2669,8 @@ lookup_zone (parser_control const *pc, char const *name)
return NULL;
}
#if ! HAVE_TM_GMTOFF
// #if ! HAVE_TM_GMTOFF
#if 1 // Always true for us
/* Yield the difference between *A and *B,
measured in seconds, ignoring leap seconds.
The body of this function is taken directly from the GNU C Library;
@@ -3304,10 +3295,10 @@ parse_datetime (struct timespec *result, char const *p,
time_t t1 = t0 + d1;
long int d2 = 60 * pc.rel.minutes;
time_t t2 = t1 + d2;
long_time_t d3 = pc.rel.seconds;
long_time_t t3 = t2 + d3;
intmax_t d3 = pc.rel.seconds;
intmax_t t3 = t2 + d3;
long int d4 = (sum_ns - normalized_ns) / BILLION;
long_time_t t4 = t3 + d4;
intmax_t t4 = t3 + d4;
time_t t5 = t4;
if ((d1 / (60 * 60) ^ pc.rel.hour)
@@ -3335,39 +3326,3 @@ parse_datetime (struct timespec *result, char const *p,
free (tz0);
return ok;
}
#if TEST
int
main (int ac, char **av)
{
char buff[BUFSIZ];
printf ("Enter date, or blank line to exit.\n\t> ");
fflush (stdout);
buff[BUFSIZ - 1] = '\0';
while (fgets (buff, BUFSIZ - 1, stdin) && buff[0])
{
struct timespec d;
struct tm const *tm;
if (! parse_datetime (&d, buff, NULL))
printf ("Bad format - couldn't convert.\n");
else if (! (tm = localtime (&d.tv_sec)))
{
long int sec = d.tv_sec;
printf ("localtime (%ld) failed\n", sec);
}
else
{
int ns = d.tv_nsec;
printf ("%04ld-%02d-%02d %02d:%02d:%02d.%09d\n",
tm->tm_year + 1900L, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec, ns);
}
printf ("\t> ");
fflush (stdout);
}
return 0;
}
#endif /* TEST */
+11 -56
View File
@@ -38,6 +38,7 @@
#include <stdlib.h>
#include <sys/time.h>
#include <glib.h>
#include <stdint.h>
/* There's no need to extend the stack, so there's no need to involve
alloca. */
@@ -54,11 +55,11 @@ xmemdup (void const *p, size_t s)
static void
gettime (struct timespec *ts)
{
#if HAVE_NANOTIME
#ifdef HAVE_NANOTIME
nanotime (ts);
#else
# if defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME
# if defined(CLOCK_REALTIME) && defined(HAVE_CLOCK_GETTIME)
if (clock_gettime (CLOCK_REALTIME, ts) == 0)
return;
# endif
@@ -134,13 +135,6 @@ gettime (struct timespec *ts)
#define HOUR(x) ((x) * 60)
/* long_time_t is a signed integer type that contains all time_t values. */
#if TIME_T_FITS_IN_LONG_INT
typedef long int long_time_t;
#else
typedef time_t long_time_t;
#endif
/* Convert a possibly-signed character to an unsigned character. This is
a bit safer than casting to unsigned char, since it catches some type
errors that the cast doesn't. */
@@ -180,15 +174,11 @@ typedef struct
long int day;
long int hour;
long int minutes;
long_time_t seconds;
long int ns;
intmax_t seconds;
int ns;
} relative_time;
#if HAVE_COMPOUND_LITERALS
# define RELATIVE_TIME_0 ((relative_time) { 0, 0, 0, 0, 0, 0, 0 })
#else
static relative_time const RELATIVE_TIME_0;
#endif
#define RELATIVE_TIME_0 ((relative_time) { 0, 0, 0, 0, 0, 0, 0 })
/* Information passed to and from the parser. */
typedef struct
@@ -955,7 +945,8 @@ lookup_zone (parser_control const *pc, char const *name)
return NULL;
}
#if ! HAVE_TM_GMTOFF
// #if ! HAVE_TM_GMTOFF
#if 1 // Always true for us
/* Yield the difference between *A and *B,
measured in seconds, ignoring leap seconds.
The body of this function is taken directly from the GNU C Library;
@@ -1580,10 +1571,10 @@ parse_datetime (struct timespec *result, char const *p,
time_t t1 = t0 + d1;
long int d2 = 60 * pc.rel.minutes;
time_t t2 = t1 + d2;
long_time_t d3 = pc.rel.seconds;
long_time_t t3 = t2 + d3;
intmax_t d3 = pc.rel.seconds;
intmax_t t3 = t2 + d3;
long int d4 = (sum_ns - normalized_ns) / BILLION;
long_time_t t4 = t3 + d4;
intmax_t t4 = t3 + d4;
time_t t5 = t4;
if ((d1 / (60 * 60) ^ pc.rel.hour)
@@ -1611,39 +1602,3 @@ parse_datetime (struct timespec *result, char const *p,
free (tz0);
return ok;
}
#if TEST
int
main (int ac, char **av)
{
char buff[BUFSIZ];
printf ("Enter date, or blank line to exit.\n\t> ");
fflush (stdout);
buff[BUFSIZ - 1] = '\0';
while (fgets (buff, BUFSIZ - 1, stdin) && buff[0])
{
struct timespec d;
struct tm const *tm;
if (! parse_datetime (&d, buff, NULL))
printf ("Bad format - couldn't convert.\n");
else if (! (tm = localtime (&d.tv_sec)))
{
long int sec = d.tv_sec;
printf ("localtime (%ld) failed\n", sec);
}
else
{
int ns = d.tv_nsec;
printf ("%04ld-%02d-%02d %02d:%02d:%02d.%09d\n",
tm->tm_year + 1900L, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec, ns);
}
printf ("\t> ");
fflush (stdout);
}
return 0;
}
#endif /* TEST */
+3 -10
View File
@@ -284,18 +284,11 @@ callback_truncate (const char *path, off_t size)
}
static int
callback_utime (const char *path, struct utimbuf *buf)
callback_utimens (const char *path, const struct timespec tv[2])
{
struct timespec ts[2];
path = ENSURE_RELPATH (path);
ts[0].tv_sec = buf->actime;
ts[0].tv_nsec = UTIME_OMIT;
ts[1].tv_sec = buf->modtime;
ts[1].tv_nsec = UTIME_OMIT;
if (utimensat (basefd, path, ts, AT_SYMLINK_NOFOLLOW) == -1)
if (utimensat (basefd, path, tv, AT_SYMLINK_NOFOLLOW) == -1)
return -errno;
return 0;
@@ -506,7 +499,7 @@ struct fuse_operations callback_oper = {
.chmod = callback_chmod,
.chown = callback_chown,
.truncate = callback_truncate,
.utime = callback_utime,
.utimens = callback_utimens,
.create = callback_create,
.open = callback_open,
.read_buf = callback_read_buf,