~ubuntu-branches/ubuntu/karmic/gnupg2/karmic-updates

« back to all changes in this revision

Viewing changes to common/estream.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-10-04 10:25:53 UTC
  • mfrom: (5.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081004102553-fv62pp8dsitxli47
Tags: 2.0.9-3.1
* Non-maintainer upload.
* agent/gpg-agent.c: Deinit the threading library before exec'ing
  the command to run in --daemon mode. And because that still doesn't
  restore the sigprocmask, do that manually. Closes: #499569

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* estream.c - Extended stream I/O/ Library
2
 
   Copyright (C) 2004 g10 Code GmbH
3
 
 
4
 
   This file is part of Libestream.
5
 
 
6
 
   Libestream is free software; you can redistribute it and/or modify
7
 
   it under the terms of the GNU General Public License as published
8
 
   by the Free Software Foundation; either version 2 of the License,
9
 
   or (at your option) any later version.
10
 
 
11
 
   Libestream is distributed in the hope that it will be useful, but
12
 
   WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
   Lesser General Public License for more details.
15
 
 
16
 
   You should have received a copy of the GNU General Public License
17
 
   along with Libestream; if not, write to the Free Software
18
 
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19
 
   02111-1307, USA.  */
 
1
/* estream.c - Extended Stream I/O Library
 
2
 * Copyright (C) 2004, 2005, 2006, 2007 g10 Code GmbH
 
3
 *
 
4
 * This file is part of Libestream.
 
5
 *
 
6
 * Libestream is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published
 
8
 * by the Free Software Foundation; either version 2 of the License,
 
9
 * or (at your option) any later version.
 
10
 *
 
11
 * Libestream is distributed in the hope that it will be useful, but
 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
 * General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with Libestream; if not, see <http://www.gnu.org/licenses/>.
 
18
 */
20
19
 
21
20
#ifdef USE_ESTREAM_SUPPORT_H
22
21
# include <estream-support.h>
26
25
# include <config.h>
27
26
#endif
28
27
 
 
28
#if defined(_WIN32) && !defined(HAVE_W32_SYSTEM)
 
29
# define HAVE_W32_SYSTEM 1
 
30
#endif
 
31
 
29
32
#include <sys/types.h>
30
33
#include <sys/file.h>
31
34
#include <sys/stat.h>
 
35
#include <stdio.h>
32
36
#include <stdlib.h>
33
37
#include <string.h>
34
38
#include <unistd.h>
37
41
#include <errno.h>
38
42
#include <stddef.h>
39
43
#include <assert.h>
 
44
#ifdef HAVE_W32_SYSTEM
 
45
# include <windows.h>
 
46
#endif
 
47
 
 
48
#ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth.  */
 
49
# undef HAVE_PTH
 
50
# undef USE_GNU_PTH
 
51
#endif
40
52
 
41
53
#ifdef HAVE_PTH
 
54
# define PTH_SYSCALL_SOFT 0
42
55
# include <pth.h>
43
56
#endif
44
57
 
 
58
/* This is for the special hack to use estream.c in GnuPG.  */
 
59
#ifdef GNUPG_MAJOR_VERSION
 
60
# include "../common/util.h"
 
61
#endif
 
62
 
45
63
#ifndef HAVE_MKSTEMP
46
64
int mkstemp (char *template);
47
65
#endif
51
69
#endif
52
70
 
53
71
#include <estream.h>
 
72
#include <estream-printf.h>
54
73
 
55
74
 
56
75
 
 
76
#ifndef O_BINARY
 
77
#define O_BINARY 0
 
78
#endif
 
79
 
57
80
/* Generally used types.  */
58
81
 
59
82
typedef void *(*func_realloc_t) (void *mem, size_t size);
60
83
typedef void (*func_free_t) (void *mem);
61
84
 
 
85
 
62
86
 
63
87
 
64
88
/* Buffer management layer.  */
71
95
/* Macros.  */
72
96
 
73
97
#define BUFFER_ROUND_TO_BLOCK(size, block_size) \
74
 
  (((size) + (block_size - 1)) / block_size)
75
98
 
76
99
 
77
100
 
89
112
  ((pth_mutex_acquire (&(mutex), 1, NULL) == TRUE) ? 0 : -1)
90
113
# define ESTREAM_MUTEX_INITIALIZE(mutex)  \
91
114
  pth_mutex_init    (&(mutex))
92
 
# define ESTREAM_THREADING_INIT() ((pth_init () == TRUE) ? 0 : -1)
93
 
 
94
115
#else
95
116
 
96
117
typedef void *estream_mutex_t;
99
120
# define ESTREAM_MUTEX_UNLOCK(mutex) (void) 0
100
121
# define ESTREAM_MUTEX_TRYLOCK(mutex) 0
101
122
# define ESTREAM_MUTEX_INITIALIZE(mutex) (void) 0
102
 
# define ESTREAM_THREADING_INIT() 0
103
 
 
104
123
#endif
105
124
 
106
 
/* Memory allocator functions.  */
107
 
 
108
 
#define MEM_ALLOC   malloc
109
 
#define MEM_REALLOC realloc
110
 
#define MEM_FREE    free
111
 
 
112
125
/* Primitive system I/O.  */
113
126
 
114
127
#ifdef HAVE_PTH
123
136
 
124
137
#define ES_DEFAULT_OPEN_MODE (S_IRUSR | S_IWUSR)
125
138
 
126
 
#define ES_FLAG_WRITING ES__FLAG_WRITING
127
 
 
128
139
/* An internal stream object.  */
129
140
 
130
141
struct estream_internal
132
143
  unsigned char buffer[BUFFER_BLOCK_SIZE];
133
144
  unsigned char unread_buffer[BUFFER_UNREAD_SIZE];
134
145
  estream_mutex_t lock;          /* Lock. */
135
 
  void *cookie;                  /* Cookie.               */
136
 
  void *opaque;                  /* Opaque data.          */
137
 
  unsigned int flags;            /* Flags.                */
 
146
  void *cookie;                  /* Cookie.                */
 
147
  void *opaque;                  /* Opaque data.           */
 
148
  unsigned int modeflags;        /* Flags for the backend. */
138
149
  off_t offset;
139
150
  es_cookie_read_function_t func_read;
140
151
  es_cookie_write_function_t func_write;
148
159
    unsigned int eof: 1;
149
160
  } indicators;
150
161
  unsigned int deallocate_buffer: 1;
 
162
  unsigned int print_err: 1;     /* Error in print_fun_writer.  */
 
163
  int print_errno;               /* Errno from print_fun_writer.  */
 
164
  size_t print_ntotal;           /* Bytes written from in print_fun_writer. */
 
165
  FILE *print_fp;                /* Stdio stream used by print_fun_writer.  */
151
166
};
152
167
 
 
168
 
153
169
typedef struct estream_internal *estream_internal_t;
154
170
 
155
171
#define ESTREAM_LOCK(stream) ESTREAM_MUTEX_LOCK (stream->intern->lock)
169
185
 
170
186
static estream_list_t estream_list;
171
187
#ifdef HAVE_PTH
172
 
static estream_mutex_t estream_list_lock = ESTREAM_MUTEX_INITIALIZER;
 
188
/* Note that we can't use a static initialization with W32Pth, thus we
 
189
   do it in es_init. */
 
190
static estream_mutex_t estream_list_lock;
173
191
#endif
174
192
 
175
193
#define ESTREAM_LIST_LOCK   ESTREAM_MUTEX_LOCK   (estream_list_lock)
185
203
/* Macros.  */
186
204
 
187
205
/* Calculate array dimension.  */
 
206
#ifndef DIM
188
207
#define DIM(array) (sizeof (array) / sizeof (*array))
 
208
#endif
 
209
 
 
210
#define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
 
211
 
189
212
 
190
213
/* Evaluate EXPRESSION, setting VARIABLE to the return code, if
191
214
   VARIABLE is zero.  */
198
221
    }                                                          \
199
222
  while (0)
200
223
 
 
224
 
 
225
/* Malloc wrappers to overcvome problems on some older OSes.  */
 
226
static void *
 
227
mem_alloc (size_t n)
 
228
{
 
229
  if (!n)
 
230
    n++;
 
231
  return malloc (n);
 
232
}
 
233
 
 
234
static void *
 
235
mem_realloc (void *p, size_t n)
 
236
{
 
237
  if (!p)
 
238
    return mem_alloc (n);
 
239
  return realloc (p, n);
 
240
}
 
241
 
 
242
static void
 
243
mem_free (void *p)
 
244
{
 
245
  if (p)
 
246
    free (p);
 
247
}
 
248
 
 
249
 
 
250
 
201
251
/*
202
252
 * List manipulation.
203
253
 */
209
259
  estream_list_t list_obj;
210
260
  int ret;
211
261
 
212
 
  list_obj = MEM_ALLOC (sizeof (*list_obj));
 
262
  list_obj = mem_alloc (sizeof (*list_obj));
213
263
  if (! list_obj)
214
264
    ret = -1;
215
265
  else
241
291
        *list_obj->prev_cdr = list_obj->cdr;
242
292
        if (list_obj->cdr)
243
293
          list_obj->cdr->prev_cdr = list_obj->prev_cdr;
244
 
        MEM_FREE (list_obj);
 
294
        mem_free (list_obj);
245
295
        break;
246
296
      }
247
297
  ESTREAM_LIST_UNLOCK;
275
325
static int
276
326
es_init_do (void)
277
327
{
278
 
  int err;
279
 
 
280
 
  err = ESTREAM_THREADING_INIT ();
281
 
 
282
 
  return err;
 
328
#ifdef HAVE_PTH
 
329
  static int initialized;
 
330
 
 
331
  if (!initialized)
 
332
    {
 
333
      if (!pth_init () && errno != EPERM )
 
334
        return -1;
 
335
      if (pth_mutex_init (&estream_list_lock))
 
336
        initialized = 1;
 
337
    }
 
338
#endif
 
339
  return 0;
283
340
}
284
341
 
285
342
 
