home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 182.lha / PathDev / device.c < prev    next >
C/C++ Source or Header  |  1988-10-22  |  22KB  |  804 lines

  1. /*
  2.  *  DOSDEVICE.C     V1.10    2 November 1987
  3.  *
  4.  *  EXAMPLE DOS DEVICE DRIVER FOR AZTEC.C   PUBLIC DOMAIN.
  5.  *
  6.  *  By Matthew Dillon.
  7.  *
  8.  *  Debugging routines are disabled by simply attempting to open the
  9.  *  file "debugoff", turned on again with "debugon".  No prefix may be
  10.  *  attached to these names (you must be CD'd to TEST:).
  11.  *
  12.  *  See Documentation for a detailed discussion.
  13.  *
  14.  *  BUGS:
  15.  *    Currently the only known bug is with the implementation of the
  16.  *    RAM disk itself.  Specifically, if filehandle A is at the end of
  17.  *    the file, and somebody appends to the file with another filehandle,
  18.  *    B, filehandle A will get confused as to it's current position in
  19.  *    the file.
  20.  *
  21.  *    I am probably not updating all the right timestamps.  This is
  22.  *    easy to fix... All you have to do is fool with the floppy and
  23.  *    see which datestamps get updated for certain operations.
  24.  */
  25.  
  26. #include "dos.h"
  27.  
  28. /*
  29.  *  Since this code might be called several times in a row without being
  30.  *  unloaded, you CANNOT ASSUME GLOBALS HAVE BEEN ZERO'D!!  This also goes
  31.  *  for any global/static assignments that might be changed by running the
  32.  *  code.
  33.  */
  34.  
  35. PORT    *DosPort;   /*  Our DOS port... this is slick... */
  36. PROC    *DosProc;   /*    Our Process                    */
  37. DEVNODE *DosNode;   /*    Our DOS node.. created by DOS for us        */
  38. DEVLIST *DevList;   /*    Device List structure for our volume node   */
  39.  
  40. void    *SysBase;   /*    EXEC library base            */
  41. DOSLIB    *DOSBase;   /*    DOS library base for debug process    */
  42. RAMFILE RFRoot;     /*    Directory/File structure    (root node) */
  43. LIST    FHBase;     /*    Open Files                */
  44. LIST    LCBase;     /*    Open Locks                */
  45.  
  46. long    TotalBytes; /*    total bytes of data in filesystem    */
  47.  
  48.  
  49.             /*    DEBUGGING            */
  50. PORT *Dbport;        /*    owned by the debug process    */
  51. PORT *Dback;        /*    owned by the DOS device driver    */
  52. MSG DummyMsg;        /*    Dummy message that debug proc can use    */
  53.  
  54. RAMFILE xpath;        /*  This is used in case of off device path */
  55. char *buf1;        /*  This holds the translated path names */
  56. char *volname;        /*  This is my volume name         */
  57.  
  58. RAMFILE * checkoutpath();
  59. RAMFILE * vsearchpath();
  60. void *DeviceProc();
  61.  
  62. /*
  63.  *  Don't call the entry point main().  This way, if you make a mistake
  64.  *  with the compile options you'll get a link error.
  65.  */
  66.  
  67. void
  68. noname()
  69. {
  70.     register PACKET *packet;
  71.     register short   error;
  72.     register ubyte *ptr;
  73.     MSG     *msg;
  74.     ubyte   notdone;
  75.     ubyte   buf[256];
  76.     void    *tmp;
  77.  
  78.     /*
  79.      *    Initialize all global variables.  SysBase MUST be initialized before
  80.      *    we can make Exec calls.  AbsExecBase is a library symbol
  81.      *    referencing absolute memory location 4.  The DOS library is openned
  82.      *    for the debug process only.
  83.      */
  84.  
  85.     Dbport = Dback = NULL;
  86.     TotalBytes = 0;
  87.     SysBase = AbsExecBase;
  88.     DOSBase = OpenLibrary("dos.library",0);
  89.     DosProc = FindTask(NULL);
  90.     DosPort  = (PORT *)AllocMem(sizeof(PORT), MEMF_CLEAR | MEMF_PUBLIC);
  91.     DosPort->mp_Node.ln_Type = NT_MSGPORT;
  92.     DosPort->mp_Node.ln_Name = "Dos Port";
  93.     DosPort->mp_Flags   = PA_SIGNAL;
  94.     DosPort->mp_SigBit  = AllocSignal(-1);
  95.     DosPort->mp_SigTask = FindTask(NULL);
  96.     NewList(&DosPort->mp_MsgList);
  97.     buf1  = AllocMem(512, MEMF_PUBLIC);
  98.     {
  99.     WaitPort(&DosProc->pr_MsgPort);     /*  Get Startup Packet    */
  100.     msg = GetMsg(&DosProc->pr_MsgPort);
  101.     packet = (PACKET *)msg->mn_Node.ln_Name;
  102.  
  103.     /*
  104.      *  Loading DosNode->dn_Task causes DOS *NOT* to startup a new
  105.      *  instance of the device driver for every reference.    E.G. if
  106.      *  you were writing a CON device you would want this field to
  107.      *  be NULL.
  108.      */
  109.  
  110.     if (DOSBase) {
  111.         DOSINFO *di = BTOC(((ROOTNODE *)DOSBase->dl_Root)->rn_Info);
  112.         register DEVLIST *dl = dosalloc(sizeof(DEVLIST));
  113.  
  114.         DosNode = BTOC(PArg3);
  115.  
  116.         /*
  117.          *    Create Volume node and add to the device list.    This will
  118.          *    cause the WORKBENCH to recognize us as a disk.    If we don't
  119.          *    create a Volume node, Wb will not recognize us.  However,
  120.          *    we are a RAM: disk, Volume node or not.
  121.          */
  122.  
  123.         volname = AllocMem(32,MEMF_PUBLIC);
  124.         volname[0] = 11;
  125.         strcpy(volname+1,"Path Server");
  126.  
  127.         DevList = dl;
  128.         dl->dl_Type = DLT_VOLUME;
  129.         dl->dl_Task = DosPort;
  130.         dl->dl_DiskType = ID_DOS_DISK;
  131.         dl->dl_Name = CTOB(volname); /* DosNode->dn_Name*/;
  132.         dl->dl_Next = di->di_DevInfo;
  133.         di->di_DevInfo = (long)CTOB(dl);
  134.  
  135.         /*
  136.          *    Set dn_Task field which tells DOS not to startup a new
  137.          *    process on every reference.
  138.          */
  139.  
  140.         DosNode->dn_Task = DosPort;
  141.         PRes1 = DOS_TRUE;
  142.         PRes2 = 0;
  143.     } else {                /*    couldn't open dos.library  */
  144.         PRes1 = DOS_FALSE;
  145.         returnpacket(packet);
  146.         return;                /*    exit process       */
  147.     }
  148.     returnpacket(packet);
  149.     }
  150.  
  151.     /*
  152.      *    Initialize debugging code
  153.      */
  154.  
  155. /*DB*/  dbinit();
  156.  
  157.     /*    Initialize  RAM disk    */
  158.  
  159.     {
  160.     ubyte *ptr = BTOC(DosNode->dn_Name);
  161.     short len = *ptr;
  162.  
  163.     NewList(&FHBase);                /*    more globals    */
  164.     NewList(&LCBase);
  165.     bzero(&RFRoot,sizeof(RFRoot));
  166.     RFRoot.type = FILE_DIR;             /*    root directory    */
  167.     DateStamp(&RFRoot.date);            /*    datestamp    */
  168.     NewList(&RFRoot.list);                /*    sub dirs    */
  169.     RFRoot.name = AllocMem(len+1, MEMF_PUBLIC); /*    Root NAME    */
  170.     bmov(ptr+1,RFRoot.name,len);
  171.     RFRoot.name[len] = 0;
  172. /*DB*/    dbprintf("ROOT NAME: %ld '%s'\n", len, RFRoot.name);
  173.     }
  174.  
  175.     /*
  176.      *    Here begins the endless loop, waiting for requests over our
  177.      *    message port and executing them.  Since requests are sent over
  178.      *    our message port, this precludes being able to call DOS functions
  179.      *    ourselves (that is why the debugging routines are a separate process)
  180.      */
  181.  
  182.      WaitPort(&DosProc->pr_MsgPort);        /*  Get Startup Packet    */
  183.      msg = GetMsg(&DosProc->pr_MsgPort);
  184.      notdone = 1;
  185.      goto entry;
  186.  
  187. top:
  188.     for (notdone = 1; notdone;) {
  189.     WaitPort(DosPort);
  190.     while (msg = GetMsg(DosPort)) {
  191. entry:
  192.         packet = (PACKET *)msg->mn_Node.ln_Name;
  193.         PRes1 = DOS_TRUE;
  194.         PRes2 = 0;
  195.         error = 0;
  196. /*DB*/        dbprintf("Packet: %3ld %08lx %08lx %08lx %10s ",
  197. /*DB*/            PType, PArg1, PArg2, PArg3, typetostr(PType) );
  198.  
  199.         switch(PType) {
  200.         case ACTION_DIE:        /*    attempt to die?  */
  201.         notdone = 0;        /*    try to die     */
  202.         break;
  203.         case ACTION_OPENRW:     /*    FileHandle,Lock,Name       Bool    */
  204.         case ACTION_OPENOLD:    /*    FileHandle,Lock,Name       Bool    */
  205.         case ACTION_OPENNEW:    /*    FileHandle,Lock,Name       Bool    */
  206.         {
  207.             register RAMFILE *ramfile;
  208.             RAMFILE *parentdir = getlockfile(PArg2);
  209.             char    *ptr;
  210.  
  211.             btos(PArg3,buf);
  212. /*DB*/            dbprintf("'%s' ", buf);
  213.             if (ramfile = searchpath(&parentdir,buf,&ptr)) {
  214.                 if (ramfile == &xpath) {
  215.                 FH *p;
  216.                 if (p = Open(buf1,PType)) {
  217.                     bmov(BTOC(p),BTOC(PArg1),sizeof(FH));
  218.                 FreeMem(BTOC(p),sizeof(FH));
  219.                 }
  220.                 else
  221.                     error = IoErr();
  222.                 goto openbreak;
  223.             }
  224.             if (ramfile->type == FILE_DIR) {
  225.                 error = ERROR_OBJECT_WRONG_TYPE;
  226.                 goto openbreak;
  227.             }
  228.             if (ramfile->locks < 0) {
  229.                 error = ERROR_OBJECT_IN_USE;
  230.                 goto openbreak;
  231.             }
  232.             if (PType == ACTION_OPENOLD) {
  233.                 ++ramfile->locks;
  234.             } else {
  235.                 if (ramfile->locks > 0) {
  236.                 error = ERROR_OBJECT_IN_USE;
  237.                 } else {
  238.                 if (PType == ACTION_OPENNEW) {
  239.                     freedata(ramfile);
  240.                     ramfile->protection = 0;
  241.                 }
  242.                 --ramfile->locks;
  243.                 }
  244.             }
  245.             } else {
  246.             if (!parentdir) {
  247.                 error = ERROR_INVALID_COMPONENT_NAME;
  248.                 goto openbreak;
  249.             }
  250.             if (PType == ACTION_OPENNEW) {
  251.                ramfile = createramfile(parentdir,FILE_FILE,ptr);
  252.                --ramfile->locks;
  253.             } else {
  254.                 error = ERROR_OBJECT_NOT_FOUND;
  255.             }
  256.             }
  257.             if (!error) {
  258.             register MYFH *mfh = AllocMem(sizeof(MYFH), MEMF_PUBLIC|MEMF_CLEAR);
  259.             ((FH *)BTOC(PArg1))->fh_Arg1 = (long)mfh;
  260.             mfh->file = ramfile;
  261.             mfh->fentry = GetHead(&ramfile->list);
  262.             AddHead(&FHBase,mfh);
  263.             }
  264.         }
  265.           openbreak:
  266.         if (!GetHead(&FHBase) && !GetHead(&LCBase))
  267.             notdone = 0;
  268.         break;
  269.         case ACTION_READ:        /*     FHArg1,CPTRBuffer,Length   ActLength  */
  270.         {
  271.             register MYFH   *mfh = (MYFH *)PArg1;
  272.             register FENTRY *fen = mfh->fentry;
  273.             register ubyte  *ptr = (ubyte *)PArg2;
  274.             register long   left = PArg3;
  275.             register long   scr;
  276.  
  277.             while (left && fen) {
  278.             scr = fen->bytes - mfh->offset;
  279.             if (left < scr) {
  280.                 bmov(fen->buf + mfh->offset, ptr, left);
  281.                 mfh->offset += left;
  282.                 left = 0;
  283.             } else {
  284.                 bmov(fen->buf + mfh->offset, ptr, scr);
  285.                 left -= scr;
  286.                 ptr += scr;
  287.                 mfh->base += fen->bytes;
  288.                 mfh->offset = 0;
  289.                 fen = NextNode(fen);
  290.             }
  291.             }
  292.             mfh->fentry = fen;
  293.             PRes1 = PArg3 - left;
  294.         }
  295.         break;
  296.         case ACTION_WRITE:        /*     FHArg1,CPTRBuffer,Length   ActLength  */
  297.         {
  298.             register MYFH   *mfh = (MYFH *)PArg1;
  299.             register FENTRY *fen = (FENTRY *)mfh->fentry;
  300.             ubyte  *ptr = (ubyte *)PArg2;
  301.             long   left = PArg3;
  302.             long   scr;
  303.  
  304.             /*
  305.              *    Doesn't work right if multiple readers/appenders.
  306.              */
  307.  
  308.             while (left) {
  309.             if (fen) {
  310. /*DB*/                dbprintf("FEN: %ld left: %ld\n",fen->bytes,left);
  311.                 scr = fen->bytes - mfh->offset;
  312.                 if (left < scr) {
  313.                 if (fen->bytes < mfh->offset + left) {
  314. /*DB*/                    dbprintf("PANIC! AWR0\n");
  315.                 }
  316.                 else
  317.                     bmov(ptr, fen->buf + mfh->offset, left);
  318.                 mfh->offset += left;
  319.                 left = 0;
  320.                 } else {
  321.                 if (fen->bytes < mfh->offset + scr) {
  322. /*DB*/                    dbprintf("PANIC! AWR1\n");
  323.                 }
  324.                 else
  325.                     bmov(ptr, fen->buf + mfh->offset, scr);
  326.                 ptr += scr;
  327.                 left -= scr;
  328.                 mfh->base += fen->bytes;
  329.                 mfh->offset = 0;
  330.                 fen = NextNode(fen);
  331.                 }
  332.             } else {
  333.                 fen = AllocMem(sizeof(FENTRY), MEMF_PUBLIC);
  334.                 if (fen->buf = AllocMem(left, MEMF_PUBLIC)) {
  335.                 fen->bytes = left;
  336.                 mfh->file->bytes += left;
  337.                 mfh->base  += left;
  338.                 mfh->offset = 0;
  339.                 TotalBytes += left;
  340.                 AddTail(&mfh->file->list, fen);
  341. /*DB*/                dbprintf("NEWFEN: (%ld)\n", fen->bytes);
  342.                 bmov(ptr, fen->buf, left);
  343.                 left = 0;
  344.                 } else {
  345.                 FreeMem(fen, sizeof(FENTRY));
  346. /*DB*/                dbprintf("NEWFEN: ****** Unable to allocate buffer %ld\n", left);
  347.                 mfh->offset = 0;
  348.                 break;
  349.                 }
  350.                 fen = NULL;     /*    cause append    */
  351.             }
  352.             }
  353.             PRes1 = PArg3 - left;
  354.             mfh->fentry = fen;
  355.         }
  356.         break;
  357.         case ACTION_CLOSE:        /*     FHArg1             Bool:TRUE  */
  358.         {
  359.             register MYFH   *mfh = (MYFH *)PArg1;
  360.             register RAMFILE *file = mfh->file;
  361.  
  362.             Remove(mfh);
  363.             FreeMem(mfh,sizeof(*mfh));
  364.             if (--file->locks < 0)
  365.             file->locks = 0;
  366.         }
  367.         if (!GetHead(&FHBase) && !GetHead(&LCBase))
  368.             notdone = 0;
  369.         break;
  370.         case ACTION_SEEK:        /*     FHArg1,Position,Mode        OldPosition*/
  371.         {
  372.             register MYFH *mfh = (MYFH *)PArg1;
  373.             register FENTRY *fen;
  374.             register long absseek;
  375.  
  376.             PRes1 = mfh->base + mfh->offset;
  377.             absseek = PArg2;
  378.             if (PArg3 == 0)
  379.             absseek += mfh->base + mfh->offset;
  380.             if (PArg3 == 1)
  381.             absseek = mfh->file->bytes + absseek;
  382.             if (absseek < 0 || absseek > mfh->file->bytes) {
  383.             error = ERROR_SEEK_ERROR;
  384.             break;
  385.             }
  386.             mfh->base = mfh->offset = 0;
  387.  
  388.             /*
  389.              *    Stupid way to do it but....
  390.              */
  391.  
  392.             for (fen = GetHead(&mfh->file->list); fen; fen = NextNode(fen)) {
  393.             if (mfh->base + fen->bytes > absseek) {
  394.                 mfh->offset = absseek - mfh->base;
  395.                 break;
  396.             }
  397.             mfh->base += fen->bytes;
  398.             }
  399.             mfh->fentry = fen;
  400.         }
  401.         break;
  402.         /*
  403.          *    This implementation sucks.  The right way to do it is with
  404.          *    a hash table.  The directory must be searched for the file
  405.          *    name, then the next entry retrieved.  If the next entry is
  406.          *    NULL there are no more entries.  If the filename could not
  407.          *    be found we return the first entry, if any.
  408.          *
  409.          *    You can't simply keep a pointer around to the next node
  410.          *    because it can be moved or removed at any time.
  411.          */
  412.  
  413.         case ACTION_EXAMINE_NEXT: /*   Lock,Fib              Bool     */
  414.         {
  415.             register FIB *fib = BTOC(PArg2);
  416.             register RAMFILE *dir = getlockfile(PArg1);
  417.             register RAMFILE *file;
  418.  
  419.             if (dir->type == FILE_FILE) {
  420.             error = ERROR_OBJECT_WRONG_TYPE;
  421.             break;
  422.             }
  423.             file = GetHead(&dir->list);
  424.             if (fib->fib_DiskKey) {
  425.             register int len = *(ubyte *)fib->fib_FileName;
  426.             for (; file; file = NextNode(file)) {
  427.                 if (strlen(file->name) == len && nccmp(file->name, fib->fib_FileName+1, len))
  428.                 break;
  429.             }
  430.             if (file)
  431.                 file = NextNode(file);
  432.             else
  433.                 file = GetHead(&dir->list);
  434.             }
  435.             fib->fib_DiskKey = 1;
  436.             error = -1;
  437.             if (!(tmp=file)) {
  438.             error = ERROR_NO_MORE_ENTRIES;
  439.             break;
  440.             }
  441.         }
  442.         /*  fall through    */
  443.         case ACTION_EXAMINE_OBJECT: /*   Lock,Fib            Bool       */
  444.         {
  445.             register FIB *fib;
  446.             register RAMFILE *file;
  447.             register RAMFILE *dummy;
  448.  
  449.             fib = BTOC(PArg2);
  450.             if (error) {
  451.             file = tmp;    /*  fall through from above */
  452.             } else {
  453.             file = getlockfile(PArg1);
  454.             fib->fib_DiskKey = 0;
  455.             }
  456.             error = 0;
  457.             fib->fib_DirEntryType = file->type;
  458.             strcpy(fib->fib_FileName+1, file->name);
  459.             fib->fib_FileName[0] = strlen(file->name);
  460.             fib->fib_Protection = file->protection;
  461.             fib->fib_EntryType = NULL;
  462.             fib->fib_Size = file->bytes;
  463.             fib->fib_NumBlocks = file->bytes >> 9;
  464.             fib->fib_Date = file->date;
  465.             if (file->comment) {
  466.             strcpy(fib->fib_Comment+1, file->comment);
  467.             fib->fib_Comment[0] = strlen(file->comment);
  468.             } else {
  469.             fib->fib_Comment[0] = 0;
  470.             }
  471.         }
  472.         break;
  473.         case ACTION_INFO:        /*    Lock, InfoData      Bool:TRUE    */
  474.         tmp = BTOC(PArg2);
  475.         error = -1;
  476.         /*  fall through    */
  477.         case ACTION_DISK_INFO:  /*    InfoData      Bool:TRUE    */
  478.         {
  479.             register INFODATA *id;
  480.  
  481.             /*
  482.              *    Note:    id_NumBlocks is never 0, but only to get
  483.              *    around a bug I found in my shell (where I divide
  484.              *    by id_NumBlocks).  Other programs probably break
  485.              *    as well.
  486.              */
  487.  
  488.             (error) ? (id = tmp) : (id = BTOC(PArg1));
  489.             error = 0;
  490.             bzero(id, sizeof(*id));
  491.             id->id_DiskState = ID_VALIDATED;
  492.             id->id_NumBlocks     = (TotalBytes >> 9) + 1;
  493.             id->id_NumBlocksUsed = (TotalBytes >> 9) + 1;
  494.             id->id_BytesPerBlock = 512;
  495.             id->id_DiskType = ID_DOS_DISK;
  496.             id->id_VolumeNode = (long)CTOB(DosNode);
  497.             id->id_InUse = (long)GetHead(&LCBase);
  498.         }
  499.         break;
  500.         case ACTION_PARENT:     /*     Lock              ParentLock */
  501.         {
  502.             register RAMFILE *file = getlockfile(PArg1);
  503.             /*
  504.             if (file->type == FILE_FILE) {
  505.             error = ERROR_OBJECT_NOT_FOUND;
  506.             break;
  507.             }
  508.             */
  509.             if (file->locks < 0) {
  510.             error = ERROR_OBJECT_IN_USE;
  511.             break;
  512.             }
  513.             if (file->parent)
  514.             PRes1 = (long)CTOB(ramlock(file->parent, ACCESS_READ));
  515.             else
  516.             error = ERROR_OBJECT_NOT_FOUND;
  517.         }
  518.         break;
  519.         case ACTION_DELETE_OBJECT: /*Lock,Name  Bool       */
  520.         {
  521.             RAMFILE *parentdir = getlockfile(PArg1);
  522.             RAMFILE *ramfile;
  523.  
  524.             btos(PArg2, buf);
  525.             if (ramfile = searchpath(&parentdir,buf,NULL)) {
  526.                 if (ramfile == &xpath) {
  527.                 if (!DeleteFile(buf1)) error = IoErr();
  528.                 break;
  529.             }
  530.             if (ramfile->locks || ramfile == &RFRoot) {
  531.                 error = ERROR_OBJECT_IN_USE;
  532.                 break;
  533.             }
  534.             if (ramfile->type == FILE_DIR) {
  535.                 if (GetHead(&ramfile->list))
  536.                 error = ERROR_DIRECTORY_NOT_EMPTY;
  537.             } else {
  538.                 freedata(ramfile);
  539.             }
  540.             if (!error) {
  541.                 freeramfile(ramfile);
  542.                 DateStamp(&parentdir->date);
  543.             }
  544.             } else {
  545.             if (!parentdir)
  546.                 error = ERROR_INVALID_COMPONENT_NAME;
  547.             else
  548.                 error = ERROR_OBJECT_NOT_FOUND;
  549.             }
  550.         }
  551.         if (!GetHead(&FHBase) && !GetHead(&LCBase))
  552.             notdone = 0;
  553.         break;
  554.         case ACTION_CREATE_DIR: /*     Lock,Name      Lock       */
  555.         {
  556.             RAMFILE *parentdir = getlockfile(PArg1);
  557.             RAMFILE *ramfile;
  558.             char *ptr;
  559.  
  560.             btos(PArg2, buf);
  561.             if (ramfile = vsearchpath(&parentdir,buf,&ptr)) {
  562.             error = ERROR_OBJECT_EXISTS;
  563.             break;
  564.             }
  565.             if (!parentdir) {
  566.             error = ERROR_INVALID_COMPONENT_NAME;
  567.             break;
  568.             }
  569.             ramfile = createramfile(parentdir, FILE_DIR, ptr);
  570.             PRes1 = (long)CTOB(ramlock(ramfile, ACCESS_WRITE));
  571.         }
  572.         break;
  573.         case ACTION_LOCATE_OBJECT:    /*   Lock,Name,Mode    Lock       */
  574.         {
  575.             RAMFILE *parentdir = getlockfile(PArg1);
  576.             RAMFILE *ramfile;
  577.  
  578.             btos(PArg2, buf);
  579. /*DB*/            dbprintf("'%s' %ld ", buf, PArg3);
  580.             if (ramfile = searchpath(&parentdir,buf,NULL)) {
  581.                 if (ramfile == &xpath) {
  582.                PRes1 = Lock(buf1,PArg3);
  583.                if (!PRes1) PRes2 = IoErr();
  584.                break;
  585.             }
  586.             if (ramfile->locks < 0 || (ramfile->locks && PArg3 == ACCESS_WRITE)) {
  587.                 error = ERROR_OBJECT_IN_USE;
  588.                 break;
  589.             }
  590.             PRes1 = (long)CTOB(ramlock(ramfile, PArg3));
  591.             } else {
  592.             if (!parentdir)
  593.                 error = ERROR_INVALID_COMPONENT_NAME;
  594.             else
  595.                 error = ERROR_OBJECT_NOT_FOUND;
  596.             }
  597.         }
  598.         break;
  599.         case ACTION_COPY_DIR:   /*     Lock,                Lock       */
  600.         {
  601.             register RAMFILE *ramfile = getlockfile(PArg1);
  602.             if (ramfile->locks < 0)
  603.             error = ERROR_OBJECT_IN_USE;
  604.             else
  605.             PRes1 = (long)CTOB(ramlock(ramfile, ACCESS_READ));
  606.         }
  607.         break;
  608.         case ACTION_FREE_LOCK:  /*     Lock,                Bool       */
  609.         if (PArg1);
  610.             ramunlock(BTOC(PArg1));
  611.         if (!GetHead(&FHBase) && !GetHead(&LCBase))
  612.             notdone = 0;
  613.         break;
  614.         case ACTION_SET_PROTECT:/*     -,Lock,Name,Mask       Bool       */
  615.         {
  616.             register RAMFILE *ramfile;
  617.             RAMFILE *parentdir = getlockfile(PArg2);
  618.             char *ptr;
  619.  
  620.             btos(PArg3, buf);
  621.             if (ramfile = searchpath(&parentdir,buf,&ptr)) {
  622.                 if (ramfile == &xpath) {
  623.                 if (!SetProtection(buf1,PArg4))
  624.                         error = IoErr();
  625.                 break;
  626.             }
  627.             ramfile->protection = PArg4;
  628.             } else {
  629.             if (parentdir)
  630.                 error = ERROR_OBJECT_NOT_FOUND;
  631.             else
  632.                 error = ERROR_INVALID_COMPONENT_NAME;
  633.             }
  634.         }
  635.         break;
  636.         case ACTION_SET_COMMENT:/*     -,Lock,Name,Comment       Bool       */
  637.         {
  638.             register RAMFILE *ramfile;
  639.             RAMFILE *parentdir = getlockfile(PArg2);
  640.             char *ptr;
  641.  
  642.             btos(PArg3, buf);
  643.             if (ramfile = searchpath(&parentdir,buf,&ptr)) {
  644.                 if (ramfile == &xpath) {
  645.                 btos(PArg4,buf);
  646.                 if (!SetComment(buf1,buf))
  647.                     error = IoErr();
  648.                 break;
  649.             }
  650.             btos(PArg4, buf);
  651.             if (ramfile->comment)
  652.                 FreeMem(ramfile->comment,strlen(ramfile->comment)+1);
  653.             ramfile->comment = AllocMem(strlen(buf)+1, MEMF_PUBLIC);
  654.             strcpy(ramfile->comment, buf);
  655.             } else {
  656.             if (parentdir)
  657.                 error = ERROR_OBJECT_NOT_FOUND;
  658.             else
  659.                 error = ERROR_INVALID_COMPONENT_NAME;
  660.             }
  661.         }
  662.         break;
  663.         case ACTION_RENAME_OBJECT:/* SLock,SName,DLock,DName    Bool       */
  664.         {
  665.             register RAMFILE *file1;
  666.             RAMFILE *sourcedir = getlockfile(PArg1);
  667.             RAMFILE *destdir   = getlockfile(PArg3);
  668.             char *ptr;
  669.  
  670.             btos(PArg2,buf);
  671. /*DB*/            dbprintf("\nRENAME '%s' (%ld)  ", buf, strlen(buf));
  672.             if (file1 = vsearchpath(&sourcedir,buf,NULL)) {
  673.             btos(PArg4,buf);
  674. /*DB*/            dbprintf("TO '%s' (%ld)", buf, strlen(buf));
  675.             if (vsearchpath(&destdir,buf,&ptr)) {
  676.                 error = ERROR_OBJECT_EXISTS;
  677.             } else {
  678.                 if (destdir) {
  679.                 if (file1 == destdir) { 
  680.                     /* moving inside self */
  681.                     error = ERROR_OBJECT_IN_USE;
  682.                     break;
  683.                 }
  684. /*DB*/                dbprintf("REN '%s' %ld", ptr, strlen(ptr));
  685.                 DateStamp(&sourcedir->date);
  686.                 DateStamp(&destdir->date);
  687.                 Remove(file1);
  688.                 file1->name = AllocMem(strlen(ptr)+1,MEMF_PUBLIC);
  689.                 file1->parent = destdir;
  690.                 strcpy(file1->name, ptr);
  691.                 AddHead(&destdir->list, file1);
  692.                 } else {
  693.                 error = ERROR_INVALID_COMPONENT_NAME;
  694.                 }
  695.             }
  696.             } else {
  697.             if (sourcedir)
  698.                 error = ERROR_OBJECT_NOT_FOUND;
  699.             else
  700.                 error = ERROR_INVALID_COMPONENT_NAME;
  701.             }
  702.         }
  703.         break;
  704.         /*
  705.          *    A few other packet types which we do not support
  706.          */
  707.         case ACTION_INHIBIT:    /*     Bool        Bool       */
  708.         /*  Return success for the hell of it    */
  709.         break;
  710.         case ACTION_RENAME_DISK:/*     BSTR:NewName    Bool       */
  711.         case ACTION_MORECACHE:  /*     #BufsToAdd    Bool       */
  712.         case ACTION_WAIT_CHAR:  /*     Timeout, ticks Bool       */
  713.         case ACTION_FLUSH:        /*     writeout bufs, disk motor off      */
  714.         case ACTION_RAWMODE:    /*     Bool(-1:RAW 0:CON)    OldState   */
  715.         default:
  716.         error = ERROR_ACTION_NOT_KNOWN;
  717.         break;
  718.         }
  719.         if (packet) {
  720.         if (error) {
  721. /*DB*/            dbprintf("ERR=%ld\n", error);
  722.             PRes1 = DOS_FALSE;
  723.             PRes2 = error;
  724.         } else {
  725. /*DB*/            dbprintf("RES=%06lx\n", PRes1);
  726.         }
  727.         returnpacket(packet);
  728.         }
  729.         else {
  730. /*DB*/         dbprintf("NOREP\n");
  731.         }
  732.     }
  733.     }
  734. /*DB*/  dbprintf("Can we remove ourselves? ");
  735. /*DB*/  Delay(50);        /*    I wanna even see the debug message! */
  736.     Forbid();
  737.     if (packetsqueued() || GetHead(&FHBase) || GetHead(&LCBase)
  738.       || GetHead(&RFRoot.list)) {
  739.     Permit();
  740. /*DB*/    dbprintf(" ..  not yet!\n");
  741.     goto top;        /*  sorry... can't exit     */
  742.     }
  743.  
  744.     /*
  745.      *    Causes a new process to be created on next reference
  746.      */
  747.  
  748.     DosNode->dn_Task = FALSE;
  749.  
  750.     /*
  751.      *    Remove Volume entry.  Since DOS uses singly linked lists, we
  752.      *    must (ugg) search it manually to find the link before our
  753.      *    Volume entry.
  754.      */
  755.  
  756.     {
  757.     DOSINFO *di = BTOC(((ROOTNODE *)DOSBase->dl_Root)->rn_Info);
  758.     register DEVLIST *dl;
  759.     register void *dlp;
  760.  
  761.     dlp = &di->di_DevInfo;
  762.     for (dl = BTOC(di->di_DevInfo); dl && dl != DevList; dl = BTOC(dl->dl_Next))
  763.         dlp = &dl->dl_Next;
  764.     if (dl == DevList) {
  765.         *(BPTR *)dlp = dl->dl_Next;
  766.         dosfree(dl);
  767.     } else {
  768. /*DB*/        dbprintf("****PANIC: Unable to find volume node\n");
  769.     }
  770.     }
  771.  
  772.     /*
  773.      *    Remove debug process, closedown, fall of the end of the world
  774.      *    (which is how you kill yourself if a PROCESS.  A TASK would have
  775.      *    had to RemTask(NULL) itself).
  776.      */
  777.  
  778. /*DB*/  dbuninit();
  779.         CloseLibrary(DOSBase);
  780. }
  781.  
  782.  
  783. /*DB*/ static FH *debugfh;
  784. /*DB*/
  785. /*DB*/ dbinit()
  786. /*DB*/ {
  787. /*DB*/     debugfh = Open("con:0/0/640/150/debugwindow", 1006);
  788. /*DB*/
  789. /*DB*/ }
  790. /*DB*/
  791. /*DB*/ dbuninit()
  792. /*DB*/ {
  793. /*DB*/    Close(debugfh);
  794. /*DB*/ }
  795. /*DB*/
  796. /*DB*/ dbprintf(a,b,c,d,e,f,g,h,i,j)
  797. /*DB*/ {
  798. /*DB*/    static char buf[256];
  799. /*DB*/
  800. /*DB*/      sprintf(buf,a,b,c,d,e,f,g,h,i,j);
  801. /*DB*/      Write(debugfh,buf,strlen(buf));
  802. /*DB*/
  803. /*DB*/ }
  804.