This file is indexed.

/usr/include/dcmtk/ofstd/offile.h is in libdcmtk2-dev 3.6.0-15+deb8u1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
/*
 *
 *  Copyright (C) 2006-2010, OFFIS e.V.
 *  All rights reserved.  See COPYRIGHT file for details.
 *
 *  This software and supporting documentation were developed by
 *
 *    OFFIS e.V.
 *    R&D Division Health
 *    Escherweg 2
 *    D-26121 Oldenburg, Germany
 *
 *
 *  Module:  ofstd
 *
 *  Author:  Marco Eichelberg
 *
 *  Purpose: C++ wrapper class for stdio FILE functions
 *
 *  Last Update:      $Author: joergr $
 *  Update Date:      $Date: 2010-12-17 10:50:30 $
 *  CVS/RCS Revision: $Revision: 1.17 $
 *  Status:           $State: Exp $
 *
 *  CVS/RCS Log at end of file
 *
 */

#ifndef OFFILE_H
#define OFFILE_H

#include "dcmtk/config/osconfig.h"
#include "dcmtk/ofstd/oftypes.h"    /* for class OFBool */
#include "dcmtk/ofstd/ofstring.h"   /* for class OFString */
#include "dcmtk/ofstd/ofstd.h"      /* for class OFStandard */

#define INCLUDE_UNISTD
#define INCLUDE_CSTDIO
#define INCLUDE_CSTRING
#define INCLUDE_CSTDARG
#define INCLUDE_CERRNO
//#define INCLUDE_CWCHAR    /* not yet implemented in "ofstdinc.h" */
#include "dcmtk/ofstd/ofstdinc.h"

BEGIN_EXTERN_C
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>       /* needed for struct _stati64 on Win32 */
#endif
END_EXTERN_C

/* HP-UX has clearerr both as macro and as a function definition. We have to
 * undef the macro so that we can define a function called "clearerr".
 */
#if defined(__hpux) && defined(clearerr)
#undef clearerr
#endif

/* When using the ISO C++ include files such as <cstdio>, <cstdarg> etc.,
 * all ANSI C functions like fopen() are declared in namespace std,
 * (e.g. we have to use std::fopen()), but non-ANSI Posix functions remain
 * in global namespace, e.g. we have to use ::fopen64().
 * To make things even more difficult, not all compilers really declare
 * ANSI C functions in namespace std in accordance with the C++ standard.
 * Yes, this is ugly.
 */

/* Find out whether current operating system needs explicit function calls
 * to handle large file support
 */
#ifdef _LARGEFILE64_SOURCE
  // Mac OS X defines _LARGEFILE64_SOURCE but anyhow expects implicit 64 bit calls.
  // The same is true for current Cygwin versions (tested with version 1.7.7-1).
  #if !(defined(__MACH__) && defined(__APPLE__)) && !defined(__CYGWIN__)
    #define EXPLICIT_LFS_64
  #endif
#endif

#if defined(_WIN32) && !defined(__MINGW32__)
  // On Win32 systems except MinGW (where Posix definitions are available)
  // we use Win32 specific definitions
  typedef __int64 offile_off_t;
  typedef fpos_t offile_fpos_t;
#else
  #ifdef EXPLICIT_LFS_64
    // Explicit LFS (LFS64)
    typedef fpos64_t offile_fpos_t;
    typedef off64_t offile_off_t;
  #else
    // Implicit LFS or no LFS
    #ifdef HAVE_FSEEKO
      typedef off_t offile_off_t;
    #else
      typedef long offile_off_t;
    #endif
    typedef fpos_t offile_fpos_t;
  #endif
#endif

// the type we use to store the last error.
typedef int offile_errno_t;

/** this class provides a simple C++ encapsulation layer for stdio FILE pointers.
 *  All stdio functions on files are directly mapped into member functions.
 *  The handling of large files (64 bit file systems) is transparent. Instead
 *  of type off_t, fseek() and ftell() use offile_off_t which is a 64 bit type
 *  if available on the underlying platform. Similarly, getpos() and setpos() use
 *  type offile_fpos_t, which is defined appropriately.
 *  This class provides both fclose() and pclose(), but these are equivalent -
 *  the code always closes pipes with pclose() and files with fclose().
 *  Finally, an abstraction for errno is provided. Error codes should always
 *  be retrieves using methods getLastError() and getLastErrorString() which
 *  on Unix platforms are based on errno and strerror/strerror_r, but may be based
 *  on other mechanisms on platforms where errno does not exist.
 */