293
350
/* Cookie for memory objects.  */
294
351
typedef struct estream_cookie_mem
295
352
{
296
 
  unsigned int flags;           /* Open flags.  */
297
 
  unsigned char *memory;        /* Data.  */
298
 
  size_t memory_size;           /* Size of MEMORY.  */
 
353
  unsigned int modeflags;       /* Open flags.  */
 
354
  unsigned char *memory;        /* Allocated data buffer.  */
 
355
  size_t memory_size;           /* Allocated size of memory.  */
 
356
  size_t memory_limit;          /* Maximum allowed allocation size or
 
357
                                   0 for no limit.  */
299
358
  size_t offset;                /* Current offset in MEMORY.  */
300
359
  size_t data_len;              /* Length of data in MEMORY.  */
301
360
  size_t block_size;            /* Block size.  */
302
 
  unsigned int grow: 1;         /* MEMORY is allowed to grow.  */
303
 
  unsigned int append_zero: 1;  /* Append zero after data.  */
304
 
  unsigned int dont_free: 1;    /* Append zero after data.  */
305
 
  char **ptr;
306
 
  size_t *size;
 
361
  struct {
 
362
    unsigned int grow: 1;       /* MEMORY is allowed to grow.  */
 
363
  } flags;
307
364
  func_realloc_t func_realloc;
308
365
  func_free_t func_free;
309
366
} *estream_cookie_mem_t;
310
367
 
 
368
 
311
369
/* Create function for memory objects.  */
312
370
static int
313
371
es_func_mem_create (void *ES__RESTRICT *ES__RESTRICT cookie,
314
372
                    unsigned char *ES__RESTRICT data, size_t data_n,
315
373
                    size_t data_len,
316
374
                    size_t block_size, unsigned int grow,
317
 
                    unsigned int append_zero, unsigned int dont_free,
318
 
                    char **ptr, size_t *size,
319
375
                    func_realloc_t func_realloc, func_free_t func_free,
320
 
                    unsigned int flags)
 
376
                    unsigned int modeflags,
 
377
                    size_t memory_limit)
321
378
{
322
379
  estream_cookie_mem_t mem_cookie;
323
380
  int err;
324
381
 
325
 
  mem_cookie = MEM_ALLOC (sizeof (*mem_cookie));
326
 
  if (! mem_cookie)
 
382
  mem_cookie = mem_alloc (sizeof (*mem_cookie));
 
383
  if (!mem_cookie)
327
384
    err = -1;
328
385
  else
329
386
    {
330
 
      mem_cookie->flags = flags;
 
387
      mem_cookie->modeflags = modeflags;
331
388
      mem_cookie->memory = data;
332
389
      mem_cookie->memory_size = data_n;
 
390
      mem_cookie->memory_limit = memory_limit;
333
391
      mem_cookie->offset = 0;
334
392
      mem_cookie->data_len = data_len;
335
393
      mem_cookie->block_size = block_size;
336
 
      mem_cookie->grow = grow ? 1 : 0;
337
 
      mem_cookie->append_zero = append_zero ? 1 : 0;
338
 
      mem_cookie->dont_free = dont_free ? 1 : 0;
339
 
      mem_cookie->ptr = ptr;
340
 
      mem_cookie->size = size;
341
 
      mem_cookie->func_realloc = func_realloc ? func_realloc : MEM_REALLOC;
342
 
      mem_cookie->func_free = func_free ? func_free : MEM_FREE;
343
 
      mem_cookie->offset = 0;
 
394
      mem_cookie->flags.grow = !!grow;
 
395
      mem_cookie->func_realloc = func_realloc ? func_realloc : mem_realloc;
 
396
      mem_cookie->func_free = func_free ? func_free : mem_free;
344
397
      *cookie = mem_cookie;
345
398
      err = 0;
346
399
    }
348
401
  return err;
349
402
}
350
403
 
 
404
 
351
405
/* Read function for memory objects.  */
352
406
static ssize_t
353
407
es_func_mem_read (void *cookie, void *buffer, size_t size)
365
419
    }
366
420
  
367
421
  ret = size;
368
 
 
369
422
  return ret;
370
423
}
371
424
 
 
425
 
372
426
/* Write function for memory objects.  */
373
427
static ssize_t
374
428
es_func_mem_write (void *cookie, const void *buffer, size_t size)
375
429
{
376
430
  estream_cookie_mem_t mem_cookie = cookie;
377
 
  func_realloc_t func_realloc = mem_cookie->func_realloc;
378
 
  unsigned char *memory_new;
379
 
  size_t newsize;
380
431
  ssize_t ret;
381
 
  int err;
382
 
 
383
 
  if (size)
384
 
    {
385
 
      /* Regular write.  */
386
 
 
387
 
      if (mem_cookie->flags & O_APPEND)
388
 
        /* Append to data.  */
389
 
        mem_cookie->offset = mem_cookie->data_len;
390
 
          
391
 
      if (! mem_cookie->grow)
392
 
        if (size > mem_cookie->memory_size - mem_cookie->offset)
393
 
          size = mem_cookie->memory_size - mem_cookie->offset;
394
 
 
395
 
      err = 0;
396
 
 
397
 
      while (size > (mem_cookie->memory_size - mem_cookie->offset))
398
 
        {
399
 
          memory_new = (*func_realloc) (mem_cookie->memory,
400
 
                                        mem_cookie->memory_size
401
 
                                        + mem_cookie->block_size);
402
 
          if (! memory_new)
403
 
            {
404
 
              err = -1;
405
 
              break;
406
 
            }
407
 
          else
408
 
            {
409
 
              if (mem_cookie->memory != memory_new)
410
 
                mem_cookie->memory = memory_new;
411
 
              mem_cookie->memory_size += mem_cookie->block_size;
412
 
            }
413
 
        }
414
 
      if (err)
415
 
        goto out;
416
 
 
417
 
      if (size)
418
 
        {
419
 
          memcpy (mem_cookie->memory + mem_cookie->offset, buffer, size);
420
 
          if (mem_cookie->offset + size > mem_cookie->data_len)
421
 
            mem_cookie->data_len = mem_cookie->offset + size;
422
 
          mem_cookie->offset += size;
423
 
        }
424
 
    }
425
 
  else
426
 
    {
427
 
      /* Flush.  */
428
 
 
429
 
      err = 0;
430
 
      if (mem_cookie->append_zero)
431
 
        {
432
 
          if (mem_cookie->data_len >= mem_cookie->memory_size)
433
 
            {
434
 
              newsize = BUFFER_ROUND_TO_BLOCK (mem_cookie->data_len + 1,
435
 
                                               mem_cookie->block_size)
436
 
                * mem_cookie->block_size;
437
 
          
438
 
              memory_new = (*func_realloc) (mem_cookie->memory, newsize);
439
 
              if (! memory_new)
440
 
                {
441
 
                  err = -1;
442
 
                  goto out;
443
 
                }
444
 
 
445
 
              if (mem_cookie->memory != memory_new)
446
 
                mem_cookie->memory = memory_new;
447
 
              mem_cookie->memory_size = newsize;
448
 
            }
449
 
 
450
 
          mem_cookie->memory[mem_cookie->data_len + 1] = 0;
451
 
        }
452
 
 
453
 
      /* Return information to user if necessary.  */
454
 
      if (mem_cookie->ptr)
455
 
        *mem_cookie->ptr = (char *) mem_cookie->memory;
456
 
      if (mem_cookie->size)
457
 
        *mem_cookie->size = mem_cookie->data_len;
458
 
    }
459
 
 
460
 
 out:
461
 
 
462
 
  if (err)
463
 
    ret = -1;
464
 
  else
465
 
    ret = size;
466
 
 
 
432
 
 
433
  if (!size)
 
434
    return 0;  /* A flush is a NOP for memory objects.  */
 
435
 
 
436
  if (mem_cookie->modeflags & O_APPEND)
 
437
    {
 
438
      /* Append to data.  */
 
439
      mem_cookie->offset = mem_cookie->data_len;
 
440
    }
 
441
          
 
442
  if (!mem_cookie->flags.grow)
 
443
    {
 
444
      /* We are not alloew to grow, thus limit the size to the left
 
445
         space.  FIXME: Does the grow flag an its semtics make sense
 
446
         at all? */
 
447
      if (size > mem_cookie->memory_size - mem_cookie->offset)
 
448
        size = mem_cookie->memory_size - mem_cookie->offset;
 
449
    }
 
450
 
 
451
  if (size > (mem_cookie->memory_size - mem_cookie->offset))
 
452
    {
 
453
      unsigned char *newbuf;
 
454
      size_t newsize;
 
455
      
 
456
      newsize = mem_cookie->memory_size + mem_cookie->block_size;
 
457
      
 
458
      newsize = mem_cookie->offset + size;
 
459
      if (newsize < mem_cookie->offset)
 
460
        {
 
461
          errno = EINVAL;
 
462
          return -1;
 
463
        }
 
464
      newsize += mem_cookie->block_size - 1;
 
465
      if (newsize < mem_cookie->offset)
 
466
        {
 
467
          errno = EINVAL;
 
468
          return -1;
 
469
        }
 
470
      newsize /= mem_cookie->block_size;
 
471
      newsize *= mem_cookie->block_size;
 
472
      
 
473
      if (mem_cookie->memory_limit && newsize > mem_cookie->memory_limit)
 
474
        {
 
475
          errno = ENOSPC;
 
476
          return -1;
 
477
        }
 
478
      
 
479
      newbuf = mem_cookie->func_realloc (mem_cookie->memory, newsize);
 
480
      if (!newbuf)
 
481
        return -1;
 
482
      
 
483
      mem_cookie->memory = newbuf;
 
484
      mem_cookie->memory_size = newsize;
 
485
      
 
486
      assert (!(size > (mem_cookie->memory_size - mem_cookie->offset)));
 
487
    }
 
488
      
 
489
  memcpy (mem_cookie->memory + mem_cookie->offset, buffer, size);
 
490
  if (mem_cookie->offset + size > mem_cookie->data_len)
 
491
    mem_cookie->data_len = mem_cookie->offset + size;
 
492
  mem_cookie->offset += size;
 
493
 
 
494
  ret = size;
467
495
  return ret;
468
496
}
469
497
 
 
498
 
