From owner-svn-src-user@FreeBSD.ORG Wed Oct 1 01:18:26 2014 Return-Path: <owner-svn-src-user@FreeBSD.ORG> Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 2087FD2F; Wed, 1 Oct 2014 01:18:26 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 0D883FFD; Wed, 1 Oct 2014 01:18:26 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s911IPCn039777; Wed, 1 Oct 2014 01:18:25 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s911IPb0039776; Wed, 1 Oct 2014 01:18:25 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201410010118.s911IPb0039776@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar <marcel@FreeBSD.org> Date: Wed, 1 Oct 2014 01:18:25 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r272338 - user/marcel/mkimg X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" <svn-src-user.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/svn-src-user/> List-Post: <mailto:svn-src-user@freebsd.org> List-Help: <mailto:svn-src-user-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=subscribe> X-List-Received-Date: Wed, 01 Oct 2014 01:18:26 -0000 Author: marcel Date: Wed Oct 1 01:18:25 2014 New Revision: 272338 URL: http://svnweb.freebsd.org/changeset/base/272338 Log: Implement image_copyout_region(): This is the one function that is responsible for writing to the output file. For eack chunk that covers all or parts of the region to write, call a corresponding function that knows how to write a chunk of that type: image_copyout_memory(): Use write(2) to write the buffer. image_copyout_zeroes(): Try and seek forward to create a sparse file. If that fails, scribble zeroes to the output file to support writing to stdout. Use image_copyout_memoryIO for that. image_copyout_file(): Iteratively map bits of the input file and use image_copyout_memory() to write the bits to the output file. With this commit all unit tests pass again. Modified: user/marcel/mkimg/image.c Modified: user/marcel/mkimg/image.c ============================================================================== --- user/marcel/mkimg/image.c Tue Sep 30 23:29:06 2014 (r272337) +++ user/marcel/mkimg/image.c Wed Oct 1 01:18:25 2014 (r272338) @@ -499,6 +499,10 @@ image_copyin(lba_t blk, int fd, uint64_t return (error); } +/* + * Output/sink file handling. + */ + int image_copyout(int fd) { @@ -523,46 +527,103 @@ image_copyout_done(int fd) return (error); } -int -image_copyout_region(int fd, lba_t blk, lba_t size) +static int +image_copyout_memory(int fd, size_t size, void *ptr) { - char *buffer; - off_t ofs; - size_t bufsz, sz; - ssize_t rdsz, wrsz; + + if (write(fd, ptr, size) == -1) + return (errno); + return (0); +} + +static int +image_copyout_zeroes(int fd, size_t size) +{ + static uint8_t *zeroes = NULL; + size_t sz; int error; - bufsz = secsz * image_swap_pgsz; + if (lseek(fd, (off_t)size, SEEK_CUR) != -1) + return (0); - ofs = lseek(fd, 0L, SEEK_CUR); + /* + * If we can't seek, we must write. + */ + + if (zeroes == NULL) { + zeroes = calloc(1, secsz); + if (zeroes == NULL) + return (ENOMEM); + } + + while (size > 0) { + sz = (size > secsz) ? secsz : size; + error = image_copyout_memory(fd, sz, zeroes); + if (error) + return (error); + size -= sz; + } + return (0); +} + +static int +image_copyout_file(int fd, size_t size, int ifd, off_t iofs) +{ + void *buf; + size_t iosz, sz; + int error; + + iosz = secsz * image_swap_pgsz; + + while (size > 0) { + sz = (size > iosz) ? iosz : size; + buf = image_file_map(ifd, iofs, sz); + if (buf == NULL) + return (errno); + error = image_copyout_memory(fd, sz, buf); + image_file_unmap(buf, sz); + if (error) + return (error); + size -= sz; + iofs += sz; + } + return (0); +} + +int +image_copyout_region(int fd, lba_t blk, lba_t size) +{ + struct chunk *ch; + size_t ofs, sz; + int error; - blk *= secsz; - if (lseek(image_swap_fd, blk, SEEK_SET) != blk) - return (errno); - buffer = malloc(bufsz); - if (buffer == NULL) - return (errno); - error = 0; size *= secsz; + while (size > 0) { - sz = ((ssize_t)bufsz < size) ? bufsz : (size_t)size; - rdsz = read(image_swap_fd, buffer, sz); - if (rdsz <= 0) { - error = (rdsz < 0) ? errno : 0; + ch = image_chunk_find(blk); + if (ch == NULL) + return (EINVAL); + ofs = (blk - ch->ch_block) * secsz; + sz = ch->ch_size - ofs; + sz = ((lba_t)sz < size) ? sz : (size_t)size; + switch (ch->ch_type) { + case CH_TYPE_ZEROES: + error = image_copyout_zeroes(fd, sz); break; - } - wrsz = (ofs == -1) ? - write(fd, buffer, rdsz) : - sparse_write(fd, buffer, rdsz); - if (wrsz < 0) { - error = errno; + case CH_TYPE_FILE: + error = image_copyout_file(fd, sz, ch->ch_u.file.fd, + ch->ch_u.file.ofs + ofs); break; + case CH_TYPE_MEMORY: + error = image_copyout_memory(fd, sz, ch->ch_u.mem.ptr); + break; + default: + return (EDOOFUS); } - assert(wrsz == rdsz); - size -= rdsz; + size -= sz; + blk += sz / secsz; } - free(buffer); - return (error); + return (0); } int