class OFFile
{
public:
  /// default constructor, creates an object that is not associated with any file.
  OFFile(): file_(NULL), popened_(OFFalse), lasterror_(0) {}

  /** create object for given stdio FILE
   *  @param f stdio FILE
   */
  OFFile(FILE *f): file_(f), popened_(OFFalse), lasterror_(0) {}

  /// destructor. Closes file if still open.
  ~OFFile()
  {
    if (file_) fclose();
  }

  /** opens the file whose name is the string pointed to by path and associates
   *  a stream with it.
   *  @param filename path to file
   *  @param modes "r", "w" or "a" with possible modifiers "+", "b"
   *  @return true if stream was successfully created, false otherwise, in which case
   *   the error code is set.
   */
  OFBool fopen(const char *filename, const char *modes)
  {
    if (file_) fclose();
#ifdef EXPLICIT_LFS_64
    file_ = :: fopen64(filename, modes);
#else
    file_ = STDIO_NAMESPACE fopen(filename, modes);
#endif
    if (file_) popened_ = OFFalse; else storeLastError();
    return (file_ != NULL);
  }

#if defined(WIDE_CHAR_FILE_IO_FUNCTIONS) && defined(_WIN32)
  /** opens the file whose name is the wide character string pointed to by path and associates
   *  a stream with it. This function is Win32 specific and only exists on WinNT and newer.
   *  @param filename Unicode filename path to file
   *  @param modes "r", "w" or "a" with possible modifiers "+", "b", as a wide character string
   *  @return true if stream was successfully created, false otherwise, in which case the error code is set.
   */
  OFBool wfopen(const wchar_t *filename, const wchar_t *modes)
  {
    if (file_) fclose();
    file_ = _wfopen(filename, modes);
    if (file_) popened_ = OFFalse; else storeLastError();
    return (file_ != NULL);
  }
#endif

  /** associates a stream with the existing file descriptor, fildes. The mode
   *  of the stream (one of the values "r", "r+", "w", "w+", "a", "a+") must be
   *  compatible with the mode of the file descriptor. The file position
   *  indicator of the new stream is set to that belongĀ­ ing to fildes, and the
   *  error and end-of-file indicators are cleared. Modes "w" or "w+" do not
   *  cause truncation of the file. The file descriptor is not dup'ed, and
   *  will be closed when the stream created by fdopen is closed. The result of
   *  applying fdopen to a shared memory object is undefined.
   *  @param fd file descriptor
   *  @param modes "r", "w" or "a" with possible modifiers "+", "b"
   *  @return true if stream was successfully created, false otherwise, in which case the error code is set.
   */
  OFBool fdopen(int fd, const char *modes)
  {
    if (file_) fclose();
    file_ = :: fdopen(fd, modes);
    if (file_) popened_ = OFFalse; else storeLastError();
    return (file_ != NULL);
  }

  /** opens a process by creating a pipe, forking, and invoking the shell.
   *  Since a pipe is by definition unidirectional, the type argument may
   *  specify only reading or writing, not both; the resulting stream is
   *  correspondingly read-only or write-only. If the object was already
   *  associated with another file or pipe, that one is closed.
   *  @param command shell command line
   *  @param modes "r" or "w"
   *  @return true if pipe was successfully created, false otherwise
   */
  OFBool popen(const char *command, const char *modes)
  {
    if (file_) fclose();
#ifdef _WIN32
    file_ = _popen(command, modes);
#else
    file_ = :: popen(command, modes);
#endif
    if (file_) popened_ = OFTrue; else storeLastError();
    return (file_ != NULL);
  }