470
499
/* Seek function for memory objects.  */
471
500
static int
472
501
es_func_mem_seek (void *cookie, off_t *offset, int whence)
473
502
{
474
503
  estream_cookie_mem_t mem_cookie = cookie;
475
504
  off_t pos_new;
476
 
  int err = 0;
477
505
 
478
506
  switch (whence)
479
507
    {
490
518
      break;
491
519
 
492
520
    default:
493
 
      /* Never reached.  */
494
 
      pos_new = 0;
 
521
      errno = EINVAL;
 
522
      return -1;
495
523
    }
496
524
 
497
525
  if (pos_new > mem_cookie->memory_size)
498
526
    {
499
 
      /* Grow buffer if possible.  */
500
 
 
501
 
      if (mem_cookie->grow)
502
 
        {
503
 
          func_realloc_t func_realloc = mem_cookie->func_realloc;
504
 
          size_t newsize;
505
 
          void *p;
506
 
 
507
 
          newsize = BUFFER_ROUND_TO_BLOCK (pos_new, mem_cookie->block_size);
508
 
          p = (*func_realloc) (mem_cookie->memory, newsize);
509
 
          if (! p)
510
 
            {
511
 
              err = -1;
512
 
              goto out;
513
 
            }
514
 
          else
515
 
            {
516
 
              if (mem_cookie->memory != p)
517
 
                mem_cookie->memory = p;
518
 
              mem_cookie->memory_size = newsize;
519
 
            }
520
 
        }
521
 
      else
522
 
        {
523
 
          errno = EINVAL;
524
 
          err = -1;
525
 
          goto out;
526
 
        }
 
527
      size_t newsize;
 
528
      void *newbuf;
 
529
 
 
530
      if (!mem_cookie->flags.grow)
 
531
        {
 
532
          errno = ENOSPC;
 
533
          return -1;
 
534
 
 
535
        }
 
536
 
 
537
      newsize = pos_new + mem_cookie->block_size - 1;
 
538
      if (newsize < pos_new)
 
539
        {
 
540
          errno = EINVAL;
 
541
          return -1;
 
542
        }
 
543
      newsize /= mem_cookie->block_size;
 
544
      newsize *= mem_cookie->block_size;
 
545
      if (mem_cookie->memory_limit && newsize > mem_cookie->memory_limit)
 
546
        {
 
547
          errno = ENOSPC;
 
548
          return -1;
 
549
        }
 
550
      
 
551
      newbuf = mem_cookie->func_realloc (mem_cookie->memory, newsize);
 
552
      if (!newbuf)
 
553
        return -1;
 
554
 
 
555
      mem_cookie->memory = newbuf;
 
556
      mem_cookie->memory_size = newsize;
527
557
    }
528
558
 
529
559
  if (pos_new > mem_cookie->data_len)
530
 
    /* Fill spare space with zeroes.  */
531
 
    memset (mem_cookie->memory + mem_cookie->data_len,
532
 
            0, pos_new - mem_cookie->data_len);
 
560
    {
 
561
      /* Fill spare space with zeroes.  */
 
562
      memset (mem_cookie->memory + mem_cookie->data_len,
 
563
              0, pos_new - mem_cookie->data_len);
 
564
      mem_cookie->data_len = pos_new;
 
565
    }
533
566
 
534
567
  mem_cookie->offset = pos_new;
535
568
  *offset = pos_new;
536
569
 
537
 
 out:
538
 
 
539
 
  return err;
 
570
  return 0;
540
571
}
541
572
 
 
573
 
542
574
/* Destroy function for memory objects.  */
543
575
static int
544
576
es_func_mem_destroy (void *cookie)
545
577
{
546
578
  estream_cookie_mem_t mem_cookie = cookie;
547
 
  func_free_t func_free = mem_cookie->func_free;
548
 
 
549
 
  if (! mem_cookie->dont_free)
550
 
    (*func_free) (mem_cookie->memory);
551
 
  MEM_FREE (mem_cookie);
552
 
 
 
579
 
 
580
  if (cookie)
 
581
    {
 
582
      mem_cookie->func_free (mem_cookie->memory);
 
583
      mem_free (mem_cookie);
 
584
    }
553
585
  return 0;
554
586
}
555
587
 
 
588
 
556
589
static es_cookie_io_functions_t estream_functions_mem =
557
590
  {
558
591
    es_func_mem_read,
559
592
    es_func_mem_write,
560
593
    es_func_mem_seek,
561
 
    es_func_mem_destroy,
 
594
    es_func_mem_destroy
562
595
  };
563
596
 
 
597
 
 
598
 
564
599
/* Implementation of fd I/O.  */
565
600
 
566
601
/* Cookie for fd objects.  */
567
602
typedef struct estream_cookie_fd
568
603
{
569
 
  int fd;
 
604
  int fd;        /* The file descriptor we are using for actual output.  */
 
605
  int no_close;  /* If set we won't close the file descriptor.  */
570
606
} *estream_cookie_fd_t;
571
607
 
572
608
/* Create function for fd objects.  */
573
609
static int
574
 
es_func_fd_create (void **cookie, int fd, unsigned int flags)
 
610
es_func_fd_create (void **cookie, int fd, unsigned int modeflags, int no_close)
575
611
{
576
612
  estream_cookie_fd_t fd_cookie;
577
613
  int err;
578
614
 
579
 
  fd_cookie = MEM_ALLOC (sizeof (*fd_cookie));
 
615
  fd_cookie = mem_alloc (sizeof (*fd_cookie));
580
616
  if (! fd_cookie)
581
617
    err = -1;
582
618
  else
583
619
    {
 
620
#ifdef HAVE_DOSISH_SYSTEM
 
621
      /* Make sure it is in binary mode if requested.  */
 
622
      if ( (modeflags & O_BINARY) )
 
623
        setmode (fd, O_BINARY);
 
624
#endif
584
625
      fd_cookie->fd = fd;
 
626
      fd_cookie->no_close = no_close;
585
627
      *cookie = fd_cookie;
586
628
      err = 0;
587
629
    }
648
690
 
649
691
  if (fd_cookie)
650
692
    {
651
 
      err = close (fd_cookie->fd);
652
 
      MEM_FREE (fd_cookie);
 
693
      err = fd_cookie->no_close? 0 : close (fd_cookie->fd);
 
694
      mem_free (fd_cookie);
653
695
    }
654
696
  else
655
697
    err = 0;
657
699
  return err;
658
700
}
659
701
 
 
702
 
660
703
static es_cookie_io_functions_t estream_functions_fd =
661
704
  {
662
705
    es_func_fd_read,
665
708
    es_func_fd_destroy
666
709
  };
667
710
 
 
711
 
 
712
 
 
713
 
 
714
/* Implementation of FILE* I/O.  */
 
715
 
 
716
/* Cookie for fp objects.  */
 
717
typedef struct estream_cookie_fp
 
718
{
 
719
  FILE *fp;      /* The file pointer we are using for actual output.  */
 
720
  int no_close;  /* If set we won't close the file pointer.  */
 
721
} *estream_cookie_fp_t;
 
722
 
 
723
/* Create function for fd objects.  */
 
724
static int
 
725
es_func_fp_create (void **cookie, FILE *fp, unsigned int modeflags, int no_close)
 
726
{
 
727
  estream_cookie_fp_t fp_cookie;
 
728
  int err;
 
729
 
 
730
  fp_cookie = mem_alloc (sizeof *fp_cookie);
 
731
  if (!fp_cookie)
 
732
    err = -1;
 
733
  else
 
734
    {
 
735
#ifdef HAVE_DOSISH_SYSTEM
 
736
      /* Make sure it is in binary mode if requested.  */
 
737
      if ( (modeflags & O_BINARY) )
 
738
        setmode (fileno (fp), O_BINARY);
 
739
#endif
 
740
      fp_cookie->fp = fp;
 
741
      fp_cookie->no_close = no_close;
 
742
      *cookie = fp_cookie;
 
743
      err = 0;
 
744
    }
 
745
  
 
746
  return err;
 
747
}
 
748
 
 
749
/* Read function for FILE* objects.  */
 
750
static ssize_t
 
751
es_func_fp_read (void *cookie, void *buffer, size_t size)
 
752
 
 
753
{
 
754
  estream_cookie_fp_t file_cookie = cookie;
 
755
  ssize_t bytes_read;
 
756
 
 
757
  bytes_read = fread (buffer, 1, size, file_cookie->fp);
 
758
  if (!bytes_read && ferror (file_cookie->fp))
 
759
    return -1;
 
760
  return bytes_read;
 
761
}
 
762
 
 
763
/* Write function for FILE* objects.  */
 
764
static ssize_t
 
765
es_func_fp_write (void *cookie, const void *buffer, size_t size)
 
766
                           
 
767
{
 
768
  estream_cookie_fp_t file_cookie = cookie;
 
769
  size_t bytes_written;
 
770
 
 
771
  bytes_written = fwrite (buffer, 1, size, file_cookie->fp);
 
772
  if (bytes_written != size)
 
773
    return -1;
 
774
  return bytes_written;
 
775
}
 
776
 
 
777
/* Seek function for FILE* objects.  */
 
778
static int
 
779
es_func_fp_seek (void *cookie, off_t *offset, int whence)
 
780
{
 
781
  estream_cookie_fp_t file_cookie = cookie;
 
782
  long int offset_new;
 
783
 
 
784
  if ( fseek (file_cookie->fp, (long int)*offset, whence) )
 
785
    {
 
786
      fprintf (stderr, "\nfseek failed: errno=%d (%s)\n", errno,strerror (errno));
 
787
    return -1;
 
788
    }
 
789
 
 
790
  offset_new = ftell (file_cookie->fp);
 
791
  if (offset_new == -1)
 
792
    {
 
793
      fprintf (stderr, "\nftell failed: errno=%d (%s)\n", errno,strerror (errno));
 
794
    return -1;
 
795
    }
 
796
  *offset = offset_new;
 
797
  return 0;
 
798
}
 
799
 
 
800
/* Destroy function for fd objects.  */
 
