home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 2
/
crawlyvol2.bin
/
alt_os
/
mint
/
mfs6011
/
source
/
minixfs
/
dir.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-30
|
4KB
|
145 lines
/* This file is part of 'minixfs' Copyright 1991,1992,1993 S.N.Henson */
#include "minixfs.h"
#include "proto.h"
#include "global.h"
/* search_dir serves 3 functions dependent on 'mode'
0 Search a directory for the entry 'name' if found return its inode number.
1 Create an entry 'name' return position of d_inum .
2 Delete an entry 'name' return inode num for success .
3 Find entry 'name', return position of d_inum.
In all cases failure is denoted by a negative error number .
*/
long search_dir(name,inum,drive,flag)
const char *name;
unsigned inum;
int drive;
int flag;
{
int entry,count;
long zone; /* Zone number within dir */
long lstfree; /* Last unused dir entry */
d_inode rip;
cache *tmp;
int tflag;
int incr;
int mfname;
static char tname[MNAME_MAX];
incr=super_ptr[drive]->increment;
mfname=MMAX_FNAME(incr);
if( (tflag=do_trans(SRCH_TOS,drive)) )
strcpy(tname,tosify(name,tflag,mfname));
read_inode(inum,&rip,drive);
/* Must be a directory ! */
if(!IS_DIR(rip)) return EPTHNF;
lstfree=-1l;
for(zone=0; (count=cnext_zone(&rip,zone,&tmp,drive)>>L_DIR_SIZE);
zone++)
{
dir_struct *try;
for(entry=0,try=tmp->buffer->bdir;entry<count;entry+=incr,try+=incr) {
unshort inumtemp;
inumtemp=try->d_inum;
if(inumtemp &&
(!strncmp(name,try->d_name,mfname) || (tflag &&
(!strcmp(tname,tosify(try->d_name,tflag,mfname)) ) )))
{
if(flag==KILL)
{
/* Never ever allow unlinking of '.' or '..' */
if(zone==0 && entry<(2 * incr))return EACCDN;
try->d_inum=0;
/* Next bit pinched from Minix,
* store old inode num in last 2 bytes of name
* This allows recovery in case of accident
*/
*((unshort *)&try->d_name[MMAX_FNAME(incr)-2])=inumtemp;
#if 1
tmp->status=2;
#else
/* buffer tmp points to _might_ be invalidated in find_zone... */
write_zone(find_zone(&rip,zone,drive,0),tmp
,drive,&syscache);
#endif
}
if(flag==ADD) return EACCDN;
if(flag==FIND || flag==KILL ) return inumtemp;
if(flag==POS) return entry*DIR_ENTRY_SIZE+zone*BLOCK_SIZE;
}
if(flag==ADD && lstfree==-1l && !inumtemp)
lstfree=zone*BLOCK_SIZE+entry*DIR_ENTRY_SIZE;
}
}
if(flag==ADD) {
dir_struct add[MAX_INCREMENT];
strncpy(tname,name,mfname );
tname[mfname]=0;
if(badname(tname)) return EACCDN;
if( do_trans(LWR_TOS,drive) ) Strlwr(tname);
strncpy(add[0].d_name,tname,mfname);
add[0].d_inum=0;
if(l_write(inum,lstfree,(long)(mfname+2),add,drive)
!=(mfname+2) ) return EACCDN;
return( lstfree==-1l ? rip.i_size : lstfree);
}
return EFILNF;
}
/* Return '1' if 'name' has any illegal characters in it */
int badname(name)
char *name;
{
if(!*name)
{
DEBUG("Minixfs: Illegal null filename");
return 1;
}
for(;*name;name++) if(BADCHR(*name))
{
DEBUG("minixfs: Bad character in filename");
return 1;
}
return 0;
}
/* Return '1' if dir2 is a parent of dir1 , otherwise 0 or negative error
* number
*/
long is_parent(dir1,dir2,drive)
unsigned dir1,dir2;
int drive;
{
long itemp=dir1;
for(;;)
{
if(itemp==dir2)
{
DEBUG("minixfs: invalid directory move");
return 1;
}
if(itemp==ROOT_INODE)break;
itemp=search_dir("..",itemp,drive,FIND);
if(itemp < 0)
{
ALERT("Couldn't trace inode %d back to root",dir1);
return EACCDN;
}
}
return 0;
}