~ubuntu-branches/ubuntu/quantal/gnupg2/quantal-proposed

« back to all changes in this revision

Viewing changes to common/estream.c

  • Committer: Bazaar Package Importer
  • Author(s): Marc Deslauriers
  • Date: 2011-05-25 14:27:35 UTC
  • mfrom: (1.1.15 upstream) (7.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20110525142735-jccyw0fopnyv728q
Tags: 2.0.17-2ubuntu1
* Merge from debian unstable. Remaining changes:
  - Add udev rules to give gpg access to some smartcard readers;
    Debian #543217.
    . debian/gnupg2.dev: udev rules to set ACLs on SCM smartcard readers.
    . debian/rules: Call dh_installudev.
  - debian/control: Rename Vcs-* to XS-Debian-Vcs-*.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* estream.c - Extended Stream I/O Library
2
 
 * Copyright (C) 2004, 2005, 2006, 2007, 2009 g10 Code GmbH
 
2
 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010 g10 Code GmbH
3
3
 *
4
4
 * This file is part of Libestream.
5
5
 *
15
15
 *
16
16
 * You should have received a copy of the GNU General Public License
17
17
 * along with Libestream; if not, see <http://www.gnu.org/licenses/>.
 
18
 *
 
19
 * ALTERNATIVELY, Libestream may be distributed under the terms of the
 
20
 * following license, in which case the provisions of this license are
 
21
 * required INSTEAD OF the GNU General Public License. If you wish to
 
22
 * allow use of your version of this file only under the terms of the
 
23
 * GNU General Public License, and not to allow others to use your
 
24
 * version of this file under the terms of the following license,
 
25
 * indicate your decision by deleting this paragraph and the license
 
26
 * below.
 
27
 *
 
28
 * Redistribution and use in source and binary forms, with or without
 
29
 * modification, are permitted provided that the following conditions
 
30
 * are met:
 
31
 * 1. Redistributions of source code must retain the above copyright
 
32
 *    notice, and the entire permission notice in its entirety,
 
33
 *    including the disclaimer of warranties.
 
34
 * 2. Redistributions in binary form must reproduce the above copyright
 
35
 *    notice, this list of conditions and the following disclaimer in the
 
36
 *    documentation and/or other materials provided with the distribution.
 
37
 * 3. The name of the author may not be used to endorse or promote
 
38
 *    products derived from this software without specific prior
 
39
 *    written permission.
 
40
 *
 
41
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 
42
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
43
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
44
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 
45
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
46
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
47
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 
49
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
50
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 
51
 * OF THE POSSIBILITY OF SUCH DAMAGE.
18
52
 */
19
53
 
20
54
#ifdef USE_ESTREAM_SUPPORT_H
27
61
 
28
62
#if defined(_WIN32) && !defined(HAVE_W32_SYSTEM)
29
63
# define HAVE_W32_SYSTEM 1
 
64
# if defined(__MINGW32CE__) && !defined (HAVE_W32CE_SYSTEM)
 
65
#  define HAVE_W32CE_SYSTEM
 
66
# endif
30
67
#endif
31
68
 
32
69
#include <sys/types.h>
44
81
#ifdef HAVE_W32_SYSTEM
45
82
# include <windows.h>
46
83
#endif
 
84
#ifdef HAVE_W32CE_SYSTEM
 
85
# include <gpg-error.h> /* ERRNO replacement.  */
 
86
#endif
47
87
 
48
88
#ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth.  */
49
89
# undef HAVE_PTH
76
116
#define O_BINARY 0
77
117
#endif
78
118
 
 
119
#ifdef HAVE_W32CE_SYSTEM
 
120
# define _set_errno(a)  gpg_err_set_errno ((a))
 
121
/* Setmode is missing in cegcc but available since CE 5.0.  */
 
122
int _setmode (int handle, int mode);
 
123
# define setmode(a,b)   _setmode ((a),(b))
 
124
#else
 
125
# define _set_errno(a)  do { errno = (a); } while (0)
 
126
#endif
 
127
 
 
128
#ifdef HAVE_W32_SYSTEM
 
129
# define IS_INVALID_FD(a) ((void*)(a) == (void*)(-1))
 
130
#else
 
131
# define IS_INVALID_FD(a) ((a) == -1)
 
132
#endif
 
133
 
 
134
 
79
135
/* Generally used types.  */
80
136
 
81
137
typedef void *(*func_realloc_t) (void *mem, size_t size);
134
190
#ifdef HAVE_PTH
135
191
# define ESTREAM_SYS_READ  es_pth_read
136
192
# define ESTREAM_SYS_WRITE es_pth_write
 
193
# define ESTREAM_SYS_YIELD() pth_yield (NULL)
137
194
#else
138
195
# define ESTREAM_SYS_READ  read
139
196
# define ESTREAM_SYS_WRITE write
 
197
# define ESTREAM_SYS_YIELD() do { } while (0)
140
198
#endif
141
199
 
142
200
/* Misc definitions.  */
153
211
  void *cookie;                  /* Cookie.                */
154
212
  void *opaque;                  /* Opaque data.           */
155
213
  unsigned int modeflags;        /* Flags for the backend. */
 
214
  char *printable_fname;         /* Malloced filename for es_fname_get.  */
156
215
  off_t offset;
157
216
  es_cookie_read_function_t func_read;
158
217
  es_cookie_write_function_t func_write;
166
225
    unsigned int eof: 1;
167
226
  } indicators;
168
227
  unsigned int deallocate_buffer: 1;
 
228
  unsigned int is_stdstream:1;   /* This is a standard stream.  */
 