801
static int
 
802
es_func_fp_destroy (void *cookie)
 
803
{
 
804
  estream_cookie_fp_t fp_cookie = cookie;
 
805
  int err;
 
806
 
 
807
  if (fp_cookie)
 
808
    {
 
809
      fflush (fp_cookie->fp);
 
810
      err = fp_cookie->no_close? 0 : fclose (fp_cookie->fp);
 
811
      mem_free (fp_cookie);
 
812
    }
 
813
  else
 
814
    err = 0;
 
815
 
 
816
  return err;
 
817
}
 
818
 
 
819
 
 
820
static es_cookie_io_functions_t estream_functions_fp =
 
821
  {
 
822
    es_func_fp_read,
 
823
    es_func_fp_write,
 
824
    es_func_fp_seek,
 
825
    es_func_fp_destroy
 
826
  };
 
827
 
 
828
 
 
829
 
 
830
 
668
831
/* Implementation of file I/O.  */
669
832
 
670
833
/* Create function for file objects.  */
671
834
static int
672
835
es_func_file_create (void **cookie, int *filedes,
673
 
                     const char *path, unsigned int flags)
 
836
                     const char *path, unsigned int modeflags)
674
837
{
675
838
  estream_cookie_fd_t file_cookie;
676
839
  int err;
679
842
  err = 0;
680
843
  fd = -1;
681
844
 
682
 
  file_cookie = MEM_ALLOC (sizeof (*file_cookie));
 
845
  file_cookie = mem_alloc (sizeof (*file_cookie));
683
846
  if (! file_cookie)
684
847
    {
685
848
      err = -1;
686
849
      goto out;
687
850
    }
688
851
 
689
 
  fd = open (path, flags, ES_DEFAULT_OPEN_MODE);
 
852
  fd = open (path, modeflags, ES_DEFAULT_OPEN_MODE);
690
853
  if (fd == -1)
691
854
    {
692
855
      err = -1;
693
856
      goto out;
694
857
    }
 
858
#ifdef HAVE_DOSISH_SYSTEM
 
859
  /* Make sure it is in binary mode if requested.  */
 
860
  if ( (modeflags & O_BINARY) )
 
861
    setmode (fd, O_BINARY);
 
862
#endif
695
863
 
696
864
  file_cookie->fd = fd;
 
865
  file_cookie->no_close = 0;
697
866
  *cookie = file_cookie;
698
867
  *filedes = fd;
699
868
 
700
869
 out:
701
870
 
702
871
  if (err)
703
 
    MEM_FREE (file_cookie);
 
872
    mem_free (file_cookie);
704
873
 
705
874
  return err;
706
875
}
718
887
/* Stream primitives.  */
719
888
 
720
889
static int
721
 
es_convert_mode (const char *mode, unsigned int *flags)
 
890
es_convert_mode (const char *mode, unsigned int *modeflags)
722
891
{
 
892
 
 
893
  /* FIXME: We need to allow all mode flags permutations.  */
723
894
  struct
724
895
  {
725
896
    const char *mode;
727
898
  } mode_flags[] = { { "r",
728
899
                       O_RDONLY },
729
900
                     { "rb",
730
 
                       O_RDONLY },
 
901
                       O_RDONLY | O_BINARY },
731
902
                     { "w",
732
903
                       O_WRONLY | O_TRUNC | O_CREAT },
733
904
                     { "wb",
734
 
                       O_WRONLY | O_TRUNC | O_CREAT },
 
905
                       O_WRONLY | O_TRUNC | O_CREAT | O_BINARY },
735
906
                     { "a",
736
907
                       O_WRONLY | O_APPEND | O_CREAT },
737
908
                     { "ab",
738
 
                       O_WRONLY | O_APPEND | O_CREAT },
 
909
                       O_WRONLY | O_APPEND | O_CREAT | O_BINARY },
739
910
                     { "r+",
740
911
                       O_RDWR },
741
912
                     { "rb+",
742
 
                       O_RDWR },
 
913
                       O_RDWR | O_BINARY },
743
914
                     { "r+b",
744
 
                       O_RDONLY | O_WRONLY },
 
915
                       O_RDONLY | O_WRONLY | O_BINARY },
745
916
                     { "w+",
746
917
                       O_RDWR | O_TRUNC | O_CREAT },
747
918
                     { "wb+",
748
 
                       O_RDWR | O_TRUNC | O_CREAT },
 
919
                       O_RDWR | O_TRUNC | O_CREAT | O_BINARY },
749
920
                     { "w+b",
750
 
                       O_RDWR | O_TRUNC | O_CREAT },
 
921
                       O_RDWR | O_TRUNC | O_CREAT | O_BINARY },
751
922
                     { "a+",
752
923
                       O_RDWR | O_CREAT | O_APPEND },
753
924
                     { "ab+",
754
 
                       O_RDWR | O_CREAT | O_APPEND },
 
925
                       O_RDWR | O_CREAT | O_APPEND | O_BINARY },
755
926
                     { "a+b",
756
 
                       O_RDWR | O_CREAT | O_APPEND } };
 
927
                       O_RDWR | O_CREAT | O_APPEND | O_BINARY }
 
928
  };
757
929
  unsigned int i;
758
930
  int err; 
759
931
 
768
940
  else
769
941
    {
770
942
      err = 0;
771
 
      *flags = mode_flags[i].flags;
 
943
      *modeflags = mode_flags[i].flags;
772
944
    }
773
945
 
774
946
  return err;
828
1000
  es_cookie_write_function_t func_write = stream->intern->func_write;
829
1001
  int err;
830
1002
 
831
 
  assert (stream->flags & ES_FLAG_WRITING);
 
1003
  assert (stream->flags.writing);
832
1004
 
833
1005
  if (stream->data_offset)
834
1006
    {
895
1067
static void
896
1068
es_empty (estream_t stream)
897
1069
{
898
 
  assert (! (stream->flags & ES_FLAG_WRITING));
 
1070
  assert (!stream->flags.writing);
899
1071
  stream->data_len = 0;
900
1072
  stream->data_offset = 0;
901
1073
  stream->unread_data_len = 0;
904
1076
/* Initialize STREAM.  */
905
1077
static void
906
1078
es_initialize (estream_t stream,
907
 
               void *cookie, int fd, es_cookie_io_functions_t functions)
 
1079
               void *cookie, int fd, es_cookie_io_functions_t functions,
 
1080
               unsigned int modeflags)
908
1081
{
909
1082
  stream->intern->cookie = cookie;
910
1083
  stream->intern->opaque = NULL;
915
1088
  stream->intern->func_close = functions.func_close;
916
1089
  stream->intern->strategy = _IOFBF;
917
1090
  stream->intern->fd = fd;
 
1091
  stream->intern->print_err = 0;
 
1092
  stream->intern->print_errno = 0;
 
1093
  stream->intern->print_ntotal = 0;
 
1094
  stream->intern->print_fp = NULL;
918
1095
  stream->intern->indicators.err = 0;
919
1096
  stream->intern->indicators.eof = 0;
920
1097
  stream->intern->deallocate_buffer = 0;
923
1100
  stream->data_offset = 0;
924
1101
  stream->data_flushed = 0;
925
1102
  stream->unread_data_len = 0;
926
 
  stream->flags = 0;
 
1103
  /* Depending on the modeflags we set whether we start in writing or
 
1104
     reading mode.  This is required in case we are working on a
 
1105
     wronly stream which is not seeekable (like stdout).  Without this
 
1106
     pre-initialization we would do a seek at the first write call and
 
1107
     as this will fail no utput will be delivered. */
 
1108
  if ((modeflags & O_WRONLY) || (modeflags & O_RDWR) )
 
1109
    stream->flags.writing = 1;
 
1110
  else
 
1111
    stream->flags.writing = 0;
927
1112
}
928
1113
 
929
1114
/* Deinitialize STREAM.  */
933
1118
  es_cookie_close_function_t func_close;
934
1119
  int err, tmp_err;
935
1120
 
 
1121
  if (stream->intern->print_fp)
 
1122
    {
 
1123
      int save_errno = errno;
 
1124
      fclose (stream->intern->print_fp);
 
1125
      stream->intern->print_fp = NULL;
 
1126
      errno = save_errno;
 
1127
    }
 
1128
 
936
1129
  func_close = stream->intern->func_close;
937
1130
 
938
1131
  err = 0;
939
 
  if (stream->flags & ES_FLAG_WRITING)
 
1132
  if (stream->flags.writing)
940
1133
    SET_UNLESS_NONZERO (err, tmp_err, es_flush (stream));
941
1134
  if (func_close)
942
1135
    SET_UNLESS_NONZERO (err, tmp_err, (*func_close) (stream->intern->cookie));
 
1136
 
943
1137
  
944
1138
  return err;
945
1139
}
947
1141
/* Create a new stream object, initialize it.  */
948
1142
static int
949
1143
es_create (estream_t *stream, void *cookie, int fd,
950
 
           es_cookie_io_functions_t functions)
 
1144
           es_cookie_io_functions_t functions, unsigned int modeflags)
