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