home *** CD-ROM | disk | FTP | other *** search
- /* 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;
- }
-
-
-