gurba-0.40/
gurba-0.40/bin/
gurba-0.40/lib/
gurba-0.40/lib/cmds/guild/fighter/
gurba-0.40/lib/cmds/monster/
gurba-0.40/lib/cmds/race/catfolk/
gurba-0.40/lib/cmds/race/dwarf/
gurba-0.40/lib/cmds/verb/
gurba-0.40/lib/daemons/data/
gurba-0.40/lib/data/boards/
gurba-0.40/lib/data/messages/
gurba-0.40/lib/data/players/
gurba-0.40/lib/design/
gurba-0.40/lib/domains/gurba/
gurba-0.40/lib/domains/gurba/guilds/fighter/
gurba-0.40/lib/domains/gurba/monsters/
gurba-0.40/lib/domains/gurba/objects/armor/
gurba-0.40/lib/domains/gurba/objects/clothing/
gurba-0.40/lib/domains/gurba/objects/weapons/
gurba-0.40/lib/domains/gurba/vendors/
gurba-0.40/lib/kernel/cmds/admin/
gurba-0.40/lib/kernel/daemons/
gurba-0.40/lib/kernel/include/
gurba-0.40/lib/kernel/lib/
gurba-0.40/lib/kernel/net/
gurba-0.40/lib/kernel/sys/
gurba-0.40/lib/logs/
gurba-0.40/lib/pub/
gurba-0.40/lib/std/modules/languages/
gurba-0.40/lib/std/races/
gurba-0.40/lib/std/races/monsters/
gurba-0.40/lib/wiz/fudge/
gurba-0.40/lib/wiz/spud/
gurba-0.40/src/host/beos/
gurba-0.40/src/host/pc/res/
gurba-0.40/src/kfun/
gurba-0.40/src/lpc/
gurba-0.40/src/parser/
gurba-0.40/tmp/
# include <Files.h>
# include <StandardFile.h>
# include <Errors.h>
# define INCLUDE_FILE_IO
# include "dgd.h"

extern Uint m2utime(long t);

typedef struct {
    short fref;		/* file ref */
    Str255 fname;	/* file name */
} fdtype;

static fdtype fdtab[20];

static long crea;	/* creator */
static long type;	/* file type */

static short vref;	/* volume refNum of current directory */
static long dirid;	/* directory ID */


/*
 * NAME:	fsinit()
 * DESCRIPTION:	initialize file functions
 */
void fsinit(long fcrea, long ftype)
{
    WDPBRec buf;
    Str255 str;

    crea = fcrea;
    type = ftype;
    buf.ioNamePtr = str;
    PBHGetVolSync(&buf);
    vref = buf.ioVRefNum;
    dirid = buf.ioWDDirID;
}


/*
 * NAME:	path_file()
 * DESCRIPTION:	convert a path to host format
 */
char *path_file(char *path)
{
    static char buf[STRINGSZ];
    char *p;

    if (path == (char *) NULL || strlen(path) >= STRINGSZ) {
	return (char *) NULL;
    }
    buf[0] = ':';
    if (path[0] == '.' && path[1] == '\0') {
	buf[1] = '\0';
	return buf;
    }
    strncpy(buf + 1, path, STRINGSZ - 1);
    buf[STRINGSZ - 1] = '\0';

    for (p = buf + 1; *p != '\0'; p++) {
	if (*p == '/') {
	    *p = ':';
	} else if (*p == ':') {
	    *p = '/';
	}
    }

    return buf;
}

/*
 * NAME:	path_unfile()
 * DESCRIPTION:	convert a path from host format
 */
char *path_unfile(char *path)
{
    static char buf[STRINGSZ];
    char *p;

    /* must start with : */
    if (path[1] == '\0') {
	buf[0] = '.';
	buf[1] = '\0';
	return buf;
    }
    strncpy(buf, path + 1, STRINGSZ - 1);
    buf[STRINGSZ - 1] = '\0';

    for (p = buf; *p != '\0'; p++) {
	if (*p == '/') {
	    *p = ':';
	} else if (*p == ':') {
	    *p = '/';
	}
    }

    return buf;
}


/*
 * NAME:	getpath()
 * DESCRIPTION:	get the full path of a file
 */