951
1145
{
952
1146
  estream_internal_t stream_internal_new;
953
1147
  estream_t stream_new;
956
1150
  stream_new = NULL;
957
1151
  stream_internal_new = NULL;
958
1152
 
959
 
  stream_new = MEM_ALLOC (sizeof (*stream_new));
 
1153
  stream_new = mem_alloc (sizeof (*stream_new));
960
1154
  if (! stream_new)
961
1155
    {
962
1156
      err = -1;
963
1157
      goto out;
964
1158
    }
965
1159
 
966
 
  stream_internal_new = MEM_ALLOC (sizeof (*stream_internal_new));
 
1160
  stream_internal_new = mem_alloc (sizeof (*stream_internal_new));
967
1161
  if (! stream_internal_new)
968
1162
    {
969
1163
      err = -1;
977
1171
  stream_new->intern = stream_internal_new;
978
1172
 
979
1173
  ESTREAM_MUTEX_INITIALIZE (stream_new->intern->lock);
980
 
  es_initialize (stream_new, cookie, fd, functions);
 
1174
  es_initialize (stream_new, cookie, fd, functions, modeflags);
981
1175
 
982
1176
  err = es_list_add (stream_new);
983
1177
  if (err)
992
1186
      if (stream_new)
993
1187
        {
994
1188
          es_deinitialize (stream_new);
995
 
          MEM_FREE (stream_new);
 
1189
          mem_free (stream_new);
996
1190
        }
997
1191
    }
998
1192
 
1009
1203
    {
1010
1204
      es_list_remove (stream);
1011
1205
      err = es_deinitialize (stream);
1012
 
      MEM_FREE (stream->intern);
1013
 
      MEM_FREE (stream);
 
1206
      mem_free (stream->intern);
 
1207
      mem_free (stream);
1014
1208
    }
1015
1209
 
1016
1210
  return err;
1133
1327
  data_read = 0;
1134
1328
  err = 0;
1135
1329
 
1136
 
  if (stream->flags & ES_FLAG_WRITING)
 
1330
  if (stream->flags.writing)
1137
1331
    {
1138
1332
      /* Switching to reading mode -> flush output.  */
1139
1333
      err = es_flush (stream);
1140
1334
      if (err)
1141
1335
        goto out;
1142
 
      stream->flags &= ~ES_FLAG_WRITING;
 
1336
      stream->flags.writing = 0;
1143
1337
    }  
1144
1338
 
1145
1339
  /* Read unread data first.  */
1221
1415
      goto out;
1222
1416
    }
1223
1417
 
1224
 
  if (stream->flags & ES_FLAG_WRITING)
 
1418
  if (stream->flags.writing)
1225
1419
    {
1226
1420
      /* Flush data first in order to prevent flushing it to the wrong
1227
1421
         offset.  */
1228
1422
      err = es_flush (stream);
1229
1423
      if (err)
1230
1424
        goto out;
1231
 
      stream->flags &= ~ES_FLAG_WRITING;
 
1425
      stream->flags.writing = 0;
1232
1426
    }
1233
1427
 
1234
1428
  off = offset;
1398
1592
  data_written = 0;
1399
1593
  err = 0;
1400
1594
  
1401
 
  if (! (stream->flags & ES_FLAG_WRITING))
 
1595
  if (!stream->flags.writing)
1402
1596
    {
1403
1597
      /* Switching to writing mode -> discard input data and seek to
1404
 
         position at which reading has stopped.  */
1405
 
 
1406
 
      err = es_seek (stream, 0, SEEK_CUR, NULL);
1407
 
      if (err)
1408
 
        {
1409
 
          if (errno == ESPIPE)
1410
 
            err = 0;
1411
 
          else
1412
 
            goto out;
1413
 
        }
 
1598
         position at which reading has stopped.  We can do this only
 
1599
         if a seek function has been registered. */
 
1600
      if (stream->intern->func_seek)
 
1601
        {
 
1602
          err = es_seek (stream, 0, SEEK_CUR, NULL);
 
1603
          if (err)
 
1604
            {
 
1605
              if (errno == ESPIPE)
 
1606
                err = 0;
 
1607
              else
 
1608
                goto out;
 
1609
            }
 
1610
        }
1414
1611
    }
1415
1612
 
1416
1613
  switch (stream->intern->strategy)
1433
1630
  if (bytes_written)
1434
1631
    *bytes_written = data_written;
1435
1632
  if (data_written)
1436
 
    if (! (stream->flags & ES_FLAG_WRITING))
1437
 
      stream->flags |= ES_FLAG_WRITING;
 
1633
    if (!stream->flags.writing)
 
1634
      stream->flags.writing = 1;
1438
1635
 
1439
1636
  return err;
