Files
oldlinux-files/study/linux-travel/minix-386/estdio21.tar/estdio21/fwrite.c
2024-02-19 00:25:23 -05:00

122 lines
3.2 KiB
C

/* f w r i t e */
#include "stdiolib.h"
/*LINTLIBRARY*/
__stdiosize_t fwrite F4(void *, ptr,
__stdiosize_t, size,
__stdiosize_t, nitems,
FILE *, fp)
{
__stdiosize_t wrote; /* bytes written in write call */
__stdiobuf_t *p; /* buffer pointer */
__stdiobuf_t *q; /* output buffer pointer */
__stdiobuf_t *pbuf; /* line buffered flush pointer */
__stdiosize_t itemsleft; /* whole or partial items left */
register __stdiosize_t leftover; /* bytes left over this iteration */
__stdiosize_t nextover; /* bytes left over next iteration */
register __stdiosize_t writesize; /* size of write */
__stdiosize_t writeitem; /* whole items written */
__stdiosize_t oversize; /* writesize less leftover */
__stdiosize_t writebytes; /* total bytes to write (small) */
__stdiosize_t bytesleft; /* bytes left to write (small) */
__stdiosize_t byteswrote; /* bytes written (small) */
__stdiosize_t bytescan; /* bytes to scan (small) */
/* Items left to write */
if (CHECKWRITE(fp) || (itemsleft = nitems) == 0 || size == 0)
return 0;
/* Fix void * casting problems */
p = (__stdiobuf_t *) ptr;
/* Small amounts go via putc */
if (! TESTFLAG(fp, _IONBF) &&
(UNUSEDINWRITEBUFFER(fp)+BUFFERSIZE(fp))/size > itemsleft) {
pbuf = GETWRITEPTR(fp);
writebytes = bytesleft = itemsleft*size;
do {
if ((writesize = UNUSEDINWRITEBUFFER(fp)) > bytesleft)
writesize = bytesleft;
if (writesize == 0) {
if (FFLUSH(fp))
break;
}
else {
bytesleft -= writesize;
q = GETWRITEPTR(fp);
if (writesize > FWRITETHRESHOLD) {
MEMCPY(q, p, (size_t) writesize);
p += writesize;
q += writesize;
}
else {
do
*q++ = *p++;
while (--writesize);
}
SETWRITEPTR(fp, q);
}
} while (bytesleft != 0);
byteswrote = writebytes - bytesleft;
if (TESTFLAG(fp, _IOLBF)) {
bytescan = byteswrote;
if (pbuf + bytescan != GETWRITEPTR(fp)) {
pbuf = fp->__base;
bytescan = BYTESINWRITEBUFFER(fp);
}
if (MEMCHR(pbuf, '\n', (size_t) bytescan) != NULL)
(void) FFLUSH(fp);
}
return byteswrote/size;
}
/* Large amounts get fed directly to the file */
if (BYTESINWRITEBUFFER(fp) != 0 && FFLUSH(fp))
return 0;
/* The rest of the data goes to the file directly */
for (nextover=writeitem=0; (itemsleft -= writeitem) != 0; p += writesize) {
leftover = nextover;
writesize = ~((__stdiosize_t) 0);
writeitem = 0;
/* Very large objects will require several large writes */
if (writesize < leftover)
nextover = leftover - writesize;
/* Account for end of last object and start of new ones */
else {
if (leftover != 0)
writeitem = 1;
oversize = writesize - leftover;
if ((writeitem += oversize/size) < itemsleft)
nextover = size - oversize%size;
else {
writeitem = itemsleft;
writesize = leftover + itemsleft*size;
if (leftover != 0)
writesize -= size;
}
}
wrote = __iowrite(fileno(fp), (char *) p, writesize);
if (wrote != writesize) {
if (wrote >= leftover) {
itemsleft -= (wrote-leftover)/size;
if (leftover != 0)
itemsleft--;
}
break;
}
}
return nitems-itemsleft;
}