  /** opens the file whose name is the string pointed to by path and associates
   *  the stream pointed maintained by this object with it. The original stream
   *  (if it exists) is closed. The mode argument is used just as in the fopen
   *  function. The primary use of the freopen function is to change the file
   *  associated with a standard text stream (stderr, stdin, or stdout).
   *  @param filename path to file
   *  @param modes "r", "w" or "a" with possible modifiers "+", "b"
   *  @return true if stream was successfully created, false otherwise, in which case the error code is set.
   */
  OFBool freopen(const char *filename, const char *modes)
  {
#if defined(EXPLICIT_LFS_64) && ! defined(__MINGW32__)
    // MinGW has EXPLICIT_LFS_64 but no freopen64()
    file_ = :: freopen64(filename, modes, file_);
#else
    file_ = STDIO_NAMESPACE freopen(filename, modes, file_);
#endif
    if (file_) popened_ = OFFalse; else storeLastError();
    return (file_ != NULL);
  }

  /** generates a unique temporary filename. The temporary file is then opened
   *  in binary read/write (w+b) mode. The file will be automatically deleted
   *  when it is closed or the program terminates normally.
   *  @return true if stream was successfully created, false otherwise, in which case the error code is set.
   */
  OFBool tmpfile()
  {
    if (file_) fclose();
#if defined(EXPLICIT_LFS_64) && ! defined(__MINGW32__)
    // MinGW has EXPLICIT_LFS_64 but no tmpfile64()
    file_ = :: tmpfile64();
#else
    file_ = STDIO_NAMESPACE tmpfile();
#endif
    if (file_) popened_ = OFFalse; else storeLastError();
    return (file_ != NULL);
  }

  /** dissociates the named stream from its underlying file or set of functions.
   *  If the stream was being used for output, any buffered data is written
   *  first, using fflush. Independent of the return value of this method,
   *  any further access (including another call to fclose()) to the stream
   *  maintained by this object results in undefined behaviour.
   *  @return 0 upon success, EOF otherwise, in which case the error code is set.
   */
  int fclose()
  {
    int result = 0;
    if (file_)
    {
      if (popened_)
      {
#ifdef _WIN32
        result = _pclose(file_);
#else
        result = :: pclose(file_);
#endif
      }
      else
      {
        result = STDIO_NAMESPACE fclose(file_);
      }
      // After calling fclose() once, the FILE* is gone even if fclose() failed.
      file_ = NULL;
    }
    if (result) storeLastError();
    return result;
  }

  /** waits for the associated process (created with popen) to terminate and
   *  returns the exit status of the command as returned by wait4.
   *  In this implementation, fclose and pclose can be used synonymously.
   *  @return process ID of the child which exited, or -1 on error, in which case the error code is set
   */
  int pclose() { return fclose(); }

  /** writes n elements of data, each size bytes long, to the stream, obtaining
   *  them from the location given by ptr. Returns the number of items successfully written
   *  (i.e., not the number of characters).  If an error occurs the return value is a short
   *  item count (or zero).
   *  @param ptr pointer to buffer
   *  @param size size of item
   *  @param n number of items
   *  @return number of items written
   */
  size_t fwrite(const void *ptr, size_t size, size_t n)
  {
    return STDIO_NAMESPACE fwrite(ptr, size, n, file_);
  }

  /** reads n elements of data, each size bytes long, from the stream, storing
   *  them at the location given by ptr. Returns the number of items successfully
   *  read (i.e., not the number of characters).  If an error occurs, or the
   *  end-of-file is reached, the return value is a short item count (or zero).
   *  fread does not distinguish between end-of-file and error, and callers must
   *  use feof and ferror to determine which occurred.
   *  @param ptr pointer to buffer
   *  @param size size of item
   *  @param n number of items
   *  @return number of items read
   */
  size_t fread(void *ptr, size_t size, size_t n)
  {
    return STDIO_NAMESPACE fread(ptr, size, n, file_);
  }

  /** forces a write of all user-space buffered data for the given output or
   *  update stream via the stream's underlying write function. The open status
   *  of the stream is unaffected.
   *  @return 0 upon success, EOF otherwise, in which case the error code is set.
   */
  int fflush()
  {
    int result = STDIO_NAMESPACE fflush(file_);
    if (result) storeLastError();
    return result;
  }

  /** reads the next character from stream and returns it as an unsigned char
   *  cast to an int, or EOF on end of file or error.
   *  @return next character from stream or EOF
   */
  int fgetc() { return STDIO_NAMESPACE fgetc(file_); }

