Blame libio/freopen64.c

Packit Service 82fcde
/* Copyright (C) 1993-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.
Packit Service 82fcde
Packit Service 82fcde
   As a special exception, if you link the code in this file with
Packit Service 82fcde
   files compiled with a GNU compiler to produce an executable,
Packit Service 82fcde
   that does not cause the resulting executable to be covered by
Packit Service 82fcde
   the GNU Lesser General Public License.  This exception does not
Packit Service 82fcde
   however invalidate any other reasons why the executable file
Packit Service 82fcde
   might be covered by the GNU Lesser General Public License.
Packit Service 82fcde
   This exception applies to code released by its copyright holders
Packit Service 82fcde
   in files containing the exception.  */
Packit Service 82fcde
Packit Service 82fcde
#include "libioP.h"
Packit Service 82fcde
#include "stdio.h"
Packit Service 82fcde
#include <fcntl.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
Packit Service 82fcde
#include <fd_to_filename.h>
Packit Service 82fcde
Packit Service 82fcde
#include <kernel-features.h>
Packit Service 82fcde
Packit Service 82fcde
FILE *
Packit Service 82fcde
freopen64 (const char *filename, const char *mode, FILE *fp)
Packit Service 82fcde
{
Packit Service 82fcde
  FILE *result;
Packit Service 82fcde
  CHECK_FILE (fp, NULL);
Packit Service 82fcde
  if (!(fp->_flags & _IO_IS_FILEBUF))
Packit Service 82fcde
    return NULL;
Packit Service 82fcde
  _IO_acquire_lock (fp);
Packit Service 82fcde
  int fd = _IO_fileno (fp);
Packit Service 82fcde
  const char *gfilename = (filename == NULL && fd >= 0
Packit Service 82fcde
			   ? fd_to_filename (fd) : filename);
Packit Service 82fcde
  fp->_flags2 |= _IO_FLAGS2_NOCLOSE;
Packit Service 82fcde
  _IO_file_close_it (fp);
Packit Service 82fcde
  _IO_JUMPS_FILE_plus (fp) = &_IO_file_jumps;
Packit Service 82fcde
  if (_IO_vtable_offset (fp) == 0 && fp->_wide_data != NULL)
Packit Service 82fcde
    fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
Packit Service 82fcde
  result = _IO_file_fopen (fp, gfilename, mode, 0);
Packit Service 82fcde
  fp->_flags2 &= ~_IO_FLAGS2_NOCLOSE;
Packit Service 82fcde
  if (result != NULL)
Packit Service 82fcde
    result = __fopen_maybe_mmap (result);
Packit Service 82fcde
  if (result != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* unbound stream orientation */
Packit Service 82fcde
      result->_mode = 0;
Packit Service 82fcde
Packit Service 82fcde
      if (fd != -1 && _IO_fileno (result) != fd)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* At this point we have both file descriptors already allocated,
Packit Service 82fcde
	     so __dup3 will not fail with EBADF, EINVAL, or EMFILE.  But
Packit Service 82fcde
	     we still need to check for EINVAL and, due Linux internal
Packit Service 82fcde
	     implementation, EBUSY.  It is because on how it internally opens
Packit Service 82fcde
	     the file by splitting the buffer allocation operation and VFS
Packit Service 82fcde
	     opening (a dup operation may run when a file is still pending
Packit Service 82fcde
	     'install' on VFS).  */
Packit Service 82fcde
	  if (__dup3 (_IO_fileno (result), fd,
Packit Service 82fcde
		      (result->_flags2 & _IO_FLAGS2_CLOEXEC) != 0
Packit Service 82fcde
		      ? O_CLOEXEC : 0) == -1)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      _IO_file_close_it (result);
Packit Service 82fcde
	      result = NULL;
Packit Service 82fcde
	      goto end;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  __close (_IO_fileno (result));
Packit Service 82fcde
	  _IO_fileno (result) = fd;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (fd != -1)
Packit Service 82fcde
    __close (fd);
Packit Service 82fcde
Packit Service 82fcde
end:
Packit Service 82fcde
  if (filename == NULL)
Packit Service 82fcde
    free ((char *) gfilename);
Packit Service 82fcde
  _IO_release_lock (fp);
Packit Service 82fcde
  return result;
Packit Service 82fcde
}