229
  unsigned int stdstream_fd:2;   /* 0, 1 or 2 for a standard stream.  */
169
230
  unsigned int print_err: 1;     /* Error in print_fun_writer.  */
 
231
  unsigned int printable_fname_inuse: 1;  /* es_fname_get has been used.  */
170
232
  int print_errno;               /* Errno from print_fun_writer.  */
171
233
  size_t print_ntotal;           /* Bytes written from in print_fun_writer. */
172
234
  FILE *print_fp;                /* Stdio stream used by print_fun_writer.  */
196
258
#define ESTREAM_LIST_LOCK   ESTREAM_MUTEX_LOCK   (estream_list_lock)
197
259
#define ESTREAM_LIST_UNLOCK ESTREAM_MUTEX_UNLOCK (estream_list_lock)
198
260
 
 
261
/* File descriptors registered to be used as the standard file handles. */
 
262
static int custom_std_fds[3];
 
263
static unsigned char custom_std_fds_valid[3];
 
264
 
 
265
 
199
266
#ifndef EOPNOTSUPP
200
267
# define EOPNOTSUPP ENOSYS
201
268
#endif
202
269
 
203
270
 
 
271
/* Local prototypes.  */
 
272
static void fname_set_internal (estream_t stream, const char *fname, int quote);
 
273
 
 
274
 
 
275
 
204
276
 
205
 
 
206
277
/* Macros.  */
207
278
 
208
279
/* Calculate array dimension.  */
255
326
 * List manipulation.
256
327
 */
257
328
 
258
 
/* Add STREAM to the list of registered stream objects.  */
 
329
/* Add STREAM to the list of registered stream objects.  If
 
330
   WITH_LOCKED_LIST is true we assumed that the list of streams is
 
331
   already locked.  */
259
332
static int
260
 
es_list_add (estream_t stream)
 
333
es_list_add (estream_t stream, int with_locked_list)
261
334
{
262
335
  estream_list_t list_obj;
263
336
  int ret;
267
340
    ret = -1;
268
341
  else
269
342
    {
270
 
      ESTREAM_LIST_LOCK;
 
343
      if (!with_locked_list)
 
344
        ESTREAM_LIST_LOCK;
271
345
      list_obj->car = stream;
272
346
      list_obj->cdr = estream_list;
273
347
      list_obj->prev_cdr = &estream_list;
274
348
      if (estream_list)
275
349
        estream_list->prev_cdr = &list_obj->cdr;
276
350
      estream_list = list_obj;
277
 
      ESTREAM_LIST_UNLOCK;
 
351
      if (!with_locked_list)
 
352
        ESTREAM_LIST_UNLOCK;
278
353
      ret = 0;
279
354
    }
280
355
 
283
358
 
284
359
/* Remove STREAM from the list of registered stream objects.  */
285
360
static void
286
 
es_list_remove (estream_t stream)
 
361
es_list_remove (estream_t stream, int with_locked_list)
287
362
{
288
363
  estream_list_t list_obj;
289
364
  
290
 
  ESTREAM_LIST_LOCK;
 
365
  if (!with_locked_list)
 
366
    ESTREAM_LIST_LOCK;
291
367
  for (list_obj = estream_list; list_obj; list_obj = list_obj->cdr)
292
368
    if (list_obj->car == stream)
293
369
      {
297
373
        mem_free (list_obj);
298
374
        break;
299
375
      }
300
 
  ESTREAM_LIST_UNLOCK;
 
376
  if (!with_locked_list)
 
377
    ESTREAM_LIST_UNLOCK;
301
378
}
302
379
 
303
380
/* Type of an stream-iterator-function.  */
360
437
 
361
438
 
362
439
 
 
440
static void
 
441
es_deinit (void)
 
442
{
 
443
  /* Flush all streams. */
 
444
  es_fflush (NULL);
 
445
}
 
446
 
 
447
 
363
448
/*
364
449
 * Initialization.
365
450
 */
367
452
static int
368
453
es_init_do (void)
369
454
{
370
 
#ifdef HAVE_PTH
371
455
  static int initialized;
372
456
 
373
457
  if (!initialized)
374
458
    {
 
459
#ifdef HAVE_PTH
375
460
      if (!pth_init () && errno != EPERM )
376
461
        return -1;
377
462
      if (pth_mutex_init (&estream_list_lock))
378
463
        initialized = 1;
 
464
#else
 
465
      initialized = 1;
 
466
#endif
 
467
      atexit (es_deinit);  
379
468
    }
380
 
#endif
381
469
  return 0;
382
470
}
383
471
 
427
515
 
428
516
  if (!data && (data_n || data_len))
429
517
    {
430
 
      errno = EINVAL;
 
518
      _set_errno (EINVAL);
431
519
      return -1;
432
520
    }
433
521
 
511
599
        newsize = mem_cookie->memory_size + (nleft - size);
512
600
      if (newsize < mem_cookie->offset)
513
601
        {
514
 
          errno = EINVAL;
 
602
          _set_errno (EINVAL);
515
603
          return -1;
516
604
        }
517
605
 
522
610
          newsize += mem_cookie->block_size - 1;
523
611
          if (newsize < mem_cookie->offset)
524
612
            {
525
 
              errno = EINVAL;
 
613
              _set_errno (EINVAL);
526
614
              return -1;
527
615
            }
528
616
          newsize /= mem_cookie->block_size;
532
620
      /* Check for a total limit.  */
533
621
      if (mem_cookie->memory_limit && newsize > mem_cookie->memory_limit)
534
622
        {
535
 
          errno = ENOSPC;
 
623
          _set_errno (ENOSPC);
536
624
          return -1;
537
625
        }
538
626
      
581
669
      break;
582
670
 
583
671
    default:
584
 
      errno = EINVAL;
 
672
      _set_errno (EINVAL);
585
673
      return -1;
586
674
    }
