xref: /onnv-gate/usr/src/lib/libast/common/sfio/_sfopen.c (revision 12068:08a39a083754)
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