Source to jet/filesys.c


Enter a symbol's name here to quickly find it.

#include <ctype.h>
#include <Files.h>
#include <Errors.h>
#include <Strings.h>
#include <OSUtils.h>

#include "jet.h"

#define FILES 10
#define F_RES 5

#define MAC_DRV ('P' - 'A')

#define TOS_NAMELEN 13

typedef struct dtabuf {
	short	index;		/* index into arrays in the PROC struct */
	long	magic;
#define SVALID	0x1234fedcL	/* magic for a valid search */
#define EVALID	0x5678ba90L	/* magic for an exhausted search */
	char	dta_pat[TOS_NAMELEN+1];	/* pointer to pattern, if necessary */
	char	dta_sattrib;	/* attributes being searched for */
/* this stuff is returned to the user */
	char	dta_attrib;
	short	dta_time;
	short	dta_date;
	long	dta_size;
	char	dta_name[TOS_NAMELEN+1];
} DTABUF;

typedef struct file_block {
	int owner;
	short ref;
} file_block;

static long rwabs(short rwflag, void *buffer, short number, short recno,
		  short dev, long lrecno);
static long mediach(short dev);
static long getbpb(short dev);

static void init_mfs_drive(void);
static long mfs_drive_rwabs(short rwflag, void *buffer, short number,
			    short recno, short dev, long lrecno);

static file_block file[FILES];

static short mac_ref;

static short mfs_drv;
static short mfs_ref;

static _BPB def_bpb = {
	512,
	2,
	1024,
	7,
	5,
	6,
	18,
	351,
	0
};

void init_filesys(void)
{
	int i;
	VolumeParam pb;

	sysvar.rwabs = rwabs;
	sysvar.mediach = mediach;
	sysvar.getbpb = getbpb;
	sysvar.drvmap = 1L << MAC_DRV;
	for (i = 1; true; i++) {
		pb.ioVolIndex = i;
		pb.ioNamePtr = 0;
		if (PBGetVInfoSync((ParmBlkPtr)&pb) != noErr)
			break;
		PBFlushVolSync((ParmBlkPtr)&pb);
	}
	for (i = 0; i < F_RES; i++) {
		file[i].ref = 0;
		file[i].owner = JET_PROC;
	}
	for (i = F_RES+1; i < FILES; i++) {
		file[i].ref = 0;
		file[i].owner = NO_PROC;
	}
	pb.ioNamePtr = 0;
	PBGetVolSync((ParmBlkPtr)&pb);
	mac_ref = pb.ioVRefNum;
	init_mfs_drive();
}

static void fname2mac(const char *fname, short *ref, Str255 mname)
{
	char *p;
	
	if (fname[0] && fname[1] == ':') {
		*mname = 0;
		if (fname[0] - 'A' != MAC_DRV) {
			*ref = 0x7fff; /* invalid */
			return;
		}
		*ref = mac_ref;
		fname += 2;
	} else {
		*ref = mac_ref;
		strcpy((char *)mname, "\\");
	}
	strcat((char *)mname, fname);
	for (p = (char *)mname; *p; p++) {
		if (*p == '\\')
			*p = ':';
		*p = toupper(*p);
	}
	C2PStr((Ptr)mname);
}

static short mac2attr(short attr)
{
	if (attr & 16)
		return FA_DIR;
	else if (attr & 1)
		return FA_RDONLY;
	else
		return 0;
}

/* low level stuff */

static long rwabs(short rwflag, void *buffer, short number, short recno,
	short dev, long lrecno)
{
	if (dev == mfs_drv)
		return mfs_drive_rwabs(rwflag, buffer, number, recno, dev, lrecno);
	return 0;
}

static long mediach(short dev)
{
	return 0;
}

static long getbpb(short dev)
{
	return (long)&def_bpb;
}

/* minix filesystem stuff */

static void init_mfs_drive(void)
{
	short map;
	ParamBlockRec pb;
	char msg[100];

	pb.ioParam.ioNamePtr = "\pMFS";
	pb.ioParam.ioVRefNum = mac_ref;
	pb.ioParam.ioVersNum = 0;
	pb.ioParam.ioPermssn = fsRdWrPerm;
	pb.ioParam.ioMisc = 0;
	if (PBOpenSync(&pb) != noErr) {
		mfs_drv = -1;
		return;
	}
	mfs_ref = pb.ioParam.ioRefNum;
	mfs_drv = 0;
	for (map = sysvar.drvmap; map & 1; map = map >> 1)
		mfs_drv++;
	sysvar.drvmap |= 1L << mfs_drv;
	sprintf(msg, "MinixFS is drive: %c\r\n", mfs_drv + 'A');
	c_conws(msg);
}

