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