2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: sfmove.c /main/3 1995/11/01 18:31:10 rswiston $ */
24 /***************************************************************
26 * AT&T - PROPRIETARY *
28 * THIS IS PROPRIETARY SOURCE CODE LICENSED BY *
31 * Copyright (c) 1995 AT&T Corp. *
32 * All Rights Reserved *
34 * This software is licensed by AT&T Corp. *
35 * under the terms and conditions of the license in *
36 * http://www.research.att.com/orgs/ssr/book/reuse *
38 * This software was created by the *
39 * Software Engineering Research Department *
40 * AT&T Bell Laboratories *
42 * For further information contact *
43 * gsf@research.att.com *
45 ***************************************************************/
48 /* Move data from one stream to another.
49 ** This code is written so that it'll work even in the presence
50 ** of stacking streams, pool, and discipline.
51 ** If you must change it, be gentle.
53 ** Written by Kiem-Phong Vo (12/07/90)
57 long sfmove(Sfio_t* fr, Sfio_t* fw, long n, reg int rc)
59 long sfmove(fr,fw,n,rc)
60 Sfio_t* fr; /* moving data from this stream */
61 Sfio_t* fw; /* moving data to this stream */
62 long n; /* number of bytes/records to move. <0 for unbounded move */
63 reg int rc; /* record separator */
71 uchar *rbuf = NIL(uchar*);
79 for(n_move = 0; n != 0; )
80 { /* get the streams into the right mode */
81 if(fr->mode != SF_READ && _sfmode(fr,SF_READ,0) < 0)
86 /* flush the write buffer as necessary to make room */
88 { if(fw->mode != SF_WRITE && _sfmode(fw,SF_WRITE,0) < 0 )
91 if(fw->next >= fw->endb ||
92 (fw->next > fw->data && fr->extent < 0 &&
93 (fw->extent < 0 || (fw->flags&SF_SHARE)) ) )
94 if(SFFLSBUF(fw,-1) < 0 )
98 /* about to move all, set map to a large amount */
99 if(n < 0 && (fr->flags&SF_MMAP))
100 fr->size = fr->size*SF_NMAP;
102 /* try reading a block of data */
104 if((r = fr->endb - (next = fr->next)) <= 0)
105 { /* amount of data remained to be read */
106 if((w = n > SF_MAXINT ? SF_MAXINT : (int)n) < 0)
108 w = fr->data == fr->tiny ? SF_GRAIN : fr->size;
109 else if((fr->extent-fr->here) > SF_NMAP*SF_PAGE)
111 else w = (int)(fr->extent-fr->here);
114 /* use a decent buffer for data transfer but make sure
115 that if we overread, the left over can be retrieved
117 if(!(fr->flags&(SF_MMAP|SF_STRING)) &&
118 (n < 0 || fr->extent >= 0L) )
119 { reg int maxw = 4*(_Sfpage > 0 ? _Sfpage : SF_PAGE);
121 /* direct transfer to a seekable write stream */
122 if(fw && fw->extent >= 0 && w <= (fw->endb-fw->next) )
123 { w = fw->endb - (next = fw->next);
126 else if(w > fr->size && maxw > fr->size)
127 { /* making our own buffer */
130 else w = ((w+fr->size-1)/fr->size)*fr->size;
131 if(rsize <= 0 && (rbuf = (uchar*)malloc(w)) )
142 { /* make sure we don't read too far ahead */
143 if(n > 0 && fr->extent < 0 && (fr->flags&SF_SHARE) )
145 { /* try peeking a large buffer */
147 if((r = SFFILBUF(fr,-1)) > 0)
149 else /* get a single record */
155 else if((long)(r = fr->size) > n)
159 if((r = SFFILBUF(fr,r)) <= 0)
165 { /* actual amount to be read */
166 if(rc < 0 && n > 0 && n < w)
169 if((r = SFRD(fr,next,w,fr->disc)) > 0)
170 fr->next = fr->endb = fr->endr = fr->data;
173 else goto again; /* popped stack */
177 /* compute the extent of data to be moved */
189 { /* count records */
190 reg int rdwr = (fr->flags&(SF_BOTH|SF_MALLOC|SF_MMAP));
197 for(cp = next; cp < endb; )
198 { /* find the line extent */
202 else while(r-- && *cp++ != rc)
204 if(cp < endb || w == rc)
206 if(n > 0 && (n -= 1) == 0)
214 { /* advance the read point by proper amount */
215 fr->mode &= ~SF_PKRD;
216 (void)read(fr->file,(Void_t*)next,r);
226 else if((w = endb-cp) > 0)
227 { /* move left-over to read stream */
230 memcpy((Void_t*)fr->data,(Void_t*)cp,w);
231 fr->endb = fr->data+w;
232 if((w = endb - (cp+w)) > 0)
233 (void)SFSK(fr,(long)(-w),1,fr->disc);
237 { if(direct == SF_WRITE)
239 else if(r <= (fw->endb-fw->next) )
240 { memcpy((Void_t*)fw->next,(Void_t*)next,r);
243 else if((w = SFWRITE(fw,(Void_t*)next,r)) != r)
244 { /* a write error happened */
251 (void)SFSEEK(fr,(long)(-r),1);
263 if(n < 0 && (fr->flags&SF_MMAP) )