aboutsummaryrefslogtreecommitdiff
path: root/src/util/crypto_hash_file.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-05-28 09:02:31 +0000
committerChristian Grothoff <christian@grothoff.org>2015-05-28 09:02:31 +0000
commit078f7063aef1d4105e71160b8764ab95c2dcdfbe (patch)
tree86d498356ceaaa1ba738f64a158cce2cd0163a15 /src/util/crypto_hash_file.c
parent9469cd334f29ca9437e13eb951b53b7690f10be9 (diff)
downloadgnunet-078f7063aef1d4105e71160b8764ab95c2dcdfbe.tar.gz
gnunet-078f7063aef1d4105e71160b8764ab95c2dcdfbe.zip
adding --enable-taler-wallet configure option to build a reduced version of libgnunetutil with only the parts needed by GNU Taler wallets
Diffstat (limited to 'src/util/crypto_hash_file.c')
-rw-r--r--src/util/crypto_hash_file.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/src/util/crypto_hash_file.c b/src/util/crypto_hash_file.c
new file mode 100644
index 000000000..2d15fac36
--- /dev/null
+++ b/src/util/crypto_hash_file.c
@@ -0,0 +1,215 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19
20*/
21
22/**
23 * @file util/crypto_hash_file.c
24 * @brief incremental hashing of files
25 * @author Christian Grothoff
26 */
27
28
29/**
30 * Context used when hashing a file.
31 */
32struct GNUNET_CRYPTO_FileHashContext
33{
34
35 /**
36 * Function to call upon completion.
37 */
38 GNUNET_CRYPTO_HashCompletedCallback callback;
39
40 /**
41 * Closure for callback.
42 */
43 void *callback_cls;
44
45 /**
46 * IO buffer.
47 */
48 unsigned char *buffer;
49
50 /**
51 * Name of the file we are hashing.
52 */
53 char *filename;
54
55 /**
56 * File descriptor.
57 */
58 struct GNUNET_DISK_FileHandle *fh;
59
60 /**
61 * Cummulated hash.
62 */
63 gcry_md_hd_t md;
64
65 /**
66 * Size of the file.
67 */
68 uint64_t fsize;
69
70 /**
71 * Current offset.
72 */
73 uint64_t offset;
74
75 /**
76 * Current task for hashing.
77 */
78 struct GNUNET_SCHEDULER_Task * task;
79
80 /**
81 * Priority we use.
82 */
83 enum GNUNET_SCHEDULER_Priority priority;
84
85 /**
86 * Blocksize.
87 */
88 size_t bsize;
89
90};
91
92
93/**
94 * Report result of hash computation to callback
95 * and free associated resources.
96 */
97static void
98file_hash_finish (struct GNUNET_CRYPTO_FileHashContext *fhc,
99 const struct GNUNET_HashCode * res)
100{
101 fhc->callback (fhc->callback_cls, res);
102 GNUNET_free (fhc->filename);
103 if (!GNUNET_DISK_handle_invalid (fhc->fh))
104 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fhc->fh));
105 gcry_md_close (fhc->md);
106 GNUNET_free (fhc); /* also frees fhc->buffer */
107}
108
109
110/**
111 * File hashing task.
112 *
113 * @param cls closure
114 * @param tc context
115 */
116static void
117file_hash_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
118{
119 struct GNUNET_CRYPTO_FileHashContext *fhc = cls;
120 struct GNUNET_HashCode *res;
121 size_t delta;
122
123 fhc->task = NULL;
124 GNUNET_assert (fhc->offset <= fhc->fsize);
125 delta = fhc->bsize;
126 if (fhc->fsize - fhc->offset < delta)
127 delta = fhc->fsize - fhc->offset;
128 if (delta != GNUNET_DISK_file_read (fhc->fh, fhc->buffer, delta))
129 {
130 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "read", fhc->filename);
131 file_hash_finish (fhc, NULL);
132 return;
133 }
134 gcry_md_write (fhc->md, fhc->buffer, delta);
135 fhc->offset += delta;
136 if (fhc->offset == fhc->fsize)
137 {
138 res = (struct GNUNET_HashCode *) gcry_md_read (fhc->md, GCRY_MD_SHA512);
139 file_hash_finish (fhc, res);
140 return;
141 }
142 fhc->task = GNUNET_SCHEDULER_add_with_priority (fhc->priority,
143 &file_hash_task, fhc);
144}
145
146
147/**
148 * Compute the hash of an entire file.
149 *
150 * @param priority scheduling priority to use
151 * @param filename name of file to hash
152 * @param blocksize number of bytes to process in one task
153 * @param callback function to call upon completion
154 * @param callback_cls closure for callback
155 * @return NULL on (immediate) errror
156 */
157struct GNUNET_CRYPTO_FileHashContext *
158GNUNET_CRYPTO_hash_file (enum GNUNET_SCHEDULER_Priority priority,
159 const char *filename, size_t blocksize,
160 GNUNET_CRYPTO_HashCompletedCallback callback,
161 void *callback_cls)
162{
163 struct GNUNET_CRYPTO_FileHashContext *fhc;
164
165 GNUNET_assert (blocksize > 0);
166 fhc =
167 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_FileHashContext) + blocksize);
168 fhc->callback = callback;
169 fhc->callback_cls = callback_cls;
170 fhc->buffer = (unsigned char *) &fhc[1];
171 fhc->filename = GNUNET_strdup (filename);
172 if (GPG_ERR_NO_ERROR != gcry_md_open (&fhc->md, GCRY_MD_SHA512, 0))
173 {
174 GNUNET_break (0);
175 GNUNET_free (fhc);
176 return NULL;
177 }
178 fhc->bsize = blocksize;
179 if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fhc->fsize, GNUNET_NO, GNUNET_YES))
180 {
181 GNUNET_free (fhc->filename);
182 GNUNET_free (fhc);
183 return NULL;
184 }
185 fhc->fh =
186 GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
187 GNUNET_DISK_PERM_NONE);
188 if (!fhc->fh)
189 {
190 GNUNET_free (fhc->filename);
191 GNUNET_free (fhc);
192 return NULL;
193 }
194 fhc->priority = priority;
195 fhc->task =
196 GNUNET_SCHEDULER_add_with_priority (priority, &file_hash_task, fhc);
197 return fhc;
198}
199
200
201/**
202 * Cancel a file hashing operation.
203 *
204 * @param fhc operation to cancel (callback must not yet have been invoked)
205 */
206void
207GNUNET_CRYPTO_hash_file_cancel (struct GNUNET_CRYPTO_FileHashContext *fhc)
208{
209 GNUNET_SCHEDULER_cancel (fhc->task);
210 GNUNET_free (fhc->filename);
211 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fhc->fh));
212 GNUNET_free (fhc);
213}
214
215/* end of crypto_hash_file.c */