  /** The three types of buffering available are unbuffered, block buffered, and
   *  line buffered. When an output stream is unbuffered, information appears on
   *  the destination file or terminal as soon as written; when it is block
   *  buffered many characters are saved up and written as a block; when it is
   *  line buffered characters are saved up until a newline is output or input
   *  is read from any stream attached to a terminal device (typically stdin).
   *  Normally all files are block buffered. if a stream refers to a  terminal
   *  (as stdout normally does) it is line buffered. The standard error  stream
   *  stderr is always unbuffered by default. this function allows to set the
   *  mode of the stream to line buffered.
   *  @return 0 upon success, nonzero otherwise, in which case the error code may be set
   *
   */
  void setlinebuf()
  {
#if defined(_WIN32) || defined(__hpux)
    this->setvbuf(NULL, _IOLBF, 0);
#else
    :: setlinebuf(file_);
#endif
  }

  /** sets the file position indicator for the stream pointed to by stream to
   *  the beginning of the file. This is equivalent to fseek(0, SEEK_SET)
   *  except that the error indicator for the stream is also cleared.
   */
  void rewind() { STDIO_NAMESPACE rewind(file_); }

  /** clears the end-of-file and error indicators for the stream
   */
  void clearerr() { STDIO_NAMESPACE clearerr(file_); }

  /** tests the end-of-file indicator for the stream, returning non-zero if it
   *  is set. The end-of-file indicator can only be cleared by the function
   *  clearerr. This method is called eof, not feof, because feof() is a macro
   *  on some systems and, therefore, cannot be used as a method name.
   *  @return non-zero if EOF, zero otherwise
   */
  int eof() const
  {
#ifdef feof
    // feof is a macro on some systems. Macros never have namespaces.
    return feof(file_);
#else
    return STDIO_NAMESPACE feof(file_);
#endif
  }

  /** tests the error indicator for the stream, returning non-zero if it is set.
   *  This method is named error, not ferror, because ferror() is a macro
   *  on some systems and, therefore, cannot be used as a method name.
   *  The error indicator can only be reset by the clearerr function.
   *  @return non-zero if error flag is set, zero otherwise
   */
  int error()
  {
#ifdef ferror
    // ferror is a macro on some systems. Macros never have namespaces.
    return ferror(file_);
#else
    return STDIO_NAMESPACE ferror(file_);
#endif
  }

  /** returns the low-level file descriptor associated with the stream.
   *  The spelling of this member function is different from stdio fileno()
   *  because on some systems (such as MinGW) fileno() is a macro
   *  and, therefore, cannot be used as a method name.
   *  @return low-level file descriptor associated with stream
   */
#ifdef fileno
  int fileNo() { return fileno(file_); }
#else
  int fileNo() { return :: fileno(file_); }
#endif

  /** The three types of buffering available are unbuffered, block buffered, and
   *  line buffered. When an output stream is unbuffered, information appears on
   *  the destination file or terminal as soon as written; when it is block
   *  buffered many characters are saved up and written as a block; when it is
   *  line buffered characters are saved up until a newline is output or input
   *  is read from any stream attached to a terminal device (typically stdin).
   *  Normally all files are block buffered. if a stream refers to a  terminal
   *  (as stdout normally does) it is line buffered. The standard error  stream
   *  stderr is always unbuffered by default. This function allows to set the
   *  mode of the stream to unbuffered (if buf is NULL) or block buffered.
   *  @param buf pointer to buffer of size BUFSIZ as declared in cstdio, or NULL
   *  @return 0 upon success, nonzero otherwise, in which case the error code may be set
   */
  void setbuf(char *buf) { STDIO_NAMESPACE setbuf(file_, buf); }

  /** The three types of buffering available are unbuffered, block buffered, and
   *  line buffered. When an output stream is unbuffered, information appears on
   *  the destination file or terminal as soon as written; when it is block
   *  buffered many characters are saved up and written as a block; when it is
   *  line buffered characters are saved up until a newline is output or input
   *  is read from any stream attached to a terminal device (typically stdin).
   *  Normally all files are block buffered. if a stream refers to a  terminal
   *  (as stdout normally does) it is line buffered. The standard error  stream
   *  stderr is always unbuffered by default. This function allows to set the
   *  stream mode.
   *  @param buf pointer to buffer, may be NULL
   *  @param modes _IONBF (unbuffered) _IOLBF (line buffered) or _IOFBF (fully buffered)
   *  @param n size of buffer, in bytes
   *  @return 0 upon success, nonzero otherwise, in which case the error code may be set
   */
  int setvbuf(char * buf, int modes, size_t n)
  {
    int result = STDIO_NAMESPACE setvbuf(file_, buf, modes, n);
    if (result) storeLastError();
    return result;
  }

