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