1*7304104dSAndroid Build Coastguard Worker /* Compute CRC32 checksum of file contents.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2006 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker
5*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
6*7304104dSAndroid Build Coastguard Worker it under the terms of either
7*7304104dSAndroid Build Coastguard Worker
8*7304104dSAndroid Build Coastguard Worker * the GNU Lesser General Public License as published by the Free
9*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 3 of the License, or (at
10*7304104dSAndroid Build Coastguard Worker your option) any later version
11*7304104dSAndroid Build Coastguard Worker
12*7304104dSAndroid Build Coastguard Worker or
13*7304104dSAndroid Build Coastguard Worker
14*7304104dSAndroid Build Coastguard Worker * the GNU General Public License as published by the Free
15*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 2 of the License, or (at
16*7304104dSAndroid Build Coastguard Worker your option) any later version
17*7304104dSAndroid Build Coastguard Worker
18*7304104dSAndroid Build Coastguard Worker or both in parallel, as here.
19*7304104dSAndroid Build Coastguard Worker
20*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
21*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
22*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23*7304104dSAndroid Build Coastguard Worker General Public License for more details.
24*7304104dSAndroid Build Coastguard Worker
25*7304104dSAndroid Build Coastguard Worker You should have received copies of the GNU General Public License and
26*7304104dSAndroid Build Coastguard Worker the GNU Lesser General Public License along with this program. If
27*7304104dSAndroid Build Coastguard Worker not, see <http://www.gnu.org/licenses/>. */
28*7304104dSAndroid Build Coastguard Worker
29*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
30*7304104dSAndroid Build Coastguard Worker # include <config.h>
31*7304104dSAndroid Build Coastguard Worker #endif
32*7304104dSAndroid Build Coastguard Worker
33*7304104dSAndroid Build Coastguard Worker #include "libeu.h"
34*7304104dSAndroid Build Coastguard Worker #include <errno.h>
35*7304104dSAndroid Build Coastguard Worker #include <unistd.h>
36*7304104dSAndroid Build Coastguard Worker #include <sys/stat.h>
37*7304104dSAndroid Build Coastguard Worker #include <sys/mman.h>
38*7304104dSAndroid Build Coastguard Worker #include "system.h"
39*7304104dSAndroid Build Coastguard Worker
40*7304104dSAndroid Build Coastguard Worker int
crc32_file(int fd,uint32_t * resp)41*7304104dSAndroid Build Coastguard Worker crc32_file (int fd, uint32_t *resp)
42*7304104dSAndroid Build Coastguard Worker {
43*7304104dSAndroid Build Coastguard Worker unsigned char buffer[1024 * 8];
44*7304104dSAndroid Build Coastguard Worker uint32_t crc = 0;
45*7304104dSAndroid Build Coastguard Worker off_t off = 0;
46*7304104dSAndroid Build Coastguard Worker ssize_t count;
47*7304104dSAndroid Build Coastguard Worker
48*7304104dSAndroid Build Coastguard Worker struct stat st;
49*7304104dSAndroid Build Coastguard Worker if (fstat (fd, &st) == 0)
50*7304104dSAndroid Build Coastguard Worker {
51*7304104dSAndroid Build Coastguard Worker /* Try mapping in the file data. */
52*7304104dSAndroid Build Coastguard Worker size_t mapsize = st.st_size;
53*7304104dSAndroid Build Coastguard Worker void *mapped = mmap (NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
54*7304104dSAndroid Build Coastguard Worker if (mapped == MAP_FAILED && errno == ENOMEM)
55*7304104dSAndroid Build Coastguard Worker {
56*7304104dSAndroid Build Coastguard Worker const size_t pagesize = sysconf (_SC_PAGESIZE);
57*7304104dSAndroid Build Coastguard Worker mapsize = ((mapsize / 2) + pagesize - 1) & -pagesize;
58*7304104dSAndroid Build Coastguard Worker while (mapsize >= pagesize
59*7304104dSAndroid Build Coastguard Worker && (mapped = mmap (NULL, mapsize, PROT_READ, MAP_PRIVATE,
60*7304104dSAndroid Build Coastguard Worker fd, 0)) == MAP_FAILED && errno == ENOMEM)
61*7304104dSAndroid Build Coastguard Worker mapsize /= 2;
62*7304104dSAndroid Build Coastguard Worker }
63*7304104dSAndroid Build Coastguard Worker if (mapped != MAP_FAILED)
64*7304104dSAndroid Build Coastguard Worker {
65*7304104dSAndroid Build Coastguard Worker do
66*7304104dSAndroid Build Coastguard Worker {
67*7304104dSAndroid Build Coastguard Worker if (st.st_size <= (off_t) mapsize)
68*7304104dSAndroid Build Coastguard Worker {
69*7304104dSAndroid Build Coastguard Worker *resp = crc32 (crc, mapped, st.st_size);
70*7304104dSAndroid Build Coastguard Worker munmap (mapped, mapsize);
71*7304104dSAndroid Build Coastguard Worker return 0;
72*7304104dSAndroid Build Coastguard Worker }
73*7304104dSAndroid Build Coastguard Worker crc = crc32 (crc, mapped, mapsize);
74*7304104dSAndroid Build Coastguard Worker off += mapsize;
75*7304104dSAndroid Build Coastguard Worker st.st_size -= mapsize;
76*7304104dSAndroid Build Coastguard Worker } while (mmap (mapped, mapsize, PROT_READ, MAP_FIXED|MAP_PRIVATE,
77*7304104dSAndroid Build Coastguard Worker fd, off) == mapped);
78*7304104dSAndroid Build Coastguard Worker munmap (mapped, mapsize);
79*7304104dSAndroid Build Coastguard Worker }
80*7304104dSAndroid Build Coastguard Worker }
81*7304104dSAndroid Build Coastguard Worker
82*7304104dSAndroid Build Coastguard Worker while ((count = TEMP_FAILURE_RETRY (pread (fd, buffer, sizeof buffer,
83*7304104dSAndroid Build Coastguard Worker off))) > 0)
84*7304104dSAndroid Build Coastguard Worker {
85*7304104dSAndroid Build Coastguard Worker off += count;
86*7304104dSAndroid Build Coastguard Worker crc = crc32 (crc, buffer, count);
87*7304104dSAndroid Build Coastguard Worker }
88*7304104dSAndroid Build Coastguard Worker
89*7304104dSAndroid Build Coastguard Worker *resp = crc;
90*7304104dSAndroid Build Coastguard Worker
91*7304104dSAndroid Build Coastguard Worker return count == 0 ? 0 : -1;
92*7304104dSAndroid Build Coastguard Worker }
93