  /** The three types of buffering available are unbuffered, block buffered, and
   *  line buffered. When an output stream is unbuffered, information appears on
   *  the destination file or terminal as soon as written; when it is block
   *  buffered many characters are saved up and written as a block; when it is
   *  line buffered characters are saved up until a newline is output or input
   *  is read from any stream attached to a terminal device (typically stdin).
   *  Normally all files are block buffered. if a stream refers to a  terminal
   *  (as stdout normally does) it is line buffered. The standard error  stream
   *  stderr is always unbuffered by default. This function allows to set the
   *  mode of the stream to unbuffered (if buf is NULL) or block buffered.
   *  @param buf pointer to buffer
   *  @param size size of buffer, in bytes
   *  @return 0 upon success, nonzero otherwise, in which case the error code may be set
   */
  void setbuffer(char *buf, size_t size)
  {
#if defined(_WIN32) || defined(__hpux)
    this->setvbuf(NULL, buf ? _IOFBF : _IONBF, size);
#else
    :: setbuffer(file_, buf, size);
#endif
  }

  /** writes the character c, cast to an unsigned char, to stream.
   *  @param c character
   *  @return the character written as an unsigned char cast to an int or EOF on error
   */
  int fputc(int c) { return STDIO_NAMESPACE fputc(c, file_); }

  /** reads in at most one less than n characters from stream and stores them
   *  into the buffer pointed to by s. Reading stops after an EOF or a newline.
   *  If a newline is read, it is stored into the buffer. A '@\0' is stored after
   *  the last character in the buffer.
   *  @param s pointer to buffer of size n
   *  @param n buffer size
   *  @return pointer to string
   */
  char *fgets(char *s, int n) { return STDIO_NAMESPACE fgets(s, n, file_); }

  /** writes the string s to stream, without its trailing '@\0'.
   *  @param s string to be written
   *  @return a non-negative number on success, or EOF on error.
   */
  int fputs(const char *s) { return STDIO_NAMESPACE fputs(s, file_); }

  /** pushes c back to stream, cast to unsigned char, where it is available for
   *  subsequent read operations. Pushed - back characters will be returned in
   *  reverse order; only one pushback is guaranteed.
   *  @param c character to push back
   *  @return c on success, or EOF on error.
   */
  int ungetc(int c) { return STDIO_NAMESPACE ungetc(c, file_); }

  /** sets the file position indicator for the stream pointed to by stream. The
   *  new position, measured in bytes, is obtained by adding offset bytes to the
   *  position specified by whence. If whence is set to SEEK_SET, SEEK_CUR, or
   *  SEEK_END, the offset is relative to the start of the file, the current
   *  position indicator, or end-of-file, respectively. A successful call to the
   *  fseek function clears the end-of- file indicator for the stream and undoes
   *  any effects of the ungetc function on the same stream.
   *  @param off offset to seek to
   *  @param whence SEEK_SET, SEEK_CUR, or SEEK_END
   *  @return 0 upon success, -1 otherwise in which case the error code is set.
   */
  int fseek(offile_off_t off, int whence)
  {
    int result;
#ifdef _WIN32
    // Windows does not have a 64-bit fseek.
    // We emulate fseek through fsetpos, which does exist on Windows.
    // fpos_t is (hopefully always) defined as __int64 on this platform
    offile_fpos_t off2 = off;
    fpos_t pos;
    struct _stati64 buf;
    switch (whence)
    {
      case SEEK_END:
        // flush write buffer, if any, so that the file size is correct
        STDIO_NAMESPACE fflush(file_);
#if 0
        // Python implementation based on _lseeki64(). May be unsafe because
        // there is no guarantee that fflush also empties read buffers.
        STDIO_NAMESPACE fflush(file_);
#ifdef fileno
        if (_lseeki64(   fileno(file_), 0, 2) == -1)
#else
        if (_lseeki64(:: fileno(file_), 0, 2) == -1)
#endif
        {
          storeLastError();
          return -1;
        }
        // fall through
#else
        // determine file size (using underlying file descriptor). This should be safe.
#ifdef fileno
        if (_fstati64(   fileno(file_), &buf) == -1)
#else
        if (_fstati64(:: fileno(file_), &buf) == -1)
#endif
        {
          storeLastError();
          return -1;
        }

        // fsetpos position is offset + file size.
        off2 += buf.st_size;
        break;
#endif
      case SEEK_CUR:
        if (STDIO_NAMESPACE fgetpos(file_, &pos) != 0)
        {
          storeLastError();
          return -1;
        }

        off2 += pos;
        break;
      case SEEK_SET:
        /* do nothing */
        break;
    }
    result = this->fsetpos(&off2);
#elif defined(__BEOS__)
    result = :: _fseek(fp, offset, whence);
#else
#ifdef HAVE_FSEEKO
#ifdef EXPLICIT_LFS_64
    result = :: fseeko64(file_, off, whence);
#else
    result = :: fseeko(file_, off, whence);
#endif
#else
    result = STDIO_NAMESPACE fseek(file_, off, whence);
#endif
#endif
    if (result) storeLastError();
    return result;
  }

