ftp.nice.ch/pub/next/unix/editor/elvis-2.0.N.bs.tar.gz#/elvis-2.0.N.bs/osmsdos/osblock.c

This is osblock.c in view mode; [Download] [Up]

/* osmsdos/osblock.c */

#include <sys/types.h>
#include <dos.h>
#include <io.h>
#include <errno.h>
#include <fcntl.h>
#include "elvis.h"
#ifndef DEFAULT_SESSION
# define DEFAULT_SESSION "ELVIS%d.SES"
#endif

/* Microsoft seems to think that the goal of ANSI C's namespace pollution
 * conventions is to make the language incompatible with existing C code.
 */
#ifndef O_RDWR
# define O_RDWR		_O_RDWR
# define O_RDONLY	_O_RDONLY
# define O_WRONLY	_O_WRONLY
# define O_CREAT	_O_CREAT
# define O_EXCL		_O_EXCL
# define O_BINARY	_O_BINARY
#endif

static int fd = -1; /* file descriptor of the session file */

/* This function creates a new block file, and returns True if successful,
 * or False if failed because the file was already busy.
 */
BOOLEAN blkopen(BOOLEAN force, BLK *buf)
{
	char	sesname[100];
	char	*sespath;
	int	len, i;

	/* If no session file was explicitly requested, use the default */
	if (!o_session)
	{
		/* search through SESSIONPATH for a writable directory */
		sespath = getenv("SESSIONPATH");
		if (!sespath)
			sespath = getenv("TMP");
		if (!sespath)
			sespath = "C:\\TMP;~;";
		do
		{
			for (len = 0; *sespath && *sespath != ';'; sespath++)
			{
				if (len == 0 && *sespath == '~')
				{
					strcpy(sesname, tochar8(o_home));
					len = strlen(sesname);
				}
				else
				{
					sesname[len++] = *sespath;
				}
			}
			if (len == 0)
			{
				strcpy(sesname, ".");
				len = 1;
			}
			if (sesname[len - 1] != '\\')
				sesname[len++] = '\\';
			strcpy(sesname + len, "elvis.tmp");
		} while ((i = open(sesname, O_RDWR|O_CREAT, 0666)) < 0 && *sespath++);
		if (i < 0)
		{
			msg(MSG_FATAL, "set \\$SESSIONPATH to a writable directory");
		}
		close(i);
		remove(sesname);

		/* create a unique session file in that directory */
		for (i = 1; i <= 999; i++)
		{
			sprintf(sesname + len, DEFAULT_SESSION, i);
			if (o_recovering)
			{
				if (access(sesname, 0) == 0)
					break;
			}
			else
			{
				if (access(sesname, 0) != 0)
					break;
			}	

			/* If the user wants to cancel, then fail */
			if (chosengui->poll && (*chosengui->poll)(False))
				return False;
		}
		if (i > 999)
		{
			msg(MSG_FATAL, "could not find default session file");
		}
		optpreset(o_session, CHARdup(toCHAR(sesname)), OPT_LOCK|OPT_FREE);
		o_tempsession = (BOOLEAN)!o_recovering;
	}

	/* Try to open the session file */
	fd = open(tochar8(o_session), O_RDWR|O_BINARY);
	if (fd < 0)
	{
		if (errno == ENOENT)
		{
			fd = open(o_session, O_RDWR|O_CREAT|O_EXCL|O_BINARY, 0600);
			if (fd >= 0)
			{
				if (write(fd, (char *)buf, (unsigned)o_blksize) < o_blksize)
				{
					close(fd);
					remove((char *)o_session);
					fd = -1;
					errno = ENOENT;
				}
				else
				{
					lseek(fd, 0L, 0);
				}
			}
		}
		if (fd < 0)
		{
			msg(MSG_FATAL, "[Sd]$1: no such session, errno=$2", o_session, (long)errno);
		}
	}
	else
	{
		/* if the session existed before elvis, it'll exist after */
		o_tempsession = False;
	}

	/* Read the first block & mark the session file as being "in use".
	 * If already marked as "in use" and !force, then fail.
	 */
	/* lockf(fd, LOCK, sizeof buf->super); */
	if (read(fd, buf, sizeof buf->super) != sizeof buf->super)
	{
		msg(MSG_FATAL, "blkopen's read failed");
	}
	if (buf->super.inuse && !force)
	{
		return False;
	}
	buf->super.inuse = 1;
	lseek(fd, 0L, 0);
	(void)write(fd, buf, sizeof buf->super);

	/* done! */
	return True;
}


/* This function closes the session file, given its handle */
void blkclose(BLK *buf)
{
	blkread(buf, 0);
	buf->super.inuse = 0L;
	blkwrite(buf, 0);
	close(fd);
	fd = -1;
	if (o_tempsession)
		remove(tochar8(o_session));
}

/* Write the contents of buf into record # blkno, for the block file
 * identified by blkhandle.  Blocks are numbered starting at 0.  The
 * requested block may be past the end of the file, in which case
 * this function is expected to extend the file.
 */
void blkwrite(BLK *buf, _BLKNO_ blkno)
{
	/* write the block */
	lseek(fd, (long)blkno * (long)o_blksize, 0);
	if (write(fd, buf, (unsigned)o_blksize) != o_blksize)
	{
		msg(MSG_FATAL, "blkwrite failed");
	}
}

/* Read the contends of record # blkno into buf, for the block file
 * identified by blkhandle.  The request block will always exist;
 * it will never be beyond the end of the file.
 */
void blkread(BLK *buf, _BLKNO_ blkno)
{
	/* read the block */
	lseek(fd, (long)blkno * o_blksize, 0);
	if (read(fd, buf, (unsigned)o_blksize) != o_blksize)
	{
		msg(MSG_FATAL, "blkread failed");
	}
}

/* Force changes out to disk. */
void blksync P_((void))
{
	close(fd);
	fd = open(tochar8(o_session), O_RDWR|O_BINARY);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.