Xinu7/src/cmd/download/lib/freedev.c

#include "/usr/include/stdio.h"
#include "/usr/include/sys/file.h"
#include "/usr/include/sys/types.h"
#include "/usr/include/sys/stat.h"

#include <freedev.h>
#include <getdev.h>

#define DEVNAME "/dev/%s"

freedev(class, request, user_rsrvd, flags)
char *class, *user_rsrvd;
int  request, flags;
{
	int retval;

	if ((flags & FD_RELES) && (flags & FD_DBENTRY))
		retval = freeD_reles(class, flags);
	else if (flags & FD_HOLD)
		retval = freeD_hold(class, request, user_rsrvd, flags);
	else if (flags & FD_FREE)
		retval = freeD_free(class, request, user_rsrvd, flags);
	else {
		fprintf(stderr, "freedev: unrecognizable request\n");
		retval = -1;
	}
	return(retval);
}

/*
 *=====================================================================
 * freeD_reles - release a physical device on reserve by somebody else
 *=====================================================================
 */
freeD_reles(phys, flags)
char *phys;
int  flags;
{
	char lknm[MAXNAMELEN], lkinfo[MAXRECLEN], *lkptr;
	char *user, *usr_lst, *get_ulock();
	int fdlk, reclen, fd_ulst, len;

	if (access(LOCKDIR, F_OK) == -1) {
		umask(0);
		mkdir(LOCKDIR, 0777);
	}
	sprintf(lknm, LOCKNAME, get_name(phys));
	if ((fdlk = open(lknm, O_RDONLY, 0)) < 0)
		return;		/* not on reserve */
	reclen = read(fdlk, lkinfo, MAXRECLEN);
	close(fdlk);
	lkinfo[reclen] = '\0';

	user = getuser(lkinfo);
	lkptr = skip_field(lkinfo);	/* move ptr to start of record,	*/
	lkptr = skip_white(lkptr);	/* so it is a db class entry	*/

	usr_lst = get_ulock(user, &len);
	if (len < 0)
		unlink(lknm);
	else {
		len = freeD_free(phys, 0, usr_lst, FD_DBENTRY);
		put_ulock(user, usr_lst, len);
	}
	return(0);
}

/*
 *==========================================================================
 * freeD_hold - release all devices held in user_rsrvd list except specific
 *    device requested.
 *==========================================================================
 */
freeD_hold(class, request, user_rsrvd, flags)
char *class;
int  request;
char *user_rsrvd;
int  flags;
{
	char lknm[MAXNAMELEN];
	char *phys, *devnm, *rsrvd_ptr;
	int found, firstfound, len, n;

	if (flags & FD_DBENTRY)
		phys = get_name(class);

	found = FALSE;
	firstfound = FALSE;
	len = 0;
	rsrvd_ptr = user_rsrvd;
	while(user_rsrvd != NULL  &&  *user_rsrvd != '\0') {
		if (flags & FD_DBENTRY) {
			if (strcmp(phys, get_phys(user_rsrvd)) == 0)
				found = TRUE;
		} else if (strcmp(class, get_class(user_rsrvd)) == 0
		       && ( ( n = atoi(get_num(user_rsrvd)) ) == request ||
			     request == FD_ANYDEV) ) {
				found = TRUE;
				request = n;
		}

		if (!found) {	/* free this entry */
			devnm = (flags & FD_DBENTRY) ? phys :
						       get_phys(user_rsrvd);
			sprintf(lknm, LOCKNAME, devnm);
			unlink(lknm);
		} 

		if (found && !firstfound) {/* first entry found--saveit */
			while (*user_rsrvd != NEWLINE) {
				*rsrvd_ptr++ = *user_rsrvd++;
				len++;
			}
			len++;	/* count the newline */
			*rsrvd_ptr++ = *user_rsrvd++;
			firstfound = TRUE;
		} else
			user_rsrvd = nextdb_entry(user_rsrvd);
		found = FALSE;
	}
	*rsrvd_ptr = '\0';
	return(len);
}

/*
 *========================================
 * freeD_free - free the specified device
 *========================================
 */
freeD_free(class, request, user_rsrvd, flags)
char *class;
int  request;
char *user_rsrvd;
int  flags;
{
	char *phys, *devnm, *list_ptr, *remove_entry;
	char *prev_ptr, *copy_ptr, lknm[MAXNAMELEN], *dbent;
	int found, len;

	if (flags & FD_DBENTRY)
		phys = get_name(class);

	remove_entry = NULL;
	list_ptr = user_rsrvd;
	len = 0;
	while(user_rsrvd != NULL  &&  *user_rsrvd != '\0') {
		if (flags & FD_DBENTRY) {
			if (strcmp(phys, get_phys(user_rsrvd)) == 0)
				remove_entry = user_rsrvd;
		} else if ( class == NULL  ||  strcmp(class,
						   get_class(user_rsrvd)) ) {
			if ( request == FD_ANYDEV  ||
			     request == atoi(get_num(user_rsrvd)) )
				remove_entry = user_rsrvd;
		}

		prev_ptr = user_rsrvd;
		user_rsrvd = nextdb_entry(user_rsrvd);

		if (remove_entry != NULL) {
			if (!(flags & FD_DBENTRY)) {
				devnm = get_phys(remove_entry);
				sprintf(lknm, LOCKNAME, devnm);
				unlink(lknm);
				if (flags & FD_VERBOSE) {
					dbent = lookup_db(devnm);
					printf("Released %s #%d (%s)\n",
						get_class(remove_entry),
						atoi(get_num(remove_entry)),
						shortname(dbent) );
				}
			}

			copy_ptr = remove_entry;
			while (*user_rsrvd != '\0')
				*remove_entry++ = *user_rsrvd++;
			*remove_entry = *user_rsrvd;
			user_rsrvd = copy_ptr;
			remove_entry = NULL;
		} else
			len += user_rsrvd - prev_ptr;
	}

	if (flags & FD_DBENTRY) {
		sprintf(lknm, LOCKNAME, phys);
		unlink(lknm);
	}
	return(len);
}