  /** obtains the current value of the file position indicator for the stream pointed to by the stream.
   *  @return current file position
   */
  offile_off_t ftell()
  {
    offile_off_t result;
#ifdef _WIN32
    // Windows does not have a 64-bit ftell, and _telli64 cannot be used
    // because it operates on file descriptors and ignores FILE buffers.
    // We emulate ftell through fgetpos, which does exist on Windows.
    // fpos_t is (hopefully always) defined as __int64 on this platform.
    offile_fpos_t pos;
    if (this->fgetpos(&pos) != 0)
    {
      storeLastError();
      return -1;
    }
    return pos;
#else
#ifdef HAVE_FSEEKO
#ifdef EXPLICIT_LFS_64
    result = :: ftello64(file_);
#else
    result = :: ftello(file_);
#endif
#else
    result = STDIO_NAMESPACE ftell(file_);
#endif
#endif
    if (result < 0) storeLastError();
    return result;
  }

  /** alternate interface equivalent to ftell, storing the current value of the
   *  file offset into the object referenced by pos. On some non-UNIX systems an
   *  fpos_t object may be a complex object and these routines may be the only
   *  way to portably reposition a text stream.
   *  @param pos pointer to offile_fpos_t structure
   *  @return 0 upon success, -1 otherwise in which case the error code is set.
   */
  int fgetpos(offile_fpos_t *pos)
  {
    int result;
#if defined(EXPLICIT_LFS_64) && ! defined(__MINGW32__)
    // MinGW has EXPLICIT_LFS_64 but no fgetpos64()
    result = :: fgetpos64(file_, pos);
#else
    result = STDIO_NAMESPACE fgetpos(file_, pos);
#endif
    if (result) storeLastError();
    return result;
  }

  /** alternate interface equivalent to fseek (with whence set to SEEK_SET),
   *  setting the current value of the file offset from the object referenced by
   *  pos. On some non-UNIX systems an fpos_t object may be a complex object and
   *  these routines may be the only way to portably reposition a text stream.
   *  @param pos pointer to offile_fpos_t structure
   *  @return 0 upon success, -1 otherwise in which case the error code is set.
   */
  int fsetpos(offile_fpos_t *pos)
  {
    int result;
#if defined(EXPLICIT_LFS_64) && ! defined(__MINGW32__)
    // MinGW has EXPLICIT_LFS_64 but no fsetpos64()
    result = :: fsetpos64(file_, pos);
#else
    result = STDIO_NAMESPACE fsetpos(file_, pos);
#endif
    if (result) storeLastError();
    return result;
  }

  /** print formatted string into stream, see printf(3)
   *  @param format format string
   *  @param ... further parameters according to format string
   *  @return number of characters printed
   */
  int fprintf(const char *format, ...)
  {
    int result = 0;
    va_list ap;
    va_start(ap, format);
    result = STDIO_NAMESPACE vfprintf(file_, format, ap);
    va_end(ap);
    return result;
  }

  /** print formatted string into stream, see printf(3)
   *  @param format format string
   *  @param arg list of further parameters according to format string
   *  @return number of characters printed
   */
   int vfprintf(const char *format, va_list arg)
   {
     return STDIO_NAMESPACE vfprintf(file_, format, arg);
   }

