richardphibel / rpms / rpm

Forked from rpms/rpm 2 years ago
Clone
629b27
From aa31421bfe835dadd29da3aa46ee446038f80d02 Mon Sep 17 00:00:00 2001
629b27
From: Matthew Almond <malmond@fb.com>
629b27
Date: Sun, 31 Jan 2021 13:51:16 -0800
629b27
Subject: [PATCH 03/30] Match formatting/style of existing code
629b27
629b27
The existing code contains some variability in formatting. I'm not sure
629b27
if { is meant to be on the end of the line, or on a new line, but I've
629b27
standardized on the former.
629b27
629b27
The indentation is intended to match the existing convention: 4 column
629b27
indent, but 8 column wide tab characters. This is easy to follow/use in
629b27
vim, but is surprisingly difficult to get right in vscode. I am doing
629b27
this reformat here and now, and future changes will be after this.
629b27
629b27
I'm keen to fold the patches together, but for now, I'm trying to keep
629b27
the history of #1470 linear so everyone can follow along.
629b27
---
629b27
 lib/rpmplugins.c  |   6 +-
629b27
 plugins/reflink.c | 407 ++++++++++++++++++---------------
629b27
 rpm2extents.c     | 562 ++++++++++++++++++++--------------------------
629b27
 3 files changed, 462 insertions(+), 513 deletions(-)
629b27
629b27
diff --git a/lib/rpmplugins.c b/lib/rpmplugins.c
629b27
index c5084d398..3da3097af 100644
629b27
--- a/lib/rpmplugins.c
629b27
+++ b/lib/rpmplugins.c
629b27
@@ -368,9 +368,9 @@ rpmRC rpmpluginsCallFsmFilePre(rpmPlugins plugins, rpmfi fi, const char *path,
629b27
 		rc = RPMRC_FAIL;
629b27
 	    } else if (hook_rc == RPMRC_PLUGIN_CONTENTS && rc != RPMRC_FAIL) {
629b27
 		if (rc == RPMRC_PLUGIN_CONTENTS) {
629b27
-		    /*
629b27
-		    Another plugin already said it'd handle contents. It's undefined how
629b27
-		    these would combine, so treat this as a failure condition.
629b27
+		    /* Another plugin already said it'd handle contents. It's
629b27
+		     * undefined how these would combine, so treat this as a
629b27
+		     * failure condition.
629b27
 		    */
629b27
 		    rc = RPMRC_FAIL;
629b27
 		} else {
629b27
diff --git a/plugins/reflink.c b/plugins/reflink.c
629b27
index d7f19acd9..9eaa87094 100644
629b27
--- a/plugins/reflink.c
629b27
+++ b/plugins/reflink.c
629b27
@@ -32,31 +32,32 @@
629b27
 #include "lib/rpmhash.H"
629b27
 #include "lib/rpmhash.C"
629b27
 
629b27
-/*
629b27
-We use this in find to indicate a key wasn't found. This is an unrecoverable
629b27
-error, but we can at least show a decent error. 0 is never a valid offset
629b27
-because it's the offset of the start of the file.
629b27
-*/
629b27
+/* We use this in find to indicate a key wasn't found. This is an
629b27
+ * unrecoverable error, but we can at least show a decent error. 0 is never a
629b27
+ * valid offset because it's the offset of the start of the file.
629b27
+ */
629b27
 #define NOT_FOUND 0
629b27
 
629b27
 #define BUFFER_SIZE (1024 * 128)
629b27
 
629b27
-/* magic value at end of file (64 bits) that indicates this is a transcoded rpm */
629b27
+/* magic value at end of file (64 bits) that indicates this is a transcoded
629b27
+ * rpm.
629b27
+ */
629b27
 #define MAGIC 3472329499408095051
629b27
 
629b27
 struct reflink_state_s {
629b27
-  /* Stuff that's used across rpms */
629b27
-  long fundamental_block_size;
629b27
-  char *buffer;
629b27
+    /* Stuff that's used across rpms */
629b27
+    long fundamental_block_size;
629b27
+    char *buffer;
629b27
 
629b27
-  /* stuff that's used/updated per psm */
629b27
-  uint32_t keys, keysize;
629b27
+    /* stuff that's used/updated per psm */
629b27
+    uint32_t keys, keysize;
629b27
 
629b27
-  // table for current rpm, keys * (keysize + sizeof(rpm_loff_t))
629b27
-  unsigned char *table;
629b27
-  FD_t fd;
629b27
-  rpmfiles files;
629b27
-  inodeIndexHash inodeIndexes;
629b27
+    /* table for current rpm, keys * (keysize + sizeof(rpm_loff_t)) */
629b27
+    unsigned char *table;
629b27
+    FD_t fd;
629b27
+    rpmfiles files;
629b27
+    inodeIndexHash inodeIndexes;
629b27
 };
629b27
 
629b27
 typedef struct reflink_state_s * reflink_state;
629b27
@@ -73,60 +74,62 @@ static unsigned int inodeId(rpm_ino_t a)
629b27
 }
629b27
 
629b27
 static rpmRC reflink_init(rpmPlugin plugin, rpmts ts) {
629b27
-  reflink_state state = rcalloc(1, sizeof(struct reflink_state_s));
629b27
+    reflink_state state = rcalloc(1, sizeof(struct reflink_state_s));
629b27
 
629b27
-  /*
629b27
-  IOCTL-FICLONERANGE(2): ...Disk filesystems generally require the offset and
629b27
-  length arguments to be aligned to the fundamental block size.
629b27
+    /* IOCTL-FICLONERANGE(2): ...Disk filesystems generally require the offset
629b27
+     * and length arguments to be aligned to the fundamental block size.
629b27
+     *
629b27
+     * The value of "fundamental block size" is directly related to the
629b27
+     * system's page size, so we should use that.
629b27
+     */
629b27
+    state->fundamental_block_size = sysconf(_SC_PAGESIZE);
629b27
+    state->buffer = rcalloc(1, BUFFER_SIZE);
629b27
+    rpmPluginSetData(plugin, state);
629b27
 
629b27
-  The value of "fundamental block size" is directly related to the system's
629b27
-  page size, so we should use that.
629b27
-  */
629b27
-  state->fundamental_block_size = sysconf(_SC_PAGESIZE);
629b27
-  state->buffer = rcalloc(1, BUFFER_SIZE);
629b27
-  rpmPluginSetData(plugin, state);
629b27
-
629b27
-  return RPMRC_OK;
629b27
+    return RPMRC_OK;
629b27
 }
629b27
 
629b27
 static void reflink_cleanup(rpmPlugin plugin) {
629b27
-  reflink_state state = rpmPluginGetData(plugin);
629b27
-  free(state->buffer);
629b27
-  free(state);
629b27
+    reflink_state state = rpmPluginGetData(plugin);
629b27
+    free(state->buffer);
629b27
+    free(state);
629b27
 }
629b27
 
629b27
 static rpmRC reflink_psm_pre(rpmPlugin plugin, rpmte te) {
629b27
     reflink_state state = rpmPluginGetData(plugin);
629b27
     state->fd = rpmteFd(te);
629b27
     if (state->fd == 0) {
629b27
-      rpmlog(RPMLOG_DEBUG, _("reflink: fd = 0, no install\n"));
629b27
-      return RPMRC_OK;
629b27
+	rpmlog(RPMLOG_DEBUG, _("reflink: fd = 0, no install\n"));
629b27
+	return RPMRC_OK;
629b27
     }
629b27
     rpm_loff_t current = Ftell(state->fd);
629b27
     uint64_t magic;
629b27
     if (Fseek(state->fd, -(sizeof(magic)), SEEK_END) < 0) {
629b27
-      rpmlog(RPMLOG_ERR, _("reflink: failed to seek for magic\n"));
629b27
-      if (Fseek(state->fd, current, SEEK_SET) < 0) {
629b27
-        /* yes this gets a bit repetitive */
629b27
-        rpmlog(RPMLOG_ERR, _("reflink: unable to seek back to original location\n"));
629b27
-      }
629b27
-      return RPMRC_FAIL;
629b27
+	rpmlog(RPMLOG_ERR, _("reflink: failed to seek for magic\n"));
629b27
+	if (Fseek(state->fd, current, SEEK_SET) < 0) {
629b27
+	    /* yes this gets a bit repetitive */
629b27
+	    rpmlog(RPMLOG_ERR,
629b27
+		 _("reflink: unable to seek back to original location\n"));
629b27
+	}
629b27
+	return RPMRC_FAIL;
629b27
     }
629b27
     size_t len = sizeof(magic);
629b27
     if (Fread(&magic, len, 1, state->fd) != len) {
629b27
-      rpmlog(RPMLOG_ERR, _("reflink: unable to read magic\n"));
629b27
-      if (Fseek(state->fd, current, SEEK_SET) < 0) {
629b27
-        rpmlog(RPMLOG_ERR, _("reflink: unable to seek back to original location\n"));
629b27
-      }
629b27
-      return RPMRC_FAIL;
629b27
+	rpmlog(RPMLOG_ERR, _("reflink: unable to read magic\n"));
629b27
+	if (Fseek(state->fd, current, SEEK_SET) < 0) {
629b27
+	    rpmlog(RPMLOG_ERR,
629b27
+		   _("reflink: unable to seek back to original location\n"));
629b27
+	}
629b27
+	return RPMRC_FAIL;
629b27
     }
629b27
     if (magic != MAGIC) {
629b27
-      rpmlog(RPMLOG_DEBUG, _("reflink: not transcoded\n"));
629b27
-      if (Fseek(state->fd, current, SEEK_SET) < 0) {
629b27
-        rpmlog(RPMLOG_ERR, _("reflink: unable to seek back to original location\n"));
629b27
-        return RPMRC_FAIL;
629b27
-      }
629b27
-      return RPMRC_OK;
629b27
+	rpmlog(RPMLOG_DEBUG, _("reflink: not transcoded\n"));
629b27
+	if (Fseek(state->fd, current, SEEK_SET) < 0) {
629b27
+	    rpmlog(RPMLOG_ERR,
629b27
+		   _("reflink: unable to seek back to original location\n"));
629b27
+	    return RPMRC_FAIL;
629b27
+	}
629b27
+	return RPMRC_OK;
629b27
     }
629b27
     rpmlog(RPMLOG_DEBUG, _("reflink: *is* transcoded\n"));
629b27
     Header h = rpmteHeader(te);
629b27
@@ -136,53 +139,60 @@ static rpmRC reflink_psm_pre(rpmPlugin plugin, rpmte te) {
629b27
     headerPutString(h, RPMTAG_PAYLOADFORMAT, "clon");
629b27
     headerFree(h);
629b27
     state->files = rpmteFiles(te);
629b27
-    /* tail of file contains offset_table, offset_checksums
629b27
-       then magic
629b27
-    */
629b27
+    /* tail of file contains offset_table, offset_checksums then magic */
629b27
     if (Fseek(state->fd, -(sizeof(rpm_loff_t) * 2 + sizeof(magic)), SEEK_END) < 0) {
629b27
-      rpmlog(RPMLOG_ERR, _("reflink: failed to seek for tail %p\n"), state->fd);
629b27
-      return RPMRC_FAIL;
629b27
+	rpmlog(RPMLOG_ERR, _("reflink: failed to seek for tail %p\n"),
629b27
+	       state->fd);
629b27
+	return RPMRC_FAIL;
629b27
     }
629b27
     rpm_loff_t table_start;
629b27
     len = sizeof(table_start);
629b27
     if (Fread(&table_start, len, 1, state->fd) != len) {
629b27
-      rpmlog(RPMLOG_ERR, _("reflink: unable to read table_start\n"));
629b27
-      return RPMRC_FAIL;
629b27
+	rpmlog(RPMLOG_ERR, _("reflink: unable to read table_start\n"));
629b27
+	return RPMRC_FAIL;
629b27
     }
629b27
     if (Fseek(state->fd, table_start, SEEK_SET) < 0) {
629b27
-      rpmlog(RPMLOG_ERR, _("reflink: unable to seek to table_start\n"));
629b27
-      return RPMRC_FAIL;
629b27
+	rpmlog(RPMLOG_ERR, _("reflink: unable to seek to table_start\n"));
629b27
+	return RPMRC_FAIL;
629b27
     }
629b27
     len = sizeof(state->keys);
629b27
     if (Fread(&state->keys, len, 1, state->fd) != len) {
629b27
-      rpmlog(RPMLOG_ERR, _("reflink: unable to read number of keys\n"));
629b27
-      return RPMRC_FAIL;
629b27
+	rpmlog(RPMLOG_ERR, _("reflink: unable to read number of keys\n"));
629b27
+	return RPMRC_FAIL;
629b27
     }
629b27
     len = sizeof(state->keysize);
629b27
     if (Fread(&state->keysize, len, 1, state->fd) != len) {
629b27
-      rpmlog(RPMLOG_ERR, _("reflink: unable to read keysize\n"));
629b27
-      return RPMRC_FAIL;
629b27
+	rpmlog(RPMLOG_ERR, _("reflink: unable to read keysize\n"));
629b27
+	return RPMRC_FAIL;
629b27
     }
629b27
-    rpmlog(RPMLOG_DEBUG, _("reflink: table_start=0x%lx, keys=%d, keysize=%d\n"), table_start, state->keys, state->keysize);
629b27
-    // now get digest table if there is a reason to have one.
629b27
+    rpmlog(
629b27
+	RPMLOG_DEBUG,
629b27
+	_("reflink: table_start=0x%lx, keys=%d, keysize=%d\n"),
629b27
+	table_start, state->keys, state->keysize
629b27
+    );
629b27
+    /* now get digest table if there is a reason to have one. */
629b27
     if (state->keys == 0 || state->keysize == 0) {
629b27
-      // no files (or no digests(!))
629b27
-      state->table = NULL;
629b27
+	/* no files (or no digests(!)) */
629b27
+	state->table = NULL;
629b27
     } else {
629b27
-      int table_size = state->keys * (state->keysize + sizeof(rpm_loff_t));
629b27
-      state->table = rcalloc(1, table_size);
629b27
-      if (Fread(state->table, table_size, 1, state->fd) != table_size) {
629b27
-        rpmlog(RPMLOG_ERR, _("reflink: unable to read table\n"));
629b27
-        return RPMRC_FAIL;
629b27
-      }
629b27
-      state->inodeIndexes = inodeIndexHashCreate(state->keys, inodeId, inodeCmp, NULL, NULL);
629b27
+	int table_size = state->keys * (state->keysize + sizeof(rpm_loff_t));
629b27
+	state->table = rcalloc(1, table_size);
629b27
+	if (Fread(state->table, table_size, 1, state->fd) != table_size) {
629b27
+	    rpmlog(RPMLOG_ERR, _("reflink: unable to read table\n"));
629b27
+	    return RPMRC_FAIL;
629b27
+	}
629b27
+	state->inodeIndexes = inodeIndexHashCreate(
629b27
+	    state->keys, inodeId, inodeCmp, NULL, NULL
629b27
+	);
629b27
     }
629b27
 
629b27
-    // seek back to original location
629b27
-    // might not be needed if we seek to offset immediately
629b27
+    /* Seek back to original location.
629b27
+     * Might not be needed if we seek to offset immediately
629b27
+     */
629b27
     if (Fseek(state->fd, current, SEEK_SET) < 0) {
629b27
-      rpmlog(RPMLOG_ERR, _("reflink: unable to seek back to original location\n"));
629b27
-      return RPMRC_FAIL;
629b27
+	rpmlog(RPMLOG_ERR,
629b27
+	       _("reflink: unable to seek back to original location\n"));
629b27
+	return RPMRC_FAIL;
629b27
     }
629b27
     return RPMRC_OK;
629b27
 }
629b27
@@ -192,40 +202,45 @@ static rpmRC reflink_psm_post(rpmPlugin plugin, rpmte te, int res)
629b27
     reflink_state state = rpmPluginGetData(plugin);
629b27
     state->files = rpmfilesFree(state->files);
629b27
     if (state->table) {
629b27
-      free(state->table);
629b27
-      state->table = NULL;
629b27
+	free(state->table);
629b27
+	state->table = NULL;
629b27
     }
629b27
     if (state->inodeIndexes) {
629b27
-      inodeIndexHashFree(state->inodeIndexes);
629b27
-      state->inodeIndexes = NULL;
629b27
+	inodeIndexHashFree(state->inodeIndexes);
629b27
+	state->inodeIndexes = NULL;
629b27
     }
629b27
     return RPMRC_OK;
629b27
 }
629b27
 
629b27
 
629b27
-// have a prototype, warnings system
629b27
+/* have a prototype, warnings system */
629b27
 rpm_loff_t find(const unsigned char *digest, reflink_state state);
629b27
 
629b27
 rpm_loff_t find(const unsigned char *digest, reflink_state state) {
629b27
 # if defined(__GNUC__)
629b27
-  /* GCC nested function because bsearch's comparison function can't access
629b27
-     state-keysize otherwise
629b27
-  */
629b27
-  int cmpdigest(const void *k1, const void *k2) {
629b27
-    rpmlog(RPMLOG_DEBUG, _("reflink: cmpdigest k1=%p k2=%p\n"), k1, k2);
629b27
-    return memcmp(k1, k2, state->keysize);
629b27
-  }
629b27
+    /* GCC nested function because bsearch's comparison function can't access
629b27
+     * state-keysize otherwise
629b27
+     */
629b27
+    int cmpdigest(const void *k1, const void *k2) {
629b27
+	rpmlog(RPMLOG_DEBUG, _("reflink: cmpdigest k1=%p k2=%p\n"), k1, k2);
629b27
+	return memcmp(k1, k2, state->keysize);
629b27
+    }
629b27
 # endif
629b27
-  rpmlog(RPMLOG_DEBUG, _("reflink: bsearch(key=%p, base=%p, nmemb=%d, size=%lu)\n"), digest, state->table, state->keys, state->keysize + sizeof(rpm_loff_t));
629b27
-  char *entry = bsearch(digest, state->table, state->keys, state->keysize + sizeof(rpm_loff_t), cmpdigest);
629b27
-  if (entry == NULL) {
629b27
-    return NOT_FOUND;
629b27
-  }
629b27
-  rpm_loff_t offset = *(rpm_loff_t *)(entry + state->keysize);
629b27
-  return offset;
629b27
+    rpmlog(RPMLOG_DEBUG,
629b27
+	   _("reflink: bsearch(key=%p, base=%p, nmemb=%d, size=%lu)\n"),
629b27
+	   digest, state->table, state->keys,
629b27
+	   state->keysize + sizeof(rpm_loff_t));
629b27
+    char *entry = bsearch(digest, state->table, state->keys,
629b27
+			  state->keysize + sizeof(rpm_loff_t), cmpdigest);
629b27
+    if (entry == NULL) {
629b27
+	return NOT_FOUND;
629b27
+    }
629b27
+    rpm_loff_t offset = *(rpm_loff_t *)(entry + state->keysize);
629b27
+    return offset;
629b27
 }
629b27
 
629b27
-static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path, mode_t file_mode, rpmFsmOp op)
629b27
+static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path,
629b27
+                                  mode_t file_mode, rpmFsmOp op)
629b27
 {
629b27
     struct file_clone_range fcr;
629b27
     rpm_loff_t size;
629b27
@@ -234,99 +249,119 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path,
629b27
 
629b27
     reflink_state state = rpmPluginGetData(plugin);
629b27
     if (state->table == NULL) {
629b27
-        // no table means rpm is not in reflink format, so leave. Now.
629b27
-        return RPMRC_OK;
629b27
+	/* no table means rpm is not in reflink format, so leave. Now. */
629b27
+	return RPMRC_OK;
629b27
     }
629b27
     if (op == FA_TOUCH) {
629b27
-        // we're not overwriting an existing file
629b27
-        return RPMRC_OK;
629b27
+	/* we're not overwriting an existing file. */
629b27
+	return RPMRC_OK;
629b27
     }
629b27
     fcr.dest_offset = 0;
629b27
     if (S_ISREG(file_mode) && !(rpmfiFFlags(fi) & RPMFILE_GHOST)) {
629b27
-      rpm_ino_t inode = rpmfiFInode(fi);
629b27
-      /* check for hard link entry in table. GetEntry overwrites hlix with the address of the first match */
629b27
-      if (inodeIndexHashGetEntry(state->inodeIndexes, inode, &hlix, NULL, NULL)) {
629b27
-        // entry is in table, use hard link
629b27
-        char *fn = rpmfilesFN(state->files, hlix[0]);
629b27
-        if (link(fn, path) != 0) {
629b27
-          rpmlog(RPMLOG_ERR, _("reflink: Unable to hard link %s -> %s due to %s\n"), fn, path, strerror(errno));
629b27
-          free(fn);
629b27
-          return RPMRC_FAIL;
629b27
-        }
629b27
-        free(fn);
629b27
-        return RPMRC_PLUGIN_CONTENTS;
629b27
-      }
629b27
-      /* if we didn't hard link, then we'll track this inode as being created soon */
629b27
-      if (rpmfiFNlink(fi) > 1) {
629b27
-        /* minor optimization: only store files with more than one link */
629b27
-        inodeIndexHashAddEntry(state->inodeIndexes, inode, rpmfiFX(fi));
629b27
-      }
629b27
-      /* derived from wfd_open in fsm.c */
629b27
-      mode_t old_umask = umask(0577);
629b27
-      dst = open(path, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR);
629b27
-      umask(old_umask);
629b27
-      if (dst == -1) {
629b27
-          rpmlog(RPMLOG_ERR, _("reflink: Unable to open %s for writing due to %s, flags = %x\n"), path, strerror(errno), rpmfiFFlags(fi));
629b27
-          return RPMRC_FAIL;
629b27
-      }
629b27
-      size = rpmfiFSize(fi);
629b27
-      if (size > 0) {
629b27
-          /* round src_length down to fundamental_block_size multiple */
629b27
-          fcr.src_length = size / state->fundamental_block_size * state->fundamental_block_size;
629b27
-          if ((size % state->fundamental_block_size) > 0) {
629b27
-              /* round up to next fundamental_block_size. We expect the data in the rpm to be similarly padded */
629b27
-              fcr.src_length += state->fundamental_block_size;
629b27
-          }
629b27
-          fcr.src_fd = Fileno(state->fd);
629b27
-          if (fcr.src_fd == -1) {
629b27
-            close(dst);
629b27
-            rpmlog(RPMLOG_ERR, _("reflink: src fd lookup failed\n"));
629b27
-            return RPMRC_FAIL;
629b27
-          }
629b27
-          fcr.src_offset = find(rpmfiFDigest(fi, NULL, NULL), state);
629b27
-          if (fcr.src_offset == NOT_FOUND) {
629b27
-            close(dst);
629b27
-            rpmlog(RPMLOG_ERR, _("reflink: digest not found\n"));
629b27
-            return RPMRC_FAIL;
629b27
-          }
629b27
-          rpmlog(RPMLOG_DEBUG, _("reflink: Reflinking %lu bytes at %lu to %s orig size=%lu, file=%ld\n"), fcr.src_length, fcr.src_offset, path, size, fcr.src_fd);
629b27
-          rc = ioctl(dst, FICLONERANGE, &fcr;;
629b27
-          if (rc) {
629b27
-            rpmlog(RPMLOG_WARNING, _("reflink: falling back to copying bits for %s due to %d, %d = %s\n"), path, rc, errno, strerror(errno));
629b27
-            if (Fseek(state->fd, fcr.src_offset, SEEK_SET) < 0) {
629b27
-                close(dst);
629b27
-                rpmlog(RPMLOG_ERR, _("reflink: unable to seek on copying bits\n"));
629b27
-                return RPMRC_FAIL;
629b27
-            }
629b27
-            rpm_loff_t left = size;
629b27
-            size_t len, read, written;
629b27
-            while (left) {
629b27
-              len = (left > BUFFER_SIZE ? BUFFER_SIZE : left);
629b27
-              read = Fread(state->buffer, len, 1, state->fd);
629b27
-              if (read != len) {
629b27
-                close(dst);
629b27
-                rpmlog(RPMLOG_ERR, _("reflink: short read on copying bits\n"));
629b27
-                return RPMRC_FAIL;
629b27
-              }
629b27
-              written = write(dst, state->buffer, len);
629b27
-              if (read != written) {
629b27
-                close(dst);
629b27
-                rpmlog(RPMLOG_ERR, _("reflink: short write on copying bits\n"));
629b27
-                return RPMRC_FAIL;
629b27
-              }
629b27
-              left -= len;
629b27
-            }
629b27
-          } else {
629b27
-            /* reflink worked, so truncate */
629b27
-            rc = ftruncate(dst, size);
629b27
-            if (rc) {
629b27
-                rpmlog(RPMLOG_ERR, _("reflink: Unable to truncate %s to %ld due to %s\n"), path, size, strerror(errno));
629b27
-                return RPMRC_FAIL;
629b27
-            }
629b27
-          }
629b27
-      }
629b27
-      close(dst);
629b27
-      return RPMRC_PLUGIN_CONTENTS;
629b27
+	rpm_ino_t inode = rpmfiFInode(fi);
629b27
+	/* check for hard link entry in table. GetEntry overwrites hlix with
629b27
+	 * the address of the first match.
629b27
+	 */
629b27
+	if (inodeIndexHashGetEntry(state->inodeIndexes, inode, &hlix, NULL,
629b27
+	                           NULL)) {
629b27
+	    /* entry is in table, use hard link */
629b27
+	    char *fn = rpmfilesFN(state->files, hlix[0]);
629b27
+	    if (link(fn, path) != 0) {
629b27
+		rpmlog(RPMLOG_ERR,
629b27
+		       _("reflink: Unable to hard link %s -> %s due to %s\n"),
629b27
+		       fn, path, strerror(errno));
629b27
+		free(fn);
629b27
+		return RPMRC_FAIL;
629b27
+	    }
629b27
+	    free(fn);
629b27
+	    return RPMRC_PLUGIN_CONTENTS;
629b27
+	}
629b27
+	/* if we didn't hard link, then we'll track this inode as being
629b27
+	 * created soon
629b27
+	 */
629b27
+	if (rpmfiFNlink(fi) > 1) {
629b27
+	    /* minor optimization: only store files with more than one link */
629b27
+	    inodeIndexHashAddEntry(state->inodeIndexes, inode, rpmfiFX(fi));
629b27
+	}
629b27
+	/* derived from wfd_open in fsm.c */
629b27
+	mode_t old_umask = umask(0577);
629b27
+	dst = open(path, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR);
629b27
+	umask(old_umask);
629b27
+	if (dst == -1) {
629b27
+	    rpmlog(RPMLOG_ERR,
629b27
+		   _("reflink: Unable to open %s for writing due to %s, flags = %x\n"),
629b27
+		   path, strerror(errno), rpmfiFFlags(fi));
629b27
+	    return RPMRC_FAIL;
629b27
+	}
629b27
+	size = rpmfiFSize(fi);
629b27
+	if (size > 0) {
629b27
+	    /* round src_length down to fundamental_block_size multiple */
629b27
+	    fcr.src_length = size / state->fundamental_block_size * state->fundamental_block_size;
629b27
+	    if ((size % state->fundamental_block_size) > 0) {
629b27
+		/* round up to next fundamental_block_size. We expect the data
629b27
+		 * in the rpm to be similarly padded.
629b27
+		 */
629b27
+		fcr.src_length += state->fundamental_block_size;
629b27
+	    }
629b27
+	    fcr.src_fd = Fileno(state->fd);
629b27
+	    if (fcr.src_fd == -1) {
629b27
+		close(dst);
629b27
+		rpmlog(RPMLOG_ERR, _("reflink: src fd lookup failed\n"));
629b27
+		return RPMRC_FAIL;
629b27
+	    }
629b27
+	    fcr.src_offset = find(rpmfiFDigest(fi, NULL, NULL), state);
629b27
+	    if (fcr.src_offset == NOT_FOUND) {
629b27
+		close(dst);
629b27
+		rpmlog(RPMLOG_ERR, _("reflink: digest not found\n"));
629b27
+		return RPMRC_FAIL;
629b27
+	    }
629b27
+	    rpmlog(RPMLOG_DEBUG,
629b27
+	           _("reflink: Reflinking %lu bytes at %lu to %s orig size=%lu, file=%ld\n"),
629b27
+		   fcr.src_length, fcr.src_offset, path, size, fcr.src_fd);
629b27
+	    rc = ioctl(dst, FICLONERANGE, &fcr;;
629b27
+	    if (rc) {
629b27
+		rpmlog(RPMLOG_WARNING,
629b27
+		       _("reflink: falling back to copying bits for %s due to %d, %d = %s\n"),
629b27
+		       path, rc, errno, strerror(errno));
629b27
+		if (Fseek(state->fd, fcr.src_offset, SEEK_SET) < 0) {
629b27
+		    close(dst);
629b27
+		    rpmlog(RPMLOG_ERR,
629b27
+			   _("reflink: unable to seek on copying bits\n"));
629b27
+		    return RPMRC_FAIL;
629b27
+		}
629b27
+		rpm_loff_t left = size;
629b27
+		size_t len, read, written;
629b27
+		while (left) {
629b27
+		    len = (left > BUFFER_SIZE ? BUFFER_SIZE : left);
629b27
+		    read = Fread(state->buffer, len, 1, state->fd);
629b27
+		    if (read != len) {
629b27
+			close(dst);
629b27
+			rpmlog(RPMLOG_ERR,
629b27
+			       _("reflink: short read on copying bits\n"));
629b27
+			return RPMRC_FAIL;
629b27
+		    }
629b27
+		    written = write(dst, state->buffer, len);
629b27
+		    if (read != written) {
629b27
+			close(dst);
629b27
+			rpmlog(RPMLOG_ERR,
629b27
+			       _("reflink: short write on copying bits\n"));
629b27
+			return RPMRC_FAIL;
629b27
+		    }
629b27
+		    left -= len;
629b27
+		}
629b27
+	    } else {
629b27
+		/* reflink worked, so truncate */
629b27
+		rc = ftruncate(dst, size);
629b27
+		if (rc) {
629b27
+		    rpmlog(RPMLOG_ERR,
629b27
+			   _("reflink: Unable to truncate %s to %ld due to %s\n"),
629b27
+			   path, size, strerror(errno));
629b27
+		     return RPMRC_FAIL;
629b27
+		}
629b27
+	    }
629b27
+	}
629b27
+	close(dst);
629b27
+	return RPMRC_PLUGIN_CONTENTS;
629b27
     }
629b27
     return RPMRC_OK;
629b27
 }
629b27
diff --git a/rpm2extents.c b/rpm2extents.c
629b27
index 5662b86a6..c111be0a2 100644
629b27
--- a/rpm2extents.c
629b27
+++ b/rpm2extents.c
629b27
@@ -24,7 +24,7 @@
629b27
 #include "debug.h"
629b27
 
629b27
 /* hash of void * (pointers) to file digests to offsets within output.
629b27
-   The length of the key depends on what the FILEDIGESTALGO is.
629b27
+ * The length of the key depends on what the FILEDIGESTALGO is.
629b27
  */
629b27
 #undef HASHTYPE
629b27
 #undef HTKEYTYPE
629b27
@@ -34,7 +34,9 @@
629b27
 #include "lib/rpmhash.H"
629b27
 #include "lib/rpmhash.C"
629b27
 
629b27
-/* magic value at end of file (64 bits) that indicates this is a transcoded rpm */
629b27
+/* magic value at end of file (64 bits) that indicates this is a transcoded
629b27
+ * rpm.
629b27
+ */
629b27
 #define MAGIC 3472329499408095051
629b27
 
629b27
 struct digestoffset {
629b27
@@ -64,77 +66,54 @@ static int digestor(
629b27
     int algo;
629b27
     rpmRC rc = RPMRC_FAIL;
629b27
 
629b27
-    for (algo = 0; algo < algos_len; algo++)
629b27
-    {
629b27
-        fdInitDigest(fdi, algos[algo], 0);
629b27
+    for (algo = 0; algo < algos_len; algo++) {
629b27
+	fdInitDigest(fdi, algos[algo], 0);
629b27
     }
629b27
     fdilength = ufdCopy(fdi, fdo);
629b27
-    if (fdilength == -1)
629b27
-    {
629b27
-        fprintf(stderr, _("digest cat failed\n"));
629b27
-        goto exit;
629b27
+    if (fdilength == -1) {
629b27
+	fprintf(stderr, _("digest cat failed\n"));
629b27
+	goto exit;
629b27
     }
629b27
 
629b27
     len = sizeof(fdilength);
629b27
-    if (Fwrite(&fdilength, len, 1, validationo) != len)
629b27
-    {
629b27
-        fprintf(stderr, _("Unable to write input length %zd\n"), fdilength);
629b27
-        goto exit;
629b27
+    if (Fwrite(&fdilength, len, 1, validationo) != len) {
629b27
+	fprintf(stderr, _("Unable to write input length %zd\n"), fdilength);
629b27
+	goto exit;
629b27
     }
629b27
     len = sizeof(algos_len);
629b27
-    if (Fwrite(&algos_len, len, 1, validationo) != len)
629b27
-    {
629b27
-        fprintf(stderr, _("Unable to write number of validation digests\n"));
629b27
-        goto exit;
629b27
+    if (Fwrite(&algos_len, len, 1, validationo) != len) {
629b27
+	fprintf(stderr, _("Unable to write number of validation digests\n"));
629b27
+	goto exit;
629b27
     }
629b27
-    for (algo = 0; algo < algos_len; algo++)
629b27
-    {
629b27
-        fdFiniDigest(fdi, algos[algo], (void **)&filedigest, &filedigest_len, 0);
629b27
-
629b27
-        algo_name = pgpValString(PGPVAL_HASHALGO, algos[algo]);
629b27
-        algo_name_len = (uint32_t)strlen(algo_name);
629b27
-        algo_digest_len = (uint32_t)filedigest_len;
629b27
-
629b27
-        len = sizeof(algo_name_len);
629b27
-        if (Fwrite(&algo_name_len, len, 1, validationo) != len)
629b27
-        {
629b27
-            fprintf(
629b27
-                stderr,
629b27
-                _("Unable to write validation algo name length\n")
629b27
-            );
629b27
-            goto exit;
629b27
-        }
629b27
-        len = sizeof(algo_digest_len);
629b27
-        if (Fwrite(&algo_digest_len, len, 1, validationo) != len)
629b27
-        {
629b27
-            fprintf(
629b27
-                stderr,
629b27
-                _("Unable to write number of bytes for validation digest\n")
629b27
-            );
629b27
-            goto exit;
629b27
-        }
629b27
-        if (Fwrite(algo_name, algo_name_len, 1, validationo) != algo_name_len)
629b27
-        {
629b27
-            fprintf(stderr, _("Unable to write validation algo name\n"));
629b27
-            goto exit;
629b27
-        }
629b27
-        if (
629b27
-            Fwrite(
629b27
-                filedigest,
629b27
-                algo_digest_len,
629b27
-                1,
629b27
-                validationo
629b27
-            ) != algo_digest_len
629b27
-        )
629b27
-        {
629b27
-            fprintf(
629b27
-                stderr,
629b27
-                _("Unable to write validation digest value %u, %zu\n"),
629b27
-                algo_digest_len,
629b27
-                filedigest_len
629b27
-            );
629b27
-            goto exit;
629b27
-        }
629b27
+    for (algo = 0; algo < algos_len; algo++) {
629b27
+	fdFiniDigest(fdi, algos[algo], (void **)&filedigest, &filedigest_len, 0);
629b27
+
629b27
+	algo_name = pgpValString(PGPVAL_HASHALGO, algos[algo]);
629b27
+	algo_name_len = (uint32_t)strlen(algo_name);
629b27
+	algo_digest_len = (uint32_t)filedigest_len;
629b27
+
629b27
+	len = sizeof(algo_name_len);
629b27
+	if (Fwrite(&algo_name_len, len, 1, validationo) != len) {
629b27
+	    fprintf(stderr,
629b27
+		    _("Unable to write validation algo name length\n"));
629b27
+	    goto exit;
629b27
+	}
629b27
+	len = sizeof(algo_digest_len);
629b27
+	if (Fwrite(&algo_digest_len, len, 1, validationo) != len) {
629b27
+	    fprintf(stderr,
629b27
+		    _("Unable to write number of bytes for validation digest\n"));
629b27
+	     goto exit;
629b27
+	}
629b27
+	if (Fwrite(algo_name, algo_name_len, 1, validationo) != algo_name_len) {
629b27
+	    fprintf(stderr, _("Unable to write validation algo name\n"));
629b27
+	    goto exit;
629b27
+	}
629b27
+	if (Fwrite(filedigest, algo_digest_len, 1, validationo ) != algo_digest_len) {
629b27
+	    fprintf(stderr,
629b27
+		    _("Unable to write validation digest value %u, %zu\n"),
629b27
+		    algo_digest_len, filedigest_len);
629b27
+	    goto exit;
629b27
+	}
629b27
     }
629b27
     rc = RPMRC_OK;
629b27
 exit:
629b27
@@ -145,23 +124,20 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
629b27
 {
629b27
     uint32_t diglen;
629b27
     /* GNU C extension: can use diglen from outer context */
629b27
-    int digestSetCmp(const unsigned char * a, const unsigned char * b)
629b27
-    {
629b27
-        return memcmp(a, b, diglen);
629b27
+    int digestSetCmp(const unsigned char * a, const unsigned char * b) {
629b27
+	return memcmp(a, b, diglen);
629b27
     }
629b27
 
629b27
-    unsigned int digestSetHash(const unsigned char * digest)
629b27
-    {
629b27
+    unsigned int digestSetHash(const unsigned char * digest) {
629b27
         /* assumes sizeof(unsigned int) < diglen */
629b27
         return *(unsigned int *)digest;
629b27
     }
629b27
 
629b27
-    int digestoffsetCmp(const void * a, const void * b)
629b27
-    {
629b27
-        return digestSetCmp(
629b27
-            ((struct digestoffset *)a)->digest,
629b27
-            ((struct digestoffset *)b)->digest
629b27
-        );
629b27
+    int digestoffsetCmp(const void * a, const void * b) {
629b27
+	return digestSetCmp(
629b27
+	    ((struct digestoffset *)a)->digest,
629b27
+	    ((struct digestoffset *)b)->digest
629b27
+	);
629b27
     }
629b27
 
629b27
     FD_t fdo;
629b27
@@ -179,65 +155,52 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
629b27
 
629b27
     fdo = fdDup(STDOUT_FILENO);
629b27
 
629b27
-    if (rpmReadPackageRaw(fdi, &sigh, &h))
629b27
-    {
629b27
-        fprintf(stderr, _("Error reading package\n"));
629b27
-        exit(EXIT_FAILURE);
629b27
+    if (rpmReadPackageRaw(fdi, &sigh, &h)) {
629b27
+	fprintf(stderr, _("Error reading package\n"));
629b27
+	exit(EXIT_FAILURE);
629b27
     }
629b27
 
629b27
     if (rpmLeadWrite(fdo, h))
629b27
     {
629b27
-        fprintf(
629b27
-            stderr,
629b27
-            _("Unable to write package lead: %s\n"),
629b27
-            Fstrerror(fdo)
629b27
-        );
629b27
-        exit(EXIT_FAILURE);
629b27
+	fprintf(stderr, _("Unable to write package lead: %s\n"),
629b27
+		Fstrerror(fdo));
629b27
+	exit(EXIT_FAILURE);
629b27
     }
629b27
 
629b27
-    if (rpmWriteSignature(fdo, sigh))
629b27
-    {
629b27
-        fprintf(stderr, _("Unable to write signature: %s\n"), Fstrerror(fdo));
629b27
-        exit(EXIT_FAILURE);
629b27
+    if (rpmWriteSignature(fdo, sigh)) {
629b27
+	fprintf(stderr, _("Unable to write signature: %s\n"), Fstrerror(fdo));
629b27
+	exit(EXIT_FAILURE);
629b27
     }
629b27
 
629b27
-    if (headerWrite(fdo, h, HEADER_MAGIC_YES))
629b27
-    {
629b27
-        fprintf(stderr, _("Unable to write headers: %s\n"), Fstrerror(fdo));
629b27
-        exit(EXIT_FAILURE);
629b27
+    if (headerWrite(fdo, h, HEADER_MAGIC_YES)) {
629b27
+	fprintf(stderr, _("Unable to write headers: %s\n"), Fstrerror(fdo));
629b27
+	exit(EXIT_FAILURE);
629b27
     }
629b27
 
629b27
     /* Retrieve payload size and compression type. */
629b27
-    {	const char *compr = headerGetString(h, RPMTAG_PAYLOADCOMPRESSOR);
629b27
-        rpmio_flags = rstrscat(NULL, "r.", compr ? compr : "gzip", NULL);
629b27
+    {
629b27
+	const char *compr = headerGetString(h, RPMTAG_PAYLOADCOMPRESSOR);
629b27
+	rpmio_flags = rstrscat(NULL, "r.", compr ? compr : "gzip", NULL);
629b27
     }
629b27
 
629b27
     gzdi = Fdopen(fdi, rpmio_flags);	/* XXX gzdi == fdi */
629b27
     free(rpmio_flags);
629b27
 
629b27
-    if (gzdi == NULL)
629b27
-    {
629b27
-        fprintf(stderr, _("cannot re-open payload: %s\n"), Fstrerror(gzdi));
629b27
-        exit(EXIT_FAILURE);
629b27
+    if (gzdi == NULL) {
629b27
+	fprintf(stderr, _("cannot re-open payload: %s\n"), Fstrerror(gzdi));
629b27
+	exit(EXIT_FAILURE);
629b27
     }
629b27
 
629b27
     rpmfiles files = rpmfilesNew(NULL, h, 0, RPMFI_KEEPHEADER);
629b27
-    rpmfi fi = rpmfiNewArchiveReader(
629b27
-        gzdi,
629b27
-        files,
629b27
-        RPMFI_ITER_READ_ARCHIVE_CONTENT_FIRST
629b27
-    );
629b27
+    rpmfi fi = rpmfiNewArchiveReader(gzdi, files,
629b27
+				     RPMFI_ITER_READ_ARCHIVE_CONTENT_FIRST);
629b27
 
629b27
     /* this is encoded in the file format, so needs to be fixed size (for
629b27
-        now?)
629b27
-    */
629b27
+     * now?)
629b27
+     */
629b27
     diglen = (uint32_t)rpmDigestLength(rpmfiDigestAlgo(fi));
629b27
-    digestSet ds = digestSetCreate(
629b27
-        rpmfiFC(fi),
629b27
-        digestSetHash,
629b27
-        digestSetCmp,
629b27
-        NULL
629b27
-    );
629b27
+    digestSet ds = digestSetCreate(rpmfiFC(fi), digestSetHash, digestSetCmp,
629b27
+				   NULL);
629b27
     struct digestoffset offsets[rpmfiFC(fi)];
629b27
     pos = RPMLEAD_SIZE + headerSizeof(sigh, HEADER_MAGIC_YES);
629b27
 
629b27
@@ -247,139 +210,114 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
629b27
 
629b27
     zeros = xcalloc(fundamental_block_size, 1);
629b27
 
629b27
-    while (next >= 0)
629b27
-    {
629b27
-        next = rpmfiNext(fi);
629b27
-        if (next == RPMERR_ITER_END)
629b27
-        {
629b27
-            rc = RPMRC_OK;
629b27
-            break;
629b27
-        }
629b27
-        mode = rpmfiFMode(fi);
629b27
-        if (!S_ISREG(mode) || !rpmfiArchiveHasContent(fi))
629b27
-        {
629b27
-            /* not a regular file, or the archive doesn't contain any content for
629b27
-               this entry
629b27
-            */
629b27
-            continue;
629b27
-        }
629b27
-        digest = rpmfiFDigest(fi, NULL, NULL);
629b27
-        if (digestSetGetEntry(ds, digest, NULL))
629b27
-        {
629b27
-            /* This specific digest has already been included, so skip it */
629b27
-            continue;
629b27
-        }
629b27
-        pad = pad_to(pos, fundamental_block_size);
629b27
-        if (Fwrite(zeros, sizeof(char), pad, fdo) != pad)
629b27
-        {
629b27
-            fprintf(stderr, _("Unable to write padding\n"));
629b27
-            rc = RPMRC_FAIL;
629b27
-            goto exit;
629b27
-        }
629b27
-        /* round up to next fundamental_block_size */
629b27
-        pos += pad;
629b27
-        digestSetAddEntry(ds, digest);
629b27
-        offsets[offset_ix].digest = digest;
629b27
-        offsets[offset_ix].pos = pos;
629b27
-        offset_ix++;
629b27
-        size = rpmfiFSize(fi);
629b27
-        rc = rpmfiArchiveReadToFile(fi, fdo, 0);
629b27
-        if (rc != RPMRC_OK)
629b27
-        {
629b27
-            fprintf(stderr, _("rpmfiArchiveReadToFile failed with %d\n"), rc);
629b27
-            goto exit;
629b27
-        }
629b27
-        pos += size;
629b27
+    while (next >= 0) {
629b27
+	next = rpmfiNext(fi);
629b27
+	if (next == RPMERR_ITER_END) {
629b27
+	    rc = RPMRC_OK;
629b27
+	    break;
629b27
+	}
629b27
+	mode = rpmfiFMode(fi);
629b27
+	if (!S_ISREG(mode) || !rpmfiArchiveHasContent(fi)) {
629b27
+	    /* not a regular file, or the archive doesn't contain any content
629b27
+	     * for this entry.
629b27
+	    */
629b27
+	    continue;
629b27
+	}
629b27
+	digest = rpmfiFDigest(fi, NULL, NULL);
629b27
+	if (digestSetGetEntry(ds, digest, NULL)) {
629b27
+	    /* This specific digest has already been included, so skip it. */
629b27
+	    continue;
629b27
+	}
629b27
+	pad = pad_to(pos, fundamental_block_size);
629b27
+	if (Fwrite(zeros, sizeof(char), pad, fdo) != pad) {
629b27
+	    fprintf(stderr, _("Unable to write padding\n"));
629b27
+	    rc = RPMRC_FAIL;
629b27
+	    goto exit;
629b27
+	}
629b27
+	/* round up to next fundamental_block_size */
629b27
+	pos += pad;
629b27
+	digestSetAddEntry(ds, digest);
629b27
+	offsets[offset_ix].digest = digest;
629b27
+	offsets[offset_ix].pos = pos;
629b27
+	offset_ix++;
629b27
+	size = rpmfiFSize(fi);
629b27
+	rc = rpmfiArchiveReadToFile(fi, fdo, 0);
629b27
+	if (rc != RPMRC_OK) {
629b27
+	    fprintf(stderr, _("rpmfiArchiveReadToFile failed with %d\n"), rc);
629b27
+	    goto exit;
629b27
+	}
629b27
+	pos += size;
629b27
     }
629b27
     Fclose(gzdi);	/* XXX gzdi == fdi */
629b27
 
629b27
-    qsort(
629b27
-        offsets,
629b27
-        (size_t)offset_ix,
629b27
-        sizeof(struct digestoffset),
629b27
-        digestoffsetCmp
629b27
-    );
629b27
+    qsort(offsets, (size_t)offset_ix, sizeof(struct digestoffset),
629b27
+	  digestoffsetCmp);
629b27
 
629b27
     len = sizeof(offset_ix);
629b27
-    if (Fwrite(&offset_ix, len, 1, fdo) != len)
629b27
-    {
629b27
-        fprintf(stderr, _("Unable to write length of table\n"));
629b27
-        rc = RPMRC_FAIL;
629b27
-        goto exit;
629b27
+    if (Fwrite(&offset_ix, len, 1, fdo) != len) {
629b27
+	fprintf(stderr, _("Unable to write length of table\n"));
629b27
+	rc = RPMRC_FAIL;
629b27
+	goto exit;
629b27
     }
629b27
     len = sizeof(diglen);
629b27
-    if (Fwrite(&diglen, len, 1, fdo) != len)
629b27
-    {
629b27
-        fprintf(stderr, _("Unable to write length of digest\n"));
629b27
-        rc = RPMRC_FAIL;
629b27
-        goto exit;
629b27
+    if (Fwrite(&diglen, len, 1, fdo) != len) {
629b27
+	fprintf(stderr, _("Unable to write length of digest\n"));
629b27
+	rc = RPMRC_FAIL;
629b27
+	goto exit;
629b27
     }
629b27
     len = sizeof(rpm_loff_t);
629b27
-    for (int x = 0; x < offset_ix; x++)
629b27
-    {
629b27
-        if (Fwrite(offsets[x].digest, diglen, 1, fdo) != diglen)
629b27
-        {
629b27
-            fprintf(stderr, _("Unable to write digest\n"));
629b27
-            rc = RPMRC_FAIL;
629b27
-            goto exit;
629b27
-        }
629b27
-        if (Fwrite(&offsets[x].pos, len, 1, fdo) != len)
629b27
-        {
629b27
-            fprintf(stderr, _("Unable to write offset\n"));
629b27
-            rc = RPMRC_FAIL;
629b27
-            goto exit;
629b27
-        }
629b27
+    for (int x = 0; x < offset_ix; x++) {
629b27
+	if (Fwrite(offsets[x].digest, diglen, 1, fdo) != diglen) {
629b27
+	    fprintf(stderr, _("Unable to write digest\n"));
629b27
+	    rc = RPMRC_FAIL;
629b27
+	    goto exit;
629b27
+	}
629b27
+	if (Fwrite(&offsets[x].pos, len, 1, fdo) != len) {
629b27
+	    fprintf(stderr, _("Unable to write offset\n"));
629b27
+	    rc = RPMRC_FAIL;
629b27
+	    goto exit;
629b27
+	}
629b27
     }
629b27
     validation_pos = (
629b27
-        pos + sizeof(offset_ix) + sizeof(diglen) +
629b27
-        offset_ix * (diglen + sizeof(rpm_loff_t))
629b27
+	pos + sizeof(offset_ix) + sizeof(diglen) +
629b27
+	offset_ix * (diglen + sizeof(rpm_loff_t))
629b27
     );
629b27
 
629b27
     ssize_t validation_len = ufdCopy(validationi, fdo);
629b27
-    if (validation_len == -1)
629b27
-    {
629b27
-        fprintf(stderr, _("digest table ufdCopy failed\n"));
629b27
-        rc = RPMRC_FAIL;
629b27
-        goto exit;
629b27
+    if (validation_len == -1) {
629b27
+	fprintf(stderr, _("digest table ufdCopy failed\n"));
629b27
+	rc = RPMRC_FAIL;
629b27
+	goto exit;
629b27
     }
629b27
     /* add more padding so the last file can be cloned. It doesn't matter that
629b27
-       the table and validation etc are in this space. In fact, it's pretty
629b27
-       efficient if it is
629b27
+     * the table and validation etc are in this space. In fact, it's pretty
629b27
+     * efficient if it is.
629b27
     */
629b27
 
629b27
-    pad = pad_to(
629b27
-        (
629b27
-            validation_pos + validation_len + 2 * sizeof(rpm_loff_t) +
629b27
-            sizeof(uint64_t)
629b27
-        ),
629b27
-        fundamental_block_size
629b27
-    );
629b27
-    if (Fwrite(zeros, sizeof(char), pad, fdo) != pad)
629b27
-    {
629b27
-        fprintf(stderr, _("Unable to write final padding\n"));
629b27
-        rc = RPMRC_FAIL;
629b27
-        goto exit;
629b27
+    pad = pad_to((validation_pos + validation_len + 2 * sizeof(rpm_loff_t) +
629b27
+		 sizeof(uint64_t)), fundamental_block_size);
629b27
+    if (Fwrite(zeros, sizeof(char), pad, fdo) != pad) {
629b27
+	fprintf(stderr, _("Unable to write final padding\n"));
629b27
+	rc = RPMRC_FAIL;
629b27
+	goto exit;
629b27
     }
629b27
     zeros = _free(zeros);
629b27
-    if (Fwrite(&pos, len, 1, fdo) != len)
629b27
-    {
629b27
-        fprintf(stderr, _("Unable to write offset of digest table\n"));
629b27
-        rc = RPMRC_FAIL;
629b27
-        goto exit;
629b27
+    if (Fwrite(&pos, len, 1, fdo) != len) {
629b27
+	fprintf(stderr, _("Unable to write offset of digest table\n"));
629b27
+	rc = RPMRC_FAIL;
629b27
+	goto exit;
629b27
     }
629b27
-    if (Fwrite(&validation_pos, len, 1, fdo) != len)
629b27
-    {
629b27
-        fprintf(stderr, _("Unable to write offset of validation table\n"));
629b27
-        rc = RPMRC_FAIL;
629b27
-        goto exit;
629b27
+    if (Fwrite(&validation_pos, len, 1, fdo) != len) {
629b27
+	fprintf(stderr, _("Unable to write offset of validation table\n"));
629b27
+	rc = RPMRC_FAIL;
629b27
+	goto exit;
629b27
     }
629b27
     uint64_t magic = MAGIC;
629b27
     len = sizeof(magic);
629b27
-    if (Fwrite(&magic, len, 1, fdo) != len)
629b27
-    {
629b27
-        fprintf(stderr, _("Unable to write magic\n"));
629b27
-        rc = RPMRC_FAIL;
629b27
-        goto exit;
629b27
+    if (Fwrite(&magic, len, 1, fdo) != len) {
629b27
+	fprintf(stderr, _("Unable to write magic\n"));
629b27
+	rc = RPMRC_FAIL;
629b27
+	goto exit;
629b27
     }
629b27
 
629b27
 exit:
629b27
@@ -389,8 +327,7 @@ exit:
629b27
     return rc;
629b27
 }
629b27
 
629b27
-int main(int argc, char *argv[])
629b27
-{
629b27
+int main(int argc, char *argv[]) {
629b27
     rpmRC rc;
629b27
     int cprc = 0;
629b27
     uint8_t algos[argc - 1];
629b27
@@ -402,118 +339,95 @@ int main(int argc, char *argv[])
629b27
     xsetprogname(argv[0]);	/* Portability call -- see system.h */
629b27
     rpmReadConfigFiles(NULL, NULL);
629b27
 
629b27
-    if (argc > 1 && (rstreq(argv[1], "-h") || rstreq(argv[1], "--help")))
629b27
-    {
629b27
-        fprintf(stderr, _("Usage: %s [DIGESTALGO]...\n"), argv[0]);
629b27
-        exit(EXIT_FAILURE);
629b27
+    if (argc > 1 && (rstreq(argv[1], "-h") || rstreq(argv[1], "--help"))) {
629b27
+	fprintf(stderr, _("Usage: %s [DIGESTALGO]...\n"), argv[0]);
629b27
+	exit(EXIT_FAILURE);
629b27
     }
629b27
 
629b27
-    if (argc == 1)
629b27
-    {
629b27
-        fprintf(
629b27
-            stderr,
629b27
-            _("Need at least one DIGESTALGO parameter, e.g. 'SHA256'\n")
629b27
-        );
629b27
-        exit(EXIT_FAILURE);
629b27
+    if (argc == 1) {
629b27
+	fprintf(stderr,
629b27
+		_("Need at least one DIGESTALGO parameter, e.g. 'SHA256'\n"));
629b27
+	exit(EXIT_FAILURE);
629b27
     }
629b27
 
629b27
-    for (int x = 0; x < (argc - 1); x++)
629b27
-    {
629b27
-        if (pgpStringVal(PGPVAL_HASHALGO, argv[x + 1], &algos[x]) != 0)
629b27
-        {
629b27
-            fprintf(
629b27
-                stderr,
629b27
-                _("Unable to resolve '%s' as a digest algorithm, exiting\n"),
629b27
-                argv[x + 1]
629b27
-            );
629b27
-            exit(EXIT_FAILURE);
629b27
-        }
629b27
+    for (int x = 0; x < (argc - 1); x++) {
629b27
+	if (pgpStringVal(PGPVAL_HASHALGO, argv[x + 1], &algos[x]) != 0)
629b27
+	{
629b27
+	    fprintf(stderr,
629b27
+		    _("Unable to resolve '%s' as a digest algorithm, exiting\n"),
629b27
+		    argv[x + 1]);
629b27
+	    exit(EXIT_FAILURE);
629b27
+	}
629b27
     }
629b27
 
629b27
 
629b27
-    if (pipe(mainpipefd) == -1)
629b27
-    {
629b27
-        fprintf(stderr, _("Main pipe failure\n"));
629b27
-        exit(EXIT_FAILURE);
629b27
+    if (pipe(mainpipefd) == -1) {
629b27
+	fprintf(stderr, _("Main pipe failure\n"));
629b27
+	exit(EXIT_FAILURE);
629b27
     }
629b27
-    if (pipe(metapipefd) == -1)
629b27
-    {
629b27
-        fprintf(stderr, _("Meta pipe failure\n"));
629b27
-        exit(EXIT_FAILURE);
629b27
+    if (pipe(metapipefd) == -1) {
629b27
+	fprintf(stderr, _("Meta pipe failure\n"));
629b27
+	exit(EXIT_FAILURE);
629b27
     }
629b27
     cpid = fork();
629b27
-    if (cpid == 0)
629b27
-    {
629b27
-        /* child: digestor */
629b27
-        close(mainpipefd[0]);
629b27
-        close(metapipefd[0]);
629b27
-        FD_t fdi = fdDup(STDIN_FILENO);
629b27
-        FD_t fdo = fdDup(mainpipefd[1]);
629b27
-        FD_t validationo = fdDup(metapipefd[1]);
629b27
-        rc = digestor(fdi, fdo, validationo, algos, argc - 1);
629b27
-        Fclose(validationo);
629b27
-        Fclose(fdo);
629b27
-        Fclose(fdi);
629b27
+    if (cpid == 0) {
629b27
+	/* child: digestor */
629b27
+	close(mainpipefd[0]);
629b27
+	close(metapipefd[0]);
629b27
+	FD_t fdi = fdDup(STDIN_FILENO);
629b27
+	FD_t fdo = fdDup(mainpipefd[1]);
629b27
+	FD_t validationo = fdDup(metapipefd[1]);
629b27
+	rc = digestor(fdi, fdo, validationo, algos, argc - 1);
629b27
+	Fclose(validationo);
629b27
+	Fclose(fdo);
629b27
+	Fclose(fdi);
629b27
     } else {
629b27
-        /* parent: main program */
629b27
-        close(mainpipefd[1]);
629b27
-        close(metapipefd[1]);
629b27
-        FD_t fdi = fdDup(mainpipefd[0]);
629b27
-        FD_t validationi = fdDup(metapipefd[0]);
629b27
-        rc = process_package(fdi, validationi);
629b27
-        Fclose(validationi);
629b27
-        /* fdi is normally closed through the stacked file gzdi in the function. */
629b27
-        /* wait for child process (digestor for stdin) to complete. */
629b27
-        if (rc != RPMRC_OK)
629b27
-        {
629b27
-            if (kill(cpid, SIGTERM) != 0)
629b27
-            {
629b27
-                fprintf(
629b27
-                    stderr,
629b27
-                    _("Failed to kill digest process when main process failed: %s\n"),
629b27
-                    strerror(errno)
629b27
-                );
629b27
-            }
629b27
-        }
629b27
-        w = waitpid(cpid, &wstatus, 0);
629b27
-        if (w == -1)
629b27
-        {
629b27
-            fprintf(stderr, _("waitpid failed\n"));
629b27
-            cprc = EXIT_FAILURE;
629b27
-        } else if (WIFEXITED(wstatus))
629b27
-        {
629b27
-            cprc = WEXITSTATUS(wstatus);
629b27
-            if (cprc != 0)
629b27
-            {
629b27
-                fprintf(
629b27
-                    stderr,
629b27
-                    _("Digest process non-zero exit code %d\n"),
629b27
-                    cprc
629b27
-                );
629b27
-            }
629b27
-        } else if (WIFSIGNALED(wstatus))
629b27
-        {
629b27
-            fprintf(
629b27
-                stderr,
629b27
-                _("Digest process was terminated with a signal: %d\n"),
629b27
-                WTERMSIG(wstatus)
629b27
-            );
629b27
-            cprc = EXIT_FAILURE;
629b27
-        } else
629b27
-        {
629b27
-            /* don't think this can happen, but covering all bases */
629b27
-            fprintf(stderr, _("Unhandled circumstance in waitpid\n"));
629b27
-            cprc = EXIT_FAILURE;
629b27
-        }
629b27
-        if (cprc != EXIT_SUCCESS)
629b27
-        {
629b27
-            rc = RPMRC_FAIL;
629b27
-        }
629b27
+	/* parent: main program */
629b27
+	close(mainpipefd[1]);
629b27
+	close(metapipefd[1]);
629b27
+	FD_t fdi = fdDup(mainpipefd[0]);
629b27
+	FD_t validationi = fdDup(metapipefd[0]);
629b27
+	rc = process_package(fdi, validationi);
629b27
+	Fclose(validationi);
629b27
+	/* fdi is normally closed through the stacked file gzdi in the
629b27
+	 * function.
629b27
+	 * Wait for child process (digestor for stdin) to complete.
629b27
+	 */
629b27
+	if (rc != RPMRC_OK) {
629b27
+	    if (kill(cpid, SIGTERM) != 0) {
629b27
+		fprintf(stderr,
629b27
+		        _("Failed to kill digest process when main process failed: %s\n"),
629b27
+			strerror(errno));
629b27
+	    }
629b27
+	}
629b27
+	w = waitpid(cpid, &wstatus, 0);
629b27
+	if (w == -1) {
629b27
+	    fprintf(stderr, _("waitpid failed\n"));
629b27
+	    cprc = EXIT_FAILURE;
629b27
+	} else if (WIFEXITED(wstatus)) {
629b27
+	    cprc = WEXITSTATUS(wstatus);
629b27
+	    if (cprc != 0) {
629b27
+		fprintf(stderr,
629b27
+			_("Digest process non-zero exit code %d\n"),
629b27
+			cprc);
629b27
+	    }
629b27
+	} else if (WIFSIGNALED(wstatus)) {
629b27
+	    fprintf(stderr,
629b27
+		    _("Digest process was terminated with a signal: %d\n"),
629b27
+		    WTERMSIG(wstatus));
629b27
+	    cprc = EXIT_FAILURE;
629b27
+	} else {
629b27
+	    /* Don't think this can happen, but covering all bases */
629b27
+	    fprintf(stderr, _("Unhandled circumstance in waitpid\n"));
629b27
+	    cprc = EXIT_FAILURE;
629b27
+	}
629b27
+	if (cprc != EXIT_SUCCESS) {
629b27
+	    rc = RPMRC_FAIL;
629b27
+	}
629b27
     }
629b27
-    if (rc != RPMRC_OK)
629b27
-    {
629b27
-        /* translate rpmRC into generic failure return code. */
629b27
-        return EXIT_FAILURE;
629b27
+    if (rc != RPMRC_OK) {
629b27
+	/* translate rpmRC into generic failure return code. */
629b27
+	return EXIT_FAILURE;
629b27
     }
629b27
     return EXIT_SUCCESS;
629b27
 }
629b27
-- 
629b27
2.35.1
629b27