(root)/
tar-1.35/
gnu/
stdio-write.c
       1  /* POSIX compatible FILE stream write function.
       2     Copyright (C) 2008-2023 Free Software Foundation, Inc.
       3     Written by Bruno Haible <bruno@clisp.org>, 2008.
       4  
       5     This file is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU Lesser General Public License as
       7     published by the Free Software Foundation; either version 2.1 of the
       8     License, or (at your option) any later version.
       9  
      10     This file 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 Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser 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 <stdio.h>
      22  
      23  /* Replace these functions only if module 'nonblocking' or module 'sigpipe' is
      24     requested.  */
      25  #if GNULIB_NONBLOCKING || GNULIB_SIGPIPE
      26  
      27  /* On native Windows platforms, SIGPIPE does not exist.  When write() is
      28     called on a pipe with no readers, WriteFile() fails with error
      29     GetLastError() = ERROR_NO_DATA, and write() in consequence fails with
      30     error EINVAL.  This write() function is at the basis of the function
      31     which flushes the buffer of a FILE stream.  */
      32  
      33  # if defined _WIN32 && ! defined __CYGWIN__
      34  
      35  #  include <errno.h>
      36  #  include <signal.h>
      37  #  include <io.h>
      38  
      39  #  define WIN32_LEAN_AND_MEAN  /* avoid including junk */
      40  #  include <windows.h>
      41  
      42  #  if GNULIB_MSVC_NOTHROW
      43  #   include "msvc-nothrow.h"
      44  #  else
      45  #   include <io.h>
      46  #  endif
      47  
      48  /* Don't assume that UNICODE is not defined.  */
      49  #  undef GetNamedPipeHandleState
      50  #  define GetNamedPipeHandleState GetNamedPipeHandleStateA
      51  
      52  #  if GNULIB_NONBLOCKING
      53  #   define CLEAR_ERRNO \
      54        errno = 0;
      55  #   define HANDLE_ENOSPC \
      56            if (errno == ENOSPC && ferror (stream))                             \
      57              {                                                                 \
      58                int fd = fileno (stream);                                       \
      59                if (fd >= 0)                                                    \
      60                  {                                                             \
      61                    HANDLE h = (HANDLE) _get_osfhandle (fd);                    \
      62                    if (GetFileType (h) == FILE_TYPE_PIPE)                      \
      63                      {                                                         \
      64                        /* h is a pipe or socket.  */                           \
      65                        DWORD state;                                            \
      66                        if (GetNamedPipeHandleState (h, &state, NULL, NULL,     \
      67                                                     NULL, NULL, 0)             \
      68                            && (state & PIPE_NOWAIT) != 0)                      \
      69                          /* h is a pipe in non-blocking mode.                  \
      70                             Change errno from ENOSPC to EAGAIN.  */            \
      71                          errno = EAGAIN;                                       \
      72                      }                                                         \
      73                  }                                                             \
      74              }                                                                 \
      75            else
      76  #  else
      77  #   define CLEAR_ERRNO
      78  #   define HANDLE_ENOSPC
      79  #  endif
      80  
      81  #  if GNULIB_SIGPIPE
      82  #   define CLEAR_LastError \
      83        SetLastError (0);
      84  #   define HANDLE_ERROR_NO_DATA \
      85            if (GetLastError () == ERROR_NO_DATA && ferror (stream))            \
      86              {                                                                 \
      87                int fd = fileno (stream);                                       \
      88                if (fd >= 0                                                     \
      89                    && GetFileType ((HANDLE) _get_osfhandle (fd))               \
      90                       == FILE_TYPE_PIPE)                                       \
      91                  {                                                             \
      92                    /* Try to raise signal SIGPIPE.  */                         \
      93                    raise (SIGPIPE);                                            \
      94                    /* If it is currently blocked or ignored, change errno from \
      95                       EINVAL to EPIPE.  */                                     \
      96                    errno = EPIPE;                                              \
      97                  }                                                             \
      98              }                                                                 \
      99            else
     100  #  else
     101  #   define CLEAR_LastError
     102  #   define HANDLE_ERROR_NO_DATA
     103  #  endif
     104  
     105  #  define CALL_WITH_SIGPIPE_EMULATION(RETTYPE, EXPRESSION, FAILED) \
     106    if (ferror (stream))                                                        \
     107      return (EXPRESSION);                                                      \
     108    else                                                                        \
     109      {                                                                         \
     110        RETTYPE ret;                                                            \
     111        CLEAR_ERRNO                                                             \
     112        CLEAR_LastError                                                         \
     113        ret = (EXPRESSION);                                                     \
     114        if (FAILED)                                                             \
     115          {                                                                     \
     116            HANDLE_ENOSPC                                                       \
     117            HANDLE_ERROR_NO_DATA                                                \
     118            ;                                                                   \
     119          }                                                                     \
     120        return ret;                                                             \
     121      }
     122  
     123  #  if !REPLACE_PRINTF_POSIX /* avoid collision with printf.c */
     124  int
     125  printf (const char *format, ...)
     126  {
     127    int retval;
     128    va_list args;
     129  
     130    va_start (args, format);
     131    retval = vfprintf (stdout, format, args);
     132    va_end (args);
     133  
     134    return retval;
     135  }
     136  #  endif
     137  
     138  #  if !REPLACE_FPRINTF_POSIX /* avoid collision with fprintf.c */
     139  int
     140  fprintf (FILE *stream, const char *format, ...)
     141  {
     142    int retval;
     143    va_list args;
     144  
     145    va_start (args, format);
     146    retval = vfprintf (stream, format, args);
     147    va_end (args);
     148  
     149    return retval;
     150  }
     151  #  endif
     152  
     153  #  if !REPLACE_VPRINTF_POSIX /* avoid collision with vprintf.c */
     154  int
     155  vprintf (const char *format, va_list args)
     156  {
     157    return vfprintf (stdout, format, args);
     158  }
     159  #  endif
     160  
     161  #  if !REPLACE_VFPRINTF_POSIX /* avoid collision with vfprintf.c */
     162  int
     163  vfprintf (FILE *stream, const char *format, va_list args)
     164  #undef vfprintf
     165  {
     166    CALL_WITH_SIGPIPE_EMULATION (int, vfprintf (stream, format, args), ret == EOF)
     167  }
     168  #  endif
     169  
     170  int
     171  putchar (int c)
     172  {
     173    return fputc (c, stdout);
     174  }
     175  
     176  int
     177  fputc (int c, FILE *stream)
     178  #undef fputc
     179  {
     180    CALL_WITH_SIGPIPE_EMULATION (int, fputc (c, stream), ret == EOF)
     181  }
     182  
     183  int
     184  fputs (const char *string, FILE *stream)
     185  #undef fputs
     186  {
     187    CALL_WITH_SIGPIPE_EMULATION (int, fputs (string, stream), ret == EOF)
     188  }
     189  
     190  int
     191  puts (const char *string)
     192  #undef puts
     193  {
     194    FILE *stream = stdout;
     195    CALL_WITH_SIGPIPE_EMULATION (int, puts (string), ret == EOF)
     196  }
     197  
     198  size_t
     199  fwrite (const void *ptr, size_t s, size_t n, FILE *stream)
     200  #undef fwrite
     201  {
     202    CALL_WITH_SIGPIPE_EMULATION (size_t, fwrite (ptr, s, n, stream), ret < n)
     203  }
     204  
     205  # endif
     206  #endif