home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / programs / compress / misc / xfh / source.lha / src / CFS.c < prev    next >
C/C++ Source or Header  |  1993-03-09  |  32KB  |  993 lines

  1. /* CFS.c - main packet loop.
  2.    Copyright (C) 1991, 1992, 1993 Kristian Nielsen.
  3.  
  4.    This file is part of XFH, the compressing file system handler.
  5.  
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            */
  19.  
  20. /* This file replaces the startup code! Make sure the object file
  21.  * corresponding to this source is linked into the head of the final
  22.  * executeable.
  23.  */
  24.  
  25. #include "CFS.h"
  26.  
  27. #include <exec/ports.h>
  28. #include <exec/memory.h>
  29. #include <libraries/filehandler.h>
  30.  
  31. #include <proto/exec.h>
  32. #include <proto/dos.h>
  33.  
  34. #include <clib/alib_protos.h>
  35.  
  36. #include <string.h>
  37. #include <stdarg.h>
  38. #include <stdio.h>
  39.  
  40. #include <dossupport.h>
  41.  
  42. struct ExecBase *SysBase;
  43. struct DosLibrary *DOSBase;
  44.  
  45. const char versiontag[] = "\0$VER: XFH-Handler " VERSION " (" __DATE__ ")";
  46. const char cporighttag[]
  47.       = "\0$COPYRIGHT: Copyright (C) 1991, 1992, 1993 Kristian Nielsen";
  48.  
  49. /**************************************************************************
  50.  *                                                                        *
  51.  * Handler entry point.                                                   *
  52.  *                                                                        *
  53.  * Do initialisation and allocation, then enter main loop after returning *
  54.  *    our initial packet.                                                 *
  55.  *                                                                        *
  56.  **************************************************************************/
  57.  
  58. int __saveds NotReallyMain(void){
  59.    glb glob;
  60.    struct DosPacket *pkt;
  61.    int ret=0;
  62.    struct FileLock *parent;
  63.    void handle_packet(glb glob, struct DosPacket *pkt);
  64.    
  65.    SysBase=(void *)*(ULONG *)4L;
  66.    if(!(glob=AllocMem(sizeof(struct glob),MEMF_CLEAR))) return(100);
  67.    glob->ioerr = ERROR_ACTION_NOT_KNOWN;  /* Default error code. */
  68. #ifdef DEBUG
  69.    opendebug();
  70.    debug(("XFH/CFS compressing file system handler v" VERSION ".\n"
  71.           "Copyright (C) 1991,1992,1993 Kristian Nielsen.\n"));
  72.    debug(("Starting handler with task at 0x%lx.\n",FindTask(0L)));
  73. #endif
  74.  
  75.    glob->dosport=&(glob->myproc=(struct Process *)
  76.                    (glob->mytask=FindTask(0L)))->pr_MsgPort;
  77.    pkt=getpkt(glob);
  78.    glob->devnode = (struct DeviceNode *)b2c(pkt->dp_Arg3);
  79.    if(!glob->devnode->dn_Name){
  80.       debug(("Error: NULL device name - exiting.\n"));
  81.       glob->ioerr = ERROR_INVALID_COMPONENT_NAME;
  82.       returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
  83.       ret=100;
  84.       goto exitthis;
  85.    }
  86.    if(!(glob->devname=copybstr(glob->devnode->dn_Name))){
  87.       debug(("Error copying device name - exiting.\n"));
  88.       OUTOFMEM;
  89.       returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
  90.       ret=100;
  91.       goto exitthis;
  92.    }
  93.    if(!glob->devname[0]){
  94.       debug(("Error: Empty device name - exiting.\n"));
  95.       glob->ioerr = ERROR_INVALID_COMPONENT_NAME;
  96.       returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
  97.       ret=100;
  98.       goto exitthis;
  99.    }
  100.  
  101.    debug(("Using device name '%s'.\n",glob->devname));
  102.  
  103.    glob->bcplstartup = glob->devnode->dn_Startup;
  104.    
  105.    if(!(glob->ioport=CreatePort(NULL,0L))){
  106.       OUTOFMEM;
  107.       returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
  108.       ret=100;
  109.       debug(("Error creating message port - exiting.\n"));
  110.       goto exitthis;
  111.    }
  112.  
  113.    if(!(glob->DOSBase=OpenLibrary("dos.library",0L))){
  114.       glob->ioerr = ERROR_INVALID_RESIDENT_LIBRARY;
  115.       returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
  116.       debug(("Error opening dos.library - exiting.\n"));
  117.       ret=100;
  118.       goto exitthis;
  119.    }
  120.    DOSBase=glob->DOSBase;
  121.  
  122.    /* Set primary options (from S:.xfhrc.<unit>, if available). */
  123.    if( !InitOptions(glob) ){
  124.       returnpkt(pkt,DOSFALSE,ERROR_BAD_TEMPLATE,glob);
  125.       debug(("Error setting primary options - exiting.\n"));
  126.       ret=100;
  127.       goto exitthis;
  128.    }
  129.  
  130.    if( !InitXpk(glob) ){
  131.       returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
  132.       debug(("Error initialising Xpk routines - exiting.\n"));
  133.       ret=100;
  134.       goto exitthis;
  135.    }
  136.  
  137.    debug(("Using '%s' as root directory...\n",glob->xRootName));
  138.    glob->xprocid = DoDeviceProc( (LONG *)&glob->xrootlock, glob->xRootName, glob );
  139.    if( !glob->xprocid ){
  140.       glob->xrootlock = 0L;                      /* Don't xUnLock() */
  141.       returnpkt(pkt,DOSFALSE,ERROR_OBJECT_NOT_FOUND,glob);
  142.       ret=100;
  143.       debug(("Error doing DeviceProc(%s) - exiting.\n",glob->xRootName));
  144.       goto exitthis;
  145.    }
  146.    glob->xrootlock = b2c(glob->xrootlock);
  147.    debug(("DeviceProc(%s) returned: %lx %lx\n",glob->xRootName,
  148.           glob->xprocid,glob->xrootlock));
  149.    glob->xrootlock = xLock( glob, glob->xrootlock, glob->xRootName, ACCESS_READ );
  150.    if( !glob->xrootlock ){
  151.       returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
  152.       ret=100;
  153.       debug(("Error obtaining xrootlock: %ld - exiting.\n",glob->ioerr,
  154.              glob->xRootName));
  155.       goto exitthis;
  156.    }
  157.    debug(("Obtained xrootlock: %lx\n",glob->xrootlock ));
  158.  
  159.    if(!SetOptionsFromFile(glob, glob->xrootlock, ALTOPTIONPATH)){
  160.       returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
  161.       ret=100;
  162.       debug(("Error setting secondary options.\n"));
  163.       goto exitthis;
  164.    }
  165.  
  166.    if(!xInfo(glob, glob->xrootlock, &glob->infodata)){
  167.       returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
  168.       ret=100;
  169.       debug(("Error obtaining disk info: %ld\n",glob->ioerr));
  170.       goto exitthis;
  171.    }
  172.    glob->bytesperblock = glob->infodata.id_BytesPerBlock;
  173.    
  174.    if(parent = xParentDir(glob, glob->xrootlock)){
  175.       xUnLock(glob, parent);
  176.    }
  177.    if(!xExamine(glob, glob->xrootlock, &glob->fib1)){
  178.       returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
  179.       ret=100;
  180.       debug(("Error finding name for volume: %ld\n",glob->ioerr));
  181.       goto exitthis;
  182.    }
  183.    
  184.    if( !(glob->rootlock = makerootlockdayone(glob)) ){
  185.       returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
  186.       ret=100;
  187.       debug(("Error creating rootlock: %ld - exiting.\n",glob->ioerr));
  188.       goto exitthis;
  189.    }
  190.    
  191.    if(!createvolnode(glob, parent == NULL, &glob->fib1)){
  192.       returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
  193.       ret=100;
  194.       debug(("Error creating volume node - exiting.\n"));
  195.       goto exitthis;
  196.    }
  197.  
  198.    if(!InitArexx(glob)){
  199.       returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
  200.       ret=100;
  201.       debug(("Error initialising AREXX stuff.\n"));
  202.       goto exitthis;
  203.    }
  204.  
  205.    if(!UpdateXFHNode(glob)){
  206.       debug(("Error initialising XFHNode.\n"));
  207.       /* Carry on... */
  208.    }
  209.    
  210.    /* Handler opened succesfully. Patch in task address so that we will
  211.     * stay in control for all future references.
  212.     */
  213.    glob->devnode->dn_Task = glob->dosport;
  214.       
  215.    debug(("1: Packet type received: %lx\n",pkt->dp_Type));
  216.    returnpkt(pkt,DOSTRUE,0L,glob);
  217.  
  218.    glob->opencnt=0;        /* Just for good measure... */
  219.    /* Ready to go for the main loop.
  220.     * Lets pray that we get no new messages before the initial ReplyPkt()
  221.     * (otherwise we may loose the signal for the message port).
  222.     */
  223.    for(glob->done=FALSE;!glob->done;){
  224.       ULONG signals = Wait(arexxsigmask(glob) | getpktsigmask(glob) 
  225.                          | guisigmask(glob));
  226.  
  227.       if(signals & arexxsigmask(glob)) checkarexxmsg(glob);
  228.       if(signals & guisigmask(glob)){
  229.          if(!UpdateXFHNode(glob)){
  230.             debug(("Error during UpdateXFHNode().\n"));
  231.          }
  232.       }
  233.       if(signals & getpktsigmask(glob)){
  234.          while(!glob->done && (pkt=checkpkt(glob))){
  235.             handle_packet(glob, pkt);
  236.          }
  237.       }
  238.    }
  239.       
  240.  exitthis:
  241.    debug(("CFS exiting...\n"));
  242.    CleanupArexx(glob);
  243.    if( glob->volnode ) freevolnode(glob);
  244.    if( glob->rootlock ) CFSUnLock( glob, glob->rootlock );
  245.    CleanupXpk(glob);
  246.    CleanupOptions(glob);
  247.    if(glob->ioport) DeletePort(glob->ioport);
  248.    if(glob->devname) freestr(glob->devname);
  249. #ifdef DEBUG
  250.    closedebug();
  251. #endif
  252.    
  253. /*
  254.  * Unload the code. This is mostly to serve the ACTION_DIE packet.
  255.  * Useful for debugging (otherwise countless copies might end up in memory.
  256.  * It is rather ugly, however, and propably not really useful.
  257.  */
  258.    Forbid();
  259.    UnLoadSeg(glob->devnode->dn_SegList);
  260.    glob->devnode->dn_SegList=NULL;
  261.    
  262.    if(glob->DOSBase) CloseLibrary(glob->DOSBase);
  263.    FreeMem(glob,sizeof(struct glob));
  264.    return(ret);
  265. }
  266.  
  267.  
  268. void handle_packet(glb glob, struct DosPacket *pkt){
  269.    glob->ioerr = 0L;
  270.    switch(pkt->dp_Type){
  271.       case ACTION_LOCATE_OBJECT:{
  272.          struct FileLock *mylock;
  273.          struct CFSLock *mycfslock;
  274.          
  275.          debug(("ACTION_LOCATE_OBJECT(%lx,\"%s\",%ld)",
  276.                 pkt->dp_Arg1,
  277.                 bstr2c(pkt->dp_Arg2,glob->debugbuf1),
  278.                 pkt->dp_Arg3));
  279.          mylock = b2c(pkt->dp_Arg1);
  280.          mycfslock = mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock;
  281.          mycfslock = CFSLock( glob, 
  282.                               mycfslock,
  283.                               bstr2c(pkt->dp_Arg2,glob->pktstringbuf),
  284.                               pkt->dp_Arg3);
  285.          if (mycfslock){
  286.             if( mylock = CreateFileLock( glob, mycfslock ) )
  287.                glob->opencnt++;
  288.             else{
  289.                LONG saveioerr;
  290.  
  291.                saveioerr = glob->ioerr;
  292.                CFSUnLock(glob, mycfslock);
  293.                glob->ioerr = saveioerr;
  294.             }
  295.          }else{
  296.             mylock = NULL;
  297.          }
  298.          debug((" = %lx\n",c2b(mylock)));
  299.          returnpkt(pkt, c2b(mylock), glob->ioerr, glob);
  300.          break;
  301.       }
  302.       
  303.       case ACTION_COPY_DIR:{
  304.          struct FileLock *mylock;
  305.          struct CFSLock *mycfslock;
  306.          
  307.          debug(("ACTION_COPY_DIR(%lx)",pkt->dp_Arg1));
  308.          mylock = b2c(pkt->dp_Arg1);
  309.          mycfslock = mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock;
  310.          if( mycfslock = CFSDupLock( glob, mycfslock ) ){
  311.             if( mylock = CreateFileLock(glob, mycfslock ) ){
  312.                glob->opencnt++;
  313.             }else{
  314.                LONG saveioerr;
  315.  
  316.                saveioerr = glob->ioerr;
  317.                CFSUnLock(glob, mycfslock);
  318.                glob->ioerr = saveioerr;
  319.             }
  320.          }else mylock = NULL;
  321.  
  322.          debug((" = %lx\n",c2b(mylock)));
  323.          returnpkt(pkt, c2b(mylock), glob->ioerr, glob);
  324.          break;
  325.       }
  326.       case ACTION_PARENT:{
  327.          struct FileLock *mylock;
  328.          struct CFSLock *mycfslock;
  329.          
  330.          debug(("ACTION_PARENT(%lx)",pkt->dp_Arg1));
  331.          mylock = b2c(pkt->dp_Arg1);
  332.          mycfslock = mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock;
  333.          if( mycfslock = CFSParentDir( glob, mycfslock ) ){
  334.             if( mylock = CreateFileLock(glob, mycfslock ) ){
  335.                glob->opencnt++;
  336.             }else{
  337.                LONG saveioerr;
  338.  
  339.                saveioerr = glob->ioerr;
  340.                CFSUnLock(glob, mycfslock);
  341.                glob->ioerr = saveioerr;
  342.         }
  343.          }else mylock = NULL;
  344.  
  345.          debug((" = %lx\n",c2b(mylock)));
  346.          returnpkt(pkt, c2b(mylock), glob->ioerr, glob);
  347.          break;
  348.       }
  349.       case ACTION_FREE_LOCK:{
  350.          BOOL err;
  351.          struct FileLock *mylock;
  352.          
  353.          debug(("ACTION_FREE_LOCK(%lx)\n",pkt->dp_Arg1));
  354.          mylock = b2c(pkt->dp_Arg1);
  355.          if(mylock){
  356.             err = CFSUnLock(glob, (void *)mylock->fl_Key);
  357.             if(err){
  358.                dfree(mylock);
  359.                glob->opencnt--;
  360.             }
  361.          }else err = ERROR_OBJECT_WRONG_TYPE;
  362.          returnpkt(pkt,err,glob->ioerr,glob);
  363.          break;
  364.       }
  365.       
  366.       /* ToDo: Handle NULL locks correct (but what is correct?)
  367.        * Now, a NULL lock is equal to out root lock.
  368.        */
  369.       case ACTION_SAME_LOCK:{
  370.          struct FileLock *fl1,*fl2;
  371.          BOOL res;
  372.          
  373.          fl1 = b2c(pkt->dp_Arg1);
  374.          fl2 = b2c(pkt->dp_Arg2);
  375.          debug(("ACTION_SAME_LOCK(%lx,%lx)",fl1,fl2));
  376.          /* ToDo: This bit tests that both locks belong to us - this
  377.           * is probably bogus.
  378.           */
  379.          if(fl1 && fl1->fl_Task != glob->dosport){
  380.             res = FALSE;
  381.          }else if(fl2 && fl2->fl_Task!=glob->dosport){
  382.             res = FALSE;
  383.          }else{
  384.             struct CFSLock *f1,*f2;
  385.             f1 = fl1 ? (struct CFSLock *)fl1->fl_Key : glob->rootlock;
  386.             f2 = fl2 ? (struct CFSLock *)fl2->fl_Key : glob->rootlock;
  387.             res = CFSSameLock( glob, f1, f2 );
  388.          }
  389.          debug((" = %ld\n",res));
  390.          /* ToDo: DOCS mention error code in case of zero return.
  391.           * Not currently implemented.
  392.           */
  393.          returnpkt(pkt,res,glob->ioerr,glob);
  394.          break;
  395.       }
  396.  
  397.       case ACTION_FINDINPUT:   /* (filehandle, lock, name)->BOOL */
  398.       case ACTION_FINDOUTPUT:
  399.       case ACTION_FINDUPDATE:
  400.       {
  401.          struct FileHandle *fh;
  402.          struct CFSFH *cfsfh;
  403.          char *name;
  404.          struct FileLock *parentlock;
  405.          struct CFSLock *cfsparentlock;
  406.          
  407.          debug(("%s(%lx,%lx,\"%s\")\n",
  408.                 pkt->dp_Type==ACTION_FINDINPUT  ? "ACTION_FINDINPUT"  : 
  409.                 pkt->dp_Type==ACTION_FINDOUTPUT ? "ACTION_FINDOUTPUT" :
  410.                                                   "ACTION_FINDUPDATE" ,
  411.                 pkt->dp_Arg1,pkt->dp_Arg2,
  412.                 bstr2c(pkt->dp_Arg3,glob->debugbuf1)));
  413.          
  414.          fh = b2c(pkt->dp_Arg1);
  415.          parentlock = b2c(pkt->dp_Arg2);
  416.          cfsparentlock =
  417.        parentlock ? (struct CFSLock *)parentlock->fl_Key : glob->rootlock;
  418.          name = bstr2c(pkt->dp_Arg3, glob->pktstringbuf);
  419.          cfsfh = CFSOpen(glob, cfsparentlock, name, pkt->dp_Type);
  420.          debug(("(=%lx)\n",cfsfh));
  421.          if( cfsfh ){
  422.             glob->opencnt++;
  423.             fh->fh_Arg1 = c2b(cfsfh);
  424.             returnpkt(pkt, DOSTRUE, glob->ioerr, glob);
  425.          }else{
  426.             returnpkt(pkt, DOSFALSE, glob->ioerr, glob);
  427.          }
  428.          break;
  429.       }
  430.          
  431.       case ACTION_READ:    /* (fh->arg1, buf, len)->actlen */
  432.       {
  433.          struct CFSFH *cfsfh;
  434.          LONG len;
  435.          void *buf;
  436.          
  437.          debug(("ACTION_READ(%lx,%lx,%ld)\n",
  438.                  pkt->dp_Arg1,pkt->dp_Arg2,pkt->dp_Arg3));
  439.          cfsfh = b2c(pkt->dp_Arg1);
  440.          buf = (void *)pkt->dp_Arg2;
  441.          len = pkt->dp_Arg3;
  442.          len = CFSRead(glob, cfsfh, buf, len);
  443.          returnpkt(pkt, len, glob->ioerr, glob);
  444.          break;
  445.       }
  446.        case ACTION_WRITE:    /* (fh->arg1, buf, len)->actlen */
  447.       {
  448.          struct CFSFH *cfsfh;
  449.          LONG len;
  450.          void *buf;
  451.          
  452.          debug(("ACTION_WRITE(%lx,%lx,%ld)\n",
  453.                  pkt->dp_Arg1,pkt->dp_Arg2,pkt->dp_Arg3));
  454.          cfsfh = b2c(pkt->dp_Arg1);
  455.          buf = (void *)pkt->dp_Arg2;
  456.          len = pkt->dp_Arg3;
  457.          len = CFSWrite(glob, cfsfh, buf, len);
  458.      debug(("ACTION_WRITE returns %ld %ld.\n",len, glob->ioerr));
  459.          returnpkt(pkt, len, glob->ioerr, glob);
  460.          break;
  461.       }
  462.  
  463.       case ACTION_SEEK:    /* (fh->arg1, pos, offset)->actlen */
  464.       {
  465.          struct CFSFH *cfsfh;
  466.          LONG pos;
  467.          LONG offset;
  468.          
  469.          debug(("ACTION_SEEK(%lx,%lx,%ld)\n",
  470.                  pkt->dp_Arg1,pkt->dp_Arg2,pkt->dp_Arg3));
  471.          cfsfh = b2c(pkt->dp_Arg1);
  472.          pos = pkt->dp_Arg2;
  473.          offset = pkt->dp_Arg3;
  474.          pos = CFSSeek(glob, cfsfh, pos, offset);
  475.          returnpkt(pkt, pos, glob->ioerr, glob);
  476.          break;
  477.       }
  478.  
  479.       case ACTION_END:     /* (fh->arg1) -> BOOL */
  480.       {
  481.          struct CFSFH *cfsfh;
  482.          BOOL res;
  483.          
  484.          cfsfh = b2c(pkt->dp_Arg1);
  485.          debug(("ACTION_END(%lx)\n",cfsfh));
  486.          res = CFSClose( glob, cfsfh );
  487.          if( res ) glob->opencnt--;
  488.          debug(("Closing file - still %ld files open.\n",glob->opencnt));
  489.          returnpkt(pkt,res,pkt->dp_Res2,glob);
  490.          break;
  491.       }
  492.  
  493.       case ACTION_DIE:
  494.          debug(("ACTION_DIE()\n"));
  495.          Forbid();
  496.          if(!glob->opencnt){
  497.             glob->done=TRUE;
  498.             returnpkt(pkt,DOSTRUE,pkt->dp_Res2,glob);
  499.             glob->devnode->dn_Task = NULL;
  500.             debug(("No open files - Handler exiting.\n"));
  501.          }else{
  502.             returnpkt(pkt,DOSFALSE,ERROR_OBJECT_IN_USE,glob);
  503.             debug(("Cannot end yet - still %ld open files.\n",glob->opencnt));
  504.          }
  505.          Permit();
  506.          break;
  507.  
  508.       case ACTION_EXAMINE_OBJECT:{
  509.          struct FileInfoBlock *fib;
  510.          struct FileLock *mylock;
  511.          BOOL err;
  512.          
  513.          debug(("ACTION_EXAMINE_OBJECT(%lx,%lx)\n",pkt->dp_Arg1,pkt->dp_Arg2));
  514.          mylock = b2c(pkt->dp_Arg1);
  515.          fib = b2c(pkt->dp_Arg2);
  516.          err = CFSExamine(glob, 
  517.                           mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock,
  518.                           fib);
  519.          debug(("NAME: %s DirEntryType: %ld err: %ld\n",
  520.                 fib->fib_FileName, fib->fib_DirEntryType,err));
  521.          cstr2binplace(&fib->fib_FileName[0]);
  522.          cstr2binplace(&fib->fib_Comment[0]);
  523.          returnpkt(pkt,err,glob->ioerr,glob);
  524.          break;
  525.       }
  526.  
  527.       case ACTION_EXAMINE_NEXT:{
  528.          struct FileInfoBlock *fib;
  529.          struct FileLock *mylock;
  530.          BOOL err;
  531.          
  532.          debug(("ACTION_EXAMINE_NEXT(%lx,%lx)\n",pkt->dp_Arg1,pkt->dp_Arg2));
  533.          mylock = b2c(pkt->dp_Arg1);
  534.          fib = b2c(pkt->dp_Arg2);
  535.          bstr2cinplace(&fib->fib_FileName[0]);
  536.          safebstr2cinplace(&fib->fib_Comment[0],80);
  537.          err = CFSExamineNext(glob, 
  538.                           mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock,
  539.                           fib);
  540.          debug(("NAME: %s DirEntryType: %ld err: %ld\n",
  541.                 fib->fib_FileName, fib->fib_DirEntryType,err));
  542.          cstr2binplace(&fib->fib_FileName[0]);
  543.          cstr2binplace(&fib->fib_Comment[0]);
  544.          returnpkt(pkt,err,glob->ioerr,glob);
  545.          break;
  546.       }
  547.  
  548.       case ACTION_CREATE_DIR:{ /* (parentlock, name) -> lock */
  549.          struct FileLock *mylock;
  550.          struct CFSLock *lock;
  551.  
  552.          debug(("ACTION_CREATE_DIR(%lx,\"%s\") ",
  553.             pkt->dp_Arg1,bstr2c(pkt->dp_Arg2,glob->debugbuf1)));
  554.          mylock = b2c(pkt->dp_Arg1);
  555.          lock = CFSCreateDir(glob, 
  556.                           mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock,
  557.                           bstr2c(pkt->dp_Arg2,glob->pktstringbuf)   );
  558.          if (lock){
  559.             if( mylock = CreateFileLock( glob, lock ) )
  560.                glob->opencnt++;
  561.             else{
  562.                LONG saveioerr;
  563.  
  564.                saveioerr = glob->ioerr;
  565.                CFSUnLock(glob, lock);
  566.                glob->ioerr = saveioerr;
  567.             }
  568.          }else{
  569.             mylock = NULL;
  570.          }
  571.          debug(("= %lx\n",mylock));
  572.          returnpkt(pkt, c2b(mylock), glob->ioerr, glob);
  573.          break;
  574.       }
  575.       case ACTION_DELETE_OBJECT:{ /* (parentlock, name) -> succes */
  576.          struct FileLock *mylock;
  577.          BOOL err;
  578.  
  579.          debug(("ACTION_DELETE_OBJECT(%lx,\"%s\")\n", pkt->dp_Arg1,
  580.                 bstr2c(pkt->dp_Arg2,glob->debugbuf1)));
  581.          mylock = b2c(pkt->dp_Arg1);
  582.          err = CFSDeleteFile(glob,
  583.                      mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock,
  584.                      bstr2c(pkt->dp_Arg2,glob->pktstringbuf)   );
  585.          if( !err )
  586.             debug(("Error deleting file!\n"));
  587.          returnpkt(pkt, err, glob->ioerr, glob);
  588.          break;
  589.       }
  590.  
  591.       case ACTION_RENAME_OBJECT:{ /* (lock1,name1,lock2,name2) -> succes */
  592.          struct FileLock *mylock1, *mylock2;
  593.          BOOL err;
  594.  
  595.          /* ToDo: Check that both locks belong to us? */
  596.          debug(("ACTION_RENAME_OBJECT(%lx,\"%s\", %lx,\"%s\")\n",pkt->dp_Arg1,
  597.             bstr2c(pkt->dp_Arg2,glob->debugbuf1),
  598.             pkt->dp_Arg3,
  599.             bstr2c(pkt->dp_Arg4,glob->debugbuf2)));
  600.          mylock1 = b2c(pkt->dp_Arg1);
  601.          mylock2 = b2c(pkt->dp_Arg3);
  602.          err = CFSRename(glob,
  603.                   mylock1 ? (struct CFSLock *)mylock1->fl_Key : glob->rootlock,
  604.                   bstr2c(pkt->dp_Arg2,glob->pktstringbuf),
  605.                   mylock2 ? (struct CFSLock *)mylock2->fl_Key : glob->rootlock,
  606.                   bstr2c(pkt->dp_Arg4,glob->pktstringbuf2)   );
  607.          if( !err )
  608.             debug(("Error renaming file!\n"));
  609.          returnpkt(pkt, err, glob->ioerr, glob);
  610.          break;
  611.       }
  612.  
  613.       case ACTION_SET_PROTECT:{ /* (dummy, parentlock, name, bits) -> succes */
  614.          struct FileLock *mylock;
  615.          BOOL err;
  616.  
  617.          debug(("ACTION_SET_PROTECT([%lx] %lx,\"%s\",%lx)\n",
  618.                   pkt->dp_Arg1,pkt->dp_Arg2,
  619.                   bstr2c(pkt->dp_Arg3,glob->debugbuf1),
  620.                   pkt->dp_Arg4));
  621.          mylock = b2c(pkt->dp_Arg2);
  622.          err = CFSSetProtection(glob,
  623.              mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock,
  624.              bstr2c(pkt->dp_Arg3,glob->pktstringbuf),
  625.                  pkt->dp_Arg4 );
  626.          if( !err )
  627.             debug(("Error changing protection bits!\n"));
  628.          returnpkt(pkt, err, glob->ioerr, glob);
  629.          break;
  630.       }
  631.  
  632.       case ACTION_SET_COMMENT:{ /* (dummy, parentlock, name, comment) -> succes */
  633.          struct FileLock *mylock;
  634.          BOOL err;
  635.  
  636.          debug(("ACTION_SET_COMMENT([%lx] %lx,\"%s\",\"%s\")\n",
  637.                      pkt->dp_Arg1,pkt->dp_Arg2,
  638.                      bstr2c(pkt->dp_Arg3,glob->debugbuf1),
  639.                      bstr2c(pkt->dp_Arg4,glob->debugbuf2)));
  640.          mylock = b2c(pkt->dp_Arg2);
  641.          err = CFSSetComment(glob,
  642.              mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock,
  643.              bstr2c(pkt->dp_Arg3,glob->pktstringbuf),
  644.              bstr2c(pkt->dp_Arg4,glob->pktstringbuf2) );
  645.          if( !err )
  646.             debug(("Error changing file comment!\n"));
  647.          returnpkt(pkt, err, glob->ioerr, glob);
  648.          break;
  649.       }
  650.  
  651.       case ACTION_SET_DATE:{ /* (dummy, parentlock, name, datestamp) -> succes */
  652.          struct FileLock *mylock;
  653.          BOOL err;
  654.  
  655.          debug(("ACTION_SET_DATE([%lx] %lx,\"%s\",%ld,%ld,%ld)\n",
  656.              pkt->dp_Arg1,pkt->dp_Arg2,
  657.              bstr2c(pkt->dp_Arg3,glob->debugbuf1),
  658.              ((struct DateStamp *)(pkt->dp_Arg4))->ds_Days,
  659.              ((struct DateStamp *)(pkt->dp_Arg4))->ds_Minute,
  660.              ((struct DateStamp *)(pkt->dp_Arg4))->ds_Tick 
  661.          ));
  662.          mylock = b2c(pkt->dp_Arg2);
  663.          err = CFSSetDate(glob,
  664.              mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock,
  665.              bstr2c(pkt->dp_Arg3,glob->pktstringbuf),
  666.              (struct DateStamp *)pkt->dp_Arg4 );
  667.          if( !err )
  668.             debug(("Error changing objects date!\n"));
  669.          returnpkt(pkt, err, glob->ioerr, glob);
  670.          break;
  671.       }
  672.  
  673.       case ACTION_DISK_INFO:    /* (infodata) = BOOL */
  674.          debug(("ACTION_DISK_INFO(%lx)\n",pkt->dp_Arg1));
  675.          returnpkt(pkt, diskinfo(glob,b2c(pkt->dp_Arg1)), 0L, glob);
  676.          break;
  677.       case ACTION_INFO:         /* (lock,infodata) = BOOL */
  678.          debug(("ACTION_INFO(%lx,%lx)\n",pkt->dp_Arg1,pkt->dp_Arg2));
  679.          returnpkt(pkt, diskinfo(glob,b2c(pkt->dp_Arg2)), 0L, glob);
  680.          break;
  681.       case ACTION_RENAME_DISK:{  /* (BCPLNAME) = BOOL */
  682.     BOOL res;
  683.  
  684.     debug(("ACTION_RENAME_DISK(%s)\n",
  685.            bstr2c(pkt->dp_Arg1,glob->debugbuf1)));
  686.     res = SetOptionPermanent(glob, "VOLUMENAME",
  687.                  bstr2c(pkt->dp_Arg1,glob->pktstringbuf));
  688.     if(!res) debug(("Error during relabel: %ld.\n",glob->ioerr));
  689.     returnpkt(pkt, res, glob->ioerr, glob);
  690.     break;
  691.       }
  692.  
  693.       case ACTION_IS_FILESYSTEM:
  694.     debug(("ACTION_IS_FILESYSTEM\n"));
  695.     returnpkt(pkt, DOSTRUE, 0L, glob);
  696.     break;
  697.       case ACTION_PARENT_FH:{
  698.          struct FileLock *mylock;
  699.          struct CFSLock *mycfslock;
  700.          
  701.          debug(("ACTION_PARENT_FH(%lx)",pkt->dp_Arg1));
  702.          if ( mycfslock = CFSParentFH( glob, b2c(pkt->dp_Arg1) ) ){
  703.             if( mylock = CreateFileLock(glob, mycfslock ) ){
  704.                glob->opencnt++;
  705.             }else{
  706.                LONG saveioerr;
  707.  
  708.                saveioerr = glob->ioerr;
  709.                CFSUnLock(glob, mycfslock);
  710.                glob->ioerr = saveioerr;
  711.         }
  712.          }else mylock = NULL;
  713.  
  714.          debug((" = %lx\n",c2b(mylock)));
  715.          returnpkt(pkt, c2b(mylock), glob->ioerr, glob);
  716.          break;
  717.       }
  718.       default:
  719.          debug(("Unknown packet received: %ld\n",pkt->dp_Type));
  720.          returnpkt(pkt,DOSFALSE,ERROR_ACTION_NOT_KNOWN,glob);
  721.    }
  722. }
  723.  
  724.  
  725. struct DosPacket *getpkt(glb glob){
  726.    struct Message *msg;
  727.    
  728.    while(!(msg=GetMsg(glob->dosport)))
  729.       WaitPort(glob->dosport);
  730.    return (struct DosPacket *)msg->mn_Node.ln_Name;
  731. }
  732.  
  733.  
  734. ULONG getpktsigmask(glb glob){
  735.    return (ULONG)1 << glob->dosport->mp_SigBit;
  736. }
  737.  
  738.  
  739. struct DosPacket *checkpkt(glb glob){
  740.    struct Message *msg;
  741.    
  742.    if(msg = GetMsg(glob->dosport)){
  743.      return (struct DosPacket *)msg->mn_Node.ln_Name;
  744.    }else{
  745.       return NULL;
  746.    }
  747. }
  748.  
  749.  
  750. void returnpkt(struct DosPacket *pkt,LONG res1,LONG res2,glb glob){
  751.    struct MsgPort *port;
  752.    struct Message *msg;
  753.    
  754.    port=pkt->dp_Port;
  755.    msg=pkt->dp_Link;
  756.  
  757.    msg->mn_Node.ln_Succ=msg->mn_Node.ln_Pred=NULL;
  758.    msg->mn_Node.ln_Name=(char *)pkt;
  759.    
  760.    pkt->dp_Res1=res1;
  761.    pkt->dp_Res2=res2;
  762.    pkt->dp_Port=glob->dosport;
  763.    
  764.    PutMsg(port,msg);
  765. }
  766.  
  767.  
  768.  
  769. struct devprocmsg{
  770.    struct Message msg;
  771.    void (*func)();
  772.    char *filedesc;
  773.    struct MsgPort *procid;
  774.    LONG res2;
  775. };
  776.  
  777. void __asm CallDeviceProc(register __a0 struct devprocmsg *msg){
  778.   msg->procid=DeviceProc(msg->filedesc);
  779.   msg->res2=IoErr();
  780. }
  781.  
  782. struct MsgPort *DoDeviceProc(LONG *res2,char *filedesc,glb glob){
  783.    struct devprocmsg msg,*msg2;
  784.    extern void DoDOSSeg();
  785.    struct MsgPort *procid;
  786.    
  787.    msg.msg.mn_Node.ln_Succ=NULL;
  788.    msg.msg.mn_Node.ln_Pred=NULL;
  789.    msg.msg.mn_Node.ln_Name=NULL;
  790.    msg.msg.mn_Node.ln_Type=NT_MESSAGE;
  791.    msg.msg.mn_Node.ln_Pri=0;
  792.    msg.msg.mn_ReplyPort=glob->ioport;
  793.    msg.msg.mn_Length=sizeof(msg);
  794.    msg.func=(void (*)())CallDeviceProc;
  795.    msg.filedesc=filedesc;
  796.    
  797.    if(!(procid=CreateProc
  798.      ("DoDOS",glob->mytask->tc_Node.ln_Pri,(BPTR)((ULONG)DoDOSSeg>>2),4000L)))
  799.      return 0L;
  800.    
  801.    PutMsg(procid,(struct Message *)&msg);
  802.    do WaitPort(glob->ioport);
  803.    while(!(msg2=(struct devprocmsg *)GetMsg(glob->ioport)));
  804.  
  805. #ifdef DEBUG
  806.    if(msg2!=&msg)
  807.       dprintf("ERROR: bogus return message: &msg=%lx msg2=%lx\n",&msg,msg2);
  808. #endif
  809.    if(res2) *res2=msg2->res2;
  810.    return msg2->procid;
  811. }
  812.  
  813.  
  814. /* DOS device list locking.
  815.  * ToDo: Use correct 2.0 locking calls.
  816.  */
  817. static void MyLockDosList(glb glob){
  818.   Forbid();
  819. }
  820.  
  821. static void MyUnlockDosList(glb glob){
  822.   Permit();
  823. }
  824.  
  825.  
  826. void addvolnode(glb glob, struct DeviceList *volnode){
  827.    struct DosInfo *dosinfo;
  828.  
  829.    MyLockDosList(glob);
  830.    dosinfo = b2c( ((struct RootNode *)DOSBase->dl_Root)->rn_Info);
  831.    volnode->dl_Next = dosinfo->di_DevInfo;
  832.    dosinfo->di_DevInfo = c2b(volnode);
  833.    MyUnlockDosList(glob);
  834. }
  835.  
  836. BOOL removevolnode(glb glob, struct DeviceList *volnode){
  837.    struct DosInfo *dosinfo;
  838.    BPTR *p;
  839.    
  840.    /* ToDo: check for 2.0 device list locking. */
  841.    MyLockDosList(glob);
  842.    dosinfo = b2c( ((struct RootNode *)DOSBase->dl_Root)->rn_Info);
  843.    p = &dosinfo->di_DevInfo;
  844.    
  845.    while(*p){
  846.       if(b2c(*p) == volnode ){
  847.          *p = volnode->dl_Next;
  848.          MyUnlockDosList(glob);
  849.          return TRUE;
  850.       }
  851.       p = &( ((struct DeviceList *)b2c(*p)) -> dl_Next);
  852.    }
  853.    MyUnlockDosList(glob);
  854.    /* Hey - we didn't find the node in the list! */
  855.    debug(("WARNING!:removevolnode(): volume node not found.\n"));
  856.    return FALSE;
  857. }
  858.  
  859.  
  860. /* Used to update the 'Startup' field in our device node (used in option
  861.  * 'KILLSTARTUP').
  862.  */
  863. void DevNode_Stuff_Startup_String(glb glob, BSTR value){
  864.   MyLockDosList(glob);
  865.   glob->devnode->dn_Startup = value;
  866.   MyUnlockDosList(glob);
  867. }
  868.  
  869.  
  870. /* NOTE: this function assumes properly dos device list locking!
  871.  * This function will fail if 'name' is NULL.
  872.  * NOTE: createvolnode(), below does this in it's own way.
  873.  */
  874. static BOOL stuffvolnamevolnode(glb glob, char *name){
  875.   UBYTE *bcplname, *oldbcplname;
  876.  
  877.   /* NASTY BUG: It seems that the volume name is expected to be zero 
  878.    * terminated even though it is a BSTR. Hence strlen()+2 in alloc. */
  879.   /* Check if user specified a volume name. */
  880.   if(name){
  881.     if(!(bcplname=dosalloc(strlen(name)+2))){
  882.       OUTOFMEM;
  883.       return FALSE;
  884.     }
  885.     /* Free any old name. */
  886.     oldbcplname = b2c(glob->volnode->dl_Name);
  887.     if(oldbcplname) dosfree(oldbcplname);
  888.  
  889.     strcpy(bcplname,name);
  890.     cstr2binplace(bcplname);
  891.     glob->volnode->dl_Name = c2b(bcplname);
  892.     debug(("Using user suplied volumename '%s'.\n",bcplname+1));
  893.     return TRUE;
  894.   }else{
  895.     glob->ioerr = ERROR_INVALID_COMPONENT_NAME;
  896.     return FALSE;
  897.   }
  898. }
  899.  
  900.  
  901. /* This function creates our volumenode. The argument 'fixroot' is
  902.  * a hack, telling whether the volumename should be changed to prevent
  903.  * name-clashing with the volume name of the UFS.
  904.  */
  905. BOOL createvolnode(glb glob, BOOL fixroot, struct FileInfoBlock *fib){
  906.    UBYTE *bcplname;
  907.  
  908.    if(!dalloc(glob->volnode)) return FALSE;
  909.    /* NASTY BUG: It seems that the volume name is expected to be zero 
  910.     * terminated even though it is a BSTR. Hence strlen()+2 in alloc. */
  911.    /* Check if user specified a volume name. */
  912.    if(glob->uservolname){
  913.       if(!(bcplname=dosalloc(strlen(glob->uservolname)+2))){
  914.          dfree(glob->volnode);
  915.          return FALSE;
  916.       }
  917.       strcpy(bcplname,glob->uservolname);
  918.       debug(("Using user suplied volumename '%s'.\n",bcplname));
  919.    }else{
  920.       if(!(bcplname=dosalloc(strlen(fib->fib_FileName)+2
  921.                     + (fixroot ? strlen(XROOTNAME)+1 : 0) ))){
  922.          dfree(glob->volnode);
  923.          return FALSE;
  924.       }
  925.       strcpy(bcplname, fixroot ? XROOTNAME "_" : "");
  926.       strcat(bcplname, &fib->fib_FileName[0]);
  927.       debug(("Using default volume name '%s'.\n",bcplname));
  928.    }
  929.    
  930.    glob->volnode->dl_Type = DLT_VOLUME;
  931.    glob->volnode->dl_Task = glob->dosport;
  932.    glob->volnode->dl_Lock = c2b(NULL);
  933.    glob->volnode->dl_VolumeDate = fib->fib_Date;
  934.    glob->volnode->dl_LockList = c2b(NULL);
  935.    glob->volnode->dl_DiskType = ID_DOS_DISK; /*Wonder what would be right*/
  936.    glob->volnode->dl_unused = 0L;
  937.    cstr2binplace(bcplname);
  938.    glob->volnode->dl_Name = c2b(bcplname);
  939.    
  940.    /* Check if user requested that we create a volume node. */
  941. /*   if(glob->createvolnode){*/
  942.       addvolnode(glob, glob->volnode);
  943. /*   }*/
  944.    return TRUE;
  945. }
  946.  
  947.  
  948. /* Set the volume name in the volnode. */
  949. BOOL SetVolumeNameVolNode(glb glob, char *name){
  950.   BOOL res;
  951.  
  952.   MyLockDosList(glob);
  953.   res = stuffvolnamevolnode(glob, name);
  954.   MyUnlockDosList(glob);
  955.   return res;
  956. }
  957.  
  958. BOOL freevolnode(glb glob){
  959.    /* Check if user requested that we create a volume node. */
  960. /*   if(glob->createvolnode){*/
  961.       if( !removevolnode( glob, glob->volnode ) ) return FALSE;
  962. /*   }*/
  963.    dosfree( b2c(glob->volnode->dl_Name) );
  964.    dfree( glob->volnode );
  965.    return TRUE;
  966. }
  967.  
  968.  
  969. BOOL diskinfo(glb glob, struct InfoData *infodata){
  970.  
  971.    if(!xInfo( glob, glob->xrootlock, infodata )){
  972.      debug(("Error: diskinfo(): xInfo() returned zero (%ld).\n",glob->ioerr));
  973.      return DOSFALSE;
  974.    }
  975. /*   infodata->id_NumSoftErrors = 0;*/
  976. /*   infodata->id_UnitNumber = glob->fsstartup ?*/
  977. /*                             glob->fsstartup->fssm_Unit : 0;*/
  978. /*   infodata->id_DiskState = ID_VALIDATED;*/
  979. /*   infodata->id_NumBlocks = 1;*/
  980. /*   infodata->id_NumBlocksUsed = 1;*/
  981. /*   infodata->id_BytesPerBlock = 1;*/
  982. /*   infodata->id_DiskType = ID_DOS_DISK;*/
  983.    infodata->id_VolumeNode = c2b( glob->volnode );
  984.    infodata->id_InUse = glob->opencnt ? 1 : 0;
  985.    debug(("diskinfo(): U=%ld DS=%lx #=%ld #u=%ld #b=%ld IU=%ld.\n",
  986.        infodata->id_UnitNumber,infodata->id_DiskState,infodata->id_NumBlocks,
  987.        infodata->id_NumBlocksUsed,infodata->id_BytesPerBlock,
  988.        infodata->id_InUse));
  989.    return DOSTRUE;
  990. }
  991.  
  992. /* End of CFS.c */
  993.