GNUnet  0.20.0
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  */
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include <gcrypt.h>
30 
31 #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-hash-file", \
32  __VA_ARGS__)
33 
34 #define LOG_STRERROR_FILE(kind, syscall, \
35  filename) GNUNET_log_from_strerror_file (kind, \
36  "util-crypto-hash-file", \
37  syscall, \
38  filename)
39 
40 
45 {
50 
54  void *callback_cls;
55 
59  unsigned char *buffer;
60 
64  char *filename;
65 
70 
74  gcry_md_hd_t md;
75 
79  uint64_t fsize;
80 
84  uint64_t offset;
85 
90 
95 
99  size_t bsize;
100 };
101 
102 
107 static void
109  const struct GNUNET_HashCode *res)
110 {
111  fhc->callback (fhc->callback_cls, res);
112  GNUNET_free (fhc->filename);
113  if (! GNUNET_DISK_handle_invalid (fhc->fh))
115  gcry_md_close (fhc->md);
116  GNUNET_free (fhc); /* also frees fhc->buffer */
117 }
118 
119 
125 static void
126 file_hash_task (void *cls)
127 {
128  struct GNUNET_CRYPTO_FileHashContext *fhc = cls;
129  struct GNUNET_HashCode *res;
130  size_t delta;
131  ssize_t sret;
132 
133  fhc->task = NULL;
134  GNUNET_assert (fhc->offset <= fhc->fsize);
135  delta = fhc->bsize;
136  if (fhc->fsize - fhc->offset < delta)
137  delta = fhc->fsize - fhc->offset;
138  sret = GNUNET_DISK_file_read (fhc->fh,
139  fhc->buffer,
140  delta);
141  if ((sret < 0) ||
142  (delta != (size_t) sret))
143  {
145  "read",
146  fhc->filename);
147  file_hash_finish (fhc,
148  NULL);
149  return;
150  }
151  gcry_md_write (fhc->md,
152  fhc->buffer,
153  delta);
154  fhc->offset += delta;
155  if (fhc->offset == fhc->fsize)
156  {
157  res = (struct GNUNET_HashCode *) gcry_md_read (fhc->md,
158  GCRY_MD_SHA512);
159  file_hash_finish (fhc, res);
160  return;
161  }
164  fhc);
165 }
166 
167 
170  const char *filename,
171  size_t blocksize,
173  void *callback_cls)
174 {
175  struct GNUNET_CRYPTO_FileHashContext *fhc;
176 
177  GNUNET_assert (blocksize > 0);
178  fhc =
179  GNUNET_malloc (sizeof(struct GNUNET_CRYPTO_FileHashContext) + blocksize);
180  fhc->callback = callback;
181  fhc->callback_cls = callback_cls;
182  fhc->buffer = (unsigned char *) &fhc[1];
184  if (GPG_ERR_NO_ERROR != gcry_md_open (&fhc->md, GCRY_MD_SHA512, 0))
185  {
186  GNUNET_break (0);
187  GNUNET_free (fhc->filename);
188  GNUNET_free (fhc);
189  return NULL;
190  }
191  fhc->bsize = blocksize;
192  if (GNUNET_OK !=
194  &fhc->fsize,
195  GNUNET_NO,
196  GNUNET_YES))
197  {
198  GNUNET_free (fhc->filename);
199  GNUNET_free (fhc);
200  return NULL;
201  }
205  if (! fhc->fh)
206  {
207  GNUNET_free (fhc->filename);
208  GNUNET_free (fhc);
209  return NULL;
210  }
211  fhc->priority = priority;
214  fhc);
215  return fhc;
216 }
217 
218 
224 void
226 {
228  GNUNET_free (fhc->filename);
230  GNUNET_DISK_file_close (fhc->fh));
231  gcry_md_close (fhc->md);
232  GNUNET_free (fhc);
233 }
234 
235 
236 /* end of crypto_hash_file.c */
static void file_hash_task(void *cls)
File hashing task.
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.
#define LOG_STRERROR_FILE(kind, syscall, filename)
static int res
static char * filename
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:1237
enum GNUNET_GenericReturnValue 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:221
enum GNUNET_GenericReturnValue GNUNET_DISK_handle_invalid(const struct GNUNET_DISK_FileHandle *h)
Checks whether a handle is invalid.
Definition: disk.c:185
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1308
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:622
@ GNUNET_DISK_OPEN_READ
Open the file for reading.
@ GNUNET_DISK_PERM_NONE
Nobody is allowed to do anything to the file.
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.
void(* GNUNET_CRYPTO_HashCompletedCallback)(void *cls, const struct GNUNET_HashCode *res)
Function called once the hash computation over the specified file has completed.
void GNUNET_CRYPTO_hash_file_cancel(struct GNUNET_CRYPTO_FileHashContext *fhc)
Cancel a file hashing operation.
GNUNET_SCHEDULER_Priority
Valid task priorities.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_WARNING
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
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:1226
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:36
Context used when hashing a file.
uint64_t fsize
Size of the file.
gcry_md_hd_t md
Cummulated hash.
unsigned char * buffer
IO buffer.
GNUNET_CRYPTO_HashCompletedCallback callback
Function to call upon completion.
struct GNUNET_DISK_FileHandle * fh
File descriptor.
void * callback_cls
Closure for callback.
uint64_t offset
Current offset.
struct GNUNET_SCHEDULER_Task * task
Current task for hashing.
char * filename
Name of the file we are hashing.
enum GNUNET_SCHEDULER_Priority priority
Priority we use.
Handle used to access files (and pipes).
A 512-bit hashcode.
Entry in list of pending tasks.
Definition: scheduler.c:136