1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 20 * * 21 ***********************************************************************/ 22 #include "sfhdr.h" 23 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. 27 ** 28 ** Written by Kiem-Phong Vo. 29 */ 30 31 #if _BLD_sfio && defined(__EXPORT__) 32 #define extern __EXPORT__ 33 #endif 34 extern 35 #undef extern 36 37 #if __STD_C 38 Sfio_t* _sfopen(reg Sfio_t* f, const char* file, const char* mode) 39 #else 40 Sfio_t* _sfopen(f,file,mode) 41 reg Sfio_t* f; /* old stream structure */ 42 char* file; /* file/string to be opened */ 43 reg char* mode; /* mode of the stream */ 44 #endif 45 { 46 int fd, oldfd, oflags, sflags; 47 48 /* get the control flags */ 49 if((sflags = _sftype(mode,&oflags,NIL(int*))) == 0) 50 return NIL(Sfio_t*); 51 52 /* changing the control flags */ 53 if(f && !file && !((f->flags|sflags)&SF_STRING) ) 54 { SFMTXSTART(f, NIL(Sfio_t*)); 55 56 if(f->mode&SF_INIT ) /* stream uninitialized, ok to set flags */ 57 { f->flags |= (sflags & (SF_FLAGS & ~SF_RDWR)); 58 59 if((sflags &= SF_RDWR) != 0) /* reset read/write modes */ 60 { f->flags = (f->flags & ~SF_RDWR) | sflags; 61 62 if((f->flags&SF_RDWR) == SF_RDWR) 63 f->bits |= SF_BOTH; 64 else f->bits &= ~SF_BOTH; 65 66 if(f->flags&SF_READ) 67 f->mode = (f->mode&~SF_WRITE)|SF_READ; 68 else f->mode = (f->mode&~SF_READ)|SF_WRITE; 69 } 70 } 71 else /* make sure there is no buffered data */ 72 { if(sfsync(f) < 0) 73 SFMTXRETURN(f,NIL(Sfio_t*)); 74 } 75 76 if(f->file >= 0 && (oflags &= (O_TEXT|O_BINARY|O_APPEND)) != 0 ) 77 { /* set file access control */ 78 int ctl = sysfcntlf(f->file, F_GETFL, 0); 79 ctl = (ctl & ~(O_TEXT|O_BINARY|O_APPEND)) | oflags; 80 sysfcntlf(f->file, F_SETFL, ctl); 81 } 82 83 SFMTXRETURN(f,f); 84 } 85 86 if(sflags&SF_STRING) 87 { f = sfnew(f,(char*)file, 88 file ? (size_t)strlen((char*)file) : (size_t)SF_UNBOUND, 89 -1,sflags); 90 } 91 else 92 { if(!file) 93 return NIL(Sfio_t*); 94 95 #if _has_oflags /* open the file */ 96 while((fd = sysopenf((char*)file,oflags,SF_CREATMODE)) < 0 && errno == EINTR) 97 errno = 0; 98 #else 99 while((fd = sysopenf(file,oflags&O_ACCMODE)) < 0 && errno == EINTR) 100 errno = 0; 101 if(fd >= 0) 102 { if((oflags&(O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) ) 103 { CLOSE(fd); /* error: file already exists */ 104 return NIL(Sfio_t*); 105 } 106 if(oflags&O_TRUNC ) /* truncate file */ 107 { reg int tf; 108 while((tf = syscreatf(file,SF_CREATMODE)) < 0 && 109 errno == EINTR) 110 errno = 0; 111 CLOSE(tf); 112 } 113 } 114 else if(oflags&O_CREAT) 115 { while((fd = syscreatf(file,SF_CREATMODE)) < 0 && errno == EINTR) 116 errno = 0; 117 if((oflags&O_ACCMODE) != O_WRONLY) 118 { /* the file now exists, reopen it for read/write */ 119 CLOSE(fd); 120 while((fd = sysopenf(file,oflags&O_ACCMODE)) < 0 && 121 errno == EINTR) 122 errno = 0; 123 } 124 } 125 #endif 126 if(fd < 0) 127 return NIL(Sfio_t*); 128 129 /* we may have to reset the file descriptor to its old value */ 130 oldfd = f ? f->file : -1; 131 if((f = sfnew(f,NIL(char*),(size_t)SF_UNBOUND,fd,sflags)) && oldfd >= 0) 132 (void)sfsetfd(f,oldfd); 133 } 134 135 return f; 136 } 137 138 #if __STD_C 139 int _sftype(reg const char* mode, int* oflagsp, int* uflagp) 140 #else 141 int _sftype(mode, oflagsp, uflagp) 142 reg char* mode; 143 int* oflagsp; 144 int* uflagp; 145 #endif 146 { 147 reg int sflags, oflags, uflag; 148 149 if(!mode) 150 return 0; 151 152 /* construct the open flags */ 153 sflags = oflags = uflag = 0; 154 while(1) switch(*mode++) 155 { 156 case 'w' : 157 sflags |= SF_WRITE; 158 oflags |= O_WRONLY | O_CREAT; 159 if(!(sflags&SF_READ)) 160 oflags |= O_TRUNC; 161 continue; 162 case 'a' : 163 sflags |= SF_WRITE | SF_APPENDWR; 164 oflags |= O_WRONLY | O_APPEND | O_CREAT; 165 continue; 166 case 'r' : 167 sflags |= SF_READ; 168 oflags |= O_RDONLY; 169 continue; 170 case 's' : 171 sflags |= SF_STRING; 172 continue; 173 case 'b' : 174 oflags |= O_BINARY; 175 continue; 176 case 't' : 177 oflags |= O_TEXT; 178 continue; 179 case 'x' : 180 oflags |= O_EXCL; 181 continue; 182 case '+' : 183 if(sflags) 184 sflags |= SF_READ|SF_WRITE; 185 continue; 186 case 'm' : 187 sflags |= SF_MTSAFE; 188 uflag = 0; 189 continue; 190 case 'u' : 191 sflags &= ~SF_MTSAFE; 192 uflag = 1; 193 continue; 194 case 'W' : 195 sflags |= SF_WCWIDTH; 196 uflag = 0; 197 continue; 198 default : 199 if(!(oflags&O_CREAT) ) 200 oflags &= ~O_EXCL; 201 #if _WIN32 && !_WINIX 202 if(!(oflags&(O_BINARY|O_TEXT))) 203 oflags |= O_BINARY; 204 #endif 205 if((sflags&SF_RDWR) == SF_RDWR) 206 oflags = (oflags&~O_ACCMODE)|O_RDWR; 207 if(oflagsp) 208 *oflagsp = oflags; 209 if(uflagp) 210 *uflagp = uflag; 211 if((sflags&(SF_STRING|SF_RDWR)) == SF_STRING) 212 sflags |= SF_READ; 213 return sflags; 214 } 215 } 216