1440
1637
}
1446
1643
{
1447
1644
  int err;
1448
1645
 
1449
 
  if (stream->flags & ES_FLAG_WRITING)
 
1646
  if (stream->flags.writing)
1450
1647
    {
1451
1648
      /* Switching to reading mode -> flush output.  */
1452
1649
      err = es_flush (stream);
1453
1650
      if (err)
1454
1651
        goto out;
1455
 
      stream->flags &= ~ES_FLAG_WRITING;
 
1652
      stream->flags.writing = 0;
1456
1653
    }  
1457
1654
 
1458
1655
  if (stream->data_offset == stream->data_len)
1497
1694
 
1498
1695
 
1499
1696
static int
1500
 
es_read_line (estream_t ES__RESTRICT stream, size_t max_length,
1501
 
              char *ES__RESTRICT *ES__RESTRICT line,
1502
 
              size_t *ES__RESTRICT line_length)
 
1697
doreadline (estream_t ES__RESTRICT stream, size_t max_length,
 
1698
            char *ES__RESTRICT *ES__RESTRICT line,
 
1699
            size_t *ES__RESTRICT line_length)
1503
1700
{
1504
1701
  size_t space_left;
1505
1702
  size_t line_size;
1515
1712
  line_stream = NULL;
1516
1713
  line_stream_cookie = NULL;
1517
1714
 
1518
 
  err = es_func_mem_create (&line_stream_cookie, NULL, 0, 0, BUFFER_BLOCK_SIZE,
1519
 
                            1, 0, 0, NULL, 0, MEM_REALLOC, MEM_FREE, O_RDWR);
 
1715
  err = es_func_mem_create (&line_stream_cookie, NULL, 0, 0,
 
1716
                            BUFFER_BLOCK_SIZE, 1,
 
1717
                            mem_realloc, mem_free, 
 
1718
                            O_RDWR,
 
1719
                            0);
1520
1720
  if (err)
1521
1721
    goto out;
1522
1722
 
1523
1723
  err = es_create (&line_stream, line_stream_cookie, -1,
1524
 
                   estream_functions_mem);
 
1724
                   estream_functions_mem, O_RDWR);
1525
1725
  if (err)
1526
1726
    goto out;
1527
1727
 
1582
1782
 
1583
1783
  if (! *line)
1584
1784
    {
1585
 
      line_new = MEM_ALLOC (line_size + 1);
 
1785
      line_new = mem_alloc (line_size + 1);
1586
1786
      if (! line_new)
1587
1787
        {
1588
1788
          err = -1;
1613
1813
  if (err)
1614
1814
    {
1615
1815
      if (! *line)
1616
 
        MEM_FREE (line_new);
 
1816
        mem_free (line_new);
1617
1817
      stream->intern->indicators.err = 1;
1618
1818
    }
1619
1819
 
1621
1821
}
1622
1822
 
1623
1823
 
 
1824
/* Output fucntion used for estream_format.  */
 
1825
static int
 
1826
print_writer (void *outfncarg, const char *buf, size_t buflen)
 
1827
{
 
1828
  estream_t stream = outfncarg;
 
1829
  size_t nwritten;
 
1830
  int rc;
 
1831
 
 
1832
  nwritten = 0;
 
1833
  rc = es_writen (stream, buf, buflen, &nwritten);
 
1834
  stream->intern->print_ntotal += nwritten;
 
1835
  return rc;
 
1836
}
 
1837
 
 
1838
 
 
1839
/* The core of our printf function.  This is called in locked state. */
1624
1840
static int
1625
1841
es_print (estream_t ES__RESTRICT stream,
1626
1842
          const char *ES__RESTRICT format, va_list ap)
1627
1843
{
1628
 
  char data[BUFFER_BLOCK_SIZE];
1629
 
  size_t bytes_written;
1630
 
  size_t bytes_read;
1631
 
  FILE *tmp_stream;
1632
 
  int err;
1633
 
 
1634
 
  bytes_written = 0;
1635
 
  tmp_stream = NULL;
1636
 
  err = 0;
1637
 
  
1638
 
  tmp_stream = tmpfile ();
1639
 
  if (! tmp_stream)
1640
 
    {
1641
 
      err = errno;
1642
 
      goto out;
1643
 
    }
1644
 
 
1645
 
  err = vfprintf (tmp_stream, format, ap);
1646
 
  if (err < 0)
1647
 
    goto out;
1648
 
 
1649
 
  err = fseek (tmp_stream, 0, SEEK_SET);
1650
 
  if (err)
1651
 
    goto out;
1652
 
 
1653
 
  while (1)
1654
 
    {
1655
 
      bytes_read = fread (data, 1, sizeof (data), tmp_stream);
1656
 
      if (ferror (tmp_stream))
1657
 
        {
1658
 
          err = -1;
1659
 
          break;
1660
 
        }
1661
 
 
1662
 
      err = es_writen (stream, data, bytes_read, NULL);
1663
 
      if (err)
1664
 
        break;
1665
 
      else
1666
 
        bytes_written += bytes_read;
1667
 
      if (feof (tmp_stream))
1668
 
        break;
1669
 
    }
1670
 
  if (err)
1671
 
    goto out;
1672
 
 
1673
 
 out:
1674
 
 
1675
 
  if (tmp_stream)
1676
 
    fclose (tmp_stream);
1677
 
 
1678
 
  return err ? -1 : bytes_written;
 
1844
  int rc;
 
1845
 
 
1846
  stream->intern->print_ntotal = 0;
 
1847
  rc = estream_format (print_writer, stream, format, ap);
 
1848
  if (rc)
 
1849
    return -1;
 
1850
  return (int)stream->intern->print_ntotal;
1679
1851
}
1680
1852
 
1681
1853
 
1710
1882
  int err;
1711
1883
 
1712
1884
  /* Flush or empty buffer depending on mode.  */
1713
 
  if (stream->flags & ES_FLAG_WRITING)
 
1885
  if (stream->flags.writing)
1714
1886
    {
1715
1887
      err = es_flush (stream);
1716
1888
      if (err)
1725
1897
  if (stream->intern->deallocate_buffer)
1726
1898
    {
1727
1899
      stream->intern->deallocate_buffer = 0;
1728
 
      MEM_FREE (stream->buffer);
 
1900
      mem_free (stream->buffer);
1729
1901
      stream->buffer = NULL;
1730
1902
    }
1731
1903
 
1739
1911
        buffer_new = buffer;
1740
1912
      else
1741
1913
        {
1742
 
          buffer_new = MEM_ALLOC (size);
 
1914
          buffer_new = mem_alloc (size);
1743
1915
          if (! buffer_new)
1744
1916
            {
1745
1917
              err = -1;
1811
1983
estream_t
1812
1984
es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode)
1813
1985
{
1814
 
  unsigned int flags;
 
1986
  unsigned int modeflags;
1815
1987
  int create_called;
1816
1988
  estream_t stream;
1817
1989
  void *cookie;
1822
1994
  cookie = NULL;
1823
1995
  create_called = 0;
1824
1996
 
1825
 
  err = es_convert_mode (mode, &flags);
 
1997
  err = es_convert_mode (mode, &modeflags);
1826
1998
  if (err)
1827
1999
    goto out;
1828
2000
  
1829
 
  err = es_func_file_create (&cookie, &fd, path, flags);
 
2001
  err = es_func_file_create (&cookie, &fd, path, modeflags);
1830
2002
  if (err)
1831
2003
    goto out;
1832
2004
 
1833
2005
  create_called = 1;
1834
 
  err = es_create (&stream, cookie, fd, estream_functions_file);
 
2006
  err = es_create (&stream, cookie, fd, estream_functions_file, modeflags);
1835
2007
  if (err)
1836
2008
    goto out;
1837
2009
 
1850
2022
          func_realloc_t func_realloc, func_free_t func_free,
1851
2023
          const char *ES__RESTRICT mode)
1852
2024
{
1853
 
  unsigned int flags;
 
2025
  unsigned int modeflags;
1854
2026
  int create_called;
1855
2027
  estream_t stream;
1856
2028
  void *cookie;
1860
2032
  stream = NULL;
1861
2033
  create_called = 0;
1862
2034
  
1863
 
  err = es_convert_mode (mode, &flags);
 
2035
  err = es_convert_mode (mode, &modeflags);
1864
2036
  if (err)
1865
2037
    goto out;
1866
2038
 
1867
2039
  err = es_func_mem_create (&cookie, data, data_n, data_len,
1868
 
                            BUFFER_BLOCK_SIZE, grow, 0, 0,
1869
 
                            NULL, 0, func_realloc, func_free, flags);
 
2040
                            BUFFER_BLOCK_SIZE, grow, 
 
2041
                            func_realloc, func_free, modeflags, 0);
1870
2042
  if (err)
1871
2043
    goto out;
1872
2044
  
1873
2045
  create_called = 1;
1874
 
  err = es_create (&stream, cookie, -1, estream_functions_mem);
 
2046
  err = es_create (&stream, cookie, -1, estream_functions_mem, modeflags);
1875
2047
 
1876
2048
 out:
1877
2049
 
1883
2055
 
1884
2056
 
1885
2057
estream_t
1886
 
es_open_memstream (char **ptr, size_t *size)
 
2058
es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode)
1887
2059
{
1888
 
  unsigned int flags;
1889
 
  int create_called;
1890
 
  estream_t stream;
1891
 
  void *cookie;
1892
 
  int err;
1893
 
 
1894
 
  flags = O_RDWR;
1895
 
  create_called = 0;
1896
 
  stream = NULL;
1897
 
  cookie = 0;
1898
 
  
1899
 
  err = es_func_mem_create (&cookie, NULL, 0, 0,
1900
 
                            BUFFER_BLOCK_SIZE, 1, 1, 1,
1901
 
                            ptr, size, MEM_REALLOC, MEM_FREE, flags);
1902
 
  if (err)
1903
 
    goto out;
1904
 
  
1905
 
  create_called = 1;
1906
 
  err = es_create (&stream, cookie, -1, estream_functions_mem);
1907
 
 
1908
 
 out:
1909
 
 
1910
 
  if (err && create_called)
 
2060
  unsigned int modeflags;
 
2061
  estream_t stream = NULL;
 
2062
  void *cookie = NULL;
 
2063
 
 
2064
  /* Memory streams are always read/write.  We use MODE only to get
 
2065
     the append flag.  */
 
2066
  if (es_convert_mode (mode, &modeflags))
 
2067
    return NULL;
 
2068
  modeflags |= O_RDWR;
 
2069
 
 
2070
  
 
2071
  if (es_func_mem_create (&cookie, NULL, 0, 0,
 
2072
                          BUFFER_BLOCK_SIZE, 1,
 
2073
                          mem_realloc, mem_free, modeflags,
 
2074
                          memlimit))
 
2075
    return NULL;
 
2076
  
 
2077
  if (es_create (&stream, cookie, -1, estream_functions_mem, modeflags))
1911
2078
    (*estream_functions_mem.func_close) (cookie);
1912
2079
 
1913
2080
  return stream;
1914
2081
}
1915
2082
 
1916
2083
 
 
2084
 
1917
2085
estream_t
1918
2086
es_fopencookie (void *ES__RESTRICT cookie,
1919
2087
                const char *ES__RESTRICT mode,
1920
2088
                es_cookie_io_functions_t functions)
1921
2089
{
1922
 
  unsigned int flags;
 
2090
  unsigned int modeflags;
1923
2091
  estream_t stream;
1924
2092
  int err;
1925
2093
 
1926
2094
  stream = NULL;
1927
 
  flags = 0;
 
2095
  modeflags = 0;
1928
2096
  
1929
 
  err = es_convert_mode (mode, &flags);
1930
 
  if (err)
1931
 
    goto out;
1932
 
 
1933
 
  err = es_create (&stream, cookie, -1, functions);
1934
 
  if (err)
1935
 
    goto out;
1936
 
 
1937
 
 out:
1938
 
 
1939
 
  return stream;
1940
 
}
1941
 
 
 
2097
  err = es_convert_mode (mode, &modeflags);
 
2098
  if (err)
 
2099
    goto out;
 
2100
 
 
2101
  err = es_create (&stream, cookie, -1, functions, modeflags);
 
2102
  if (err)
 
2103
    goto out;
 
2104
 
 
2105
 out:
 
2106
 
 
2107
  return stream;
 
2108
}
 
2109
 
 
2110
 
 
2111
estream_t
 
2112
do_fdopen (int filedes, const char *mode, int no_close)
 
2113
{
 
2114
  unsigned int modeflags;
 
2115
  int create_called;
 
2116
  estream_t stream;
 
2117
  void *cookie;
 
2118
  int err;
 
2119
 
 
2120
  stream = NULL;
 
2121
  cookie = NULL;
 
2122
  create_called = 0;
 
2123
 
 
2124
  err = es_convert_mode (mode, &modeflags);
 
2125
  if (err)
 
2126
    goto out;
 
2127
 
 
2128
  err = es_func_fd_create (&cookie, filedes, modeflags, no_close);
 
2129
  if (err)
 
2130
    goto out;
 
2131
 
 
2132
  create_called = 1;
 
2133
  err = es_create (&stream, cookie, filedes, estream_functions_fd, modeflags);
 
2134
 
 
2135
 out:
 
2136
 
 
2137
  if (err && create_called)
 
2138
    (*estream_functions_fd.func_close) (cookie);
 
2139
 
 
2140
  return stream;
 
2141
}
1942
2142
 
1943
2143
estream_t
1944
2144
es_fdopen (int filedes, const char *mode)
1945
2145
{
1946
 
  unsigned int flags;
 
2146
  return do_fdopen (filedes, mode, 0);
 
2147
}
 
2148
 
 
2149
/* A variant of es_fdopen which does not close FILEDES at the end.  */
 
2150
estream_t
 
2151
es_fdopen_nc (int filedes, const char *mode)
 
2152
{
 
2153
  return do_fdopen (filedes, mode, 1);
 
2154
}
 
2155
 
 
2156
 
 
2157
estream_t
 
2158
do_fpopen (FILE *fp, const char *mode, int no_close)
 
2159
{
 
2160
  unsigned int modeflags;
1947
2161
  int create_called;
1948
2162
  estream_t stream;
1949
2163
  void *cookie;
1953
2167
  cookie = NULL;
1954
2168
  create_called = 0;
1955
2169
 
1956
 
  err = es_convert_mode (mode, &flags);
 
2170
  err = es_convert_mode (mode, &modeflags);
1957
2171
  if (err)
1958
2172
    goto out;
1959
2173
 
1960
 
  err = es_func_fd_create (&cookie, filedes, flags);
 
2174
  fflush (fp);
 
2175
  err = es_func_fp_create (&cookie, fp, modeflags, no_close);
1961
2176
  if (err)
1962
2177
    goto out;
1963
2178
 
1964
2179
  create_called = 1;
1965
 
  err = es_create (&stream, cookie, filedes, estream_functions_fd);
 
2180
  err = es_create (&stream, cookie, fileno (fp), estream_functions_fp,
 
2181
                   modeflags);
1966
2182
 
1967
2183
 out:
1968
2184
 
1969
2185
  if (err && create_called)
1970
 
    (*estream_functions_fd.func_close) (cookie);
 
2186
    (*estream_functions_fp.func_close) (cookie);
1971
2187
 
1972
2188
  return stream;
1973
2189
}
 
2190
 
1974
2191
  
 
2192
/* Create an estream from the stdio stream FP.  This mechanism is
 
2193
   useful in case the stdio streams have special properties and may
 
2194
   not be mixed with fd based functions.  This is for example the case
 
2195
   under Windows where the 3 standard streams are associated with the
 
2196
   console whereas a duped and fd-opened stream of one of this stream
 
2197
   won't be associated with the console.  As this messes things up it
 
2198
   is easier to keep on using the standard I/O stream as a backend for
 
2199
   estream. */
 
2200
estream_t
 
2201
es_fpopen (FILE *fp, const char *mode)
 
2202
{
 
2203
  return do_fpopen (fp, mode, 0);
 
2204
}
 
2205
 
 
2206
 
 
2207
/* Same as es_fpopen but does not close  FP at the end.  */
 
2208
estream_t
 
2209
es_fpopen_nc (FILE *fp, const char *mode)
 
2210
{
 
2211
  return do_fpopen (fp, mode, 1);
 
2212
}
 
2213
 
1975
2214
 
1976
2215
estream_t
1977
2216
es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
1981
2220
 
1982
2221
  if (path)
1983
2222
    {
1984
 
      unsigned int flags;
 
2223
      unsigned int modeflags;
1985
2224
      int create_called;
1986
2225
      void *cookie;
1987
2226
      int fd;
1993
2232
 
1994
2233
      es_deinitialize (stream);
1995
2234
 
1996
 
      err = es_convert_mode (mode, &flags);
 
2235
      err = es_convert_mode (mode, &modeflags);
1997
2236
      if (err)
1998
2237
        goto leave;
1999
2238
      
2000
 
      err = es_func_file_create (&cookie, &fd, path, flags);
 
2239
      err = es_func_file_create (&cookie, &fd, path, modeflags);
2001
2240
      if (err)
2002
2241
        goto leave;
2003
2242
 
2004
2243
      create_called = 1;
2005
 
      es_initialize (stream, cookie, fd, estream_functions_file);
 
2244
      es_initialize (stream, cookie, fd, estream_functions_file, modeflags);
2006
2245
 
2007
2246
    leave:
2008
2247
 
2145
2384
  if (stream)
2146
2385
    {
2147
2386
      ESTREAM_LOCK (stream);
2148
 
      if (stream->flags & ES_FLAG_WRITING)
 
2387
      if (stream->flags.writing)
2149
2388
        err = es_flush (stream);
2150
2389
      else
2151
2390
        {
2373
2612
 
2374
2613
 
2375
2614
char *
2376
 
es_fgets (char *ES__RESTRICT s, int n, estream_t ES__RESTRICT stream)
 
2615
es_fgets (char *ES__RESTRICT buffer, int length, estream_t ES__RESTRICT stream)
2377
2616
{
2378
 
  char *ret = NULL;
2379
 
  
2380
 
  if (n)
 
2617
  unsigned char *s = (unsigned char*)buffer;
 
2618
  int c;
 
2619
   
 
2620
  if (!length)
 
2621
    return NULL;
 
2622
     
 
2623
  c = EOF;
 
2624
  ESTREAM_LOCK (stream);
 
2625
  while (length > 1 && (c = es_getc_unlocked (stream)) != EOF && c != '\n')
2381
2626
    {
2382
 
      int err;
2383
 
      
2384
 
      ESTREAM_LOCK (stream);
2385
 
      err = es_read_line (stream, n, &s, NULL);
2386
 
      ESTREAM_UNLOCK (stream);
2387
 
      if (! err)
2388
 
        ret = s;
 
2627
      *s++ = c;
 
2628
      length--;
2389
2629
    }
2390
 
  
2391
 
  return ret;
 
2630
  ESTREAM_UNLOCK (stream);
 
2631
 
 
2632
  if (c == EOF && s == (unsigned char*)buffer)
 
2633
    return NULL; /* Nothing read.  */
 
2634
 
 
2635
  if (c != EOF && length > 1)
 
2636
    *s++ = c;
 
2637
 
 
2638
  *s = 0;
 
2639
  return buffer;
2392
2640
}
2393
2641
 
2394
2642
 
2416
2664
  int err;
2417
2665
 
2418
2666
  ESTREAM_LOCK (stream);
2419
 
  err = es_read_line (stream, 0, &line, &line_n);
 
2667
  err = doreadline (stream, 0, &line, &line_n);
2420
2668
  ESTREAM_UNLOCK (stream);
2421
2669
  if (err)
2422
2670
    goto out;
2431
2679
 
2432
2680
          void *p;
2433
2681
 
2434
 
          p = MEM_REALLOC (*lineptr, line_n + 1);
 
2682
          p = mem_realloc (*lineptr, line_n + 1);
2435
2683
          if (! p)
2436
2684
            err = -1;
2437
2685
          else
2447
2695
          if (*n != line_n)
2448
2696
            *n = line_n;
2449
2697
        }
2450
 
      MEM_FREE (line);
 
2698
      mem_free (line);
2451
2699
    }
2452
2700
  else
2453
2701
    {
2462
2710
}
2463
2711
 
2464
2712
 
 
2713
 
 
2714
/* Same as fgets() but if the provided buffer is too short a larger
 
2715
   one will be allocated.  This is similar to getline. A line is
 
2716
   considered a byte stream ending in a LF.
 
2717
 
 
2718
   If MAX_LENGTH is not NULL, it shall point to a value with the
 
2719
   maximum allowed allocation.  
 
2720
 
 
2721
   Returns the length of the line. EOF is indicated by a line of
 
2722
   length zero. A truncated line is indicated my setting the value at
 
2723
   MAX_LENGTH to 0.  If the returned value is less then 0 not enough
 
2724
   memory was enable or another error occurred; ERRNO is then set
 
2725
   accordingly.
 
2726
 
 
2727
   If a line has been truncated, the file pointer is moved forward to
 
2728
   the end of the line so that the next read starts with the next
 
2729
   line.  Note that MAX_LENGTH must be re-initialzied in this case.
 
2730
 
 
2731
   The caller initially needs to provide the address of a variable,
 
2732
   initialized to NULL, at ADDR_OF_BUFFER and don't change this value
 
2733
   anymore with the following invocations.  LENGTH_OF_BUFFER should be
 
2734
   the address of a variable, initialized to 0, which is also
 
2735
   maintained by this function.  Thus, both paramaters should be
 
2736
   considered the state of this function.
 
2737
 
 
2738
   Note: The returned buffer is allocated with enough extra space to
 
2739
   allow the caller to append a CR,LF,Nul.  The buffer should be
 
2740
   released using es_free.
 
2741
 */
 
2742
ssize_t
 
2743
es_read_line (estream_t stream, 
 
2744
              char **addr_of_buffer, size_t *length_of_buffer,
 
2745
              size_t *max_length)
 
2746
{
 
2747
  int c;
 
2748
  char  *buffer = *addr_of_buffer;
 
2749
  size_t length = *length_of_buffer;
 
2750
  size_t nbytes = 0;
 
2751
  size_t maxlen = max_length? *max_length : 0;
 
2752
  char *p;
 
2753
 
 
2754
  if (!buffer)
 
2755
    { 
 
2756
      /* No buffer given - allocate a new one. */
 
2757
      length = 256;
 
2758
      buffer = mem_alloc (length);
 
2759
      *addr_of_buffer = buffer;
 
2760
      if (!buffer)
 
2761
        {
 
2762
          *length_of_buffer = 0;
 
2763
          if (max_length)
 
2764
            *max_length = 0;
 
2765
          return -1;
 
2766
        }
 
2767
      *length_of_buffer = length;
 
2768
    }
 
2769
 
 
2770
  if (length < 4)
 
2771
    {
 
2772
      /* This should never happen. If it does, the function has been
 
2773
         called with wrong arguments. */
 
2774
      errno = EINVAL;
 
2775
      return -1;
 
2776
    }
 
2777
  length -= 3; /* Reserve 3 bytes for CR,LF,EOL. */
 
2778
 
 
2779
  ESTREAM_LOCK (stream);
 
2780
  p = buffer;
 
2781
  while  ((c = es_getc_unlocked (stream)) != EOF)
 
2782
    {
 
2783
      if (nbytes == length)
 
2784
        { 
 
2785
          /* Enlarge the buffer. */
 
2786
          if (maxlen && length > maxlen) 
 
2787
            {
 
2788
              /* We are beyond our limit: Skip the rest of the line. */
 
2789
              while (c != '\n' && (c=es_getc_unlocked (stream)) != EOF)
 
2790
                ;
 
2791
              *p++ = '\n'; /* Always append a LF (we reserved some space). */
 
2792
              nbytes++;
 
2793
              if (max_length)
 
2794
                *max_length = 0; /* Indicate truncation. */
 
2795
              break; /* the while loop. */
 
2796
            }
 
2797
          length += 3; /* Adjust for the reserved bytes. */
 
2798
          length += length < 1024? 256 : 1024;
 
2799
          *addr_of_buffer = mem_realloc (buffer, length);
 
2800
          if (!*addr_of_buffer)
 
2801
            {
 
2802
              int save_errno = errno;
 
2803
              mem_free (buffer); 
 
2804
              *length_of_buffer = *max_length = 0;
 
2805
              ESTREAM_UNLOCK (stream);
 
2806
              errno = save_errno;
 
2807
              return -1;
 
2808
            }
 
2809
          buffer = *addr_of_buffer;
 
2810
          *length_of_buffer = length;
 
2811
          length -= 3; 
 
2812
          p = buffer + nbytes;
 
2813
        }
 
2814
      *p++ = c;
 
2815
      nbytes++;
 
2816
      if (c == '\n')
 
2817
        break;
 
2818
    }
 
2819
  *p = 0; /* Make sure the line is a string. */
 
2820
  ESTREAM_UNLOCK (stream);
 
2821
 
 
2822
  return nbytes;
 
2823
}
 
2824
 
 
2825
/* Wrapper around free() to match the memory allocation system used
 
2826
   by estream.  Should be used for all buffers returned to the caller
 
2827
   by libestream. */
 
2828
void
 
2829
es_free (void *a)
 
2830
{
 
2831
  mem_free (a);
 
2832
}
 
2833
 
 
2834
 
2465
2835
int
2466
2836
es_vfprintf (estream_t ES__RESTRICT stream, const char *ES__RESTRICT format,
2467
2837
             va_list ap)
2476
2846
}
2477
2847
 
2478
2848
 
 
2849
static int
 
2850
es_fprintf_unlocked (estream_t ES__RESTRICT stream,
 
2851
           const char *ES__RESTRICT format, ...)
 
2852
{
 
2853
  int ret;
 
2854
  
 
2855
  va_list ap;
 
2856
  va_start (ap, format);
 
2857
  ret = es_print (stream, format, ap);
 
2858
  va_end (ap);
 
2859
 
 
2860
  return ret;
 
2861
}
 
2862
 
 
2863
 
2479
2864
int
2480
2865
es_fprintf (estream_t ES__RESTRICT stream,
2481
2866
            const char *ES__RESTRICT format, ...)
2492
2877
  return ret;
2493
2878
}
2494
2879
 
 
2880
 
2495
2881
static int
2496
2882
tmpfd (void)
2497
2883
{
 
2884
#ifdef HAVE_W32_SYSTEM
 
2885
  int attempts, n;
 
2886
  char buffer[MAX_PATH+9+12+1];
 
2887
  char *name, *p;
 
2888
  HANDLE file;
 
2889
  int pid = GetCurrentProcessId ();
 
2890
  unsigned int value;
 
2891
  int i;
 
2892
  
 
2893
  n = GetTempPath (MAX_PATH+1, buffer);
 
2894
  if (!n || n > MAX_PATH || strlen (buffer) > MAX_PATH)
 
2895
    {
 
2896
      errno = ENOENT;
 
2897
      return -1;
 
2898
    }
 
2899
  p = buffer + strlen (buffer);
 
2900
  strcpy (p, "_estream");
 
2901
  p += 8;
 
2902
  /* We try to create the directory but don't care about an error as
 
2903
     it may already exist and the CreateFile would throw an error
 
2904
     anyway.  */
 
2905
  CreateDirectory (buffer, NULL);
 
2906
  *p++ = '\\';
 
2907
  name = p;
 
2908
  for (attempts=0; attempts < 10; attempts++)
 
2909
    {
 
2910
      p = name;
 
2911
      value = (GetTickCount () ^ ((pid<<16) & 0xffff0000));
 
2912
      for (i=0; i < 8; i++)
 
2913
        {
 
2914
          *p++ = tohex (((value >> 28) & 0x0f));
 
2915
          value <<= 4;
 
2916
        }
 
2917
      strcpy (p, ".tmp");
 
2918
      file = CreateFile (buffer,
 
2919
                         GENERIC_READ | GENERIC_WRITE,
 
2920
                         0,
 
2921
                         NULL,
 
2922
                         CREATE_NEW,
 
2923
                         FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
 
2924
                         NULL);
 
2925
      if (file != INVALID_HANDLE_VALUE)
 
2926
        {
 
2927
          int fd = _open_osfhandle ((long)file, 0);
 
2928
          if (fd == -1)
 
2929
            {
 
2930
              CloseHandle (file);
 
2931
              return -1;
 
2932
            }
 
2933
          return fd;
 
2934
        }
 
2935
      Sleep (1); /* One ms as this is the granularity of GetTickCount.  */
 
2936
    }
 
2937
  errno = ENOENT;
 
2938
  return -1;
 
2939
#else /*!HAVE_W32_SYSTEM*/
2498
2940
  FILE *fp;
2499
2941
  int fp_fd;
2500
2942
  int fd;
2515
2957
    fclose (fp);
2516
2958
 
2517
2959
  return fd;
 
2960
#endif /*!HAVE_W32_SYSTEM*/
2518
2961
}
2519
2962
 
2520
2963
estream_t
2521
2964
es_tmpfile (void)
2522
2965
{
2523
 
  unsigned int flags;
 
2966
  unsigned int modeflags;
2524
2967
  int create_called;
2525
2968
  estream_t stream;
2526
2969
  void *cookie;
2529
2972
 
2530
2973
  create_called = 0;
2531
2974
  stream = NULL;
2532
 
  flags = O_RDWR | O_TRUNC | O_CREAT;
 
2975
  modeflags = O_RDWR | O_TRUNC | O_CREAT;
2533
2976
  cookie = NULL;
2534
2977
  
2535
2978
  fd = tmpfd ();
2539
2982
      goto out;
2540
2983
    }
2541
2984
 
2542
 
  err = es_func_fd_create (&cookie, fd, flags);
 
2985
  err = es_func_fd_create (&cookie, fd, modeflags, 0);
2543
2986
  if (err)
2544
2987
    goto out;
2545
2988
 
2546
2989
  create_called = 1;
2547
 
  err = es_create (&stream, cookie, fd, estream_functions_fd);
 
2990
  err = es_create (&stream, cookie, fd, estream_functions_fd, modeflags);
2548
2991
 
2549
2992
 out:
2550
2993
 
2612
3055
 
2613
3056
  return opaque;
2614
3057
}
 
