14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * David Korn <dgk@research.att.com> *
194887Schin * Phong Vo <kpv@research.att.com> *
204887Schin * *
214887Schin ***********************************************************************/
224887Schin #include "sfhdr.h"
234887Schin
244887Schin /* Open a file/string for IO.
254887Schin ** If f is not nil, it is taken as an existing stream that should be
264887Schin ** closed and its structure reused for the new stream.
274887Schin **
284887Schin ** Written by Kiem-Phong Vo.
294887Schin */
304887Schin
314887Schin #if _BLD_sfio && defined(__EXPORT__)
324887Schin #define extern __EXPORT__
334887Schin #endif
344887Schin extern
354887Schin #undef extern
364887Schin
374887Schin #if __STD_C
_sfopen(Sfio_t * f,const char * file,const char * mode)388462SApril.Chin@Sun.COM Sfio_t* _sfopen(Sfio_t* f, const char* file, const char* mode)
394887Schin #else
404887Schin Sfio_t* _sfopen(f,file,mode)
418462SApril.Chin@Sun.COM Sfio_t* f; /* old stream structure */
424887Schin char* file; /* file/string to be opened */
438462SApril.Chin@Sun.COM char* mode; /* mode of the stream */
444887Schin #endif
454887Schin {
464887Schin int fd, oldfd, oflags, sflags;
478462SApril.Chin@Sun.COM SFMTXDECL(f);
484887Schin
494887Schin /* get the control flags */
504887Schin if((sflags = _sftype(mode,&oflags,NIL(int*))) == 0)
514887Schin return NIL(Sfio_t*);
524887Schin
534887Schin /* changing the control flags */
544887Schin if(f && !file && !((f->flags|sflags)&SF_STRING) )
558462SApril.Chin@Sun.COM { SFMTXENTER(f, NIL(Sfio_t*));
564887Schin
574887Schin if(f->mode&SF_INIT ) /* stream uninitialized, ok to set flags */
584887Schin { f->flags |= (sflags & (SF_FLAGS & ~SF_RDWR));
594887Schin
604887Schin if((sflags &= SF_RDWR) != 0) /* reset read/write modes */
614887Schin { f->flags = (f->flags & ~SF_RDWR) | sflags;
624887Schin
634887Schin if((f->flags&SF_RDWR) == SF_RDWR)
644887Schin f->bits |= SF_BOTH;
654887Schin else f->bits &= ~SF_BOTH;
664887Schin
674887Schin if(f->flags&SF_READ)
684887Schin f->mode = (f->mode&~SF_WRITE)|SF_READ;
694887Schin else f->mode = (f->mode&~SF_READ)|SF_WRITE;
704887Schin }
714887Schin }
724887Schin else /* make sure there is no buffered data */
734887Schin { if(sfsync(f) < 0)
744887Schin SFMTXRETURN(f,NIL(Sfio_t*));
754887Schin }
764887Schin
774887Schin if(f->file >= 0 && (oflags &= (O_TEXT|O_BINARY|O_APPEND)) != 0 )
784887Schin { /* set file access control */
794887Schin int ctl = sysfcntlf(f->file, F_GETFL, 0);
804887Schin ctl = (ctl & ~(O_TEXT|O_BINARY|O_APPEND)) | oflags;
814887Schin sysfcntlf(f->file, F_SETFL, ctl);
824887Schin }
834887Schin
844887Schin SFMTXRETURN(f,f);
854887Schin }
864887Schin
874887Schin if(sflags&SF_STRING)
884887Schin { f = sfnew(f,(char*)file,
894887Schin file ? (size_t)strlen((char*)file) : (size_t)SF_UNBOUND,
904887Schin -1,sflags);
914887Schin }
924887Schin else
934887Schin { if(!file)
944887Schin return NIL(Sfio_t*);
954887Schin
964887Schin #if _has_oflags /* open the file */
974887Schin while((fd = sysopenf((char*)file,oflags,SF_CREATMODE)) < 0 && errno == EINTR)
984887Schin errno = 0;
994887Schin #else
1004887Schin while((fd = sysopenf(file,oflags&O_ACCMODE)) < 0 && errno == EINTR)
1014887Schin errno = 0;
1024887Schin if(fd >= 0)
1034887Schin { if((oflags&(O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) )
1044887Schin { CLOSE(fd); /* error: file already exists */
1054887Schin return NIL(Sfio_t*);
1064887Schin }
1074887Schin if(oflags&O_TRUNC ) /* truncate file */
1084887Schin { reg int tf;
1094887Schin while((tf = syscreatf(file,SF_CREATMODE)) < 0 &&
1104887Schin errno == EINTR)
1114887Schin errno = 0;
1124887Schin CLOSE(tf);
1134887Schin }
1144887Schin }
1154887Schin else if(oflags&O_CREAT)
1164887Schin { while((fd = syscreatf(file,SF_CREATMODE)) < 0 && errno == EINTR)
1174887Schin errno = 0;
1184887Schin if((oflags&O_ACCMODE) != O_WRONLY)
1194887Schin { /* the file now exists, reopen it for read/write */
1204887Schin CLOSE(fd);
1214887Schin while((fd = sysopenf(file,oflags&O_ACCMODE)) < 0 &&
1224887Schin errno == EINTR)
1234887Schin errno = 0;
1244887Schin }
1254887Schin }
1264887Schin #endif
1274887Schin if(fd < 0)
1284887Schin return NIL(Sfio_t*);
1294887Schin
1304887Schin /* we may have to reset the file descriptor to its old value */
1314887Schin oldfd = f ? f->file : -1;
1324887Schin if((f = sfnew(f,NIL(char*),(size_t)SF_UNBOUND,fd,sflags)) && oldfd >= 0)
1334887Schin (void)sfsetfd(f,oldfd);
1344887Schin }
1354887Schin
1364887Schin return f;
1374887Schin }
1384887Schin
1394887Schin #if __STD_C
_sftype(reg const char * mode,int * oflagsp,int * uflagp)1404887Schin int _sftype(reg const char* mode, int* oflagsp, int* uflagp)
1414887Schin #else
1424887Schin int _sftype(mode, oflagsp, uflagp)
1434887Schin reg char* mode;
1444887Schin int* oflagsp;
1454887Schin int* uflagp;
1464887Schin #endif
1474887Schin {
1484887Schin reg int sflags, oflags, uflag;
1494887Schin
1504887Schin if(!mode)
1514887Schin return 0;
1524887Schin
1534887Schin /* construct the open flags */
1544887Schin sflags = oflags = uflag = 0;
1554887Schin while(1) switch(*mode++)
1564887Schin {
1574887Schin case 'a' :
1584887Schin sflags |= SF_WRITE | SF_APPENDWR;
1594887Schin oflags |= O_WRONLY | O_APPEND | O_CREAT;
1604887Schin continue;
16110898Sroland.mainz@nrubsig.org case 'b' :
16210898Sroland.mainz@nrubsig.org oflags |= O_BINARY;
16310898Sroland.mainz@nrubsig.org continue;
16410898Sroland.mainz@nrubsig.org case 'm' :
16510898Sroland.mainz@nrubsig.org sflags |= SF_MTSAFE;
16610898Sroland.mainz@nrubsig.org uflag = 0;
16710898Sroland.mainz@nrubsig.org continue;
1684887Schin case 'r' :
1694887Schin sflags |= SF_READ;
1704887Schin oflags |= O_RDONLY;
1714887Schin continue;
1724887Schin case 's' :
1734887Schin sflags |= SF_STRING;
1744887Schin continue;
1754887Schin case 't' :
1764887Schin oflags |= O_TEXT;
1774887Schin continue;
1784887Schin case 'u' :
1794887Schin sflags &= ~SF_MTSAFE;
1804887Schin uflag = 1;
1814887Schin continue;
18210898Sroland.mainz@nrubsig.org case 'w' :
18310898Sroland.mainz@nrubsig.org sflags |= SF_WRITE;
18410898Sroland.mainz@nrubsig.org oflags |= O_WRONLY | O_CREAT;
18510898Sroland.mainz@nrubsig.org if(!(sflags&SF_READ))
18610898Sroland.mainz@nrubsig.org oflags |= O_TRUNC;
18710898Sroland.mainz@nrubsig.org continue;
18810898Sroland.mainz@nrubsig.org case 'x' :
18910898Sroland.mainz@nrubsig.org oflags |= O_EXCL;
19010898Sroland.mainz@nrubsig.org continue;
19110898Sroland.mainz@nrubsig.org case 'F':
19210898Sroland.mainz@nrubsig.org /* stdio compatibility -- fd >= FOPEN_MAX (or other magic number) ok */
19310898Sroland.mainz@nrubsig.org continue;
1944887Schin case 'W' :
1954887Schin sflags |= SF_WCWIDTH;
1964887Schin uflag = 0;
1974887Schin continue;
19810898Sroland.mainz@nrubsig.org case '+' :
19910898Sroland.mainz@nrubsig.org if(sflags)
20010898Sroland.mainz@nrubsig.org sflags |= SF_READ|SF_WRITE;
20110898Sroland.mainz@nrubsig.org continue;
2024887Schin default :
2034887Schin if(!(oflags&O_CREAT) )
2044887Schin oflags &= ~O_EXCL;
2054887Schin #if _WIN32 && !_WINIX
2064887Schin if(!(oflags&(O_BINARY|O_TEXT)))
2074887Schin oflags |= O_BINARY;
2084887Schin #endif
2094887Schin if((sflags&SF_RDWR) == SF_RDWR)
2104887Schin oflags = (oflags&~O_ACCMODE)|O_RDWR;
2114887Schin if(oflagsp)
2124887Schin *oflagsp = oflags;
2134887Schin if(uflagp)
2144887Schin *uflagp = uflag;
2154887Schin if((sflags&(SF_STRING|SF_RDWR)) == SF_STRING)
2164887Schin sflags |= SF_READ;
2174887Schin return sflags;
2184887Schin }
2194887Schin }
220