static long mfs_drive_rwabs(short rwflag, void *buffer, short number, short recno, short dev, long lrecno)
{
	ParamBlockRec pb;
	char *p;
	long n;

	pb.ioParam.ioRefNum = mfs_ref;
	pb.ioParam.ioBuffer = buffer;
	pb.ioParam.ioReqCount = 512L * number;
	pb.ioParam.ioPosMode = 1;
	pb.ioParam.ioPosOffset = 512L * recno;
	if (rwflag == 2) {
		PBReadSync(&pb);
		if (pb.ioParam.ioResult == eofErr) {
			for (p = buffer, n = 0; n < 512L * number; p++, n++)
				*p = 0;
			pb.ioParam.ioResult = 0;
		}
		if (pb.ioParam.ioResult != 0)
			pb.ioParam.ioResult = -1;
		return pb.ioParam.ioResult;
	}
	if (rwflag == 3) {
		PBWriteSync(&pb);
		if (pb.ioParam.ioResult != 0)
			pb.ioParam.ioResult = -1;
		return pb.ioParam.ioResult;
	}
	return -1;
}

/* file stuff */

long f_create(const char *filename, short attr)
{
	return -EACCESS;
}

long f_delete(const char *filename)
{
	return -EACCESS;
}

long f_rename(short zero, const char *oldname, const char *newname)
{
	return -EACCESS;
}

long f_attrib(const char *filename, short wflag, short attrib)
{
	CInfoPBRec cinfo;
	short ref;
	Str255 pname;
	
	fname2mac(filename, &ref, pname);
	cinfo.hFileInfo.ioNamePtr = (StringPtr)pname;
	cinfo.hFileInfo.ioVRefNum = ref;
	cinfo.hFileInfo.ioFDirIndex = 0;
	cinfo.hFileInfo.ioDirID = 0;
	if (PBGetCatInfoSync(&cinfo) != 0)
		return -ENOENT;
	return mac2attr(cinfo.hFileInfo.ioFlAttrib);
}

long f_datime(_DOSTIME *timeptr, short handle, short wflag)
{
	if (!wflag) {
		timeptr->time = 0;
		timeptr->date = 0;
	}
	return 0;
}

long f_open(const char *filename, short mode)
{
	int i;
	short ref;
	Str255 pname;
	ParamBlockRec pb;
	
	fname2mac(filename, &ref, pname);
	for (i = 0; i < FILES; i++)
		if (file[i].owner == NO_PROC)
			break;
	if (i >= FILES) {
		c_conws("JET filesys: too many open files");
		return -ENMFIL;
	}
	pb.ioParam.ioNamePtr = pname;
	pb.ioParam.ioVRefNum = ref;
	pb.ioParam.ioVersNum = 0;
	pb.ioParam.ioPermssn = mode + 1;
	pb.ioParam.ioMisc = 0;
	if (PBOpenSync(&pb))
		return -ENOENT;
	file[i].ref = pb.ioParam.ioRefNum;
	file[i].owner = JET_PROC;
	return i;
}

long f_close(short handle)
{
	if (file[handle].ref)
		FSClose(file[handle].ref);
	file[handle].ref = 0;
	file[handle].owner = NO_PROC;
	return 0;
}

long f_read(short handle, long count, void *buf)
{
	OSErr r;
	
	r = FSRead(file[handle].ref, &count, buf);
	if ((r != noErr) && (r != eofErr))
		return -EERROR;
	return count;
}

long f_write(short handle, long count, void *buf)
{
	return -EERROR;
}

long f_seek(long offset, short handle, short seekmode)
{
	long newoff;
	static mode_map[] = { 1, 3, 2 };
	short mode;
	
	if ((handle < F_RES) || (handle >= FILES))
		return 0;
	mode = mode_map[seekmode];
	SetFPos(file[handle].ref, mode, offset);
	GetFPos(file[handle].ref, &newoff);
	return newoff;
}

long f_force(short stch, short nonstdh)
{
	return 0; /* ? */
}

/* drive/path stuff */

long d_setdrv(short drv)
{
	if (drv != MAC_DRV)
		return -EERROR;
	return sysvar.drvmap;
}

long d_getdrv(void)
{
	return MAC_DRV;
}

long d_getpath(char *path, short driveno)
{
	strcpy(path, "\\");
	return 0;
}

/* directory stuff */

long d_create(const char *path)
{
	return -EACCESS;
}

long d_delete (const char *path)
{
	return -EACCESS;
}

/* search stuff */

void f_setdta(_DTA *buf)
{
	curbp->p_dta = (char *)buf;
}

_DTA *f_getdta(void)
{
	return (_DTA *)curbp->p_dta;
}

static short fs_vref;
static long fs_dirid;
static int fs_index;

