home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 2
/
crawlyvol2.bin
/
alt_os
/
mint
/
mfs6011
/
source
/
minixfs
/
inode.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-30
|
9KB
|
379 lines
/* This file is part of 'minixfs' Copyright 1991,1992,1993 S.N.Henson */
#include "minixfs.h"
#include "proto.h"
#include "global.h"
/* Inode routines */
/* Read an inode from the cache , if the filesystem is V1 convert to V2
* first , this greatly simplifies matters as other routines can then deal
* exclusively with V2 inodes.
*/
int read_inode(num,rip,drv)
unsigned num;
d_inode *rip;
int drv;
{
bufr *tmp;
super_info *psblk=super_ptr[drv];
num-=1;
tmp=cget_block(num/psblk->ipb+psblk->ioff,drv,&icache);
if(psblk->version) *rip=tmp->binode[num%psblk->ipb];
else
{
d_inode1 *oldrip;
int i;
oldrip=&tmp->binode1[num%psblk->ipb];
/* Convert V1 inode to V2 */
rip->i_mode=oldrip->i_mode;
rip->i_nlinks=oldrip->i_nlinks;
rip->i_uid=oldrip->i_uid;
rip->i_gid=oldrip->i_gid;
rip->i_size=oldrip->i_size;
rip->i_atime=oldrip->i_mtime;
rip->i_mtime=oldrip->i_mtime;
rip->i_ctime=oldrip->i_mtime;
for(i=0;i< NR_ZONE_NUMS;i++) rip->i_zone[i]=oldrip->i_zone[i];
rip->i_zone[NR_ZONE_NUMS]=0;
}
return(0);
}
/* Write out an inode , assuming it is V2. If the filesystem is V1 it converts
* the supplied inode first.
*/
int write_inode(num,rip,drv)
unsigned num;
d_inode *rip;
int drv;
{
cache *tmp;
super_info *psblk=super_ptr[drv];
num-=1;
tmp=cache_get(num/psblk->ipb+psblk->ioff,drv,&icache,NOGUESS);
if(psblk->version) tmp->buffer->binode[num%psblk->ipb]=*rip;
else
{
d_inode1 *oldrip;
int i;
oldrip=&tmp->buffer->binode1[num%psblk->ipb];
/* Convert V2 inode to V1 */
oldrip->i_mode=rip->i_mode;
oldrip->i_nlinks=rip->i_nlinks;
oldrip->i_uid=rip->i_uid;
oldrip->i_gid=rip->i_gid;
oldrip->i_size=rip->i_size;
oldrip->i_mtime=rip->i_mtime;
for(i=0;i<NR_ZONE_NUMS;i++) oldrip->i_zone[i]=rip->i_zone[i];
}
tmp->status=2;
return(0);
}
/* 'get' an inode from the cache, return a pointer to the inode and
* if the pointer 'flag' is non-zero, return a pointer to the 'status'
* flag as well. Need two versions for this as well.
*/
d_inode1 *get_inode1(inum,drive,flag,guess)
unsigned inum;
int drive;
int **flag;
cache **guess;
{
cache *tmp;
super_info *psblk=super_ptr[drive];
inum-=1;
tmp=cache_get((inum>>L_IPB)+psblk->ioff,drive,&icache,guess);
if(flag) *flag=&tmp->status;
return &tmp->buffer->binode1[inum & (INODES_PER_BLOCK-1)] ;
}
d_inode *get_inode2(inum,drive,flag,guess)
unsigned inum;
int drive;
int **flag;
cache **guess;
{
cache *tmp;
super_info *psblk=super_ptr[drive];
inum-=1;
tmp=cache_get((inum>>L_IPB2)+psblk->ioff,drive,&icache,guess);
if(flag) *flag=&tmp->status;
return &tmp->buffer->binode[inum & (INODES_PER_BLOCK2-1)] ;
}
/* Truncate an inode to 'count' zones, this is used by unlink() as well as
* (f)truncate() . Bit tricky this , we have to note which blocks to free,
* and free indirection/double indirection blocks too but iff all the blocks
* inside them are free too. We also need to keep count of how much to leave
* alone , sparse files complicate this a bit .... so do 2 fs versions ....
*/
void trunc_inode(rip,drive,count,zap)
d_inode *rip;
int drive;
long count; /* number of blocks to leave */
int zap; /* flag to alter inode */
{
int i,j;
bufr *tmp;
char some,dirty;
super_info *psblk=super_ptr[drive];
char vers;
cache_control *control = (IS_DIR((*rip))||IS_SYM((*rip))) ? &syscache : &usrcache;
cache *p, *q, *guess = control->start;
vers=psblk->version;
/* Handle zones in inode first */
if(count<psblk->dzpi)
{
for(i=count;i<psblk->dzpi;i++) {
if(rip->i_zone[i]) {
/* remove zones from cache too so they can't end up
in both ones when later reallocated... also may
save a few needless writes. -nox */
if( (p=in_cache(rip->i_zone[i],drive,control,&guess)) )
p->status=0;
free_zone(rip->i_zone[i],drive);
}
if(zap)rip->i_zone[i]=0;
}
count=0;
}
else count-=psblk->dzpi;
/* Handle indirect zone */
if(count< psblk->zpind) {
some=0;
dirty=0;
if(rip->i_zone[7]) {
tmp=(q=cache_get(rip->i_zone[7],drive,&syscache,NOGUESS))->buffer;
for(i=0;i<psblk->zpind;i++) {
if(PIND(vers,tmp,i)) {
if(count)some=1;
else {
if( (p=in_cache(PIND(vers,tmp,i),drive,control,&guess)) )
p->status=0;
free_zone(PIND(vers,tmp,i),drive);
if(zap)PIND(vers,tmp,i)=0;
dirty=1;
}
}
if(count)count--;
}
if(!some) {
q->status=0;
free_zone(rip->i_zone[7],drive);
if(zap)rip->i_zone[7]=0;
}
else if(dirty)
#if 1
/* a bit faster :) */
q->status=2;
#else
write_zone(rip->i_zone[7],tmp,drive,&syscache);
#endif
}
}
else count-=psblk->zpind;
/* Handle double indirect ... */
if (count < (long) psblk->zpind * psblk->zpind) {
if(rip->i_zone[8]) {
some=0;
dirty=0;
read_zone(rip->i_zone[8],&temp,drive,&syscache);
for(i=0;i<psblk->zpind;i++) {
if(IND(vers,temp,i)) {
char lsome,ldirty; /* local some,dirty for inds */
lsome=0;
ldirty=0;
tmp=(q=cache_get(IND(vers,temp,i),drive,&syscache,NOGUESS))->buffer;
for(j=0;j<psblk->zpind;j++) {
if(PIND(vers,tmp,j)) {
if(count) {
some=1;
lsome=1;
}
else {
if( (p=in_cache(PIND(vers,tmp,j),drive,control,&guess)) )
p->status=0;
free_zone(PIND(vers,tmp,j),drive);
if(zap)PIND(vers,tmp,j)=0;
ldirty=1;
}
}
if(count)count--;
}
if(!lsome) {
q->status=0;
free_zone(IND(vers,temp,i),drive);
if(zap)IND(vers,temp,i)=0;
dirty=1;
}
else if(ldirty)
#if 1
q->status=2;
#else
write_zone(IND(vers,temp,i),tmp,drive,&syscache);
#endif
}
else
{
if(count>=psblk->zpind)count-=psblk->zpind;
else count=0;
}
}
if(!some) {
if( (p=in_cache(rip->i_zone[8],drive,&syscache,NOGUESS)) )
p->status=0;
free_zone(rip->i_zone[8],drive);
if(zap)rip->i_zone[8]=0;
}
else if(dirty)write_zone(rip->i_zone[8],&temp,drive,&syscache);
}
}
else
count -= (long) psblk->zpind * psblk->zpind;
/* Handle triple indirect ... */
if (rip->i_zone[9])
{
some = 0;
dirty = 0;
read_zone (rip->i_zone[9], &temp, drive, &syscache);
for (i = 0; i < psblk->zpind; i++)
{
if (IND (vers, temp, i))
{
char lsome, ldirty; /* local some, dirty for inds */
lsome = 0;
ldirty = 0;
q = cache_get (IND (vers, temp, i), drive, &syscache,
NOGUESS);
tmp = q->buffer;
for (j = 0; j < psblk->zpind; j++)
{
if (PIND (vers, tmp, j))
{
char lsome1, ldirty1;
int k;
bufr *tmp2;
cache *r;
lsome1 = 0;
ldirty1 = 0;
r = cache_get (PIND (vers, tmp, j), drive,
&syscache, NOGUESS);
tmp2 = q->buffer;
for (k = 0; k < psblk->zpind; k++)
{
if (PIND (vers, tmp2, k))
{
if (count)
{
some = 1;
lsome = 1;
lsome1 = 1;
}
else
{
p = in_cache (PIND (vers, tmp2, k),
drive, control, &guess);
if (p)
p->status = 0;
free_zone (PIND (vers, tmp2, k),
drive);
if (zap)
PIND (vers, tmp2, k) = 0;
ldirty1 = 1;
}
}
if (count)
count--;
}
if (!lsome1)
{
r->status = 0;
free_zone (PIND (vers, tmp, j), drive);
if (zap)
PIND (vers, tmp, j) = 0;
ldirty = 1;
}
else if (ldirty1)
r->status = 2;
}
}
if (!lsome)
{
q->status = 0;
free_zone (IND (vers, temp, i), drive);
if (zap)
IND (vers, temp, i) = 0;
dirty = 1;
}
else if (ldirty)
q->status = 2;
}
else
{
if (count >= psblk->zpind)
count -= psblk->zpind;
else
count = 0;
}
}
if (!some)
{
p = in_cache (rip->i_zone[9], drive, &syscache, NOGUESS);
if (p)
p->status = 0;
free_zone (rip->i_zone[9], drive);
if (zap)
rip->i_zone[9] = 0;
}
else if (dirty)
write_zone (rip->i_zone[9], &temp, drive, &syscache);
}
}
/* Inode version of (f)truncate , truncates a file to size 'length'
*/
long itruncate(inum,drive,length)
unsigned inum;
int drive;
long length;
{
long count;
d_inode rip;
FILEPTR *p;
read_inode(inum,&rip,drive);
/* Regulars only , clever directory compaction stuff later ... */
if(!IS_REG(rip))return EACCDN;
/* If file smaller than 'length' nothing to do */
if(rip.i_size <= length)
{
#if 0
rip.i_size=length;
#endif
return 0;
}
count=(length+1023)/1024;
/* invalidate f_cache zones */
for(p=firstptr;p;p=p->next)
if((drive==p->fc.dev) && (inum==p->fc.index) &&
((f_cache *) p->devinfo)->lzone > count)
((f_cache *) p->devinfo)->lzone = 0;
trunc_inode(&rip,drive,count,1);
rip.i_size=length;
write_inode(inum,&rip,drive);
if(cache_mode) l_sync();
return 0;
}