3058
 
 
3059
/* Print a BUFFER to STREAM while replacing all control characters and
 
3060
   the characters in DELIMITERS by standard C escape sequences.
 
3061
   Returns 0 on success or -1 on error.  If BYTES_WRITTEN is not NULL
 
3062
   the number of bytes actually written are stored at this
 
3063
   address.  */
 
3064
int 
 
3065
es_write_sanitized (estream_t ES__RESTRICT stream,
 
3066
                    const void * ES__RESTRICT buffer, size_t length,
 
3067
                    const char * delimiters, 
 
3068
                    size_t * ES__RESTRICT bytes_written)
 
3069
{
 
3070
  const unsigned char *p = buffer;
 
3071
  size_t count = 0;
 
3072
  int ret;
 
3073
 
 
3074
  ESTREAM_LOCK (stream);
 
3075
  for (; length; length--, p++, count++)
 
3076
    {
 
3077
      if (*p < 0x20 
 
3078
          || (*p >= 0x7f && *p < 0xa0)
 
3079
          || (delimiters 
 
3080
              && (strchr (delimiters, *p) || *p == '\\')))
 
3081
        {
 
3082
          es_putc_unlocked ('\\', stream);
 
3083
          count++;
 
3084
          if (*p == '\n')
 
3085
            {
 
3086
              es_putc_unlocked ('n', stream);
 
3087
              count++;
 
3088
            }
 
3089
          else if (*p == '\r')
 
3090
            {
 
3091
              es_putc_unlocked ('r', stream);
 
3092
              count++;
 
3093
            }
 
3094
          else if (*p == '\f')
 
3095
            {
 
3096
              es_putc_unlocked ('f', stream);
 
3097
              count++;
 
3098
            }
 
3099
          else if (*p == '\v')
 
3100
            {
 
3101
              es_putc_unlocked ('v', stream);
 
3102
              count++;
 
3103
            }
 
3104
          else if (*p == '\b')
 
3105
            {
 
3106
              es_putc_unlocked ('b', stream);
 
3107
              count++;
 
3108
            }
 
3109
          else if (!*p)
 
3110
            {
 
3111
              es_putc_unlocked('0', stream);
 
3112
              count++;
 
3113
            }
 
3114
          else
 
3115
            {
 
3116
              es_fprintf_unlocked (stream, "x%02x", *p);
 
3117
              count += 3;
 
3118
            }
 
3119
        }
 
3120
      else
 
3121
        {
 
3122
          es_putc_unlocked (*p, stream);
 
3123
          count++;
 
3124
        }
 
3125
    }
 
3126
 
 
3127
  if (bytes_written)
 
3128
    *bytes_written = count;
 
3129
  ret =  es_ferror_unlocked (stream)? -1 : 0;
 
3130
  ESTREAM_UNLOCK (stream);
 
3131
 
 
3132
  return ret;
 
3133
}
 