char *getpath(char *buf, short vref, unsigned char *fname)
{
    Str255 str;
    DirInfo dir;

    buf += STRINGSZ - 1;
    buf[0] = '\0';
    memcpy(str, fname, fname[0] + 1);
    memcpy(buf -= fname[0], fname + 1, fname[0]);

    dir.ioNamePtr = str;
    dir.ioCompletion = NULL;
    dir.ioFDirIndex = 0;
    dir.ioVRefNum = vref;
    dir.ioDrDirID = 0;
    for (;;) {
	PBGetCatInfoSync((CInfoPBPtr) &dir);
	memcpy(buf -= str[0], str + 1, str[0]);
	if (dir.ioDrDirID == 2) {
	    return buf;
	}
	dir.ioFDirIndex = -1;
	dir.ioDrDirID = dir.ioDrParID;
	*--buf = ':';
    }
}

/*
 * NAME:	getfile()
 * DESCRIPTION:	get the path of a specific file with a standard dialog
 */
char *getfile(char *buf, long type)
{
    Point where;
    SFTypeList list;
    SFReply reply;

    where.h = 82;
    where.v = 124;
    list[0] = type;
    SFGetFile(where, NULL, NULL, 1, list, NULL, &reply);
    if (reply.good) {
	return getpath(buf, reply.vRefNum, reply.fName);
    } else {
	return NULL;
    }
}


/*
 * NAME:	filename()
 * DESCRIPTION:	translate a path to a pascal string
 */
static unsigned char *filename(unsigned char *to, const char *from)
{
    int n;

    n = strlen(from);
    to[0] = n;
    memcpy(to + 1, from, n);

    return to;
}

/*
 * NAME:	pathname()
 * DESCRIPTION:	translate a pascal string to a path
 */
static char *pathname(char *to, const unsigned char *from)
{
    memcpy(to, from, from[0] + 1);
    to[0] = ':';
    to[from[0] + 1] = '\0';

    return to;
}


static long sdirid;		/* scan directory ID */
static short sdiridx;		/* scan directory index */
static HFileInfo sdirbuf;	/* scan dir file info */

/*
 * NAME:	P->opendir()
 * DESCRIPTION:	open a directory
 */
bool P_opendir(char *path)
{
    HFileInfo buf;
    Str255 str;

    buf.ioVRefNum = vref;
    buf.ioFDirIndex = 0;
    buf.ioNamePtr = filename(str, path);
    buf.ioDirID = dirid;
    if (PBGetCatInfoSync((CInfoPBPtr) &buf) != noErr ||
	(buf.ioFlAttrib & ioDirMask) == 0) {
	return FALSE;
    }
    sdirid = buf.ioDirID;
    sdiridx = 1;
    return TRUE;
}

/*
 * NAME:	P->readdir()
 * DESCRIPTION:	read the next filename from the currently open directory
 */
char *P_readdir(void)
{
    Str255 str;
    static char path[34];

    sdirbuf.ioVRefNum = vref;
    sdirbuf.ioFDirIndex = sdiridx++;
    sdirbuf.ioNamePtr = str;
    sdirbuf.ioDirID = sdirid;
    if (PBGetCatInfoSync((CInfoPBPtr) &sdirbuf) != noErr) {
	return NULL;
    }

    return pathname(path, str);
}

/*
 * NAME:	P->closedir()
 * DESCRIPTION:	close the currently open directory
 */
void P_closedir(void)
{
    sdiridx = 0;
}


/*
 * NAME:	open()
 * DESCRIPTION:	open a file
 */
int open(const char *path, int flags, int mode)
{
    int fd;
    short fref;

    for (fd = 0; fdtab[fd].fref != 0; fd++) {
	if (fd == sizeof(fdtab) / sizeof(short) - 1) {
	    return -1;
	}
    }

    switch (HOpen(vref, dirid, filename(fdtab[fd].fname, path), fsRdWrShPerm,
		  &fref)) {
    case noErr:
	if ((flags & O_EXCL) ||
	    ((flags & O_TRUNC) && SetEOF(fref, 0L) != noErr) ||
	    ((flags & O_APPEND) && SetFPos(fref, fsFromLEOF, 0) != noErr)) {
	    FSClose(fref);
	    return -1;
	}
	break;

    case fnfErr:
    case dirNFErr:
	if ((flags & O_CREAT) &&
	    HCreate(vref, dirid, fdtab[fd].fname, crea, type) == noErr &&
	    HOpen(vref, dirid, fdtab[fd].fname, fsRdWrShPerm, &fref) == noErr) {
	    break;
	}
	/* fall through */

    default:
	return -1;
    }

    fdtab[fd].fref = fref;
    return fd;
}

/*
 * NAME:	close()
 * DESCRIPTION:	close a file
 */
int close(int fd)
{
    FSClose(fdtab[fd].fref);
    fdtab[fd].fref = 0;

    return 0;
}