  // we cannot emulate fscanf because we would need vfscanf for this
  // purpose, which does not exist, e.g. on Win32.

  /** return FILE pointer managed by this object. This allows the user
   *  to call some stdio functions that are not encapsulated in this class
   *  (but possibly should be).
   *  @return pointer to FILE structure managed by this object
   */
  FILE *file() { return file_; }

  /** return true if this object is currently associated with a stream, false otherwise
   *  @return true if this object is currently associated with a stream, false otherwise
   */
  OFBool open() const { return file_ != NULL; }

  /** return last error code for this stream
   *  @return last error code for this stream
   */
  offile_errno_t getLastError() const { return lasterror_; }

  /** return string describing last error code for this stream
   *  @param s string describing last error code for this stream returned in this parameter
   */
  void getLastErrorString(OFString& s) const
  {
    char buf[1000];
    s = OFStandard::strerror(lasterror_, buf, 1000);
  }

// wide character functions (disabled by default, since currently not used within DCMTK)
#ifdef WIDE_CHAR_FILE_IO_FUNCTIONS

  /** When mode is zero, the fwide function determines the current orientation
   *  of stream. It returns a value > 0 if stream is wide-character oriented,
   *  i.e.  if wide character I/O is permitted but char I/O is disallowed. It
   *  returns a  value < 0 if stream is byte oriented, i.e. if char I/O is
   *  permitted but wide  character I/O is disallowed. It returns zero if stream
   *  has no orientation yet;  in this case the next I/O operation might change
   *  the orientation (to byte  oriented if it is a char I/O operation, or to
   *  wide-character oriented if it  is a wide character I/O operation).
   *  Once a stream has an orientation, it cannot be changed and persists until
   *  the stream is closed.
   *  When mode is non-zero, the fwide function first attempts to set stream's
   *  orientation (to wide-character oriented if mode > 0, or to byte oriented
   *  if mode < 0). It then returns a value denoting the current orientation, as
   *  above.
   *  @param mode mode of operation for fwide
   *  @return orientation of stream
   */
  int fwide(int mode)
  {
    return STDIO_NAMESPACE fwide(file_, mode);
  }

  /** reads a wide character from stream and returns it. If the end of stream is
   *  reached, or if ferror(stream) becomes true, it returns WEOF. If a wide
   *  character conversion error occurs, it sets the error code to EILSEQ and returns
   *  WEOF.
   *  @return next character from stream or WEOF
   */
  wint_t fgetwc()
  {
    wint_t result = STDIO_NAMESPACE fgetwc(file_);
    if (result == WEOF) storeLastError();
    return result;
  }

  /** writes the wide character wc to stream. If ferror(stream) becomes true, it returns WEOF.
   *  If a wide character conversion error occurs, it sets the error code to EILSEQ and returns WEOF.
   *  Otherwise it returns wc.
   *  @param wc wide character to write to stream
   *  @return character written or WEOF
   */
  wint_t fputwc(wchar_t wc)
  {
    wint_t result = STDIO_NAMESPACE fputwc(wc, file_);
    if (result == WEOF) storeLastError();
    return result;
  }

  /** pushes back a wide character onto stream and returns it. If wc is WEOF, it
   *  returns WEOF. If wc is an invalid wide character, it sets errno to EILSEQ
   *  and returns WEOF. If wc is a valid wide character, it is pushed back  onto
   *  the stream and thus becomes available for future wide character read
   *  operations. The file-position indicator is decremented by one or more.
   *  The end-of-file indicator is cleared. The backing storage of the file is
   *  not affected. Note: wc need not be the last wide character read from the
   *  stream; it can be any other valid wide character. If the implementation
   *  supports multiple push-back operations in a row, the pushed-back wide
   *  characters will be read in reverse order; however, only one level of
   *  push-back is guaranteed.
   *  @param wc wide character to put back to stream
   *  @return character put back or WEOF
   */
  wint_t ungetwc(wint_t wc)
  {
    wint_t result = STDIO_NAMESPACE ungetwc(wc, file_);
    if (result == WEOF) storeLastError();
    return result;
  }

