1/*- 2 * Copyright (c) 2003-2007 Tim Kientzle 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "archive_platform.h" 27__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_data_into_fd.c,v 1.16 2008/05/23 05:01:29 cperciva Exp $"); 28 29#ifdef HAVE_SYS_TYPES_H 30#include <sys/types.h> 31#endif 32#ifdef HAVE_ERRNO_H 33#include <errno.h> 34#endif 35#ifdef HAVE_UNISTD_H 36#include <unistd.h> 37#endif 38 39#include "archive.h" 40#include "archive_private.h" 41 42/* Maximum amount of data to write at one time. */ 43#define MAX_WRITE (1024 * 1024) 44 45/* 46 * This implementation minimizes copying of data and is sparse-file aware. 47 */ 48int 49archive_read_data_into_fd(struct archive *a, int fd) 50{ 51 int r; 52 const void *buff; 53 size_t size, bytes_to_write; 54 ssize_t bytes_written, total_written; 55 off_t offset; 56 off_t output_offset; 57 58 __archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, "archive_read_data_into_fd"); 59 60 total_written = 0; 61 output_offset = 0; 62 63 while ((r = archive_read_data_block(a, &buff, &size, &offset)) == 64 ARCHIVE_OK) { 65 const char *p = buff; 66 if (offset > output_offset) { 67 output_offset = lseek(fd, 68 offset - output_offset, SEEK_CUR); 69 if (output_offset != offset) { 70 archive_set_error(a, errno, "Seek error"); 71 return (ARCHIVE_FATAL); 72 } 73 } 74 while (size > 0) { 75 bytes_to_write = size; 76 if (bytes_to_write > MAX_WRITE) 77 bytes_to_write = MAX_WRITE; 78 bytes_written = write(fd, p, bytes_to_write); 79 if (bytes_written < 0) { 80 archive_set_error(a, errno, "Write error"); 81 return (ARCHIVE_FATAL); 82 } 83 output_offset += bytes_written; 84 total_written += bytes_written; 85 p += bytes_written; 86 size -= bytes_written; 87 } 88 } 89 90 if (r != ARCHIVE_EOF) 91 return (r); 92 return (ARCHIVE_OK); 93} 94