/*
 * NAME:	read()
 * DESCRIPTION:	read from a file
 */
int read(int fd, void *buf, int nbytes)
{
    long count;

    count = nbytes;
    switch (FSRead(fdtab[fd].fref, &count, buf)) {
    case noErr:
    case eofErr:
	return (int) count;

    default:
	return -1;
    }
}

/*
 * NAME:	write()
 * DESCRIPTION:	write to a file
 */
int write(int fd, const void *buf, int nbytes)
{
    long count;

    count = nbytes;
    switch (FSWrite(fdtab[fd].fref, &count, buf)) {
    case noErr:
    case dskFulErr:
	return (int) count;

    default:
	return -1;
    }
}

/*
 * NAME:	lseek()
 * DESCRIPTION:	seek on a file
 */
long lseek(int fd, long offset, int whence)
{
    short mode;

    switch (whence) {
    case SEEK_SET:
	mode = fsFromStart;
	break;

    case SEEK_CUR:
	mode = fsFromMark;
	break;

    case SEEK_END:
	mode = fsFromLEOF;
	break;
    }

    /*
     * note: no seek beyond the end of the file
     */
    if (SetFPos(fdtab[fd].fref, mode, offset) != noErr) {
	return -1;
    }
    if (mode != fsFromStart) {
	GetFPos(fdtab[fd].fref, &offset);
    }
    return offset;
}

/*
 * NAME:	stat()
 * DESCRIPTION:	get information about a file
 */
int stat(const char *path, struct stat *sb)
{
    HFileInfo buf;
    Str255 str;

    if (sdiridx != 0) {
	buf = sdirbuf;
    } else {
	buf.ioVRefNum = vref;
	buf.ioFDirIndex = 0;
	buf.ioNamePtr = filename(str, path);
	buf.ioDirID = dirid;
	if (PBGetCatInfoSync((CInfoPBPtr) &buf) != noErr) {
	    return -1;
	}
    }

    sb->st_mode = (buf.ioFlAttrib & ioDirMask) ? S_IFDIR : S_IFREG;
    sb->st_size = buf.ioFlLgLen;
    sb->st_mtime = (long) m2utime(buf.ioFlMdDat);

    return 0;
}

/*
 * NAME:	fstat()
 * DESCRIPTION:	get information about an open file
 */
int fstat(int fd, struct stat *sb)
{
    HFileInfo buf;

    buf.ioVRefNum = vref;
    buf.ioFDirIndex = 0;
    buf.ioNamePtr = fdtab[fd].fname;
    buf.ioDirID = dirid;
    if (PBGetCatInfoSync((CInfoPBPtr) &buf) != noErr) {
	return -1;
    }

    sb->st_mode = (buf.ioFlAttrib & ioDirMask) ? S_IFDIR : S_IFREG;
    sb->st_size = buf.ioFlLgLen;
    sb->st_mtime = (long) m2utime(buf.ioFlMdDat);

    return 0;
}

/*
 * NAME:	unlink()
 * DESCRIPTION:	remove a file (but not a directory)
 */
int unlink(const char *path)
{
    HFileInfo buf;
    Str255 str;

    buf.ioVRefNum = vref;
    buf.ioFDirIndex = 0;
    buf.ioNamePtr = filename(str, path);
    buf.ioDirID = dirid;
    if (PBGetCatInfoSync((CInfoPBPtr) &buf) != noErr ||
	(buf.ioFlAttrib & ioDirMask)) {
	return -1;
    }
    return (HDelete(vref, dirid, str) == noErr) ? 0 : -1;
}

/*
 * NAME:	rename()
 * DESCRIPTION:	rename a file
 */
