/* This file is part of 'minixfs' Copyright 1991,1992,1993 S.N. Henson */

#include "minixfs.h"
#include "proto.h"
#include "global.h"

/* inode_busy() scans the list for a given inode, this is used to stop
 * unlink blowing away a busy inode. In addition f->aux flag is set if 'flag'
 * is non zero. This is to allow a subsequent close to recognise that the inode
 * is marked for zapping.
 */

int inode_busy(inum,drive,flag)
unsigned inum;
int drive;
int flag;	/* Propagate AUX_DEL */
{
    FILEPTR *f;
    int found;

    found=0;
    for(f=firstptr;f;f=f->next)
    {
	if((f->fc.index==inum) && (f->fc.dev==drive))
	{
		if(flag) f->fc.aux|=AUX_DEL;
		if(found!=2) found++;
	}
	else if(found) break; /* Since same files consecutive, halt search */
    }
    return (found);
}


/* Copy characters from 'from' to 'to' translating backslashes to slashes */

void btos_cpy(to,from)
char *to;
const char *from;
{
	char c;
	do {
		c=*from++;	
		if(c=='\\')*to++='/';
		else *to++=c;
	}
	while(c);
}

/* Translate slashes to backslashes , return zero if all characters copied */

int stob_ncpy(to,from,n)
char *to;
const char *from;
long n;
{
	char c;

	if(n==0) return 0;

	do
	{
		c=*from++;
		if(c=='/')*to++='\\';
		else *to++=c;
	}
	while(--n && c );

	if(c)
	{
		*--to='\0';
		return 1;
	}
	return 0;
}

/* Check for access 'access' for given uid/gid/mode
 * return 0 if access allowed.
 */

int check_mode(euid,egid,rip,access)
int euid,egid,access;
d_inode *rip;
{
	if(!euid) return 0;
	if( euid==rip->i_uid && (rip->i_mode & access) ) return 0;
	if( egid==rip->i_gid && (rip->i_mode & (access >> 3) ) ) return 0;
	if( rip->i_mode & ( access >>6 ) ) return 0;
	return 1;
}

/*
 * Check an fcookie for a mount point, if mounted translate to the new FS.
 * Return 1 if it is a mount point.
 */

int check_mount(fc)
fcookie *fc;
{
	super_info *psblk;
	/* Go through list of filesystems mounted on this device */
	for(psblk=super_ptr[fc->dev]->mnt_first;psblk;psblk=psblk->mnt_next)
	{
		if(psblk->mnt_inode==fc->index)
		{
			fc->dev=psblk->dev;
			fc->index=ROOT_INODE;
			fc->aux=0;
			return 1;
		}
	}
	return 0;
}

/*
 * Change an to the point it is mounted on.
 * Returns zero for success or EMOUNT for failure.
 */

int cross_mount(fc)
fcookie *fc;
{
	super_info *psblk;
	psblk=super_ptr[fc->dev];
	if(!psblk->mnt_inode) return EMOUNT;
	fc->dev=psblk->mnt_dev;
	fc->index=psblk->mnt_inode;
	fc->aux=0;
	return 0;
}
