home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / alt_os / mint / mfs6011 / source / minixfs / minixdev.c < prev    next >
C/C++ Source or Header  |  1994-12-30  |  15KB  |  668 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. DEVDRV minix_dev = {
  8.     m_open, m_write, m_read,
  9.     m_seek, m_ioctl, m_datime,
  10.     m_close,m_select, m_unselect
  11. };
  12.  
  13. #ifndef IO_Q
  14. #define IO_Q 3
  15. #endif
  16.  
  17. /* Minix fs device driver */
  18.  
  19. /* Under minixfs there is no 'per file structure' , that is all references to
  20. the same file are independent.This complicates file sharing a bit , the 'next'
  21. field points to the next fileptr for the minixfs , so that a search checks the
  22. list sequentially (the global variable 'firstptr' is the start of the list) ,
  23. references to the same file are grouped together so that the first reference
  24. can act as a list pointer to denyshare() , though the last reference's 'next'
  25. pointer is temporarily set to NULL to keep denyshare() happy.
  26. */
  27.  
  28. long m_open(f)
  29. FILEPTR *f;
  30. {
  31.     FILEPTR *lst,*elst,*tmplst;
  32.     f_cache *fch,*old_fch;
  33.     d_inode rip;
  34.  
  35.     /* do some sanity checking */
  36.     read_inode(f->fc.index,&rip,f->fc.dev);
  37.  
  38.     if (!IS_REG(rip)) {
  39.         DEBUG("m_open: not a regular file");
  40.         return EACCDN;
  41.     }
  42.  
  43.  
  44.     /* Set up f_cache structure */
  45.     if( ! (fch=(f_cache *)Kmalloc(sizeof(f_cache)) ) )
  46.     {
  47.         DEBUG("No memory for f_cache structure");
  48.         return ENSMEM;
  49.     }
  50.     bzero(fch,sizeof(f_cache));
  51.  
  52.     f->devinfo=(long)fch;
  53.  
  54.     /* Find first pointer to same file , if any */
  55.     for(lst=firstptr;lst;lst=lst->next)
  56.         if((f->fc.dev==lst->fc.dev) && (f->fc.index==lst->fc.index))break;
  57.     if(lst)
  58.     {
  59.         /* Find last pointer to file */
  60.         for(elst=lst;elst->next;elst=elst->next)
  61.         if((elst->next->fc.dev!=lst->fc.dev) || 
  62.             (elst->next->fc.index!=lst->fc.index))break;
  63.  
  64.         tmplst=elst->next;
  65.         elst->next=0;
  66.  
  67.         if(Denyshare(lst,f))
  68.         {
  69.             elst->next=tmplst;
  70.             Kfree(fch);
  71.             return EACCDN;
  72.         }
  73.         elst->next=f;
  74.         /* If truncating invalidate all f_cache zones */
  75.         if(f->flags & O_TRUNC)
  76.         {
  77.             FILEPTR *p;
  78.             for (p = lst; p; p = p->next)
  79.               ((f_cache *) p->devinfo)->lzone = 0;
  80.         }
  81.         f->next=tmplst;
  82.         fch->lfirst=((f_cache *)elst->devinfo)->lfirst;
  83.  
  84.         /* If file opened already, fill in guesses from first entry */
  85.         old_fch=(f_cache *)lst->devinfo;
  86.         fch->iguess=old_fch->iguess;
  87.         fch->izguess=old_fch->izguess;
  88.         fch->dizguess=old_fch->dizguess;        
  89.         fch->zguess=usrcache.start;
  90.     }
  91.     else
  92.     {
  93.         /* Stick new fptr at top */
  94.         f->next=firstptr;
  95.         firstptr=f;
  96.         fch->lfirst=(LOCK **)Kmalloc(sizeof(LOCK *)); /* List of locks */
  97.         *fch->lfirst=0;    /* No locks yet */
  98.         fch->iguess=icache.start;
  99.         fch->zguess=usrcache.start;
  100.         fch->izguess=syscache.start;
  101.         fch->dizguess=syscache.start;
  102.     }
  103.     /* should we truncate the file? */
  104.     if (f->flags & O_TRUNC) {
  105.         trunc_inode(&rip,f->fc.dev,0L,1);
  106.         rip.i_size = 0;
  107.         rip.i_mtime = Unixtime(Timestamp(), Datestamp());
  108.         write_inode(f->fc.index,&rip,f->fc.dev);
  109.  
  110.         if(cache_mode) l_sync();
  111.  
  112.     }
  113.     return 0;
  114. }
  115.  
  116. long m_close(f, pid)
  117.     FILEPTR *f;
  118.     int pid;
  119. {
  120.     FILEPTR **last;
  121.     f_cache *fch=(f_cache *)f->devinfo;
  122.  
  123.     /* If locked remove any locks for this pid */
  124.     if(f->flags & O_LOCK)
  125.     {
  126.         LOCK *lck, **oldl;
  127.         TRACE("minixfs: removing locks for pid %d",pid);
  128.         oldl = fch->lfirst;
  129.         lck = *oldl;
  130.         while(lck)
  131.         {
  132.             if(lck->l.l_pid == pid) 
  133.             {
  134.                 *oldl=lck->next;
  135.                                Wake (IO_Q, (long) lck);
  136.                 Kfree(lck);
  137.             }
  138.             else oldl = &lck->next;
  139.  
  140.             lck = *oldl;
  141.         }
  142.     }
  143.  
  144.     if (f->links <= 0) {
  145.         /* Last fptr ? */
  146.         if (inode_busy (f->fc.index, f->fc.dev, 0) < 2)
  147.         {
  148.             /* Free LOCK pointer */
  149.             Kfree(fch->lfirst);
  150.             if(f->fc.aux & AUX_DEL)
  151.             {
  152.                 d_inode rip;
  153.                 DEBUG("minixfs: Deleting unlinked file");
  154.                 read_inode(f->fc.index,&rip,f->fc.dev);
  155.                 trunc_inode(&rip, f->fc.dev,0L,0);
  156.                 rip.i_mode=0;
  157.                 write_inode(f->fc.index,&rip,f->fc.dev);
  158.                 free_inode(f->fc.index,f->fc.dev);
  159.             }
  160.         }
  161.         Kfree(fch);
  162.         for (last = &firstptr;; last = &(*last)->next)
  163.           {
  164.             if (*last == f)
  165.               {
  166.             *last = f->next;
  167.             break;
  168.               }
  169.             else if (!*last)
  170.               {
  171.             ALERT ("Minixfs FILEPTR chain corruption!");
  172.             break;
  173.               }
  174.           }
  175.     }
  176.     if(cache_mode) l_sync(); /* always sync on close */
  177.  
  178.     return 0;
  179. }
  180.  
  181. /* Minix read , all manner of horrible things can happen during 
  182.  * a read , if fptr->pos is not block aligned we need to copy a partial
  183.  * block then a load of full blocks then a final possibly partial block
  184.  * any of these can hit EOF and we mustn't copy anything past EOF ...
  185.  * my poor head :-( 
  186.  */
  187.  
  188. long m_read(f,buf,len)
  189. FILEPTR *f;
  190. char *buf;
  191. long len;
  192. {
  193.     if(super_ptr[f->fc.dev]->version) return m_read2(f,buf,len);
  194.     return m_read1(f,buf,len);
  195.  
  196. }
  197.  
  198. long m_read1(f,buf,len)
  199. FILEPTR *f;
  200. char *buf;
  201. long len;
  202. {
  203.     d_inode1 *rip;
  204.     long chunk,znew,rc,actual_read;
  205.     int i;
  206.     f_cache *fch=(f_cache *)f->devinfo;
  207.  
  208.     chunk=f->pos>>L_BS;
  209.  
  210.     rip=get_inode1(f->fc.index,f->fc.dev,0,&fch->iguess);
  211.  
  212.     actual_read=min(rip->i_size-f->pos,len); /* Number of characters read */
  213.  
  214.     rc=actual_read;    /* Characters remaining to read */
  215.     if(rc<=0) return 0;    /* At or past EOF */
  216.  
  217.     /* Every PRE_READ blocks, try to read in PRE_READ zones into cache */
  218.  
  219.     if( (chunk>=fch->lzone) && ( (len>>L_BS) < PRE_READ) )
  220.     {
  221.         for(i=0;i<PRE_READ;i++)
  222.             fch->zones[i]=find_zone11(rip,i+chunk,f->fc.dev,0,fch);
  223.  
  224.         fch->fzone=chunk;
  225.         fch->lzone=chunk+PRE_READ;
  226.         readin(fch->zones,PRE_READ,f->fc.dev,&usrcache);
  227.     }
  228.  
  229.     /* Are we block aligned ? If not read/copy partial block */
  230.     if(f->pos & (BLOCK_SIZE-1))
  231.     {
  232.         int bpos=f->pos & (BLOCK_SIZE-1);
  233.         int valid=min(rc,BLOCK_SIZE-bpos);
  234.  
  235.         if( (chunk >= fch->fzone) && (chunk < fch->lzone) )
  236.                     znew=fch->zones[chunk-fch->fzone];
  237.         else znew=0;
  238.  
  239.         if(!znew)
  240.             znew=find_zone11(rip,chunk,f->fc.dev,0,fch);
  241.  
  242.         chunk++;
  243.         if(znew)    /* Sparse file ? */
  244. bcopy(cache_get(znew,f->fc.dev,&usrcache,&fch->zguess)->buffer->bdata+bpos,buf,
  245.                                      valid);
  246.  
  247.         else bzero(buf,valid);
  248.         buf+=valid;
  249.         rc-=valid;
  250.     }
  251.  
  252.     if(rc>>L_BS) /* Any full blocks to read ? */
  253.     {
  254.         for(i=0;i < rc>>L_BS;i++)
  255.         {
  256.  
  257.             if( (chunk>=fch->fzone) && (chunk < fch->lzone) )
  258.                 znew=fch->zones[chunk-fch->fzone];
  259.             else znew=0;
  260.             if(!znew)
  261.                 znew=find_zone11(rip,chunk,f->fc.dev,0,fch);
  262.             chunk++;
  263.             read_zones(znew,buf,f->fc.dev,&usrcache);
  264.             buf+=BLOCK_SIZE;
  265.         }
  266.         read_zones(0,NULL,-1,&usrcache);
  267.         rc &=BLOCK_SIZE-1;
  268.  
  269.     }
  270.  
  271.     if(rc) /* Anything left ? */
  272.     {
  273.  
  274.         if( (chunk>=fch->fzone) && (chunk < fch->lzone))
  275.                     znew=fch->zones[chunk-fch->fzone];
  276.         else znew=0;
  277.         if(!znew)
  278.             znew=find_zone11(rip,chunk,f->fc.dev,0,fch);
  279.         if(znew)
  280. bcopy(cache_get(znew,f->fc.dev,&usrcache,&fch->zguess)->buffer->bdata,buf,rc);
  281.         else bzero(buf,rc);
  282.     }
  283.  
  284.     f->pos+=actual_read;
  285.     return actual_read;
  286. }
  287.  
  288. long m_read2(f,buf,len)
  289. FILEPTR *f;
  290. char *buf;
  291. long len;
  292. {
  293.     d_inode *rip;
  294.     long chunk,znew,rc,actual_read;
  295.     int i;
  296.  
  297.     int *status;
  298.     f_cache *fch=(f_cache *)f->devinfo;
  299.  
  300.  
  301.     chunk=f->pos>>L_BS;
  302.     rip = get_inode2(f->fc.index,f->fc.dev,&status,&fch->iguess);
  303.  
  304.     actual_read=min(rip->i_size-f->pos,len); /* Number of characters read */
  305.  
  306.     rc=actual_read;    /* Characters remaining to read */
  307.     if(rc<=0) return 0;    /* At or past EOF */
  308.  
  309.     /* Every PRE_READ blocks , try to read in PRE_READ zones into cache */
  310.  
  311.     if(chunk>=fch->lzone && (len>>L_BS < PRE_READ ) )
  312.     {
  313.         for(i=0;i<PRE_READ;i++)
  314.             fch->zones[i]=find_zone2(rip,i+chunk,f->fc.dev,0,fch);
  315.         readin(fch->zones,PRE_READ,f->fc.dev,&usrcache);
  316.         fch->fzone=chunk;
  317.         fch->lzone=chunk+PRE_READ;
  318.     }
  319.  
  320.     /* Are we block aligned ? If not read/copy partial block */
  321.     if(f->pos & (BLOCK_SIZE-1))
  322.     {
  323.         int bpos=f->pos & (BLOCK_SIZE-1);
  324.         int valid=min(rc,BLOCK_SIZE-bpos);
  325.  
  326.         if( (chunk >= fch->fzone) && (chunk < fch->lzone) )
  327.                     znew=fch->zones[chunk-fch->fzone];
  328.         else znew=0;
  329.  
  330.         if(!znew)
  331.             znew=find_zone2(rip,chunk,f->fc.dev,0,fch);
  332.         chunk++;
  333.         if(znew)    /* Sparse file ? */
  334. bcopy(cache_get(znew,f->fc.dev,&usrcache,&fch->zguess)->buffer->bdata+bpos
  335.                                     ,buf,valid);
  336.         else bzero(buf,valid);
  337.         buf+=valid;
  338.         rc-=valid;
  339.     }
  340.  
  341.     if(rc>>L_BS) /* Any full blocks to read ? */
  342.     {
  343.         int i;
  344.         for(i=0;i < rc>>L_BS;i++)
  345.         {
  346.             if( (chunk>=fch->fzone) && (chunk < fch->lzone) )
  347.                 znew=fch->zones[chunk-fch->fzone];
  348.             else znew=0;
  349.             if(!znew) 
  350.                 znew=find_zone2(rip,chunk,f->fc.dev,0,fch);
  351.             chunk++;
  352.             read_zones(znew,buf,f->fc.dev,&usrcache);
  353.             buf+=BLOCK_SIZE;
  354.         }
  355.         read_zones(0,NULL,-1,&usrcache);
  356.         rc &=BLOCK_SIZE-1;
  357.  
  358.     }
  359.  
  360.     if(rc) /* Anything left ? */
  361.     {
  362.         if( (chunk>=fch->fzone) && (chunk < fch->lzone))
  363.                     znew=fch->zones[chunk-fch->fzone];
  364.         else znew=0;
  365.         if(!znew)
  366.             znew=find_zone2(rip,chunk,f->fc.dev,0,fch);
  367.         if(znew)
  368. bcopy(cache_get(znew,f->fc.dev,&usrcache,&fch->zguess)->buffer->bdata,buf,rc);
  369.         else bzero(buf,rc);
  370.     }
  371.  
  372.     /*
  373.      * For floppies never update atime this is a bit of a hack, should 
  374.      * really test write protection and act accordingly. Status is '3'
  375.      * so that, for example, if a program run on a Minixfs filesystem 
  376.      * causes a disk change, nasty error messages are avoided. 
  377.      */
  378.  
  379.     if(f->fc.dev > 1)
  380.     {
  381.         rip->i_atime=Unixtime(Timestamp(),Datestamp());
  382.         *status=3;
  383.     }
  384.  
  385.     f->pos+=actual_read;
  386.     return actual_read;
  387. }
  388.  
  389. /* seek is a bit easier */
  390.  
  391. long m_seek(f,offset,flag)
  392. FILEPTR *f;
  393. long offset;
  394. int flag;
  395. {
  396.     d_inode rip;
  397.     unsigned long max_size = super_ptr[f->fc.dev]->sblk.s_max_size;
  398.  
  399.     switch(flag) {
  400.     case SEEK_SET :
  401.         if (offset >= 0 && offset <= max_size)
  402.           f->pos = offset;
  403.         else return(ERANGE);
  404.         break;
  405.  
  406.     case SEEK_CUR :
  407.         if (f->pos + offset >= 0 && f->pos + offset <= max_size)
  408.           f->pos += offset;
  409.         else return(ERANGE);
  410.         break;
  411.  
  412.     case SEEK_END :
  413.         read_inode(f->fc.index,&rip,f->fc.dev);
  414.         if (rip.i_size + offset >= 0 && rip.i_size + offset <= max_size)
  415.           f->pos = rip.i_size + offset; 
  416.         else return(ERANGE);
  417.         break;
  418.  
  419.     default :
  420.         return(EINVFN);
  421.  
  422.     }
  423.     return (f->pos);
  424. }
  425.  
  426. long m_write(f,buf,len)
  427. FILEPTR *f;
  428. char *buf;
  429. long len;
  430. {
  431.     long ret;
  432.  
  433.     ret=l_write(f->fc.index,f->pos,len,buf,f->fc.dev);
  434.  
  435.     if(ret<0) return ret;
  436.  
  437.     if(cache_mode==ROBUST) l_sync();
  438.  
  439.     f->pos+=ret;
  440.  
  441.     return(ret);
  442. }
  443.  
  444. long m_ioctl(f,mode,buf)
  445. FILEPTR *f;
  446. int mode;
  447. void *buf;
  448. {
  449.     switch (mode)
  450.       {
  451.       case FIONREAD:
  452.        {
  453.          d_inode rip;
  454.          long nread;
  455.          read_inode (f->fc.index, &rip, f->fc.dev);
  456.          nread = rip.i_size - f->pos;
  457.          if (nread < 0)
  458.            nread = 0;
  459.          *(long *) buf = nread;
  460.          return 0;
  461.        }
  462.  
  463.       case FIONWRITE:
  464.     {
  465.         *((long *) buf)=1;
  466.         return 0;
  467.     }
  468.  
  469. /* File locking code , unlike sharing *lfirst of the f_cache structure 
  470.  * exists on a 'per-file' basis, this simplifies things somewhat.
  471.  */
  472.  
  473.       case F_SETLK:
  474.       case F_SETLKW:
  475.       case F_GETLK:
  476.     {
  477.  
  478.         f_cache *fch;
  479.         LOCK t, *lck, **lastlck;
  480.  
  481.         struct flock *fl;
  482.  
  483.         int cpid;    /* Current proc pid */
  484.  
  485.         fch=(f_cache *)f->devinfo;
  486.  
  487.         if(!lockok)
  488.         {
  489.             DEBUG("Locking Not Installed");
  490.             return EINVFN;
  491.         }
  492.  
  493.         fl= ( struct flock *)buf;
  494.         t.l=*fl;
  495.  
  496.         switch(t.l.l_whence)
  497.         {
  498.  
  499.             case SEEK_SET:
  500.             break;
  501.  
  502.             case SEEK_CUR:
  503.             t.l.l_start+=f->pos;
  504.             break;
  505.  
  506.             case SEEK_END:
  507.             {
  508.                 d_inode rip;
  509.                 read_inode(f->fc.index,&rip,f->fc.dev);
  510.                                t.l.l_start += rip.i_size;
  511.             }
  512.             break;
  513.  
  514.             default:
  515.             DEBUG("Invalid value for l_whence");
  516.             return EINVFN;
  517.         }
  518.         
  519.         if(t.l.l_start < 0) t.l.l_start=0;
  520.         t.l.l_whence=0;
  521.  
  522.         if(mode == F_GETLK) {
  523.             lck = Denylock(*fch->lfirst,&t);
  524.             if(lck) *fl = lck->l;
  525.             else fl->l_type = F_UNLCK;
  526.             return 0;    
  527.         }
  528.  
  529.         cpid=Getpid();
  530.  
  531.         if(t.l.l_type==F_UNLCK)
  532.         {
  533.             /* Try to find the lock */
  534.             lastlck = fch->lfirst;
  535.             for (lck = *lastlck; lck; lck = lck->next)
  536.              if( lck->l.l_pid == cpid &&
  537.                  lck->l.l_start == t.l.l_start &&
  538.                  lck->l.l_len == t.l.l_len)
  539.                {
  540.                  *lastlck = lck->next;
  541.                  Kfree (lck);
  542.                  return 0;
  543.                }
  544.              else
  545.                lastlck = &lck->next;
  546.             return ENSLOCK;
  547.         }
  548.  
  549.                while (lck = Denylock (*fch->lfirst, &t), lck != 0)
  550.                  {
  551.                    if (mode == F_SETLKW)
  552.                      Sleep (IO_Q, (long) lck); /* sleep a while */
  553.                    else
  554.                      return ELOCKED;
  555.                  }
  556.  
  557.         lck = Kmalloc(SIZEOF(LOCK));
  558.  
  559.         if(!lck) return ENSMEM;
  560.  
  561.         lck->l = t.l;
  562.         lck->l.l_pid = cpid;
  563.  
  564.         /* Insert lck at top of list */
  565.         lck->next=*fch->lfirst;
  566.         *fch->lfirst=lck;
  567.  
  568.         f->flags |=O_LOCK;    /* Lock op done on FILEPTR */
  569.         return 0;
  570.     }
  571.  
  572.       case FUTIME:
  573.     {
  574.       d_inode rip;
  575.       short *timeptr = (short *) buf;
  576.       int uid = Geteuid ();
  577.  
  578.       read_inode (f->fc.index, &rip, f->fc.dev);
  579.  
  580.       /* The owner or super-user can always touch, others only
  581.          if timeptr == 0 and open for writing */
  582.       if (uid && uid != rip.i_uid
  583.           && (timeptr || ( (f->flags & O_RWMODE) == O_RDONLY )) )
  584.         return EACCDN;
  585.  
  586.       rip.i_ctime = Unixtime (Timestamp (), Datestamp ());
  587.  
  588.       if(timeptr)
  589.       {
  590.         rip.i_atime = Unixtime (timeptr[0], timeptr[1]);
  591.         rip.i_mtime = Unixtime (timeptr[2], timeptr[3]);
  592.       }
  593.       else rip.i_mtime = rip.i_atime = rip.i_ctime;
  594.  
  595.       write_inode (f->fc.index, &rip, f->fc.dev);
  596.       if (cache_mode != TURBO)
  597.         l_sync ();
  598.       return 0;
  599.     }
  600.  
  601.       case FTRUNCATE:
  602.     {
  603.       if( (f->flags & O_RWMODE) == O_RDONLY ) return EACCDN;
  604.  
  605.       itruncate(f->fc.index,f->fc.dev,*((long *)buf));
  606.  
  607.       if (cache_mode != TURBO)
  608.         l_sync ();
  609.       return 0;
  610.     }
  611.  
  612.       default:
  613.     return EINVFN;
  614.       }
  615. }
  616.  
  617. /* Made this a bit like utimes, sets atime,mtime and ctime=current time */
  618.  
  619. long m_datime(f,timeptr,flag)
  620. FILEPTR *f;
  621. int *timeptr;
  622. int flag;
  623. {
  624.     d_inode rip;
  625.     super_info *psblk;
  626.     psblk=super_ptr[f->fc.dev];
  627.     read_inode(f->fc.index,&rip,f->fc.dev);
  628.     switch (flag)
  629.     {
  630.  
  631.         case 0 :
  632.         *((long *)timeptr)=Dostime(_corr(rip.i_mtime));
  633.         break;
  634.  
  635.         case 1 :
  636.         rip.i_mtime=Unixtime(timeptr[0],timeptr[1]);
  637.         rip.i_atime=rip.i_mtime;
  638.         rip.i_ctime=Unixtime(Timestamp(),Datestamp());
  639.         write_inode(f->fc.index,&rip,f->fc.dev);
  640.  
  641.         if(cache_mode) l_sync();
  642.  
  643.         break;
  644.  
  645.         default :
  646.         return -1;
  647.         break;
  648.     }    
  649.     return 0;
  650. }
  651.  
  652. long m_select(f,proc,mode)
  653. FILEPTR *f;
  654. long proc;
  655. int mode;
  656. {
  657.     return 1;
  658. }
  659.  
  660. void m_unselect(f,proc,mode)
  661. FILEPTR *f;
  662. long proc;
  663. int mode;
  664. {
  665. /* Do nothing */
  666. }
  667.  
  668.