GNUnet  0.10.x
crypto_hash_file.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2001-2013 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your 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  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19 
20  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include <gcrypt.h>
29 
30 #define LOG(kind, ...) GNUNET_log_from(kind, "util-crypto-hash-file", __VA_ARGS__)
31 
32 #define LOG_STRERROR_FILE(kind, syscall, filename) GNUNET_log_from_strerror_file(kind, "util-crypto-hash-file", syscall, filename)
33 
34 
43 
47  void *callback_cls;
48 
52  unsigned char *buffer;
53 
57  char *filename;
58 
63 
67  gcry_md_hd_t md;
68 
72  uint64_t fsize;
73 
77  uint64_t offset;
78 
83 
88 
92  size_t bsize;
93 };
94 
95 
100 static void
102  const struct GNUNET_HashCode * res)
103 {
104  fhc->callback(fhc->callback_cls, res);
105  GNUNET_free(fhc->filename);
106  if (!GNUNET_DISK_handle_invalid(fhc->fh))
108  gcry_md_close(fhc->md);
109  GNUNET_free(fhc); /* also frees fhc->buffer */
110 }
111 
112 
118 static void
119 file_hash_task(void *cls)
120 {
121  struct GNUNET_CRYPTO_FileHashContext *fhc = cls;
122  struct GNUNET_HashCode *res;
123  size_t delta;
124  ssize_t sret;
125 
126  fhc->task = NULL;
127  GNUNET_assert(fhc->offset <= fhc->fsize);
128  delta = fhc->bsize;
129  if (fhc->fsize - fhc->offset < delta)
130  delta = fhc->fsize - fhc->offset;
131  sret = GNUNET_DISK_file_read(fhc->fh,
132  fhc->buffer,
133  delta);
134  if ((sret < 0) ||
135  (delta != (size_t)sret))
136  {
138  "read",
139  fhc->filename);
140  file_hash_finish(fhc,
141  NULL);
142  return;
143  }
144  gcry_md_write(fhc->md,
145  fhc->buffer,
146  delta);
147  fhc->offset += delta;
148  if (fhc->offset == fhc->fsize)
149  {
150  res = (struct GNUNET_HashCode *)gcry_md_read(fhc->md,
151  GCRY_MD_SHA512);
152  file_hash_finish(fhc, res);
153  return;
154  }
157  fhc);
158 }
159 
160 
173  const char *filename,
174  size_t blocksize,
176  void *callback_cls)
177 {
178  struct GNUNET_CRYPTO_FileHashContext *fhc;
179 
180  GNUNET_assert(blocksize > 0);
181  fhc =
182  GNUNET_malloc(sizeof(struct GNUNET_CRYPTO_FileHashContext) + blocksize);
183  fhc->callback = callback;
184  fhc->callback_cls = callback_cls;
185  fhc->buffer = (unsigned char *)&fhc[1];
186  fhc->filename = GNUNET_strdup(filename);
187  if (GPG_ERR_NO_ERROR != gcry_md_open(&fhc->md, GCRY_MD_SHA512, 0))
188  {
189  GNUNET_break(0);
190  GNUNET_free(fhc);
191  return NULL;
192  }
193  fhc->bsize = blocksize;
194  if (GNUNET_OK !=
195  GNUNET_DISK_file_size(filename,
196  &fhc->fsize,
197  GNUNET_NO,
198  GNUNET_YES))
199  {
200  GNUNET_free(fhc->filename);
201  GNUNET_free(fhc);
202  return NULL;
203  }
204  fhc->fh = GNUNET_DISK_file_open(filename,
207  if (!fhc->fh)
208  {
209  GNUNET_free(fhc->filename);
210  GNUNET_free(fhc);
211  return NULL;
212  }
213  fhc->priority = priority;
216  fhc);
217  return fhc;
218 }
219 
220 
226 void
228 {
230  GNUNET_free(fhc->filename);
232  GNUNET_DISK_file_close(fhc->fh));
233  GNUNET_free(fhc);
234 }
235 
236 /* end of crypto_hash_file.c */
Open the file for reading.
struct GNUNET_SCHEDULER_Task * task
Current task for hashing.
int GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1339
struct GNUNET_DISK_FileHandle * fh
File descriptor.
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:35
void(* GNUNET_CRYPTO_HashCompletedCallback)(void *cls, const struct GNUNET_HashCode *res)
Function called once the hash computation over the specified file has completed.
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:729
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static void file_hash_finish(struct GNUNET_CRYPTO_FileHashContext *fhc, const struct GNUNET_HashCode *res)
Report result of hash computation to callback and free associated resources.
Nobody is allowed to do anything to the file.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
GNUNET_SCHEDULER_Priority
Valid task priorities.
struct GNUNET_CRYPTO_FileHashContext * GNUNET_CRYPTO_hash_file(enum GNUNET_SCHEDULER_Priority priority, const char *filename, size_t blocksize, GNUNET_CRYPTO_HashCompletedCallback callback, void *callback_cls)
Compute the hash of an entire file.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
gcry_md_hd_t md
Cummulated hash.
int GNUNET_DISK_handle_invalid(const struct GNUNET_DISK_FileHandle *h)
Checks whether a handle is invalid.
Definition: disk.c:190
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_with_priority(enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified priority.
Definition: scheduler.c:1191
#define LOG_STRERROR_FILE(kind, syscall, filename)
unsigned char * buffer
IO buffer.
A 512-bit hashcode.
static int res
char * filename
Name of the file we are hashing.
uint64_t fsize
Size of the file.
Context used when hashing a file.
int GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition: disk.c:254
enum GNUNET_SCHEDULER_Priority priority
Priority we use.
Entry in list of pending tasks.
Definition: scheduler.c:131
GNUNET_CRYPTO_HashCompletedCallback callback
Function to call upon completion.
#define GNUNET_YES
Definition: gnunet_common.h:77
static void file_hash_task(void *cls)
File hashing task.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1262
Handle used to access files (and pipes).
uint64_t offset
Current offset.
#define GNUNET_malloc(size)
Wrapper around malloc.
void * callback_cls
Closure for callback.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_CRYPTO_hash_file_cancel(struct GNUNET_CRYPTO_FileHashContext *fhc)
Cancel a file hashing operation.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956