587
675
 
592
680
 
593
681
      if (!mem_cookie->flags.grow)
594
682
        {
595
 
          errno = ENOSPC;
 
683
          _set_errno (ENOSPC);
596
684
          return -1;
597
685
        }
598
686
 
599
687
      newsize = pos_new + mem_cookie->block_size - 1;
600
688
      if (newsize < pos_new)
601
689
        {
602
 
          errno = EINVAL;
 
690
          _set_errno (EINVAL);
603
691
          return -1;
604
692
        }
605
693
      newsize /= mem_cookie->block_size;
607
695
 
608
696
      if (mem_cookie->memory_limit && newsize > mem_cookie->memory_limit)
609
697
        {
610
 
          errno = ENOSPC;
 
698
          _set_errno (ENOSPC);
611
699
          return -1;
612
700
        }
613
701
      
703
791
{
704
792
  estream_cookie_fd_t file_cookie = cookie;
705
793
  ssize_t bytes_read;
706
 
 
707
 
  do 
708
 
    bytes_read = ESTREAM_SYS_READ (file_cookie->fd, buffer, size);
709
 
  while (bytes_read == -1 && errno == EINTR);
 
794
  
 
795
  if (IS_INVALID_FD (file_cookie->fd))
 
796
    {
 
797
      ESTREAM_SYS_YIELD ();
 
798
      bytes_read = 0;
 
799
    }
 
800
  else
 
801
    {
 
802
      do 
 
803
        bytes_read = ESTREAM_SYS_READ (file_cookie->fd, buffer, size);
 
804
      while (bytes_read == -1 && errno == EINTR);
 
805
    }
710
806
 
711
807
  return bytes_read;
712
808
}
714
810
/* Write function for fd objects.  */
715
811
static ssize_t
716
812
es_func_fd_write (void *cookie, const void *buffer, size_t size)
717
 
                           
718
813
{
719
814
  estream_cookie_fd_t file_cookie = cookie;
720
815
  ssize_t bytes_written;
721
816
 
722
 
  do
723
 
    bytes_written = ESTREAM_SYS_WRITE (file_cookie->fd, buffer, size);
724
 
  while (bytes_written == -1 && errno == EINTR);
 
817
  if (IS_INVALID_FD (file_cookie->fd))
 
818
    {
 
819
      ESTREAM_SYS_YIELD ();
 
820
      bytes_written = size; /* Yeah:  Success writing to the bit bucket.  */
 
821
    }
 
822
  else
 
823
    {
 
824
      do
 
825
        bytes_written = ESTREAM_SYS_WRITE (file_cookie->fd, buffer, size);
 
826
      while (bytes_written == -1 && errno == EINTR);
 
827
    }
725
828
 
726
829
  return bytes_written;
727
830
}
734
837
  off_t offset_new;
735
838
  int err;
736
839
 
737
 
  offset_new = lseek (file_cookie->fd, *offset, whence);
738
 
  if (offset_new == -1)
739
 
    err = -1;
 
840
  if (IS_INVALID_FD (file_cookie->fd))
 
841
    {
 
842
      _set_errno (ESPIPE);
 
843
      err = -1;
 
844
    }
740
845
  else
741
846
    {
742
 
      *offset = offset_new;
743
 
      err = 0;
 
847
      offset_new = lseek (file_cookie->fd, *offset, whence);
 
848
      if (offset_new == -1)
 
849
        err = -1;
 
850
      else
 
851
        {
 
852
          *offset = offset_new;
 
853
          err = 0;
 
854
        }
744
855
    }
745
856
 
746
857
  return err;
755
866
 
756
867
  if (fd_cookie)
757
868
    {
758
 
      err = fd_cookie->no_close? 0 : close (fd_cookie->fd);
 
869
      if (IS_INVALID_FD (fd_cookie->fd))
 
870
        err = 0;
 
871
      else
 
872
        err = fd_cookie->no_close? 0 : close (fd_cookie->fd);
759
873
      mem_free (fd_cookie);
760
874
    }
761
875
  else
822
936
  estream_cookie_fp_t file_cookie = cookie;
823
937
  ssize_t bytes_read;
824
938
 
825
 
  bytes_read = fread (buffer, 1, size, file_cookie->fp);
 
939
  if (file_cookie->fp)
 
940
    bytes_read = fread (buffer, 1, size, file_cookie->fp);
 
941
  else
 
942
    bytes_read = 0;
826
943
  if (!bytes_read && ferror (file_cookie->fp))
827
944
    return -1;
828
945
  return bytes_read;
836
953
  estream_cookie_fp_t file_cookie = cookie;
837
954
  size_t bytes_written;
838
955
 
839
 
  bytes_written = fwrite (buffer, 1, size, file_cookie->fp);
 
956
 
 
957
  if (file_cookie->fp)
 
958
    bytes_written = fwrite (buffer, 1, size, file_cookie->fp);
 
959
  else
 
960
    bytes_written = size; /* Successfully written to the bit bucket.  */
840
961
  if (bytes_written != size)
841
962
    return -1;
842
963
  return bytes_written;
849
970
  estream_cookie_fp_t file_cookie = cookie;
850
971
  long int offset_new;
851
972
 
 
973
  if (!file_cookie->fp)
 
974
    {
 
975
      _set_errno (ESPIPE);
 
976
      return -1; 
 
977
    }
 
978
 
852
979
  if ( fseek (file_cookie->fp, (long int)*offset, whence) )
