14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*10898Sroland.mainz@nrubsig.org * Copyright (c) 1985-2009 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 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 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; 161*10898Sroland.mainz@nrubsig.org case 'b' : 162*10898Sroland.mainz@nrubsig.org oflags |= O_BINARY; 163*10898Sroland.mainz@nrubsig.org continue; 164*10898Sroland.mainz@nrubsig.org case 'm' : 165*10898Sroland.mainz@nrubsig.org sflags |= SF_MTSAFE; 166*10898Sroland.mainz@nrubsig.org uflag = 0; 167*10898Sroland.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; 182*10898Sroland.mainz@nrubsig.org case 'w' : 183*10898Sroland.mainz@nrubsig.org sflags |= SF_WRITE; 184*10898Sroland.mainz@nrubsig.org oflags |= O_WRONLY | O_CREAT; 185*10898Sroland.mainz@nrubsig.org if(!(sflags&SF_READ)) 186*10898Sroland.mainz@nrubsig.org oflags |= O_TRUNC; 187*10898Sroland.mainz@nrubsig.org continue; 188*10898Sroland.mainz@nrubsig.org case 'x' : 189*10898Sroland.mainz@nrubsig.org oflags |= O_EXCL; 190*10898Sroland.mainz@nrubsig.org continue; 191*10898Sroland.mainz@nrubsig.org case 'F': 192*10898Sroland.mainz@nrubsig.org /* stdio compatibility -- fd >= FOPEN_MAX (or other magic number) ok */ 193*10898Sroland.mainz@nrubsig.org continue; 1944887Schin case 'W' : 1954887Schin sflags |= SF_WCWIDTH; 1964887Schin uflag = 0; 1974887Schin continue; 198*10898Sroland.mainz@nrubsig.org case '+' : 199*10898Sroland.mainz@nrubsig.org if(sflags) 200*10898Sroland.mainz@nrubsig.org sflags |= SF_READ|SF_WRITE; 201*10898Sroland.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