home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / alt_os / mint / mfs6011 / source / minixfs / inode.c < prev    next >
C/C++ Source or Header  |  1994-12-30  |  9KB  |  379 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))||IS_SYM((*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 (count < (long) psblk->zpind * psblk->zpind) {
  186.         if(rip->i_zone[8]) {
  187.         some=0;
  188.         dirty=0;
  189.         read_zone(rip->i_zone[8],&temp,drive,&syscache);
  190.         for(i=0;i<psblk->zpind;i++) {
  191.             if(IND(vers,temp,i)) {
  192.                 char lsome,ldirty; /* local some,dirty for inds */
  193.                 lsome=0;
  194.                 ldirty=0;
  195.                 tmp=(q=cache_get(IND(vers,temp,i),drive,&syscache,NOGUESS))->buffer;
  196.                 for(j=0;j<psblk->zpind;j++) {
  197.                 if(PIND(vers,tmp,j)) {
  198.                     if(count) { 
  199.                         some=1;
  200.                         lsome=1;
  201.                     }
  202.                     else {
  203.                         if( (p=in_cache(PIND(vers,tmp,j),drive,control,&guess)) )
  204.                             p->status=0;
  205.                         free_zone(PIND(vers,tmp,j),drive);
  206.                         if(zap)PIND(vers,tmp,j)=0;
  207.                         ldirty=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.                 dirty=1;
  217.                 }
  218.                 else if(ldirty)
  219. #if 1
  220.                 q->status=2;
  221. #else
  222.                 write_zone(IND(vers,temp,i),tmp,drive,&syscache);
  223. #endif
  224.             }
  225.             else 
  226.             {
  227.                 if(count>=psblk->zpind)count-=psblk->zpind;
  228.                 else count=0;
  229.             }
  230.         }
  231.         if(!some) {
  232.             if( (p=in_cache(rip->i_zone[8],drive,&syscache,NOGUESS)) )
  233.                 p->status=0;
  234.             free_zone(rip->i_zone[8],drive);
  235.             if(zap)rip->i_zone[8]=0;
  236.         }
  237.         else if(dirty)write_zone(rip->i_zone[8],&temp,drive,&syscache);
  238.         }
  239.     }
  240.     else
  241.         count -= (long) psblk->zpind * psblk->zpind;
  242.     /* Handle triple indirect ... */
  243.     if (rip->i_zone[9])
  244.       {
  245.         some = 0;
  246.         dirty = 0;
  247.         read_zone (rip->i_zone[9], &temp, drive, &syscache);
  248.         for (i = 0; i < psblk->zpind; i++)
  249.           {
  250.         if (IND (vers, temp, i))
  251.           {
  252.             char lsome, ldirty; /* local some, dirty for inds */
  253.             lsome = 0;
  254.             ldirty = 0;
  255.             q = cache_get (IND (vers, temp, i), drive, &syscache,
  256.                    NOGUESS);
  257.             tmp = q->buffer;
  258.             for (j = 0; j < psblk->zpind; j++)
  259.               {
  260.             if (PIND (vers, tmp, j))
  261.               {
  262.                 char lsome1, ldirty1;
  263.                 int k;
  264.                 bufr *tmp2;
  265.                 cache *r;
  266.                 lsome1 = 0;
  267.                 ldirty1 = 0;
  268.                 r = cache_get (PIND (vers, tmp, j), drive,
  269.                        &syscache, NOGUESS);
  270.                 tmp2 = q->buffer;
  271.                 for (k = 0; k < psblk->zpind; k++)
  272.                   {
  273.                 if (PIND (vers, tmp2, k))
  274.                   {
  275.                     if (count)
  276.                       {
  277.                     some = 1;
  278.                     lsome = 1;
  279.                     lsome1 = 1;
  280.                       }
  281.                     else
  282.                       {
  283.                     p = in_cache (PIND (vers, tmp2, k),
  284.                               drive, control, &guess);
  285.                     if (p)
  286.                       p->status = 0;
  287.                     free_zone (PIND (vers, tmp2, k),
  288.                            drive);
  289.                     if (zap)
  290.                       PIND (vers, tmp2, k) = 0;
  291.                     ldirty1 = 1;
  292.                       }
  293.                   }
  294.                 if (count)
  295.                   count--;
  296.                   }
  297.                 if (!lsome1)
  298.                   {
  299.                 r->status = 0;
  300.                 free_zone (PIND (vers, tmp, j), drive);
  301.                 if (zap)
  302.                   PIND (vers, tmp, j) = 0;
  303.                 ldirty = 1;
  304.                   }
  305.                 else if (ldirty1)
  306.                   r->status = 2;
  307.               }
  308.               }
  309.             if (!lsome)
  310.               {
  311.             q->status = 0;
  312.             free_zone (IND (vers, temp, i), drive);
  313.             if (zap)
  314.               IND (vers, temp, i) = 0;
  315.             dirty = 1;
  316.               }
  317.             else if (ldirty)
  318.               q->status = 2;
  319.           }
  320.         else 
  321.           {
  322.             if (count >= psblk->zpind)
  323.               count -= psblk->zpind;
  324.             else
  325.               count = 0;
  326.           }
  327.           }
  328.         if (!some)
  329.           {
  330.         p = in_cache (rip->i_zone[9], drive, &syscache, NOGUESS);
  331.         if (p)
  332.           p->status = 0;
  333.         free_zone (rip->i_zone[9], drive);
  334.         if (zap)
  335.           rip->i_zone[9] = 0;
  336.           }
  337.         else if (dirty)
  338.           write_zone (rip->i_zone[9], &temp, drive, &syscache);
  339.       }
  340. }
  341.  
  342. /* Inode version of (f)truncate , truncates a file to size 'length'
  343.  */
  344.  
  345. long itruncate(inum,drive,length)
  346. unsigned inum;
  347. int drive;
  348. long length;
  349. {
  350.     long count;
  351.     d_inode rip;
  352.     FILEPTR *p;
  353.  
  354.     read_inode(inum,&rip,drive);
  355.     /* Regulars only , clever directory compaction stuff later ... */
  356.     if(!IS_REG(rip))return EACCDN;
  357.     /* If file smaller than 'length' nothing to do */
  358.     if(rip.i_size <= length)
  359.     {
  360. #if 0
  361.         rip.i_size=length;
  362. #endif
  363.         return 0;
  364.     }
  365.     count=(length+1023)/1024;
  366.     /* invalidate f_cache zones */
  367.     for(p=firstptr;p;p=p->next)
  368.         if((drive==p->fc.dev) && (inum==p->fc.index) &&
  369.            ((f_cache *) p->devinfo)->lzone > count)
  370.               ((f_cache *) p->devinfo)->lzone = 0;
  371.     trunc_inode(&rip,drive,count,1);
  372.     rip.i_size=length;    
  373.     write_inode(inum,&rip,drive);
  374.     if(cache_mode) l_sync();
  375.     return 0;
  376. }
  377.  
  378.  
  379.