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