Git init
[external/libelf.git] / lib / input.c
1 /*
2  * input.c - low-level input for libelf.
3  * Copyright (C) 1995 - 2001, 2005 Michael Riepe
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 #include <private.h>
21
22 #ifndef lint
23 static const char rcsid[] = "@(#) $Id: input.c,v 1.11 2008/05/23 08:15:35 michael Exp $";
24 #endif /* lint */
25
26 #include <errno.h>
27
28 #if HAVE_MMAP
29 #include <sys/mman.h>
30 #endif /* HAVE_MMAP */
31
32 static int
33 xread(int fd, char *buffer, size_t len) {
34     size_t done = 0;
35     size_t n;
36
37     while (done < len) {
38         n = read(fd, buffer + done, len - done);
39         if (n == 0) {
40             /* premature end of file */
41             return -1;
42         }
43         else if (n != (size_t)-1) {
44             /* some bytes read, continue */
45             done += n;
46         }
47         else if (errno != EAGAIN && errno != EINTR) {
48             /* real error */
49             return -1;
50         }
51     }
52     return 0;
53 }
54
55 void*
56 _elf_read(Elf *elf, void *buffer, size_t off, size_t len) {
57     void *tmp;
58
59     elf_assert(elf);
60     elf_assert(elf->e_magic == ELF_MAGIC);
61     elf_assert(off >= 0 && off + len <= elf->e_size);
62     if (elf->e_disabled) {
63         seterr(ERROR_FDDISABLED);
64     }
65     else if (len) {
66         off += elf->e_base;
67         if (lseek(elf->e_fd, (off_t)off, SEEK_SET) != (off_t)off) {
68             seterr(ERROR_IO_SEEK);
69         }
70         else if (!(tmp = buffer) && !(tmp = malloc(len))) {
71             seterr(ERROR_IO_2BIG);
72         }
73         else if (xread(elf->e_fd, tmp, len)) {
74             seterr(ERROR_IO_READ);
75             if (tmp != buffer) {
76                 free(tmp);
77             }
78         }
79         else {
80             return tmp;
81         }
82     }
83     return NULL;
84 }
85
86 void*
87 _elf_mmap(Elf *elf) {
88 #if HAVE_MMAP
89     void *tmp;
90
91     elf_assert(elf);
92     elf_assert(elf->e_magic == ELF_MAGIC);
93     elf_assert(elf->e_base == 0);
94     if (elf->e_disabled) {
95         seterr(ERROR_FDDISABLED);
96     }
97     else if (elf->e_size) {
98         tmp = (void*)mmap(0, elf->e_size, PROT_READ | PROT_WRITE,
99                           MAP_PRIVATE, elf->e_fd, 0);
100         if (tmp != (void*)-1) {
101             return tmp;
102         }
103     }
104 #endif /* HAVE_MMAP */
105     return NULL;
106 }