853
980
    {
854
 
      fprintf (stderr, "\nfseek failed: errno=%d (%s)\n", errno,strerror (errno));
855
 
    return -1;
 
981
      /* fprintf (stderr, "\nfseek failed: errno=%d (%s)\n", */
 
982
      /*          errno,strerror (errno)); */
 
983
      return -1;
856
984
    }
857
985
 
858
986
  offset_new = ftell (file_cookie->fp);
859
987
  if (offset_new == -1)
860
988
    {
861
 
      fprintf (stderr, "\nftell failed: errno=%d (%s)\n", errno,strerror (errno));
862
 
    return -1;
 
989
      /* fprintf (stderr, "\nftell failed: errno=%d (%s)\n",  */
 
990
      /*          errno,strerror (errno)); */
 
991
      return -1;
863
992
    }
864
993
  *offset = offset_new;
865
994
  return 0;
866
995
}
867
996
 
868
 
/* Destroy function for fd objects.  */
 
997
/* Destroy function for FILE* objects.  */
869
998
static int
870
999
es_func_fp_destroy (void *cookie)
871
1000
{
874
1003
 
875
1004
  if (fp_cookie)
876
1005
    {
877
 
      fflush (fp_cookie->fp);
878
 
      err = fp_cookie->no_close? 0 : fclose (fp_cookie->fp);
 
1006
      if (fp_cookie->fp)
 
1007
        {
 
1008
          fflush (fp_cookie->fp);
 
1009
          err = fp_cookie->no_close? 0 : fclose (fp_cookie->fp);
 
1010
        }
 
1011
      else
 
1012
        err = 0;
879
1013
      mem_free (fp_cookie);
880
1014
    }
881
1015
  else
942
1076
  return err;
943
1077
}
944
1078
 
945
 
static es_cookie_io_functions_t estream_functions_file =
946
 
  {
947
 
    es_func_fd_read,
948
 
    es_func_fd_write,
949
 
    es_func_fd_seek,
950
 
    es_func_fd_destroy
951
 
  };
952
 
 
953
1079
 
954
1080
static int
955
1081
es_convert_mode (const char *mode, unsigned int *modeflags)
971
1097
      oflags = O_APPEND | O_CREAT;
972
1098
      break;
973
1099
    default:
974
 
      errno = EINVAL;
 
1100
      _set_errno (EINVAL);
975
1101
      return -1;
976
1102
    }
977
1103
  for (mode++; *mode; mode++)
1010
1136
 
1011
1137
  if (!stream->intern->func_read)
1012
1138
    {
1013
 
      errno = EOPNOTSUPP;
 
1139
      _set_errno (EOPNOTSUPP);
1014
1140
      err = -1;
1015
1141
    }
1016
1142
  else
1144
1270
  stream->intern->print_fp = NULL;
1145
1271
  stream->intern->indicators.err = 0;
1146
1272
  stream->intern->indicators.eof = 0;
 
1273
  stream->intern->is_stdstream = 0;
 
1274
  stream->intern->stdstream_fd = 0;
1147
1275
  stream->intern->deallocate_buffer = 0;
 
1276
  stream->intern->printable_fname = NULL;
 
1277
  stream->intern->printable_fname_inuse = 0;
1148
1278
 
1149
1279
  stream->data_len = 0;
1150
1280
  stream->data_offset = 0;
1152
1282
  stream->unread_data_len = 0;
1153
1283
  /* Depending on the modeflags we set whether we start in writing or
1154
1284
     reading mode.  This is required in case we are working on a
1155
 
     wronly stream which is not seeekable (like stdout).  Without this
 
1285
     stream which is not seeekable (like stdout).  Without this
1156
1286
     pre-initialization we would do a seek at the first write call and
1157
1287
     as this will fail no utput will be delivered. */
1158
1288
  if ((modeflags & O_WRONLY) || (modeflags & O_RDWR) )
1173
1303
      int save_errno = errno;
1174
1304
      fclose (stream->intern->print_fp);
1175
1305
      stream->intern->print_fp = NULL;
1176
 
      errno = save_errno;
 
1306
      _set_errno (save_errno);
1177
1307
    }
1178
1308
 
1179
1309
  func_close = stream->intern->func_close;
1184
1314
  if (func_close)
1185
1315
    SET_UNLESS_NONZERO (err, tmp_err, (*func_close) (stream->intern->cookie));
1186
1316
 
1187
 
  
 
1317
  mem_free (stream->intern->printable_fname);
 
1318
  stream->intern->printable_fname = NULL;
 
1319
  stream->intern->printable_fname_inuse = 0;
 
1320
 
1188
1321
  return err;
1189
1322
}
1190
1323
 
1191
1324
/* Create a new stream object, initialize it.  */
1192
1325
static int
1193
1326
es_create (estream_t *stream, void *cookie, int fd,
1194
 
           es_cookie_io_functions_t functions, unsigned int modeflags)
 
1327
           es_cookie_io_functions_t functions, unsigned int modeflags,
 
1328
           int with_locked_list)
