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