io.c 3.63 KB
Newer Older
1
/* io.c
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

   Miscellaneous functions used by the example programs.

   Copyright (C) 2002, 2012 Niels Möller

   This file is part of GNU Nettle.

   GNU Nettle is free software: you can redistribute it and/or
   modify it under the terms of either:

     * the GNU Lesser General Public License as published by the Free
       Software Foundation; either version 3 of the License, or (at your
       option) any later version.

   or

     * the GNU General Public License as published by the Free
       Software Foundation; either version 2 of the License, or (at your
       option) any later version.

   or both in parallel, as here.

   GNU Nettle is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received copies of the GNU General Public License and
   the GNU Lesser General Public License along with this program.  If
   not, see http://www.gnu.org/licenses/.
*/
33 34 35

#if HAVE_CONFIG_H
# include "config.h"
36
#endif
37 38 39 40

#include <stdarg.h>
#include <stdlib.h>

41 42 43 44
/* For errno and strerror */
#include <errno.h>
#include <string.h>

45 46
#include "io.h"

47 48 49 50 51
#define RANDOM_DEVICE "/dev/urandom"
#define BUFSIZE 1000

int quiet_flag = 0;

Niels Möller's avatar
Niels Möller committed
52 53 54 55 56 57 58 59 60 61 62 63 64
void *
xalloc(size_t size)
{
  void *p = malloc(size);
  if (!p)
    {
      fprintf(stderr, "Virtual memory exhausted.\n");
      abort();
    }

  return p;
}

65 66 67 68 69 70 71 72 73 74 75 76
void
werror(const char *format, ...)
{
  if (!quiet_flag)
    {
      va_list args;
      va_start(args, format);
      vfprintf(stderr, format, args);
      va_end(args);
    }
}

77 78
size_t
read_file(const char *name, size_t max_size, uint8_t **contents)
79
{
80 81
  size_t size, done;
  uint8_t *buffer;
82 83 84 85
  FILE *f;
    
  f = fopen(name, "rb");
  if (!f)
86
    {
87
      werror("Opening `%s' failed: %s\n", name, strerror(errno));
88 89
      return 0;
    }
90

Niels Möller's avatar
Niels Möller committed
91
  size = 100;
92

Niels Möller's avatar
Niels Möller committed
93
  for (buffer = NULL, done = 0;; size *= 2)
94
    {
95
      uint8_t *p;
96

97
      if (max_size && size > max_size)
98 99 100
	size = max_size;

      /* Space for terminating NUL */
101
      p = realloc(buffer, size + 1);
102 103 104 105 106

      if (!p)
	{
	fail:
	  fclose(f);
107 108
	  free(buffer);
	  *contents = NULL;
109 110 111
	  return 0;
	}

112
      buffer = p;
113 114
      done += fread(buffer + done, 1, size - done, f);

Niels Möller's avatar
Niels Möller committed
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
      if (done < size)
	{
	  /* Short count means EOF or read error */
	  if (ferror(f))
	    {
	      fprintf (stderr, "Reading `%s' failed: %s\n",
		       name, strerror(errno));

	      goto fail;
	    }
	  if (done == 0)
	    /* Treat empty file as error */
	    goto fail;

	  break;
	}

      if (size == max_size)
	break;
134 135 136 137 138
    }
  
  fclose(f);

  /* NUL-terminate the data. */
139 140 141
  buffer[done] = '\0';
  *contents = buffer;
  
142 143 144 145
  return done;
}

int
146
write_data(FILE *f, size_t size, const void *buffer)
147
{
148
  size_t res = fwrite(buffer, 1, size, f);
149

150
  return res == size;
Niels Möller's avatar
Niels Möller committed
151 152 153
}

int
154
write_file(const char *name, size_t size, const void *buffer)
Niels Möller's avatar
Niels Möller committed
155
{
156 157 158 159 160
  FILE *f = fopen(name, "wb");
  int res;
  
  if (!f)
    return 0;
161

162
  res = write_data(f, size, buffer);
163
  return fclose(f) == 0 && res;
164 165 166 167 168 169
}

int
simple_random(struct yarrow256_ctx *ctx, const char *name)
{
  unsigned length;
170
  uint8_t *buffer;
171 172 173 174 175 176 177 178 179 180 181

  if (name)
    length = read_file(name, 0, &buffer);
  else
    length = read_file(RANDOM_DEVICE, 20, &buffer);
  
  if (!length)
    return 0;

  yarrow256_seed(ctx, length, buffer);

182 183
  free(buffer);

184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
  return 1;
}

int
hash_file(const struct nettle_hash *hash, void *ctx, FILE *f)
{
  for (;;)
    {
      char buffer[BUFSIZE];
      size_t res = fread(buffer, 1, sizeof(buffer), f);
      if (ferror(f))
	return 0;
      
      hash->update(ctx, res, buffer);
      if (feof(f))
	return 1;
    }
}