1195
1329
{
1196
1330
  estream_internal_t stream_internal_new;
1197
1331
  estream_t stream_new;
1223
1357
  ESTREAM_MUTEX_INITIALIZE (stream_new->intern->lock);
1224
1358
  es_initialize (stream_new, cookie, fd, functions, modeflags);
1225
1359
 
1226
 
  err = es_list_add (stream_new);
 
1360
  err = es_list_add (stream_new, with_locked_list);
1227
1361
  if (err)
1228
1362
    goto out;
1229
1363
 
1245
1379
 
1246
1380
/* Deinitialize a stream object and destroy it.  */
1247
1381
static int
1248
 
es_destroy (estream_t stream)
 
1382
es_destroy (estream_t stream, int with_locked_list)
1249
1383
{
1250
1384
  int err = 0;
1251
1385
 
1252
1386
  if (stream)
1253
1387
    {
1254
 
      es_list_remove (stream);
 
1388
      es_list_remove (stream, with_locked_list);
1255
1389
      err = es_deinitialize (stream);
1256
1390
      mem_free (stream->intern);
1257
1391
      mem_free (stream);
1460
1594
 
1461
1595
  if (! func_seek)
1462
1596
    {
1463
 
      errno = EOPNOTSUPP;
 
1597
      _set_errno (EOPNOTSUPP);
1464
1598
      err = -1;
1465
1599
      goto out;
1466
1600
    }
1730
1864
 
1731
1865
  if (stream->data_offset + size > stream->data_len)
1732
1866
    {
1733
 
      errno = EINVAL;
 
1867
      _set_errno (EINVAL);
1734
1868
      err = -1;
1735
1869
    }
1736
1870
  else
1771
1905
    goto out;
1772
1906
 
1773
1907
  err = es_create (&line_stream, line_stream_cookie, -1,
1774
 
                   estream_functions_mem, O_RDWR);
 
1908
                   estream_functions_mem, O_RDWR, 0);
1775
1909
  if (err)
1776
1910
    goto out;
1777
1911
 
1856
1990
 out:
1857
1991
 
1858
1992
  if (line_stream)
1859
 
    es_destroy (line_stream);
 
1993
    es_destroy (line_stream, 0);
1860
1994
  else if (line_stream_cookie)
1861
1995
    es_func_mem_destroy (line_stream_cookie);
1862
1996
 
1961
2095
        buffer_new = buffer;
1962
2096
      else
1963
2097
        {
 
2098
          if (!size)
 
2099
            size = BUFSIZ;
1964
2100
          buffer_new = mem_alloc (size);
1965
2101
          if (! buffer_new)
1966
2102
            {
2053
2189
    goto out;
2054
2190
 
2055
2191
  create_called = 1;
2056
 
  err = es_create (&stream, cookie, fd, estream_functions_file, modeflags);
 
2192
  err = es_create (&stream, cookie, fd, estream_functions_fd, modeflags, 0);
2057
2193
  if (err)
2058
2194
    goto out;
2059
2195
 
 
2196
  if (stream && path)
 
2197
    fname_set_internal (stream, path, 1);
 
2198
 
2060
2199
 out:
2061
2200
  
2062
2201
  if (err && create_called)
2063
 
    (*estream_functions_file.func_close) (cookie);
 
2202
    (*estream_functions_fd.func_close) (cookie);
2064
2203
 
2065
2204
  return stream;
2066
2205
}
2093
2232
    goto out;
2094
2233
  
2095
2234
  create_called = 1;
2096
 
  err = es_create (&stream, cookie, -1, estream_functions_mem, modeflags);
 
2235
  err = es_create (&stream, cookie, -1, estream_functions_mem, modeflags, 0);
2097
2236
 
2098
2237
 out:
2099
2238
 
2124
2263
                          memlimit))
2125
2264
    return NULL;
2126
2265
  
2127
 
  if (es_create (&stream, cookie, -1, estream_functions_mem, modeflags))
 
2266
  if (es_create (&stream, cookie, -1, estream_functions_mem, modeflags, 0))
2128
2267
    (*estream_functions_mem.func_close) (cookie);
2129
2268
 
2130
2269
  return stream;
2148
2287
  if (err)
2149
2288
    goto out;
2150
2289
 
2151
 
  err = es_create (&stream, cookie, -1, functions, modeflags);
 
2290
  err = es_create (&stream, cookie, -1, functions, modeflags, 0);
2152
2291
  if (err)
2153
2292
    goto out;
2154
2293
 
2159
2298
 
2160
2299
 
2161
2300
estream_t
2162
 
do_fdopen (int filedes, const char *mode, int no_close)
 
2301
do_fdopen (int filedes, const char *mode, int no_close, int with_locked_list)
2163
2302
{
2164
2303
  unsigned int modeflags;
2165
2304
  int create_called;
2180
2319
    goto out;
2181
2320
 
2182
2321
  create_called = 1;
2183
 
  err = es_create (&stream, cookie, filedes, estream_functions_fd, modeflags);
 
2322
  err = es_create (&stream, cookie, filedes, estream_functions_fd,
 
2323
                   modeflags, with_locked_list);
2184
2324
 
2185
2325
 out:
2186
2326
 
2193
2333
estream_t
2194
2334
es_fdopen (int filedes, const char *mode)
2195
2335
{
2196
 
  return do_fdopen (filedes, mode, 0);
 
2336
  return do_fdopen (filedes, mode, 0, 0);
2197
2337
}
2198
2338
 
2199
2339
/* A variant of es_fdopen which does not close FILEDES at the end.  */
2200
2340
estream_t
2201
2341
es_fdopen_nc (int filedes, const char *mode)
2202
2342
{
2203
 
  return do_fdopen (filedes, mode, 1);
 
2343
  return do_fdopen (filedes, mode, 1, 0);
2204
2344
}
2205
2345
 
2206
2346
 
2207
2347
estream_t
2208
 
do_fpopen (FILE *fp, const char *mode, int no_close)
 
2348
do_fpopen (FILE *fp, const char *mode, int no_close, int with_locked_list)
2209
2349
{
2210
2350
  unsigned int modeflags;
2211
2351
  int create_called;
2221
2361
  if (err)
2222
2362
    goto out;
2223
2363
 
2224
 
  fflush (fp);
 
2364
  if (fp)
 
2365
    fflush (fp);
2225
2366
  err = es_func_fp_create (&cookie, fp, modeflags, no_close);
2226
2367
  if (err)
2227
2368
    goto out;
2228
 
 
 
2369
  
2229
2370
  create_called = 1;
2230
 
  err = es_create (&stream, cookie, fileno (fp), estream_functions_fp,
2231
 
                   modeflags);
 
2371
  err = es_create (&stream, cookie, fp? fileno (fp):-1, estream_functions_fp,
 
2372
                   modeflags, with_locked_list);
2232
2373
 
2233
2374
 out:
2234
2375
 
2250
2391
estream_t
2251
2392
es_fpopen (FILE *fp, const char *mode)
2252
2393
{
2253
 
  return do_fpopen (fp, mode, 0);
 
2394
  return do_fpopen (fp, mode, 0, 0);
2254
2395
}
2255
2396
 
2256
2397
 
2258
2399
estream_t
2259
2400
es_fpopen_nc (FILE *fp, const char *mode)
2260
2401
{
2261
 
  return do_fpopen (fp, mode, 1);
 
2402
  return do_fpopen (fp, mode, 1, 0);
 
2403
}
 
2404
 
 
2405
 
 
2406
/* Set custom standard descriptors to be used for stdin, stdout and
 
2407
   stderr.  This function needs to be called before any of the
 
2408
   standard streams are accessed.  */
 
2409
void
 
2410
_es_set_std_fd (int no, int fd)
 
2411
{
 
2412
  ESTREAM_LIST_LOCK;
 
2413
  if (no >= 0 && no < 3 && !custom_std_fds_valid[no])
 
2414
    {
 
2415
      custom_std_fds[no] = fd;
 
2416
      custom_std_fds_valid[no] = 1;
 
2417
    }
 
2418
  ESTREAM_LIST_UNLOCK;
 
2419
}
 
2420
 
 
2421
 
 
2422
/* Return the stream used for stdin, stdout or stderr.  */
 
2423
estream_t
 
2424
_es_get_std_stream (int fd)
 
2425
{
 
2426
  estream_list_t list_obj;
 
2427
  estream_t stream = NULL;
 
2428
 
 
2429
  fd %= 3; /* We only allow 0, 1 or 2 but we don't want to return an error. */
 
2430
  ESTREAM_LIST_LOCK;
 
2431
  for (list_obj = estream_list; list_obj; list_obj = list_obj->cdr)
 
2432
    if (list_obj->car->intern->is_stdstream
 
2433
        && list_obj->car->intern->stdstream_fd == fd)
 
2434
      {
 
2435
        stream = list_obj->car;
 
2436
        break;
 
2437
      }
 
2438
  if (!stream)
 
2439
    {
 
2440
      /* Standard stream not yet created.  We first try to create them
 
2441
         from registered file descriptors.  */
 
2442
      if (!fd && custom_std_fds_valid[0])
 
2443
        stream = do_fdopen (custom_std_fds[0], "r", 1, 1);
 
2444
      else if (fd == 1 && custom_std_fds_valid[1])
 
2445
        stream = do_fdopen (custom_std_fds[1], "a", 1, 1);
 
2446
      else if (custom_std_fds_valid[2])
 
2447
        stream = do_fdopen (custom_std_fds[2], "a", 1, 1);
 
2448
      
 
2449
      if (!stream)
 
2450
        {
 
2451
          /* Second try is to use the standard C streams.  */
 
2452
          if (!fd)
 
2453
            stream = do_fpopen (stdin, "r", 1, 1);
 
2454
          else if (fd == 1)
 
2455
            stream = do_fpopen (stdout, "a", 1, 1);
 
2456
          else
 
2457
            stream = do_fpopen (stderr, "a", 1, 1);
 
2458
        }
 
2459
      
 
2460
      if (!stream) 
 
2461
        {
 
2462
          /* Last try: Create a bit bucket.  */
 
2463
          stream = do_fpopen (NULL, fd? "a":"r", 0, 1);
 
2464
          if (!stream)
 
2465
            {
 
2466
              fprintf (stderr, "fatal: error creating a dummy estream"
 
2467
                       " for %d: %s\n", fd, strerror (errno));
 
2468
              abort();
 
2469
            }
 
2470
        }
 
2471
 
 
2472
      stream->intern->is_stdstream = 1;
 
2473
      stream->intern->stdstream_fd = fd;
 
2474
      if (fd == 2)
 
2475
        es_set_buffering (stream, NULL, _IOLBF, 0);
 
2476
      fname_set_internal (stream, 
 
2477
                          fd == 0? "[stdin]" :
 
2478
                          fd == 1? "[stdout]" : "[stderr]", 0);
 
2479
    }
 
2480
  ESTREAM_LIST_UNLOCK;
 
2481
  return stream;
2262
2482
}
2263
2483
 
2264
2484
 
2291
2511
        goto leave;
2292
2512
 
2293
2513
      create_called = 1;
2294
 
      es_initialize (stream, cookie, fd, estream_functions_file, modeflags);
 
2514
      es_initialize (stream, cookie, fd, estream_functions_fd, modeflags);
2295
2515
 
2296
2516
    leave:
2297
2517
 
2300
2520
          if (create_called)
2301
2521
            es_func_fd_destroy (cookie);
2302
2522
      
2303
 
          es_destroy (stream);
 
2523
          es_destroy (stream, 0);
2304
2524
          stream = NULL;
2305
2525
        }
2306
2526
      else
2307
 
        ESTREAM_UNLOCK (stream);
 
2527
        {
 
2528
          if (stream && path)
 
2529
            fname_set_internal (stream, path, 1);
 
2530
          ESTREAM_UNLOCK (stream);
 
2531
        }
2308
2532
    }
2309
2533
  else
2310
2534
    {
2311
2535
      /* FIXME?  We don't support re-opening at the moment.  */
2312
 
      errno = EINVAL;
 
2536
      _set_errno (EINVAL);
2313
2537
      es_deinitialize (stream);
2314
 
      es_destroy (stream);
 
2538
      es_destroy (stream, 0);
2315
2539
      stream = NULL;
2316
2540
    }
2317
2541
 
2324
2548
{
2325
2549
  int err;
2326
2550
 
2327
 
  err = es_destroy (stream);
 
2551
  err = es_destroy (stream, 0);
2328
2552
 
2329
2553
  return err;
2330
2554
}
2426
2650
}
2427
2651
 
