home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
LANGUAGS
/
C
/
MFILE.LBR
/
MFILE.CZ
/
MFILE.C
Wrap
Text File
|
2000-06-30
|
8KB
|
384 lines
/* mfile.c - a program to permit arbitrary numbers of concurrently
* open files
*/
#include <stdio.h>
#include "dequeue.h" /* dequeue package */
#define lruMFS lastNode /* dequeue macros */
#define mruMFS firstNode
#define ERROR -1
/* a test for valid internal fd
- used to try to catch user errors
*/
#define validMFS(x,y) ((y->mfdNum) == x)
extern long lseek();
#define MAXFILES 60 /* this value can be arbitrarily large */
#define MAXOPEN 12 /* this is the number of files the host handles */
#define OK 1
typedef int EFD; /* host system file descriptor */
typedef int MFD; /* internal file descriptor */
typedef struct mfS
{
/* dequeue structure */
struct mfS
*pMFS, *nMFS;
int mfdNum;
/* internal file descriptor data */
int status;
int efd;
/* currency data */
char fname[65];
long lpos;
}
MFS;
/* various file statuses - used in mfS.status to determine validity
of element and operations */
#define OPEN 1
#define CLOSED 2
#define UNASSIGNED 0
#define EMPTY -1 /* signals out of internal fd */
#define UNINIT -2 /* signals intialization needed */
/* hide some internal details unless debugging */
#if defined DEBUG
#define Static
#else
#define Static static
#endif
Static MFS *mFiles[MAXFILES]; /* list of all internal fd */
Static MFD mfdFree = UNINIT; /* empty free list */
Static unsigned numOpen = 0; /* number of currently open files */
/*
* (semi) standard low level file primitives
*/
MFD mOpen(fname, mode)
char *fname;
int mode;
{
int temp;
obtainEFD(); /* ensure 1 host fd is free */
temp = mfdCreate( open(fname, mode) );
#if defined(DEBUG)
printf("open:%s to mfd %d\n",fname,temp);
dump(mFiles[temp]);
#endif
if (temp < 0)
return ERROR;
numOpen++;
strcpy(mFiles[temp]->fname, fname); /* establish currency */
return(temp);
}
MFD mCreate(fname, mode)
char *fname;
int mode;
{
int temp;
obtainEFD();
temp = mfdCreate( create(fname, mode, 0) );
#if defined(DEBUG)
printf("create: %s to mfd %d\n",fname,temp);
dump(mFiles[temp]);
#endif
if (temp < 0)
return ERROR;
numOpen++;
strcpy(mFiles[temp]->fname, fname);
return(temp);
}
int mClose(mfd)
MFD mfd;
{
MFS *mfs;
#if defined(DEBUG)
printf("mClose:");
dump(mFiles[mfd]);
#endif
mfs = mFiles[mfd];
if (validMFS(mfd, mfs))
{
if (mfs->status == OPEN)
{
if (close(mfs->efd) < 0)
return ERROR;
numOpen--;
}
mfdDestroy(mfd);
return 0;
}
else return ERROR;
}
int mRead(mfd,buf,cnt)
MFD mfd;
char *buf;
int cnt;
{
#if defined(DEBUG)
int tmp;
printf("mRead(%d,%04x,%d) - %d\n",
mfd,
buf,
cnt,
tmp = read(mReopen(mfd), buf, cnt)
);
return tmp;
#else
return read(mReopen(mfd), buf, cnt);
#endif
}
int mWrite(mfd,buf,cnt)
MFD mfd;
char *buf;
int cnt;
{
#if defined(DEBUG)
int tmp;
printf("mWrite(%d,%04x,%d) - %d\n",
mfd,
buf,
cnt,
tmp = write(mReopen(mfd), buf, cnt)
);
return tmp;
#else
return write(mReopen(mfd), buf, cnt);
#endif
}
long mlseek(mfd, offs, mode)
MFD mfd;
long offs;
int mode;
{
#if defined(DEBUG)
long tmp;
printf("mlseek(%d,%ld,%d) - %d\n",
mfd,
offs,
mode,
tmp = lseek(mReopen(mfd), offs, mode)
);
return tmp;
#else
return lseek(mReopen(mfd), offs, mode);
#endif
}
/* Low level internal functions
*/
/* get host file descriptor for file, closing other files if need to. */
EFD mReopen(mfd)
MFD mfd;
{
register MFS *mfs;
mfs = mFiles[mfd];
if (validMFS(mfd,mfs)) /* check fd is valid */
{
#if defined(DEBUG)
printf("mReopen:");
dump(mfs);
#endif
switch(mfs->status) /* what is current real file status */
{
case OPEN: /* file is currently open */
mSplice(mfs); /* make this most recently used */
#if defined(DEBUG)
printf("mReopen:");
dump(mfs);
#endif
return mfs->efd;
case CLOSED: /* file needs to be reOpened */
if (obtainEFD())
{
mEnQue(mfs); /* put on open list */
mRestore(mfs); /* restore currency */
#if defined(DEBUG)
printf("mReopen:");
dump(mfs);
#endif
return mfs->efd;
}
else return ERROR;
default:
return ERROR;
}
}
else return ERROR;
}
/* routine to ensure at least one host file descriptor is available
ie: after x = obtainEFD(), numOpen < MAXOPEN or x == 0; */
Static int obtainEFD()
{
MFS *oMfs;
if (numOpen < MAXOPEN) /* still unused space */
return OK;
oMfs = lruMFS; /* get least recently used file */
#if defined(DEBUG)
printf("obtainEFD: lruMFD %d\n",oMfs->mfdNum);
#endif
/* save currency info and close file */
if (mSave(oMfs))
{
/* successfully freed up one host fd */
oMfs->status = CLOSED;
close(oMfs->efd);
mDeQue(oMfs); /* remove lru file from active queue */
return OK;
}
return 0; /* failed to close file */
}
/* mSave() - store currency information prior to temporary file closure
** you will no doubt have a better way to do this on
** your system, but it would make the package non portable.
** changing this to grab lpos and name from low level fd
** would speed it up.
*/
Static int mSave(mfs)
MFS *mfs;
{
/* save currency information */
sync(); /* flush buffers to disk - optional */
/* >>>NOTE<<< this will not work for non-seekable devices
(e.g. keyboards, printers, crts &tc */
mfs->lpos = lseek(mfs->efd, 0L, 1);
if (close(mfs->efd) < 0)
return 0;
numOpen--;
return OK;
}
/* restore currency information */
Static EFD mRestore(mfs)
MFS *mfs;
{
int temp;
mfs->efd = open(mfs->fname,0);
if (mfs->efd >= 0)
{
if (mfs->lpos != -1L) /* may be at start of file anyway */
mfs->lpos = lseek(mfs->efd, mfs->lpos, 0);
mfs->status = OPEN;
numOpen++;
}
else mfs->status = ERROR;
return mfs->efd;
}
Static MFD mfdCreate(efd)
EFD efd;
{
MFD mfd;
register MFS *mfs;
char *malloc();
if (efd < 0)
return ERROR;
if (mfdFree < 0)
if (mfdFree == EMPTY) /* out of file slots */
return ERROR;
else mInit(); /* initialise fd array */
mfd = mfdFree;
mfs = (MFS *) malloc(sizeof(MFS));
if (mfs == NULL) /* out of space for file details */
return ERROR;
mfdFree = mFiles[mfdFree]; /* pop free slot stack */
mFiles[mfd] = mfs; /* assoc mfs with mfd */
mfs->mfdNum = mfd; /* assoc mfd with mfs */
mfs->efd = efd; /* assoc eon fd with mfs */
mfs->status = OPEN; /* flag status as open */
(mfs->nMFS) = (mfs->pMFS) = UNINIT; /* not on any queue yet */
mfs->fname[0] = '\0'; /* no file name yet */
mfs->lpos = -1L; /* no position yet */
mEnQue(mfs); /* put mfs as most recently used */
return mfd; /* return file slot number */
}
Static int mfdDestroy(mfd)
MFD mfd;
{
MFS *mfs;
mfs = mFiles[mfd];
if (validMFS(mfd,mfs))
{
if ( (mfs->status) == OPEN )
mDeQue(mfs);
free(mfs);
mFiles[mfd] = mfdFree;
mfdFree = mfd;
}
else return ERROR;
}
mInit()
{
int i;
for (i = 0; i<MAXFILES; i++) mFiles[i]=i+1;
mFiles[i-1] = -1;
mfdFree = 1;
}
#if defined(DEBUG)
dump(f)
MFS *f;
{
printf(" Element %04x:%d,%s,%d[%04x|%04x]%s,%ld\n",
f,
f->mfdNum,
(
(f->status == 1) ? "OPEN" :
(f->status == 2) ? "CLOSED" :
(f->status == 0) ? "UNASSIGNED" :
(f->status ==-1) ? "ERROR" :
"???"
),
f->efd,
f->pMFS,
f->nMFS,
f->fname,
f->lpos);
}
#endif
/* end of mfile.c */