Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 1 Oct 2014 01:18:25 +0000 (UTC)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r272338 - user/marcel/mkimg
Message-ID:  <201410010118.s911IPb0039776@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201410010118.s911IPb0039776>