2428
2652
 
 
2653
static int
 
2654
do_fflush (estream_t stream)
 
2655
{
 
2656
  int err;
 
2657
  
 
2658
  if (stream->flags.writing)
 
2659
    err = es_flush (stream);
 
2660
  else
 
2661
    {
 
2662
      es_empty (stream);
 
2663
      err = 0;
 
2664
    }
 
2665
 
 
2666
  return err;
 
2667
}
 
2668
 
 
2669
 
2429
2670
int
2430
2671
es_fflush (estream_t stream)
2431
2672
{
2434
2675
  if (stream)
2435
2676
    {
2436
2677
      ESTREAM_LOCK (stream);
2437
 
      if (stream->flags.writing)
2438
 
        err = es_flush (stream);
2439
 
      else
2440
 
        {
2441
 
          es_empty (stream);
2442
 
          err = 0;
2443
 
        }
 
2678
      err = do_fflush (stream);
2444
2679
      ESTREAM_UNLOCK (stream);
2445
2680
    }
2446
2681
  else
2447
 
    err = es_list_iterate (es_fflush);
 
2682
    err = es_list_iterate (do_fflush);
2448
2683
 
2449
2684
  return err ? EOF : 0;
2450
2685
}
2691
2926
 
2692
2927
 
2693
2928
int
 
