(root)/
gettext-0.22.4/
libtextstyle/
lib/
file-ostream.oo.c
       1  /* Output stream referring to an stdio FILE.
       2     Copyright (C) 2006, 2019-2020 Free Software Foundation, Inc.
       3     Written by Bruno Haible <bruno@clisp.org>, 2006.
       4  
       5     This program is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU General Public License as published by
       7     the Free Software Foundation; either version 3 of the License, or
       8     (at your option) any later version.
       9  
      10     This program is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU General Public License for more details.
      14  
      15     You should have received a copy of the GNU General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <config.h>
      19  
      20  /* Specification.  */
      21  #include "file-ostream.h"
      22  
      23  #include <errno.h>
      24  #include <stdlib.h>
      25  #include <unistd.h>
      26  #if HAVE_TCDRAIN
      27  # include <termios.h>
      28  #endif
      29  
      30  #include "xalloc.h"
      31  
      32  struct file_ostream : struct ostream
      33  {
      34  fields:
      35    FILE *fp;
      36  };
      37  
      38  #if HAVE_TCDRAIN
      39  
      40  /* EINTR handling for tcdrain().
      41     This function can return -1/EINTR even though we don't have any
      42     signal handlers set up, namely when we get interrupted via SIGSTOP.  */
      43  
      44  static inline int
      45  nonintr_tcdrain (int fd)
      46  {
      47    int retval;
      48  
      49    do
      50      retval = tcdrain (fd);
      51    while (retval < 0 && errno == EINTR);
      52  
      53    return retval;
      54  }
      55  
      56  #endif
      57  
      58  /* Implementation of ostream_t methods.  */
      59  
      60  static void
      61  file_ostream::write_mem (file_ostream_t stream, const void *data, size_t len)
      62  {
      63    if (len > 0)
      64      fwrite (data, 1, len, stream->fp);
      65  }
      66  
      67  static void
      68  file_ostream::flush (file_ostream_t stream, ostream_flush_scope_t scope)
      69  {
      70    /* This ostream has no internal buffer, therefore nothing to do for
      71       scope == FLUSH_THIS_STREAM.  */
      72    if (scope != FLUSH_THIS_STREAM)
      73      {
      74        fflush (stream->fp);
      75        if (scope == FLUSH_ALL)
      76          {
      77            int fd = fileno (stream->fp);
      78            if (fd >= 0)
      79              {
      80                /* For streams connected to a disk file:  */
      81                fsync (fd);
      82                #if HAVE_TCDRAIN
      83                /* For streams connected to a terminal:  */
      84                nonintr_tcdrain (fd);
      85                #endif
      86              }
      87          }
      88      }
      89  }
      90  
      91  static void
      92  file_ostream::free (file_ostream_t stream)
      93  {
      94    free (stream);
      95  }
      96  
      97  /* Constructor.  */
      98  
      99  file_ostream_t
     100  file_ostream_create (FILE *fp)
     101  {
     102    file_ostream_t stream = XMALLOC (struct file_ostream_representation);
     103  
     104    stream->base.vtable = &file_ostream_vtable;
     105    stream->fp = fp;
     106  
     107    return stream;
     108  }
     109  
     110  /* Accessors.  */
     111  
     112  static FILE *
     113  file_ostream::get_stdio_stream (file_ostream_t stream)
     114  {
     115    return stream->fp;
     116  }
     117  
     118  /* Instanceof test.  */
     119  
     120  bool
     121  is_instance_of_file_ostream (ostream_t stream)
     122  {
     123    return IS_INSTANCE (stream, ostream, file_ostream);
     124  }