home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / filesy~1 / mfs610s.zoo / minixfs / inode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-19  |  6.5 KB  |  277 lines

  1. /* This file is part of 'minixfs' Copyright 1991,1992,1993 S.N.Henson */
  2.  
  3. #include "minixfs.h"
  4. #include "proto.h"
  5. #include "global.h"
  6.  
  7. /* Inode routines */
  8.  
  9. /* Read an inode from the cache , if the filesystem is V1 convert to V2
  10.  * first , this greatly simplifies matters as other routines can then deal
  11.  * exclusively with V2 inodes.
  12.  */
  13.  
  14. int read_inode(num,rip,drv)
  15. unsigned num;
  16. d_inode *rip;
  17. int drv;
  18. {
  19.     bufr *tmp;
  20.     super_info *psblk=super_ptr[drv];
  21.     num-=1;
  22.     tmp=cget_block(num/psblk->ipb+psblk->ioff,drv,&icache);
  23.     if(psblk->version) *rip=tmp->binode[num%psblk->ipb];
  24.     else
  25.     {
  26.         d_inode1 *oldrip;
  27.         int i;
  28.         oldrip=&tmp->binode1[num%psblk->ipb];
  29.         /* Convert V1 inode to V2 */
  30.         rip->i_mode=oldrip->i_mode;
  31.         rip->i_nlinks=oldrip->i_nlinks;
  32.         rip->i_uid=oldrip->i_uid;
  33.         rip->i_gid=oldrip->i_gid;
  34.         rip->i_size=oldrip->i_size;
  35.         rip->i_atime=oldrip->i_mtime;
  36.         rip->i_mtime=oldrip->i_mtime;
  37.         rip->i_ctime=oldrip->i_mtime;
  38.         for(i=0;i< NR_ZONE_NUMS;i++) rip->i_zone[i]=oldrip->i_zone[i];
  39.         rip->i_zone[NR_ZONE_NUMS]=0;
  40.     }
  41.     return(0);
  42. }
  43.  
  44. /* Write out an inode , assuming it is V2. If the filesystem is V1 it converts
  45.  * the supplied inode first.
  46.  */
  47.  
  48. int write_inode(num,rip,drv)
  49. unsigned num;
  50. d_inode *rip;
  51. int drv;
  52. {
  53.     cache *tmp;
  54.     super_info *psblk=super_ptr[drv];
  55.     num-=1;
  56.     tmp=cache_get(num/psblk->ipb+psblk->ioff,drv,&icache,NOGUESS);
  57.     if(psblk->version) tmp->buffer->binode[num%psblk->ipb]=*rip;
  58.     else
  59.     {
  60.         d_inode1 *oldrip;
  61.         int i;
  62.         oldrip=&tmp->buffer->binode1[num%psblk->ipb];
  63.         /* Convert V2 inode to V1 */
  64.         oldrip->i_mode=rip->i_mode;
  65.         oldrip->i_nlinks=rip->i_nlinks;
  66.         oldrip->i_uid=rip->i_uid;
  67.         oldrip->i_gid=rip->i_gid;
  68.         oldrip->i_size=rip->i_size;
  69.         oldrip->i_mtime=rip->i_mtime;
  70.         for(i=0;i<NR_ZONE_NUMS;i++) oldrip->i_zone[i]=rip->i_zone[i];
  71.     }
  72.     tmp->status=2;
  73.     return(0);
  74. }
  75.  
  76. /* 'get' an inode from the cache, return a pointer to the inode and
  77.  * if the pointer 'flag' is non-zero, return a pointer to the 'status' 
  78.  * flag as well. Need two versions for this as well.
  79.  */
  80.  
  81. d_inode1 *get_inode1(inum,drive,flag,guess)
  82. unsigned inum;
  83. int drive;
  84. int **flag;
  85. cache **guess;
  86. {
  87.     cache *tmp;
  88.     super_info *psblk=super_ptr[drive];
  89.     inum-=1;
  90.     tmp=cache_get((inum>>L_IPB)+psblk->ioff,drive,&icache,guess);
  91.     if(flag) *flag=&tmp->status;
  92.  
  93.     return &tmp->buffer->binode1[inum & (INODES_PER_BLOCK-1)] ;
  94. }
  95.  
  96. d_inode *get_inode2(inum,drive,flag,guess)
  97. unsigned inum;
  98. int drive;
  99. int **flag;
  100. cache **guess;
  101. {
  102.     cache *tmp;
  103.     super_info *psblk=super_ptr[drive];
  104.     inum-=1;
  105.     tmp=cache_get((inum>>L_IPB2)+psblk->ioff,drive,&icache,guess);
  106.  
  107.     if(flag) *flag=&tmp->status;
  108.  
  109.     return &tmp->buffer->binode[inum & (INODES_PER_BLOCK2-1)] ;
  110. }
  111.  
  112. /* Truncate an inode to 'count' zones, this is used by unlink() as well as
  113.  * (f)truncate() . Bit tricky this , we have to note which blocks to free,
  114.  * and free indirection/double indirection blocks too but iff all the blocks
  115.  * inside them are free too. We also need to keep count of how much to leave 
  116.  * alone , sparse files complicate this a bit .... so do 2 fs versions ....
  117.  */
  118.  
  119. void trunc_inode(rip,drive,count,zap)
  120. d_inode *rip;    
  121. int drive;
  122. long count;            /* number of blocks to leave */
  123. int zap;            /* flag to alter inode */
  124. {
  125.     int i,j;
  126.     bufr *tmp;
  127.     char some,dirty;
  128.     super_info *psblk=super_ptr[drive];
  129.     char vers;
  130.     cache_control *control = IS_DIR((*rip)) ? &syscache : &usrcache;
  131.     cache *p, *q, *guess = control->start;
  132.     vers=psblk->version;
  133.     /* Handle zones in inode first */
  134.     if(count<psblk->dzpi)
  135.     {
  136.         for(i=count;i<psblk->dzpi;i++) {
  137.             if(rip->i_zone[i]) {
  138.             /* remove zones from cache too so they can't end up
  139.                in both ones when later reallocated... also may
  140.                save a few needless writes.    -nox */
  141.                 if( (p=in_cache(rip->i_zone[i],drive,control,&guess)) )
  142.                     p->status=0;
  143.                 free_zone(rip->i_zone[i],drive);
  144.             }
  145.             if(zap)rip->i_zone[i]=0;
  146.         }
  147.         count=0;
  148.     }
  149.     else count-=psblk->dzpi;
  150. /* Handle indirect zone */
  151.     if(count< psblk->zpind) {
  152.         some=0;
  153.         dirty=0;
  154.         if(rip->i_zone[7]) {
  155.             tmp=(q=cache_get(rip->i_zone[7],drive,&syscache,NOGUESS))->buffer;
  156.             for(i=0;i<psblk->zpind;i++) {
  157.                 if(PIND(vers,tmp,i)) {
  158.                     if(count)some=1;
  159.                     else {
  160.                         if( (p=in_cache(PIND(vers,tmp,i),drive,control,&guess)) )
  161.                             p->status=0;
  162.                         free_zone(PIND(vers,tmp,i),drive);
  163.                         if(zap)PIND(vers,tmp,i)=0;
  164.                         dirty=1;
  165.                     }
  166.                 }    
  167.                 if(count)count--;
  168.             }
  169.             if(!some) {
  170.                 q->status=0;
  171.                 free_zone(rip->i_zone[7],drive);
  172.                 if(zap)rip->i_zone[7]=0;
  173.             }
  174.             else if(dirty) 
  175. #if 1
  176.             /* a bit faster :) */
  177.                 q->status=2;
  178. #else
  179.                 write_zone(rip->i_zone[7],tmp,drive,&syscache);
  180. #endif
  181.         }
  182.     }
  183.     else count-=psblk->zpind;
  184.     /* Handle double indirect ... */
  185.     if(rip->i_zone[8]) {
  186.         some=0;
  187.         dirty=0;
  188.         read_zone(rip->i_zone[8],&temp,drive,&syscache);
  189.         for(i=0;i<psblk->zpind;i++) {
  190.             if(IND(vers,temp,i)) {
  191.                 char lsome,ldirty; /* local some,dirty for inds */
  192.                 lsome=0;
  193.                 ldirty=0;
  194.                 tmp=(q=cache_get(IND(vers,temp,i),drive,&syscache,NOGUESS))->buffer;
  195.                 for(j=0;j<psblk->zpind;j++) {
  196.                 if(PIND(vers,tmp,j)) {
  197.                     if(count) { 
  198.                         some=1;
  199.                         lsome=1;
  200.                     }
  201.                     else {
  202.                         if( (p=in_cache(PIND(vers,tmp,j),drive,control,&guess)) )
  203.                             p->status=0;
  204.                         free_zone(PIND(vers,tmp,j),drive);
  205.                         if(zap)PIND(vers,tmp,j)=0;
  206.                         ldirty=1;
  207.                         dirty=1;
  208.                     }
  209.                 }
  210.                 if(count)count--;
  211.                 }
  212.                 if(!lsome) {
  213.                 q->status=0;
  214.                 free_zone(IND(vers,temp,i),drive);
  215.                 if(zap)IND(vers,temp,i)=0;
  216.                 }
  217.                 else if(ldirty)
  218. #if 1
  219.                 q->status=2;
  220. #else
  221.                 write_zone(IND(vers,temp,i),tmp,drive,&syscache);
  222. #endif
  223.             }
  224.             else 
  225.             {
  226.                 if(count>=psblk->zpind)count-=psblk->zpind;
  227.                 else count=0;
  228.             }
  229.         }
  230.         if(!some) {
  231.             if( (p=in_cache(rip->i_zone[8],drive,&syscache,NOGUESS)) )
  232.                 p->status=0;
  233.             free_zone(rip->i_zone[8],drive);
  234.             if(zap)rip->i_zone[8]=0;
  235.         }
  236.         else if(dirty)write_zone(rip->i_zone[8],&temp,drive,&syscache);
  237.     }
  238. }
  239.  
  240. /* Inode version of (f)truncate , truncates a file to size 'length'
  241.  */
  242.  
  243. long itruncate(inum,drive,length)
  244. unsigned inum;
  245. int drive;
  246. long length;
  247. {
  248.     long count;
  249.     d_inode rip;
  250.     FILEPTR *p;
  251.  
  252.     read_inode(inum,&rip,drive);
  253.     /* Regulars only , clever directory compaction stuff later ... */
  254.     if(!IS_REG(rip))return EACCDN;
  255.     /* If file smaller than 'length' nothing to do */
  256.     if(rip.i_size <= length)
  257.     {
  258. #if 0
  259.         rip.i_size=length;
  260. #endif
  261.         return 0;
  262.     }
  263.     count=(length+1023)/1024;
  264.     /* invalidate f_cache zones */
  265.     for(p=firstptr;p;p=p->next)
  266.         if((drive==p->fc.dev) && (inum==p->fc.index) &&
  267.            ((f_cache *) p->devinfo)->lzone > count)
  268.               ((f_cache *) p->devinfo)->lzone = 0;
  269.     trunc_inode(&rip,drive,count,1);
  270.     rip.i_size=length;    
  271.     write_inode(inum,&rip,drive);
  272.     if(cache_mode) l_sync();
  273.     return 0;
  274. }
  275.  
  276.  
  277.