2929
es_fputs_unlocked (const char *ES__RESTRICT s, estream_t ES__RESTRICT stream)
 
2930
{
 
2931
  size_t length;
 
2932
  int err;
 
2933
 
 
2934
  length = strlen (s);
 
2935
  err = es_writen (stream, s, length, NULL);
 
2936
  return err ? EOF : 0;
 
2937
}
 
2938
 
 
2939
int
2694
2940
es_fputs (const char *ES__RESTRICT s, estream_t ES__RESTRICT stream)
2695
2941
{
2696
2942
  size_t length;
2821
3067
    {
2822
3068
      /* This should never happen. If it does, the function has been
2823
3069
         called with wrong arguments. */
2824
 
      errno = EINVAL;
 
3070
      _set_errno (EINVAL);
2825
3071
      return -1;
2826
3072
    }
2827
3073
  length -= 3; /* Reserve 3 bytes for CR,LF,EOL. */
2855
3101
              if (max_length)
2856
3102
                *max_length = 0;
2857
3103
              ESTREAM_UNLOCK (stream);
2858
 
              errno = save_errno;
 
3104
              _set_errno (save_errno);
2859
3105
              return -1;
2860
3106
            }
2861
3107
          buffer = *addr_of_buffer;
2885
3131
 
2886
3132
 
2887
3133
int
 
3134
es_vfprintf_unlocked (estream_t ES__RESTRICT stream,
 
3135
                      const char *ES__RESTRICT format,
 
3136
                      va_list ap)
 
3137
{
 
3138
  return es_print (stream, format, ap);
 
3139
}
 
3140
 
 
3141
 
 
3142
int
2888
3143
es_vfprintf (estream_t ES__RESTRICT stream, const char *ES__RESTRICT format,
2889
3144
             va_list ap)
2890
3145
{
2898
3153
}
2899
3154
 
2900
3155
 
2901
 
static int
 
3156
int
2902
3157
es_fprintf_unlocked (estream_t ES__RESTRICT stream,
2903
 
           const char *ES__RESTRICT format, ...)
 
3158
                     const char *ES__RESTRICT format, ...)
