From bf89f67e5e1143606e32b55cc034c4a55c0606a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulrich=20=C3=96lmann?= Date: Wed, 23 Oct 2019 16:30:29 +0200 Subject: [PATCH] Support streaming a block index' content into a char device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A reasonable exemplary usecase for this is updating a UBI volume (its interface to userspace is a char device): let a parent process open the device file and prepare the resulting file descriptor for updating the UBI volume, then fork 'casync extract -' with STDOUT being redirected to that file descriptor. Without this change the only working alternative today is to fork 'casync mkdev ' and then to actively pipe the resulting block device's content into the UBI volume's prepared character device which is uneconomic as the whole data has to be shuffled around once by casync and a second time by the parent process. Signed-off-by: Ulrich Ölmann --- src/cadecoder.c | 8 ++++---- src/casync-tool.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cadecoder.c b/src/cadecoder.c index 97947922..487ad579 100644 --- a/src/cadecoder.c +++ b/src/cadecoder.c @@ -265,7 +265,7 @@ static inline bool CA_DECODER_IS_NAKED(CaDecoder *d) { return d->n_nodes == 1 && !d->nodes[0].entry && - (S_ISREG(d->nodes[0].mode) || S_ISBLK(d->nodes[0].mode)); + (S_ISREG(d->nodes[0].mode) || S_ISBLK(d->nodes[0].mode) || S_ISCHR(d->nodes[0].mode)); } static mode_t ca_decoder_node_mode(CaDecoderNode *n) { @@ -481,13 +481,13 @@ int ca_decoder_set_base_fd(CaDecoder *d, int fd) { if (fstatfs(fd, &sfs) < 0) return -errno; - if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode) && !S_ISBLK(st.st_mode)) + if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode) && !S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) return -ENOTTY; d->nodes[0] = (CaDecoderNode) { .fd = fd, .entry_offset = S_ISDIR(st.st_mode) ? 0 : UINT64_MAX, - .payload_offset = S_ISREG(st.st_mode) || S_ISBLK(st.st_mode) ? 0 : UINT64_MAX, + .payload_offset = S_ISREG(st.st_mode) || S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode) ? 0 : UINT64_MAX, .goodbye_offset = UINT64_MAX, .end_offset = UINT64_MAX, .mode = st.st_mode, @@ -4112,7 +4112,7 @@ static int ca_decoder_step_node(CaDecoder *d, CaDecoderNode *n) { if (mode == (mode_t) -1) return -EUNATCH; - assert(S_ISREG(mode) || S_ISBLK(mode)); + assert(S_ISREG(mode) || S_ISBLK(mode) || S_ISCHR(mode)); /* If the size of this payload is known, and we reached it, we are done */ if (n->size != UINT64_MAX) { diff --git a/src/casync-tool.c b/src/casync-tool.c index f9206886..46a41d58 100644 --- a/src/casync-tool.c +++ b/src/casync-tool.c @@ -1575,16 +1575,16 @@ static int verb_extract(int argc, char *argv[]) { return -EINVAL; } - } else if (S_ISREG(st.st_mode) || S_ISBLK(st.st_mode)) { + } else if (S_ISREG(st.st_mode) || S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) { if (operation == _EXTRACT_OPERATION_INVALID) operation = EXTRACT_BLOB_INDEX; else if (operation != EXTRACT_BLOB_INDEX) { - log_error("Output is a regular file or block device, but attempted to extract an archive."); + log_error("Output is a regular file, block or character device, but attempted to extract an archive."); return -EINVAL; } } else { - log_error("Output is neither a directory, a regular file, nor a block device. Refusing."); + log_error("Output is neither a directory, a regular file, nor a block or character device. Refusing."); return -EINVAL; } }