Files
Arquivotheca.AIX-4.1.3/bos/usr/bin/dosdir/dwrite.c
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

149 lines
3.5 KiB
C

static char sccsid[] = "@(#)09 1.5 src/bos/usr/bin/dosdir/dwrite.c, cmdpcdos, bos411, 9428A410j 1/25/91 01:42:27";
/*
* COMPONENT_NAME: CMDDOS routines to read dos floppies
*
* FUNCTIONS: dwrite
*
* ORIGINS: 10,27
*
* IBM CONFIDENTIAL -- (IBM Confidential Restricted when
* combined with the aggregated modules for this product)
* SOURCE MATERIALS
* (C) COPYRIGHT International Business Machines Corp. 1985, 1989
* All Rights Reserved
*
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
#include <sys/errno.h>
#include "pcdos.h"
#include "doserrno.h"
static int getnextclusterX(register FCB *file);
/*
* DWRITE returns # bytes written or -1 on error
*/
dwrite(file, buffer, length)
int length;
register FCB *file;
byte *buffer;
{
register int lwrite, rspace;
int i, ret;
extern int dos_pid;
char *bufsave = buffer;
int curcluster;
TRACE(("dwrite(file = %x, buffer = %x, length = %d)\n", file, buffer,
length));
if (file->magic != FCBMAGIC) {
doserrno = DE_INVAL;
return (-1);
}
if ((file->oflag & 3) == DO_RDONLY) {
doserrno = DE_ACCES;
return (-1);
}
_DFsetlock(file->disk);
if (file->oflag & DO_APPEND) {
if (dlseek(file, 0, 2) < 0) {
_DFunlock(file->disk);
return (-1);
}
}
if (!file->nowcluster && !_DFgetnewcluster(file, file->disk)) {
_DFunlock(file->disk);
return (-1);
}
for (i = 0; i < LOCK_RETRY_COUNT; i++) {
if ((ret = dlock(dos_pid, file,
file->offset, length, L_TEST)) == -1) {
/* hit a lock, try again */
sleep(LOCK_RETRY_TIME);
} else
break;
}
if (ret == -1) {
doserrno = DE_DEADLK;
return (-1);
}
while (length) {
int extra = length;
/* seek to current clust */
if (lseek(file->disk->fd, file->seek + file->clseek, 0) < 0) {
doserrno = errno;
_DFunlock(file->disk);
return (-1);
}
/*
* if we need more space, we get the next cluster and if it is
* the one past the current cluster, we just increase the
* amount we are going to write. The idea is to make big
* writes if we are luck and get consecutive clusters.
*/
curcluster = file->nowcluster;
if ((rspace = file->clustsize - file->clseek) > extra)
rspace = extra;
if (!(extra -= rspace)) /* fits in this cluster */
file->clseek += rspace;
else
while (extra &&
(file->nowcluster = getnextclusterX(file)) &&
file->nowcluster == curcluster + 1) {
curcluster = file->nowcluster;
if (extra > file->clustsize)
file->clseek = file->clustsize;
else
file->clseek = extra;
extra -= file->clseek;
rspace += file->clseek;
}
while (rspace) {
if ((lwrite = _devio(file->disk->protect, file->disk->fd, buffer,
rspace)) < 0) {
if (errno == EINTR)
continue;
doserrno = errno;
_DFunlock(file->disk);
return (-1);
}
length -= lwrite;
file->offset += lwrite;
file->changed |= 1;
if (file->offset > file->size)
file->size = file->offset;
buffer += lwrite;
rspace -= lwrite;
}
if (file->nowcluster == 0) {
_DFunlock(file->disk);
return (buffer - bufsave);
}
file->seek = file->disk->data +
(file->clustsize * (file->nowcluster - 2));
}
_DFunlock(file->disk);
return (buffer - bufsave);
}
static int getnextclusterX(register FCB *file)
{
int rc;
if ((rc = getnextcluster(file->disk, file->nowcluster)) >= PC_EOF)
rc = _DFgetnewcluster(file, file->disk);
return rc;
}