blob: e6d468b424fd32190ee41ea7e63ba0761b438d56 [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001#include "system.h"
2#include <errno.h>
3#include <unistd.h>
4#include <sys/stat.h>
5#include <sys/mman.h>
6
7int
8crc32_file (int fd, uint32_t *resp)
9{
10 unsigned char buffer[1024 * 8];
11 uint32_t crc = 0;
12 off_t off = 0;
13 ssize_t count;
14
15 struct stat st;
16 if (fstat (fd, &st) == 0)
17 {
18 /* Try mapping in the file data. */
19 size_t mapsize = st.st_size;
20 void *mapped = mmap (NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
21 if (mapped == MAP_FAILED && errno == ENOMEM)
22 {
23 const size_t pagesize = sysconf (_SC_PAGE_SIZE);
24 mapsize = ((mapsize / 2) + pagesize - 1) & -pagesize;
25 while (mapsize >= pagesize
26 && (mapped = mmap (NULL, mapsize, PROT_READ, MAP_PRIVATE,
27 fd, 0)) == MAP_FAILED && errno == ENOMEM)
28 mapsize /= 2;
29 }
30 if (mapped != MAP_FAILED)
31 {
32 do
33 {
34 if (st.st_size <= (off_t) mapsize)
35 {
36 *resp = crc32 (crc, mapped, st.st_size);
37 munmap (mapped, mapsize);
38 return 0;
39 }
40 crc = crc32 (crc, mapped, mapsize);
41 off += mapsize;
42 st.st_size -= mapsize;
43 } while (mmap (mapped, mapsize, PROT_READ, MAP_FIXED|MAP_PRIVATE,
44 fd, off) == mapped);
45 munmap (mapped, mapsize);
46 }
47 }
48
49 while ((count = TEMP_FAILURE_RETRY (pread (fd, buffer, sizeof buffer,
50 off))) > 0)
51 {
52 off += count;
53 crc = crc32 (crc, buffer, count);
54 }
55
56 *resp = crc;
57
58 return count == 0 ? 0 : -1;
59}