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