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 /* Write data out to the file system 25 ** 26 ** Written by Kiem-Phong Vo. 27 */ 28 29 #if __STD_C 30 ssize_t sfwrite(reg Sfio_t* f, const Void_t* buf, reg size_t n) 31 #else 32 ssize_t sfwrite(f,buf,n) 33 reg Sfio_t* f; /* write to this stream. */ 34 Void_t* buf; /* buffer to be written. */ 35 reg size_t n; /* number of bytes. */ 36 #endif 37 { 38 reg uchar *s, *begs, *next; 39 reg ssize_t w; 40 reg int local; 41 42 SFMTXSTART(f, (ssize_t)(-1)); 43 44 GETLOCAL(f,local); 45 46 if(!buf) 47 SFMTXRETURN(f, (ssize_t)(n == 0 ? 0 : -1) ); 48 49 /* release peek lock */ 50 if(f->mode&SF_PEEK) 51 { if(!(f->mode&SF_WRITE) && (f->flags&SF_RDWR) != SF_RDWR) 52 SFMTXRETURN(f, (ssize_t)(-1)); 53 54 if((uchar*)buf != f->next && 55 (!f->rsrv || f->rsrv->data != (uchar*)buf) ) 56 SFMTXRETURN(f, (ssize_t)(-1)); 57 58 f->mode &= ~SF_PEEK; 59 60 if(f->mode&SF_PKRD) 61 { /* read past peeked data */ 62 char buf[16]; 63 reg ssize_t r; 64 65 for(w = n; w > 0; ) 66 { if((r = w) > sizeof(buf)) 67 r = sizeof(buf); 68 if((r = sysreadf(f->file,buf,r)) <= 0) 69 { n -= w; 70 break; 71 } 72 else w -= r; 73 } 74 75 f->mode &= ~SF_PKRD; 76 f->endb = f->data + n; 77 f->here += n; 78 } 79 80 if((f->mode&SF_READ) && f->proc) 81 f->next += n; 82 } 83 84 s = begs = (uchar*)buf; 85 for(;; f->mode &= ~SF_LOCK) 86 { /* check stream mode */ 87 if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0 ) 88 { w = s > begs ? s-begs : -1; 89 SFMTXRETURN(f,w); 90 } 91 92 SFLOCK(f,local); 93 94 w = f->endb - f->next; 95 96 if(s == f->next) /* after sfreserve */ 97 { if(w > (ssize_t)n) 98 w = (ssize_t)n; 99 f->next = (s += w); 100 n -= w; 101 break; 102 } 103 104 /* attempt to create space in buffer */ 105 if(w == 0 || ((f->flags&SF_WHOLE) && w < (ssize_t)n) ) 106 { if(f->flags&SF_STRING) /* extend buffer */ 107 { (void)SFWR(f, s, n-w, f->disc); 108 if((w = f->endb - f->next) < (ssize_t)n) 109 { if(!(f->flags&SF_STRING)) /* maybe sftmp */ 110 { if(f->next > f->data) 111 goto fls_buf; 112 } 113 else if(w == 0) 114 break; 115 } 116 } 117 else if(f->next > f->data) 118 { fls_buf: 119 (void)SFFLSBUF(f, -1); 120 if((w = f->endb - f->next) < (ssize_t)n && 121 (f->flags&SF_WHOLE) && f->next > f->data ) 122 break; 123 } 124 } 125 126 if(!(f->flags&SF_STRING) && f->next == f->data && 127 (((f->flags&SF_WHOLE) && w <= n) || SFDIRECT(f,n)) ) 128 { /* bypass buffering */ 129 if((w = SFWR(f,s,n,f->disc)) <= 0 ) 130 break; 131 } 132 else 133 { if(w > (ssize_t)n) 134 w = (ssize_t)n; 135 if(w <= 0) /* no forward progress possible */ 136 break; 137 memcpy(f->next, s, w); 138 f->next += w; 139 } 140 141 s += w; 142 if((n -= w) <= 0) 143 break; 144 } 145 146 /* always flush buffer for share streams */ 147 if(f->extent < 0 && (f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC) ) 148 (void)SFFLSBUF(f,-1); 149 150 /* check to see if buffer should be flushed */ 151 else if(n == 0 && (f->flags&SF_LINE) && !(f->flags&SF_STRING)) 152 { if((ssize_t)(n = f->next-f->data) > (w = s-begs)) 153 n = w; 154 if(n > 0 && n < HIFORLINE) 155 { for(next = f->next-1; n > 0; --n, --next) 156 { if(*next == '\n') 157 { n = HIFORLINE; 158 break; 159 } 160 } 161 } 162 if(n >= HIFORLINE) 163 (void)SFFLSBUF(f,-1); 164 } 165 166 SFOPEN(f,local); 167 168 w = s-begs; 169 SFMTXRETURN(f,w); 170 } 171