aboutsummaryrefslogtreecommitdiff
path: root/src/util/crypto_hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/crypto_hash.c')
-rw-r--r--src/util/crypto_hash.c189
1 files changed, 1 insertions, 188 deletions
diff --git a/src/util/crypto_hash.c b/src/util/crypto_hash.c
index 64f55e14c..9456e343b 100644
--- a/src/util/crypto_hash.c
+++ b/src/util/crypto_hash.c
@@ -21,7 +21,7 @@
21 21
22/** 22/**
23 * @file util/crypto_hash.c 23 * @file util/crypto_hash.c
24 * @brief SHA-512 GNUNET_CRYPTO_hash related functions 24 * @brief SHA-512 #GNUNET_CRYPTO_hash() related functions
25 * @author Christian Grothoff 25 * @author Christian Grothoff
26 */ 26 */
27 27
@@ -49,193 +49,6 @@ GNUNET_CRYPTO_hash (const void *block,
49} 49}
50 50
51 51
52/**
53 * Context used when hashing a file.
54 */
55struct GNUNET_CRYPTO_FileHashContext
56{
57
58 /**
59 * Function to call upon completion.
60 */
61 GNUNET_CRYPTO_HashCompletedCallback callback;
62
63 /**
64 * Closure for callback.
65 */
66 void *callback_cls;
67
68 /**
69 * IO buffer.
70 */
71 unsigned char *buffer;
72
73 /**
74 * Name of the file we are hashing.
75 */
76 char *filename;
77
78 /**
79 * File descriptor.
80 */
81 struct GNUNET_DISK_FileHandle *fh;
82
83 /**
84 * Cummulated hash.
85 */
86 gcry_md_hd_t md;
87
88 /**
89 * Size of the file.
90 */
91 uint64_t fsize;
92
93 /**
94 * Current offset.
95 */
96 uint64_t offset;
97
98 /**
99 * Current task for hashing.
100 */
101 struct GNUNET_SCHEDULER_Task * task;
102
103 /**
104 * Priority we use.
105 */
106 enum GNUNET_SCHEDULER_Priority priority;
107
108 /**
109 * Blocksize.
110 */
111 size_t bsize;
112
113};
114
115
116/**
117 * Report result of hash computation to callback
118 * and free associated resources.
119 */
120static void
121file_hash_finish (struct GNUNET_CRYPTO_FileHashContext *fhc,
122 const struct GNUNET_HashCode * res)
123{
124 fhc->callback (fhc->callback_cls, res);
125 GNUNET_free (fhc->filename);
126 if (!GNUNET_DISK_handle_invalid (fhc->fh))
127 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fhc->fh));
128 gcry_md_close (fhc->md);
129 GNUNET_free (fhc); /* also frees fhc->buffer */
130}
131
132
133/**
134 * File hashing task.
135 *
136 * @param cls closure
137 * @param tc context
138 */
139static void
140file_hash_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
141{
142 struct GNUNET_CRYPTO_FileHashContext *fhc = cls;
143 struct GNUNET_HashCode *res;
144 size_t delta;
145
146 fhc->task = NULL;
147 GNUNET_assert (fhc->offset <= fhc->fsize);
148 delta = fhc->bsize;
149 if (fhc->fsize - fhc->offset < delta)
150 delta = fhc->fsize - fhc->offset;
151 if (delta != GNUNET_DISK_file_read (fhc->fh, fhc->buffer, delta))
152 {
153 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "read", fhc->filename);
154 file_hash_finish (fhc, NULL);
155 return;
156 }
157 gcry_md_write (fhc->md, fhc->buffer, delta);
158 fhc->offset += delta;
159 if (fhc->offset == fhc->fsize)
160 {
161 res = (struct GNUNET_HashCode *) gcry_md_read (fhc->md, GCRY_MD_SHA512);
162 file_hash_finish (fhc, res);
163 return;
164 }
165 fhc->task = GNUNET_SCHEDULER_add_with_priority (fhc->priority,
166 &file_hash_task, fhc);
167}
168
169
170/**
171 * Compute the hash of an entire file.
172 *
173 * @param priority scheduling priority to use
174 * @param filename name of file to hash
175 * @param blocksize number of bytes to process in one task
176 * @param callback function to call upon completion
177 * @param callback_cls closure for callback
178 * @return NULL on (immediate) errror
179 */
180struct GNUNET_CRYPTO_FileHashContext *
181GNUNET_CRYPTO_hash_file (enum GNUNET_SCHEDULER_Priority priority,
182 const char *filename, size_t blocksize,
183 GNUNET_CRYPTO_HashCompletedCallback callback,
184 void *callback_cls)
185{
186 struct GNUNET_CRYPTO_FileHashContext *fhc;
187
188 GNUNET_assert (blocksize > 0);
189 fhc =
190 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_FileHashContext) + blocksize);
191 fhc->callback = callback;
192 fhc->callback_cls = callback_cls;
193 fhc->buffer = (unsigned char *) &fhc[1];
194 fhc->filename = GNUNET_strdup (filename);
195 if (GPG_ERR_NO_ERROR != gcry_md_open (&fhc->md, GCRY_MD_SHA512, 0))
196 {
197 GNUNET_break (0);
198 GNUNET_free (fhc);
199 return NULL;
200 }
201 fhc->bsize = blocksize;
202 if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fhc->fsize, GNUNET_NO, GNUNET_YES))
203 {
204 GNUNET_free (fhc->filename);
205 GNUNET_free (fhc);
206 return NULL;
207 }
208 fhc->fh =
209 GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
210 GNUNET_DISK_PERM_NONE);
211 if (!fhc->fh)
212 {
213 GNUNET_free (fhc->filename);
214 GNUNET_free (fhc);
215 return NULL;
216 }
217 fhc->priority = priority;
218 fhc->task =
219 GNUNET_SCHEDULER_add_with_priority (priority, &file_hash_task, fhc);
220 return fhc;
221}
222
223
224/**
225 * Cancel a file hashing operation.
226 *
227 * @param fhc operation to cancel (callback must not yet have been invoked)
228 */
229void
230GNUNET_CRYPTO_hash_file_cancel (struct GNUNET_CRYPTO_FileHashContext *fhc)
231{
232 GNUNET_SCHEDULER_cancel (fhc->task);
233 GNUNET_free (fhc->filename);
234 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fhc->fh));
235 GNUNET_free (fhc);
236}
237
238
239/* ***************** binary-ASCII encoding *************** */ 52/* ***************** binary-ASCII encoding *************** */
240 53
241 54