summaryrefslogtreecommitdiffstats
path: root/newlib/libc/stdio/fdopen.c
blob: 8c1555d341631e0dfeb52302056f4aa3dc166cab (plain)
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
/*
FUNCTION
<<fdopen>>---turn open file into a stream

INDEX
	fdopen
INDEX
	_fdopen_r

ANSI_SYNOPSIS
	#include <stdio.h>
	FILE *fdopen(int <[fd]>, const char *<[mode]>);
	FILE *_fdopen_r(void *<[reent]>,
                     int <[fd]>, const char *<[mode]>);

TRAD_SYNOPSIS
	#include <stdio.h>
	FILE *fdopen(<[fd]>, <[mode]>)
	int <[fd]>;
	char *<[mode]>;

	FILE *_fdopen_r(<[reent]>, <[fd]>, <[mode]>)
	char *<[reent]>;
        int <[fd]>;
	char *<[mode]>);

DESCRIPTION
<<fdopen>> produces a file descriptor of type <<FILE *>>, from a
descriptor for an already-open file (returned, for example, by the
system subroutine <<open>> rather than by <<fopen>>).
The <[mode]> argument has the same meanings as in <<fopen>>.

RETURNS
File pointer or <<NULL>>, as for <<fopen>>.

PORTABILITY
<<fdopen>> is ANSI.
*/

#include <sys/types.h>
#include <sys/fcntl.h>

#include <stdio.h>
#include <errno.h>
#include "local.h"
#include <_syslist.h>

extern int __sflags ();

FILE *
_DEFUN (_fdopen_r, (ptr, fd, mode),
	struct _reent *ptr _AND
	int fd _AND
	_CONST char *mode)
{
  register FILE *fp;
  int flags, oflags;
#ifdef HAVE_FCNTL
  int fdflags, fdmode;
#endif

  if ((flags = __sflags (ptr, mode, &oflags)) == 0)
    return 0;

  /* make sure the mode the user wants is a subset of the actual mode */
#ifdef HAVE_FCNTL
  if ((fdflags = _fcntl_r (ptr, fd, F_GETFL, 0)) < 0)
    return 0;
  fdmode = fdflags & O_ACCMODE;
  if (fdmode != O_RDWR && (fdmode != (oflags & O_ACCMODE)))
    {
      ptr->_errno = EBADF;
      return 0;
    }
#endif

  if ((fp = __sfp (ptr)) == 0)
    return 0;

  _flockfile(fp);

  fp->_flags = flags;
  /*
   * If opened for appending, but underlying descriptor
   * does not have O_APPEND bit set, assert __SAPP so that
   * __swrite() will lseek to end before each write.
   */
  if ((oflags & O_APPEND)
#ifdef HAVE_FCNTL
       && !(fdflags & O_APPEND)
#endif
      )
    fp->_flags |= __SAPP;
  fp->_file = fd;
  fp->_cookie = (_PTR) fp;

#undef _read
#undef _write
#undef _seek
#undef _close

  fp->_read = __sread;
  fp->_write = __swrite;
  fp->_seek = __sseek;
  fp->_close = __sclose;

#ifdef __SCLE
  /* Explicit given mode results in explicit setting mode on fd */
  if (oflags & O_BINARY)
    setmode(fp->_file, O_BINARY);
  else if (oflags & O_TEXT)
    setmode(fp->_file, O_TEXT);
  if (__stextmode(fp->_file))
    fp->_flags |= __SCLE;
#endif

  _funlockfile(fp);
  return fp;
}

#ifndef _REENT_ONLY

FILE *
_DEFUN (fdopen, (fd, mode),
	int fd _AND
	_CONST char *mode)
{
  return _fdopen_r (_REENT, fd, mode);
}

#endif