3134
 
 
3135
 
 
3136
/* Write LENGTH bytes of BUFFER to STREAM as a hex encoded string.
 
3137
   RESERVED must be 0.  Returns 0 on success or -1 on error.  If
 
3138
   BYTES_WRITTEN is not NULL the number of bytes actually written are
 
3139
   stored at this address.  */
 
3140
int
 
3141
es_write_hexstring (estream_t ES__RESTRICT stream,
 
3142
                    const void *ES__RESTRICT buffer, size_t length,
 
3143
                    int reserved, size_t *ES__RESTRICT bytes_written )
 
3144
{
 
3145
  int ret;
 
3146
  const unsigned char *s;
 
3147
  size_t count = 0;
 
3148
 
 
3149
#define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
 
3150
 
 
3151
  if (!length)
 
3152
    return 0;
 
3153
 
 
3154
  ESTREAM_LOCK (stream);
 
3155
 
 
3156
  for (s = buffer; length; s++, length--)
 
3157
    {
 
3158
      es_putc_unlocked ( tohex ((*s>>4)&15), stream);
 
3159
      es_putc_unlocked ( tohex (*s&15), stream);
 
3160
      count += 2;
 
3161
    }
 
3162
 
 
3163
  if (bytes_written)
 
3164
    *bytes_written = count;
 
3165
  ret = es_ferror_unlocked (stream)? -1 : 0;
 
3166
 
 
3167
  ESTREAM_UNLOCK (stream);
 
3168
 
 
3169
  return ret;
 
3170
 
 
3171
#undef tohex
 
3172
}
 
3173
 
 
3174
 
 
3175
 
 
3176
#ifdef GNUPG_MAJOR_VERSION
 
3177
/* Special estream function to print an UTF8 string in the native
 
3178
   encoding.  The interface is the same as es_write_sanitized, however
 
3179
   only one delimiter may be supported. 
 
3180
 
 
3181
   THIS IS NOT A STANDARD ESTREAM FUNCTION AND ONLY USED BY GNUPG!. */
 
3182
int
 
3183
es_write_sanitized_utf8_buffer (estream_t stream,
 
3184
                                const void *buffer, size_t length, 
 
3185
                                const char *delimiters, size_t *bytes_written)
 
3186
{
 
3187
  const char *p = buffer;
 
3188
  size_t i;
 
3189
 
 
3190
  /* We can handle plain ascii simpler, so check for it first. */
 
3191
  for (i=0; i < length; i++ ) 
 
3192
    {
 
3193
      if ( (p[i] & 0x80) )
 
3194
        break;
 
3195
    }
 
3196
  if (i < length)
 
3197
    {
 
3198
      int delim = delimiters? *delimiters : 0;
 
3199
      char *buf;
 
3200
      int ret;
 
3201
 
 
3202
      /*(utf8 conversion already does the control character quoting). */
 
3203
      buf = utf8_to_native (p, length, delim);
 
3204
      if (bytes_written)
 
3205
        *bytes_written = strlen (buf);
 
3206
      ret = es_fputs (buf, stream);
 
3207
      xfree (buf);
 
3208
      return i;
 
3209
    }
 
3210
  else
 
3211
    return es_write_sanitized (stream, p, length, delimiters, bytes_written);
 
3212
}
 
3213
#endif /*GNUPG_MAJOR_VERSION*/