elftc_copyfile.c revision 276371
111820Sjulian/*- 211820Sjulian * Copyright (c) 2011, Joseph Koshy 311820Sjulian * All rights reserved. 411820Sjulian * 511820Sjulian * Redistribution and use in source and binary forms, with or without 611820Sjulian * modification, are permitted provided that the following conditions 711820Sjulian * are met: 811820Sjulian * 1. Redistributions of source code must retain the above copyright 911820Sjulian * notice, this list of conditions and the following disclaimer 1011820Sjulian * in this position and unchanged. 1111820Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1211820Sjulian * notice, this list of conditions and the following disclaimer in the 1311820Sjulian * documentation and/or other materials provided with the distribution. 1411820Sjulian * 1511820Sjulian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 1611820Sjulian * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1711820Sjulian * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1811820Sjulian * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 1911820Sjulian * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2011820Sjulian * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2111820Sjulian * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2211820Sjulian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2311820Sjulian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2411820Sjulian * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2511820Sjulian */ 2611820Sjulian 2711820Sjulian#include <sys/types.h> 2811820Sjulian#include <sys/stat.h> 2911820Sjulian 3011820Sjulian#include <stdlib.h> 3119948Sjhay#include <unistd.h> 3211820Sjulian 3311820Sjulian#include "libelftc.h" 3411820Sjulian#include "_libelftc.h" 3511820Sjulian 3611820Sjulian#if ELFTC_HAVE_MMAP 3719948Sjhay#include <sys/mman.h> 3811820Sjulian#endif 3911820Sjulian 4011820SjulianELFTC_VCSID("$Id: elftc_copyfile.c 2981 2014-02-01 02:41:13Z jkoshy $"); 4111820Sjulian 4211820Sjulian/* 4311820Sjulian * Copy the contents referenced by 'ifd' to 'ofd'. Returns 0 on 4411820Sjulian * success and -1 on error. 4511820Sjulian */ 4611820Sjulian 4711820Sjulianint 4811820Sjulianelftc_copyfile(int ifd, int ofd) 4911820Sjulian{ 5011820Sjulian int buf_mmapped; 5111820Sjulian struct stat sb; 5211820Sjulian char *b, *buf; 5311820Sjulian ssize_t nw; 5411820Sjulian size_t n; 5511820Sjulian 5611820Sjulian /* Determine the input file's size. */ 5711820Sjulian if (fstat(ifd, &sb) < 0) 5811820Sjulian return (-1); 5911820Sjulian 6011820Sjulian /* Skip files without content. */ 6111820Sjulian if (sb.st_size == 0) 6211820Sjulian return (0); 6311820Sjulian 6411820Sjulian buf = NULL; 6512268Sjulian buf_mmapped = 0; 6612268Sjulian 6711820Sjulian#if ELFTC_HAVE_MMAP 6811820Sjulian /* 6911820Sjulian * Prefer mmap() if it is available. 7011820Sjulian */ 7111820Sjulian buf = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, ifd, (off_t) 0); 7211820Sjulian if (buf != MAP_FAILED) 7311820Sjulian buf_mmapped = 1; 7411820Sjulian else 7511820Sjulian buf = NULL; 7611820Sjulian#endif 7711820Sjulian 7811820Sjulian /* 7911820Sjulian * If mmap() is not available, or if the mmap() operation 8011820Sjulian * failed, allocate a buffer, and read in input data. 8111820Sjulian */ 8211820Sjulian if (buf_mmapped == false) { 8311820Sjulian if ((buf = malloc(sb.st_size)) == NULL) 8411820Sjulian return (-1); 8511820Sjulian if (read(ifd, buf, sb.st_size) != sb.st_size) { 8611820Sjulian free(buf); 8711820Sjulian return (-1); 8811820Sjulian } 8911820Sjulian } 9011820Sjulian 9111820Sjulian /* 9211820Sjulian * Write data to the output file descriptor. 9311820Sjulian */ 9411820Sjulian for (n = sb.st_size, b = buf; n > 0; n -= nw, b += nw) 9511820Sjulian if ((nw = write(ofd, b, n)) <= 0) 9611820Sjulian break; 9711820Sjulian 9811820Sjulian /* Release the input buffer. */ 9911820Sjulian#if ELFTC_HAVE_MMAP 10011820Sjulian if (buf_mmapped && munmap(buf, sb.st_size) < 0) 10111820Sjulian return (-1); 10211820Sjulian#endif 10311820Sjulian 10411820Sjulian if (!buf_mmapped) 10511820Sjulian free(buf); 10611820Sjulian 10711820Sjulian return (n > 0 ? -1 : 0); 10811820Sjulian} 10911820Sjulian 11011820Sjulian