  /** print formatted wide string into stream, see wprintf(3)
   *  @param format format string
   *  @param ... further parameters according to format string
   *  @return number of characters printed
   */
  int fwprintf(const wchar_t *format, ...)
  {
    int result = 0;
    va_list ap;
    va_start(ap, format);
    result = STDIO_NAMESPACE vfwprintf(file_, format, ap);
    va_end(ap);
    return result;
  }

  /** print formatted wide string into stream, see printf(3)
   *  @param format format string
   *  @param arg list of further parameters according to format string
   *  @return number of characters printed
   */
   int vfwprintf(const wchar_t *format, va_list arg)
   {
     return STDIO_NAMESPACE vfwprintf(file_, format, arg);
   }

  // we cannot emulate fwscanf because we would need vfwscanf for this
  // purpose, which does not exist, e.g. on Win32.

#endif /* WIDE_CHAR_FILE_IO_FUNCTIONS */

private:

  // private undefined copy constructor
  OFFile(const OFFile &arg);

  // private undefined assignment operator
  OFFile &operator=(const OFFile &arg);

  /// the file maintained by this object
  FILE *file_;

  /// a flag indicating whether or not this object was created with popen().
  OFBool popened_;

  /// the last error code for operations of this stream
  offile_errno_t lasterror_;

  /// store last error code. For now we simply store the content of errno.
  inline void storeLastError()
  {
    lasterror_ = errno;
  }

};


#endif

/*
 * CVS/RCS Log:
 * $Log: offile.h,v $
 * Revision 1.17  2010-12-17 10:50:30  joergr
 * Check whether "feof" and "ferror" are defined as macros (e.g. on IRIX 6.3).
 *
 * Revision 1.16  2010-12-15 11:29:07  uli
 * Made OFFile compile successfully on HP-UX.
 *
 * Revision 1.15  2010-12-08 16:04:35  joergr
 * Disable currently unused wide character file I/O functions in order to avoid
 * problems with old compilers (e.g. gcc 2.95.3).
 *
 * Revision 1.14  2010-12-06 13:02:49  joergr
 * Fixed issue with large file support for current Cygwin systems (1.7.7-1).
 *
 * Revision 1.13  2010-10-14 13:15:50  joergr
 * Updated copyright header. Added reference to COPYRIGHT file.
 *
 * Revision 1.12  2010-06-02 12:55:30  joergr
 * Introduced new helper function strerror() which is used as a wrapper to the
 * various approaches found on different systems.
 *
 * Revision 1.11  2010-04-26 12:22:30  uli
 * Fixed a some minor doxygen warnings.
 *
 * Revision 1.10  2009-09-24 07:10:52  meichel
 * Fixed bug in class OFFile that caused undefined behaviour
 *   once fclose() failed
 *
 * Revision 1.9  2009-08-10 07:52:09  meichel
 * Some modifications needed to make class OFFile compile on MinGW.
 *
 * Revision 1.8  2009-03-12 11:37:54  joergr
 * Fixed various Doxygen API documentation issues.
 *
 * Revision 1.7  2009-02-13 12:56:18  joergr
 * Added private undefined copy constructor and assignment operator in order to
 * avoid compiler warnings (reported by gcc with additional flags).
 *
 * Revision 1.6  2009-01-30 13:49:01  joergr
 * Replaced checking of macro WIN32 by _WIN32.
 *
 * Revision 1.5  2008-05-29 10:37:11  meichel
 *  Fixed compile error on Cygwin where no wide-char FILE functions are available
 *
 * Revision 1.4  2008-02-07 16:57:46  meichel
 * Class OFFile now makes use of HAVE_CHARP_STRERROR_R to use the
 *   correct version of strerror_r.
 *
 * Revision 1.3  2007/06/06 13:55:58  onken
 * Fixed compilation for Mac OS X with making large file support function calls
 * implicit for this OS (Mac OS X misleadingly defines _LARGEFILE64_SOURCE).
 *
 * Revision 1.2  2007/02/19 16:03:47  meichel
 * Added constructor to class OFFile that takes FILE * as argument.
 *
 * Revision 1.1  2006/08/21 12:40:44  meichel
 * Added new class OFFile that provides a simple encapsulation layer for
 *   FILE based stream I/O and, in particular, provides long file support
 *   (LFS) if available on the underlying operating system platform through
 *   a single API.
 *
 *
 */