FOSSology  4.4.0
Open Source License Compliance by Open Source Software
checksum.c
Go to the documentation of this file.
1 /*
2  SPDX-FileCopyrightText: © 2007-2011 Hewlett-Packard Development Company, L.P.
3 
4  SPDX-License-Identifier: GPL-2.0-only
5 */
6 
7 #include <gcrypt.h>
8 
9 #include "checksum.h"
10 
26 CksumFile * SumOpenFile (char *Fname)
27 {
28  CksumFile *CF;
29  struct stat Stat;
30 
31  CF=(CksumFile *)calloc(1,sizeof(CksumFile));
32  if (!CF) return(NULL);
33 
34  /* open the file (memory map) */
35 #ifdef O_LARGEFILE
36  CF->FileHandle = open(Fname,O_RDONLY|O_LARGEFILE);
37 #else
38  /* BSD does not need nor use O_LARGEFILE */
39  CF->FileHandle = open(Fname,O_RDONLY);
40 #endif
41  if (CF->FileHandle == -1)
42  {
43  LOG_ERROR("Unable to open file (%s)\n",Fname);
44  free(CF);
45  return(NULL);
46  }
47  if (fstat(CF->FileHandle,&Stat) == -1)
48  {
49  LOG_ERROR("Unable to stat file (%s)\n",Fname);
50  close(CF->FileHandle);
51  free(CF);
52  return(NULL);
53  }
54  CF->MmapSize = Stat.st_size;
55  CF->MmapOffset = 0;
56 
57  /* reject files that are too long */
58  if (CF->MmapSize >= (uint32_t)(-1))
59  {
60  close(CF->FileHandle);
61  free(CF);
62  return(NULL);
63  }
64 
65  if (CF->MmapSize > 0)
66  {
67  CF->Mmap = mmap(0,CF->MmapSize,PROT_READ,MAP_PRIVATE,CF->FileHandle,0);
68  if (CF->Mmap == MAP_FAILED)
69  {
70  LOG_ERROR("Unable to mmap file (%s)\n",Fname);
71  close(CF->FileHandle);
72  free(CF);
73  return(NULL);
74  }
75  }
76  return(CF);
77 } /* SumOpenFile() */
78 
84 {
85  if ((CF->MmapSize > 0) && CF->Mmap) munmap(CF->Mmap,CF->MmapSize);
86  CF->MmapSize = 0;
87  CF->Mmap = NULL;
88  close(CF->FileHandle);
89  free(CF);
90 } /* SumCloseFile() */
91 
97 int CountDigits (uint64_t Num)
98 {
99  uint64_t Val=10;
100  int Digits=1;
101  for(Val=10; (Val > 0) && (Val < Num); Val = Val * 10)
102  {
103  Digits++;
104  }
105  return(Digits);
106 } /* CountDigits() */
107 
115 Cksum * SumComputeFile (FILE *Fin)
116 {
117  gcry_md_hd_t checksumhandler;
118  gcry_error_t checksumError = 0;
119  char Buffer[64];
120  Cksum *Sum;
121  unsigned char *tempBuff;
122  int ReadLen;
123  uint64_t ReadTotalLen=0;
124 
125  Sum = (Cksum *)calloc(1,sizeof(Cksum));
126  if (!Sum) return(NULL);
127 
128  checksumError = gcry_md_open(&checksumhandler, GCRY_MD_NONE, 0);
129  if (! checksumhandler)
130  {
131  LOG_ERROR("Unable to initialize checksum\n");
132  free(Sum);
133  return(NULL);
134  }
135  checksumError = gcry_md_enable(checksumhandler, GCRY_MD_MD5);
136  if (gcry_err_code(checksumError) != GPG_ERR_NO_ERROR)
137  {
138  LOG_ERROR("GCRY Error: %s/%s\n", gcry_strsource(checksumError),
139  gcry_strerror(checksumError));
140  free(Sum);
141  return(NULL);
142  }
143 
144  checksumError = gcry_md_enable(checksumhandler, GCRY_MD_SHA1);
145  if (gcry_err_code(checksumError) != GPG_ERR_NO_ERROR)
146  {
147  LOG_ERROR("GCRY Error: %s/%s\n", gcry_strsource(checksumError),
148  gcry_strerror(checksumError));
149  free(Sum);
150  return(NULL);
151  }
152 
153  while(!feof(Fin))
154  {
155  ReadLen = fread(Buffer,1,64,Fin);
156  if (ReadLen > 0)
157  {
158  gcry_md_write(checksumhandler, Buffer, ReadLen);
159  ReadTotalLen += ReadLen;
160  }
161  }
162 
163  Sum->DataLen = ReadTotalLen;
164 
165  tempBuff = gcry_md_read(checksumhandler, GCRY_MD_MD5);
166  memcpy(Sum->MD5digest, tempBuff, sizeof(Sum->MD5digest));
167 
168  tempBuff = gcry_md_read(checksumhandler, GCRY_MD_SHA1);
169  memcpy(Sum->SHA1digest, tempBuff, sizeof(Sum->SHA1digest));
170  gcry_md_close(checksumhandler);
171 
172  return(Sum);
173 } /* SumComputeFile() */
174 
183 {
184  Cksum *Sum;
185  gcry_md_hd_t checksumhandler;
186  gcry_error_t checksumError;
187  unsigned char *tempBuff;
188 
189  checksumError = gcry_md_open(&checksumhandler, GCRY_MD_NONE, 0);
190  if (! checksumhandler)
191  {
192  LOG_ERROR("Unable to initialize checksum\n");
193  return(NULL);
194  }
195  checksumError = gcry_md_enable(checksumhandler, GCRY_MD_MD5);
196  if (gcry_err_code(checksumError) != GPG_ERR_NO_ERROR)
197  {
198  LOG_ERROR("GCRY Error: %s/%s\n", gcry_strsource(checksumError),
199  gcry_strerror(checksumError));
200  return(NULL);
201  }
202 
203  checksumError = gcry_md_enable(checksumhandler, GCRY_MD_SHA1);
204  if (gcry_err_code(checksumError) != GPG_ERR_NO_ERROR)
205  {
206  LOG_ERROR("GCRY Error: %s/%s\n", gcry_strsource(checksumError),
207  gcry_strerror(checksumError));
208  return(NULL);
209  }
210 
211  Sum = (Cksum *)calloc(1,sizeof(Cksum));
212  if (!Sum)
213  {
214  return(NULL);
215  }
216  Sum->DataLen = CF->MmapSize;
217 
218  gcry_md_write(checksumhandler, CF->Mmap, CF->MmapSize);
219 
220  tempBuff = gcry_md_read(checksumhandler, GCRY_MD_MD5);
221  memcpy(Sum->MD5digest, tempBuff, sizeof(Sum->MD5digest));
222 
223  tempBuff = gcry_md_read(checksumhandler, GCRY_MD_SHA1);
224  memcpy(Sum->SHA1digest, tempBuff, sizeof(Sum->SHA1digest));
225 
226  gcry_md_close(checksumhandler);
227  return(Sum);
228 } /* SumComputeBuff() */
229 
230 
237 char * SumToString (Cksum *Sum)
238 {
239  int i;
240  char *Result;
241 
242  Result = (char *)calloc(1,16*2 +1+ 20*2 +1+ CountDigits(Sum->DataLen) + 1);
243  if (!Result) return(NULL);
244 
245  for(i=0; i<20; i++)
246  {
247  sprintf(Result + (i*2),"%02X",Sum->SHA1digest[i]);
248  }
249  Result[40]='.';
250  for(i=0; i<16; i++)
251  {
252  sprintf(Result + 41 + (i*2),"%02X",Sum->MD5digest[i]);
253  }
254  Result[41+32]='.';
255  sprintf(Result + 33 + 41,"%Lu",(long long unsigned int)Sum->DataLen);
256  return(Result);
257 } /* SumToString() */
258 
259 int calc_sha256sum(char*filename, char* dst) {
260  gcry_md_hd_t checksumhandler;
261  unsigned char buf[32];
262  unsigned char *tempBuff;
263  memset(buf, '\0', sizeof(buf));
264  FILE *f;
265  if(!(f=fopen(filename, "rb")))
266  {
267  LOG_FATAL("Failed to open file '%s'\n", filename);
268  return(1);
269  }
270  gcry_md_open(&checksumhandler, GCRY_MD_SHA256, 0);
271  if (! checksumhandler ||
272  (! gcry_md_is_enabled(checksumhandler, GCRY_MD_SHA256)))
273  {
274  LOG_ERROR("Unable to initialize checksum\n");
275  return(2);
276  }
277 
278  int i=0;
279  while((i=fread(buf, 1, sizeof(buf), f)) > 0) {
280  gcry_md_write(checksumhandler, buf, i);
281  }
282  fclose(f);
283  memset(buf, '\0', sizeof(buf));
284  tempBuff = gcry_md_read(checksumhandler, GCRY_MD_SHA256);
285  memcpy(buf, tempBuff, sizeof(buf));
286 
287  gcry_md_close(checksumhandler);
288 
289  for (i=0; i<32; i++)
290  {
291  snprintf(dst+i*2, 3, "%02X", buf[i]);
292  }
293 
294  return 0;
295 }
char * SumToString(Cksum *Sum)
Return string representing a Cksum. NOTE: The calling function must free() the string!
Definition: checksum.c:237
Cksum * SumComputeBuff(CksumFile *CF)
Compute the checksum, allocate and return a Cksum containing the sum value.
Definition: checksum.c:182
int CountDigits(uint64_t Num)
Count how many digits are in a number.
Definition: checksum.c:97
Cksum * SumComputeFile(FILE *Fin)
Compute the checksum, allocate and return a string containing the sum value.
Definition: checksum.c:115
CksumFile * SumOpenFile(char *Fname)
Open and mmap a file.
Definition: checksum.c:26
void SumCloseFile(CksumFile *CF)
Close a file that was opened with SumOpenFile()
Definition: checksum.c:83
Store file handler and mmap of a file.
Definition: checksum.h:44
int FileHandle
File handler for the file.
Definition: checksum.h:45
unsigned char * Mmap
Mmap of the file.
Definition: checksum.h:46
uint64_t MmapSize
Size of mmap.
Definition: checksum.h:47
uint64_t MmapOffset
Index into mmap.
Definition: checksum.h:48
Store check sum of a file.
Definition: checksum.h:33
uint8_t SHA1digest[20]
SHA1 digest of the file.
Definition: checksum.h:35
uint64_t DataLen
Size of the file.
Definition: checksum.h:36
uint8_t MD5digest[16]
MD5 digest of the file.
Definition: checksum.h:34
static int Result
Result of calls.
Definition: test_CopyFile.c:17