2904
3159
{
2905
3160
  int ret;
2906
3161
  
2973
3228
{
2974
3229
#ifdef HAVE_W32_SYSTEM
2975
3230
  int attempts, n;
 
3231
#ifdef HAVE_W32CE_SYSTEM
 
3232
  wchar_t buffer[MAX_PATH+9+12+1];
 
3233
# define mystrlen(a) wcslen (a)
 
3234
  wchar_t *name, *p;
 
3235
#else
2976
3236
  char buffer[MAX_PATH+9+12+1];
 
3237
# define mystrlen(a) strlen (a)
2977
3238
  char *name, *p;
 
3239
#endif
2978
3240
  HANDLE file;
2979
3241
  int pid = GetCurrentProcessId ();
2980
3242
  unsigned int value;
2981
3243
  int i;
2982
3244
  
2983
3245
  n = GetTempPath (MAX_PATH+1, buffer);
2984
 
  if (!n || n > MAX_PATH || strlen (buffer) > MAX_PATH)
 
3246
  if (!n || n > MAX_PATH || mystrlen (buffer) > MAX_PATH)
2985
3247
    {
2986
 
      errno = ENOENT;
 
3248
      _set_errno (ENOENT);
2987
3249
      return -1;
2988
3250
    }
2989
 
  p = buffer + strlen (buffer);
 
3251
  p = buffer + mystrlen (buffer);
 
3252
#ifdef HAVE_W32CE_SYSTEM
 
3253
  wcscpy (p, L"_estream");
 
3254
#else
2990
3255
  strcpy (p, "_estream");
 
3256
#endif
2991
3257
  p += 8;
2992
3258
  /* We try to create the directory but don't care about an error as
2993
3259
     it may already exist and the CreateFile would throw an error
3004
3270
          *p++ = tohex (((value >> 28) & 0x0f));
3005
3271
          value <<= 4;
3006
3272
        }
 
3273
#ifdef HAVE_W32CE_SYSTEM
 
3274
      wcscpy (p, L".tmp");
 
3275
#else
3007
3276
      strcpy (p, ".tmp");
 
3277
#endif
3008
3278
      file = CreateFile (buffer,
3009
3279
                         GENERIC_READ | GENERIC_WRITE,
3010
3280
                         0,
3014
3284
                         NULL);
3015
3285
      if (file != INVALID_HANDLE_VALUE)
3016
3286
        {
 
3287
#ifdef HAVE_W32CE_SYSTEM
 
3288
          int fd = (int)file;
 
3289
#else
3017
3290
          int fd = _open_osfhandle ((long)file, 0);
3018
3291
          if (fd == -1)
3019
3292
            {
3020
3293
              CloseHandle (file);
3021
3294
              return -1;
3022
3295
            }
 
3296
#endif
3023
3297
          return fd;
3024
3298
        }
3025
3299
      Sleep (1); /* One ms as this is the granularity of GetTickCount.  */
3026
3300
    }
3027
 
  errno = ENOENT;
 
3301
  _set_errno (ENOENT);
3028
3302
  return -1;
3029
3303
#else /*!HAVE_W32_SYSTEM*/
3030
3304
  FILE *fp;
3077
3351
    goto out;
3078
3352
 
3079
3353
  create_called = 1;
3080
 
  err = es_create (&stream, cookie, fd, estream_functions_fd, modeflags);
 
3354
  err = es_create (&stream, cookie, fd, estream_functions_fd, modeflags, 0);
3081
3355
 
3082
3356
 out:
3083
3357
 
3100
3374
{
3101
3375
  int err;
3102
3376
  
3103
 
  if (((type == _IOFBF) || (type == _IOLBF) || (type == _IONBF))
3104
 
      && (! ((! size) && (type != _IONBF))))
 
3377
  if ((type == _IOFBF || type == _IOLBF || type == _IONBF)
 
3378
      && (!buf || size || type == _IONBF))
3105
3379
    {
3106
3380
      ESTREAM_LOCK (stream);
3107
3381
      err = es_set_buffering (stream, buf, type, size);
3109
3383
    }
3110
3384
  else
3111
3385
    {
3112
 
      errno = EINVAL;
 
3386
      _set_errno (EINVAL);
3113
3387
      err = -1;
3114
3388
    }
3115
3389
 
3146
3420
  return opaque;
3147
3421
}
3148
3422
 
 
3423
 
 
3424
static void
 
3425
fname_set_internal (estream_t stream, const char *fname, int quote)
 
3426
{
 
3427
  if (stream->intern->printable_fname
 
3428
      && !stream->intern->printable_fname_inuse)
 
3429
    {
 
3430
      mem_free (stream->intern->printable_fname);
 
3431
      stream->intern->printable_fname = NULL;
 
3432
    }
 
3433
  if (stream->intern->printable_fname)
 
3434
    return; /* Can't change because it is in use.  */
 
3435
 
 
3436
  if (*fname != '[')
 
3437
    quote = 0;
 
3438
  else
 
3439
    quote = !!quote;
 
3440
 
 
3441
  stream->intern->printable_fname = mem_alloc (strlen (fname) + quote + 1);
 
3442
  if (fname)
 
3443
    {
 
3444
      if (quote)
 
3445
        stream->intern->printable_fname[0] = '\\';
 
3446
      strcpy (stream->intern->printable_fname+quote, fname);
 
3447
    }
 
3448
}
 
3449
 
 
3450
 
 
3451
/* Set the filename attribute of STREAM.  There is no error return.
 
3452
   as long as STREAM is valid.  This function is called internally by
 
3453
   functions which open a filename.  */
 
3454
void
 
3455
es_fname_set (estream_t stream, const char *fname)
 
3456
{
 
3457
  if (fname)
 
3458
    {
 
3459
      ESTREAM_LOCK (stream);
 
3460
      fname_set_internal (stream, fname, 1);
 
3461
      ESTREAM_UNLOCK (stream);
 
3462
    }
 
3463
}
 
3464
 
 
3465
 
 
3466
/* Return the filename attribute of STREAM.  In case no filename has
 
3467
   been set, "[?]" will be returned.  The returned file name is valid
 
3468
   as long as STREAM is valid.  */
 
3469
const char *
 
3470
es_fname_get (estream_t stream)
 
3471
{
 
3472
  const char *fname;
 
3473
 
 
3474
  ESTREAM_LOCK (stream);
 
3475
  fname = stream->intern->printable_fname;
 
3476
  if (fname)
 
3477
    stream->intern->printable_fname_inuse = 1;
 
3478
  ESTREAM_UNLOCK (stream);
 
3479
  if (!fname)
 
3480
    fname = "[?]";
 
3481
  return fname;
 
3482
}
 
3483
 
 
3484
 
3149
3485
/* Print a BUFFER to STREAM while replacing all control characters and
3150
3486
   the characters in DELIMITERS by standard C escape sequences.
3151
3487
   Returns 0 on success or -1 on error.  If BYTES_WRITTEN is not NULL