1/*********************************************************************** 2* * 3* This software is part of the ast package * 4* Copyright (c) 1985-2011 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 30ssize_t sfwrite(Sfio_t* f, const Void_t* buf, size_t n) 31#else 32ssize_t sfwrite(f,buf,n) 33Sfio_t* f; /* write to this stream. */ 34Void_t* buf; /* buffer to be written. */ 35size_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 memmove(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