int rename(const char *from, const char *to)
{
    char *p, *q;
    Str255 dir1, dir2, file1, file2;
    HFileInfo buf;
    long xdirid;

    p = strrchr(from, ':');
    q = strrchr(to, ':');
    if (p == NULL || q == NULL) {
	return -1;
    }
    memcpy(dir1 + 1, from, dir1[0] = p - from);
    if (dir1[0] == 0) {
	dir1[++(dir1[0])] = ':';
    }
    filename(file1, p);
    memcpy(dir2 + 1, to, dir2[0] = q - to);
    if (dir2[0] == 0) {
	dir2[++(dir2[0])] = ':';
    }
    filename(file2, q);

    /* source directory must exist */
    buf.ioVRefNum = vref;
    buf.ioFDirIndex = 0;
    buf.ioNamePtr = dir1;
    buf.ioDirID = dirid;
    if (PBGetCatInfoSync((CInfoPBPtr) &buf) != noErr ||
	(buf.ioFlAttrib & ioDirMask) == 0) {
	return -1;
    }
    xdirid = buf.ioDirID;

    /* source file must exist */
    buf.ioNamePtr = file1;
    if (PBGetCatInfoSync((CInfoPBPtr) &buf) != noErr) {
	return -1;
    }
    if (buf.ioFlAttrib & ioDirMask) {
	file1[++(file1[0])] = ':';
	file2[++(file2[0])] = ':';
    }

    if (p - from != q - to || memcmp(from, to, p - from) != 0) {
	CMovePBRec move;

	/*
	 * move to different directory
	 */

	/* destination directory must exist */
	buf.ioNamePtr = dir2;
	buf.ioDirID = dirid;
	if (PBGetCatInfoSync((CInfoPBPtr) &buf) != noErr ||
	    (buf.ioFlAttrib & ioDirMask) == 0) {
	    return -1;
	}
	move.ioNewDirID = buf.ioDirID;

	/* destination must not already exist */
	buf.ioNamePtr = file2;
	if (PBGetCatInfoSync((CInfoPBPtr) &buf) == noErr) {
	    return -1;
	}

	/* rename source */
	memcpy(dir1, file1, file1[0] + 1);
	memcpy(file1, "\p:_tmp0000", 6);
	do {
	    static short count;

	    if (count == 9999) {
		count = 0;
	    }
	    sprintf((char *) file1 + 6, "%04d", ++count);
	    buf.ioNamePtr = file1;
	    buf.ioDirID = xdirid;
	} while (PBGetCatInfoSync((CInfoPBPtr) &buf) == noErr);
	if (dir1[dir1[0]] == ':') {
	    file1[++(file1[0])] = ':';
	}
	if (HRename(vref, xdirid, dir1, file1) != noErr) {
	    return -1;
	}

	/* move source to new directory */
	move.ioNamePtr = file1;
	move.ioVRefNum = vref;
	move.ioNewName = NULL;
	move.ioDirID = xdirid;
	if (PBCatMoveSync(&move) != noErr) {
	    /* back to old name */
	    HRename(vref, xdirid, file1, dir1);
	    return -1;
	}

	xdirid = move.ioNewDirID;
    }

    return (HRename(vref, xdirid, file1, file2) == noErr) ? 0 : -1;
}

/*
 * NAME:	access()
 * DESCRIPTION:	check access on a file
 */
int access(const char *path, int mode)
{
    HFileInfo buf;
    Str255 str;

    buf.ioVRefNum = vref;
    buf.ioFDirIndex = 0;
    buf.ioNamePtr = filename(str, path);
    buf.ioDirID = dirid;
    if (PBGetCatInfoSync((CInfoPBPtr) &buf) != noErr) {
	return -1;
    }

    if (mode == W_OK) {
	return (buf.ioFlAttrib & 0x01) ? -1 : 0;
    }
    return 0;
}

/*
 * NAME:	mkdir()
 * DESCRIPTION:	create a directory
 */
int mkdir(const char *path, int mode)
{
    Str255 str;
    long newdir;

    if (DirCreate(vref, dirid, filename(str, path), &newdir) == noErr) {
	return 0;
    } else {
	return -1;
    }
}

/*
 * NAME:	rmdir()
 * DESCRIPTION:	remove an empty directory
 */
int rmdir(const char *path)
{
    HFileInfo buf;
    Str255 str;

    buf.ioVRefNum = vref;
    buf.ioFDirIndex = 0;
    buf.ioNamePtr = filename(str, path);
    buf.ioDirID = dirid;
    if (PBGetCatInfoSync((CInfoPBPtr) &buf) != noErr ||
	(buf.ioFlAttrib & ioDirMask) == 0) {
	return -1;
    }
    return (HDelete(vref, dirid, str) == noErr) ? 0  : -1;
}

/*
 * NAME:	chdir()
 * DESCRIPTION:	change the current directory
 */
int chdir(const char *path)
{
    HFileInfo buf;
    Str255 str;

    buf.ioVRefNum = vref;
    buf.ioFDirIndex = 0;
    buf.ioNamePtr = filename(str, path);
    buf.ioDirID = dirid;
    if (PBGetCatInfoSync((CInfoPBPtr) &buf) != noErr ||
	(buf.ioFlAttrib & ioDirMask) == 0) {
	return -1;
    }
    dirid = buf.ioDirID;
    return 0;
}