xref: /aosp_15_r20/external/elfutils/lib/crc32_file.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
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