1260684Skaiw/*- 2260684Skaiw * Copyright (c) 2011, Joseph Koshy 3260684Skaiw * All rights reserved. 4260684Skaiw * 5260684Skaiw * Redistribution and use in source and binary forms, with or without 6260684Skaiw * modification, are permitted provided that the following conditions 7260684Skaiw * are met: 8260684Skaiw * 1. Redistributions of source code must retain the above copyright 9260684Skaiw * notice, this list of conditions and the following disclaimer 10260684Skaiw * in this position and unchanged. 11260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright 12260684Skaiw * notice, this list of conditions and the following disclaimer in the 13260684Skaiw * documentation and/or other materials provided with the distribution. 14260684Skaiw * 15260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16260684Skaiw * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17260684Skaiw * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18260684Skaiw * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19260684Skaiw * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20260684Skaiw * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21260684Skaiw * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22260684Skaiw * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23260684Skaiw * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24260684Skaiw * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25260684Skaiw */ 26260684Skaiw 27260684Skaiw#include <sys/types.h> 28260684Skaiw#include <sys/stat.h> 29260684Skaiw 30260684Skaiw#include <stdlib.h> 31260684Skaiw#include <unistd.h> 32260684Skaiw 33260684Skaiw#include "libelftc.h" 34260684Skaiw#include "_libelftc.h" 35260684Skaiw 36260684Skaiw#if ELFTC_HAVE_MMAP 37260684Skaiw#include <sys/mman.h> 38260684Skaiw#endif 39260684Skaiw 40295577SemasteELFTC_VCSID("$Id: elftc_copyfile.c 3297 2016-01-09 15:26:34Z jkoshy $"); 41260684Skaiw 42260684Skaiw/* 43260684Skaiw * Copy the contents referenced by 'ifd' to 'ofd'. Returns 0 on 44260684Skaiw * success and -1 on error. 45260684Skaiw */ 46260684Skaiw 47260684Skaiwint 48260684Skaiwelftc_copyfile(int ifd, int ofd) 49260684Skaiw{ 50295577Semaste size_t file_size, n; 51260684Skaiw int buf_mmapped; 52260684Skaiw struct stat sb; 53260684Skaiw char *b, *buf; 54295577Semaste ssize_t nr, nw; 55260684Skaiw 56260684Skaiw /* Determine the input file's size. */ 57260684Skaiw if (fstat(ifd, &sb) < 0) 58260684Skaiw return (-1); 59260684Skaiw 60260684Skaiw /* Skip files without content. */ 61260684Skaiw if (sb.st_size == 0) 62260684Skaiw return (0); 63260684Skaiw 64260684Skaiw buf = NULL; 65260684Skaiw buf_mmapped = 0; 66295577Semaste file_size = (size_t) sb.st_size; 67260684Skaiw 68260684Skaiw#if ELFTC_HAVE_MMAP 69260684Skaiw /* 70260684Skaiw * Prefer mmap() if it is available. 71260684Skaiw */ 72295577Semaste buf = mmap(NULL, file_size, PROT_READ, MAP_SHARED, ifd, (off_t) 0); 73260684Skaiw if (buf != MAP_FAILED) 74260684Skaiw buf_mmapped = 1; 75260684Skaiw else 76260684Skaiw buf = NULL; 77260684Skaiw#endif 78260684Skaiw 79260684Skaiw /* 80260684Skaiw * If mmap() is not available, or if the mmap() operation 81260684Skaiw * failed, allocate a buffer, and read in input data. 82260684Skaiw */ 83276371Semaste if (buf_mmapped == false) { 84295577Semaste if ((buf = malloc(file_size)) == NULL) 85260684Skaiw return (-1); 86295577Semaste b = buf; 87295577Semaste for (n = file_size; n > 0; n -= (size_t) nr, b += nr) { 88295577Semaste if ((nr = read(ifd, b, n)) < 0) { 89295577Semaste free(buf); 90295577Semaste return (-1); 91295577Semaste } 92276371Semaste } 93260684Skaiw } 94260684Skaiw 95260684Skaiw /* 96260684Skaiw * Write data to the output file descriptor. 97260684Skaiw */ 98295577Semaste for (n = file_size, b = buf; n > 0; n -= (size_t) nw, b += nw) 99260684Skaiw if ((nw = write(ofd, b, n)) <= 0) 100260684Skaiw break; 101260684Skaiw 102260684Skaiw /* Release the input buffer. */ 103260684Skaiw#if ELFTC_HAVE_MMAP 104295577Semaste if (buf_mmapped && munmap(buf, file_size) < 0) 105260684Skaiw return (-1); 106260684Skaiw#endif 107260684Skaiw 108260684Skaiw if (!buf_mmapped) 109260684Skaiw free(buf); 110260684Skaiw 111260684Skaiw return (n > 0 ? -1 : 0); 112260684Skaiw} 113260684Skaiw 114