long f_sfirst(const char *filename, short attr)
{
	DTABUF *foo;
	Str255 pname;
	short r;
	char *p;
	CInfoPBRec cinfo;
	char path[PATH_MAX];
	
	/* setup dta */
	foo = (DTABUF *)curbp->p_dta;
	foo->magic = EVALID;
	if (strchr(filename, '\\'))
		strcpy(path, filename);
	else
		sprintf(path, "%c:\\%s", 'A' + MAC_DRV, filename);
	p = strrchr(path, '\\');
	strcpy(foo->dta_pat, p + 1);
	*(p + 1) = 0;
	foo->dta_sattrib = attr;
	fname2mac(path, &fs_vref, pname);
	cinfo.hFileInfo.ioNamePtr = (StringPtr) pname;
	cinfo.hFileInfo.ioVRefNum = fs_vref;
	cinfo.hFileInfo.ioFDirIndex = 0;
	cinfo.hFileInfo.ioDirID = 0;
	if (PBGetCatInfoSync(&cinfo) != 0)
		return -ENOENT;
	if (!(cinfo.hFileInfo.ioFlAttrib & 16))
		return -ENOENT;
	fs_dirid = cinfo.hFileInfo.ioDirID;
	fs_index = 1;
	if ((r = f_snext()) == -ENMFIL) {
		return -ENOENT;
	}
	return r;
}

/* next two routines borrowed from the mint source filesys.c, copyright Eric Smith and Atari */

void
copy8_3(dest, src)
	char *dest;
	const char *src;
{
	char fill = ' ', c;
	int i;

	if (src[0] == '.') {
		if (src[1] == 0) {
			strcpy(dest, ".       .   ");
			return;
		}
		if (src[1] == '.' && src[2] == 0) {
			strcpy(dest, "..      .   ");
			return;
		}
	}
	if (src[0] == '*' && src[1] == '.' && src[2] == '*' && src[3] == 0) {
		dest[0] = '*';
		dest[1] = 0;
		return;
	}

	for (i = 0; i < 8; i++) {
		c = *src++;
		if (!c || c == '.') break;
		if (c == '*') {
			fill = c = '?';
		}
		*dest++ = toupper(c);
	}
	while (i++ < 8) {
		*dest++ = fill;
	}
	*dest++ = '.';
	i = 0;
	fill = ' ';
	while (c && c != '.')
		c = *src++;

	if (c) {
		for( ;i < 3; i++) {
			c = *src++;
			if (!c || c == '.') break;
			if (c == '*')
				c = fill = '?';
			*dest++ = toupper(c);
		}
	}
	while (i++ < 3)
		*dest++ = fill;
	*dest = 0;
}

/*
 * int pat_match(name, patrn): returns 1 if "name" matches the template in
 * "patrn", 0 if not. "patrn" is assumed to have been expanded in 8.3
 * format by copy8_3; "name" need not be. Any '?' characters in patrn
 * will match any character in name. Note that if "patrn" has a '*' as
 * the first character, it will always match; this will happen only if
 * the original pattern (before copy8_3 was applied) was "*.*".
 *
 * BUGS: acts a lot like the silly TOS pattern matcher.
 */

int
pat_match(name, template)
	const char *name, *template;
{
	register char *s, c;
	char expname[TOS_NAMELEN+1];

	if (*template == '*') return 1;
	copy8_3(expname, name);

	s = expname;
	while ((c = *template++) != 0) {
		if (c != *s && c != '?')
			return 0;
		s++;
	}
	return 1;
}

static int f_smatch(char *pat, char *file)
{
	char expname[TOS_NAMELEN+1];

	copy8_3(expname, pat);
	return pat_match(file, expname);
}

long f_snext(void)
{
	CInfoPBRec cinfo;
	DTABUF *foo;
	Str255 pname;
	char *p;

	foo = (DTABUF *)curbp->p_dta;
	foo->magic = EVALID;
	for (;;) {
		cinfo.hFileInfo.ioNamePtr = (StringPtr) pname;
		cinfo.hFileInfo.ioVRefNum = fs_vref;
		cinfo.hFileInfo.ioFDirIndex = fs_index++;
		cinfo.hFileInfo.ioDirID = fs_dirid;
		if (PBGetCatInfoSync(&cinfo) != 0)
			return -ENMFIL;
		/* skip invisible files */
		if ((cinfo.hFileInfo.ioFlAttrib & 16) || 
		   !(cinfo.hFileInfo.ioFlFndrInfo.fdFlags & fInvisible)) {
			P2CStr(pname);
			if (f_smatch(foo->dta_pat, (char *)pname))
				break;
		}
	}
	foo->magic = SVALID;
	pname[TOS_NAMELEN] = 0;
	strncpy(foo->dta_name, (char *) pname, TOS_NAMELEN);
	for (p = foo->dta_name; *p; p++) *p = toupper(*p);
	foo->dta_attrib = mac2attr(cinfo.hFileInfo.ioFlAttrib);
	foo->dta_time = 0;
	foo->dta_date = 0;
	foo->dta_size = 0;
	if ((foo->dta_attrib & FA_DIR) == FA_DIR)
		return 0;
	foo->dta_size = cinfo.hFileInfo.ioFlLgLen;
	foo->dta_time = mac2time(cinfo.hFileInfo.ioFlMdDat);
	foo->dta_date = mac2date(cinfo.hFileInfo.ioFlMdDat);
	return 0;
}