1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2009 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 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 /* Change the file descriptor 25 ** 26 ** Written by Kiem-Phong Vo. 27 */ 28 29 #if __STD_C 30 static int _sfdup(int fd, int newfd) 31 #else 32 static int _sfdup(fd,newfd) 33 int fd; 34 int newfd; 35 #endif 36 { 37 reg int dupfd; 38 39 #ifdef F_DUPFD /* the simple case */ 40 while((dupfd = sysfcntlf(fd,F_DUPFD,newfd)) < 0 && errno == EINTR) 41 errno = 0; 42 return dupfd; 43 44 #else /* do it the hard way */ 45 if((dupfd = sysdupf(fd)) < 0 || dupfd >= newfd) 46 return dupfd; 47 48 /* dup() succeeded but didn't get the right number, recurse */ 49 newfd = _sfdup(fd,newfd); 50 51 /* close the one that didn't match */ 52 CLOSE(dupfd); 53 54 return newfd; 55 #endif 56 } 57 58 #if __STD_C 59 int sfsetfd(Sfio_t* f, int newfd) 60 #else 61 int sfsetfd(f,newfd) 62 Sfio_t *f; 63 int newfd; 64 #endif 65 { 66 reg int oldfd; 67 SFMTXDECL(f); 68 69 SFMTXENTER(f, -1); 70 71 if(f->flags&SF_STRING) 72 SFMTXRETURN(f, -1); 73 74 if((f->mode&SF_INIT) && f->file < 0) 75 { /* restoring file descriptor after a previous freeze */ 76 if(newfd < 0) 77 SFMTXRETURN(f, -1); 78 } 79 else 80 { /* change file descriptor */ 81 if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0) 82 SFMTXRETURN(f, -1); 83 SFLOCK(f,0); 84 85 oldfd = f->file; 86 if(oldfd >= 0) 87 { if(newfd >= 0) 88 { if((newfd = _sfdup(oldfd,newfd)) < 0) 89 { SFOPEN(f,0); 90 SFMTXRETURN(f, -1); 91 } 92 CLOSE(oldfd); 93 } 94 else 95 { /* sync stream if necessary */ 96 if(((f->mode&SF_WRITE) && f->next > f->data) || 97 (f->mode&SF_READ) || f->disc == _Sfudisc) 98 { if(SFSYNC(f) < 0) 99 { SFOPEN(f,0); 100 SFMTXRETURN(f, -1); 101 } 102 } 103 104 if(((f->mode&SF_WRITE) && f->next > f->data) || 105 ((f->mode&SF_READ) && f->extent < 0 && 106 f->next < f->endb) ) 107 { SFOPEN(f,0); 108 SFMTXRETURN(f, -1); 109 } 110 111 #ifdef MAP_TYPE 112 if((f->bits&SF_MMAP) && f->data) 113 { SFMUNMAP(f,f->data,f->endb-f->data); 114 f->data = NIL(uchar*); 115 } 116 #endif 117 118 /* make stream appears uninitialized */ 119 f->endb = f->endr = f->endw = f->data; 120 f->extent = f->here = 0; 121 f->mode = (f->mode&SF_RDWR)|SF_INIT; 122 f->bits &= ~SF_NULL; /* off /dev/null handling */ 123 } 124 } 125 126 SFOPEN(f,0); 127 } 128 129 /* notify changes */ 130 if(_Sfnotify) 131 (*_Sfnotify)(f, SF_SETFD, (void*)((long)newfd)); 132 133 f->file = newfd; 134 135 SFMTXRETURN(f,newfd); 136 } 137