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 :
39 : int
40 31 : crc32_file (int fd, uint32_t *resp)
41 : {
42 : unsigned char buffer[1024 * 8];
43 31 : uint32_t crc = 0;
44 31 : off_t off = 0;
45 : ssize_t count;
46 :
47 : struct stat st;
48 31 : if (fstat (fd, &st) == 0)
49 : {
50 : /* Try mapping in the file data. */
51 31 : size_t mapsize = st.st_size;
52 31 : void *mapped = mmap (NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
53 31 : if (mapped == MAP_FAILED && errno == ENOMEM)
54 : {
55 0 : const size_t pagesize = sysconf (_SC_PAGE_SIZE);
56 0 : mapsize = ((mapsize / 2) + pagesize - 1) & -pagesize;
57 0 : while (mapsize >= pagesize
58 0 : && (mapped = mmap (NULL, mapsize, PROT_READ, MAP_PRIVATE,
59 0 : fd, 0)) == MAP_FAILED && errno == ENOMEM)
60 0 : mapsize /= 2;
61 : }
62 31 : if (mapped != MAP_FAILED)
63 : {
64 : do
65 : {
66 31 : if (st.st_size <= (off_t) mapsize)
67 : {
68 31 : *resp = crc32 (crc, mapped, st.st_size);
69 31 : munmap (mapped, mapsize);
70 31 : return 0;
71 : }
72 0 : crc = crc32 (crc, mapped, mapsize);
73 0 : off += mapsize;
74 0 : st.st_size -= mapsize;
75 0 : } while (mmap (mapped, mapsize, PROT_READ, MAP_FIXED|MAP_PRIVATE,
76 0 : fd, off) == mapped);
77 0 : munmap (mapped, mapsize);
78 : }
79 : }
80 :
81 0 : while ((count = TEMP_FAILURE_RETRY (pread (fd, buffer, sizeof buffer,
82 : off))) > 0)
83 : {
84 0 : off += count;
85 0 : crc = crc32 (crc, buffer, count);
86 : }
87 :
88 0 : *resp = crc;
89 :
90 0 : return count == 0 ? 0 : -1;
91 : }
|