New upstream version 2017.14
This commit is contained in:
commit
84beec3c14
77 files changed
+1754
-1343
No files matched your search
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
Reference in new issue
Block a user