1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
24 /* Open a file/string for IO.
25 ** If f is not nil, it is taken as an existing stream that should be
26 ** closed and its structure reused for the new stream.
28 ** Written by Kiem-Phong Vo.
31 #if _BLD_sfio && defined(__EXPORT__)
32 #define extern __EXPORT__
38 Sfio_t
* _sfopen(Sfio_t
* f
, const char* file
, const char* mode
)
40 Sfio_t
* _sfopen(f
,file
,mode
)
41 Sfio_t
* f
; /* old stream structure */
42 char* file
; /* file/string to be opened */
43 char* mode
; /* mode of the stream */
46 int fd
, oldfd
, oflags
, sflags
;
49 /* get the control flags */
50 if((sflags
= _sftype(mode
,&oflags
,NIL(int*))) == 0)
53 /* changing the control flags */
54 if(f
&& !file
&& !((f
->flags
|sflags
)&SF_STRING
) )
55 { SFMTXENTER(f
, NIL(Sfio_t
*));
57 if(f
->mode
&SF_INIT
) /* stream uninitialized, ok to set flags */
58 { f
->flags
|= (sflags
& (SF_FLAGS
& ~SF_RDWR
));
60 if((sflags
&= SF_RDWR
) != 0) /* reset read/write modes */
61 { f
->flags
= (f
->flags
& ~SF_RDWR
) | sflags
;
63 if((f
->flags
&SF_RDWR
) == SF_RDWR
)
65 else f
->bits
&= ~SF_BOTH
;
68 f
->mode
= (f
->mode
&~SF_WRITE
)|SF_READ
;
69 else f
->mode
= (f
->mode
&~SF_READ
)|SF_WRITE
;
72 else /* make sure there is no buffered data */
74 SFMTXRETURN(f
,NIL(Sfio_t
*));
77 if(f
->file
>= 0 && (oflags
&= (O_TEXT
|O_BINARY
|O_APPEND
)) != 0 )
78 { /* set file access control */
79 int ctl
= sysfcntlf(f
->file
, F_GETFL
, 0);
80 ctl
= (ctl
& ~(O_TEXT
|O_BINARY
|O_APPEND
)) | oflags
;
81 sysfcntlf(f
->file
, F_SETFL
, ctl
);
88 { f
= sfnew(f
,(char*)file
,
89 file
? (size_t)strlen((char*)file
) : (size_t)SF_UNBOUND
,
96 #if _has_oflags /* open the file */
97 while((fd
= sysopenf((char*)file
,oflags
,SF_CREATMODE
)) < 0 && errno
== EINTR
)
100 while((fd
= sysopenf(file
,oflags
&O_ACCMODE
)) < 0 && errno
== EINTR
)
103 { if((oflags
&(O_CREAT
|O_EXCL
)) == (O_CREAT
|O_EXCL
) )
104 { CLOSE(fd
); /* error: file already exists */
107 if(oflags
&O_TRUNC
) /* truncate file */
109 while((tf
= syscreatf(file
,SF_CREATMODE
)) < 0 &&
115 else if(oflags
&O_CREAT
)
116 { while((fd
= syscreatf(file
,SF_CREATMODE
)) < 0 && errno
== EINTR
)
118 if((oflags
&O_ACCMODE
) != O_WRONLY
)
119 { /* the file now exists, reopen it for read/write */
121 while((fd
= sysopenf(file
,oflags
&O_ACCMODE
)) < 0 &&
130 /* we may have to reset the file descriptor to its old value */
131 oldfd
= f
? f
->file
: -1;
132 if((f
= sfnew(f
,NIL(char*),(size_t)SF_UNBOUND
,fd
,sflags
)) && oldfd
>= 0)
133 (void)sfsetfd(f
,oldfd
);
140 int _sftype(reg
const char* mode
, int* oflagsp
, int* uflagp
)
142 int _sftype(mode
, oflagsp
, uflagp
)
148 reg
int sflags
, oflags
, uflag
;
153 /* construct the open flags */
154 sflags
= oflags
= uflag
= 0;
155 while(1) switch(*mode
++)
158 sflags
|= SF_WRITE
| SF_APPENDWR
;
159 oflags
|= O_WRONLY
| O_APPEND
| O_CREAT
;
179 sflags
&= ~SF_MTSAFE
;
184 oflags
|= O_WRONLY
| O_CREAT
;
185 if(!(sflags
&SF_READ
))
192 /* stdio compatibility -- fd >= FOPEN_MAX (or other magic number) ok */
195 sflags
|= SF_WCWIDTH
;
200 sflags
|= SF_READ
|SF_WRITE
;
203 if(!(oflags
&O_CREAT
) )
205 #if _WIN32 && !_WINIX
206 if(!(oflags
&(O_BINARY
|O_TEXT
)))
209 if((sflags
&SF_RDWR
) == SF_RDWR
)
210 oflags
= (oflags
&~O_ACCMODE
)|O_RDWR
;
215 if((sflags
&(SF_STRING
|SF_RDWR
)) == SF_STRING
)