home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format 56 / af056sub.adf / parnfs.lha / pack.c < prev    next >
C/C++ Source or Header  |  1993-12-02  |  22KB  |  830 lines

  1. /*-
  2.  * $Id: pack.c,v 1.1 1993/12/02 20:45:46 Rhialto Exp $
  3.  * $Log: pack.c,v $
  4.  * Revision 1.1  1993/12/02  20:45:46  Rhialto
  5.  * Initial revision
  6.  *
  7.  *
  8.  *  Originally:
  9.  *
  10.  *    DOSDEVICE.C        V1.10   2 November 1987
  11.  *
  12.  *    EXAMPLE DOS DEVICE DRIVER FOR AZTEC.C    PUBLIC DOMAIN.
  13.  *
  14.  *    By Matthew Dillon.
  15.  *
  16.  *  This has been stripped and refilled with network filesystem code
  17.  *  by Olaf Seibert.
  18.  *
  19.  *  This code is (C) Copyright 1993 by Olaf Seibert. All rights reserved.
  20.  *  May not be used or copied without a licence.
  21. -*/
  22.  
  23. #include "netfs.h"
  24. #include <string.h>
  25.  
  26. #ifdef DEBUG
  27. #   include "syslog.h"
  28. #else
  29. #   define    debug(x)
  30. #endif
  31.  
  32.  
  33. #define NETFL(something)     ((NetFileLock *)(something))
  34. #define NETFH(something)     ((NetFileHandle *)(something))
  35.  
  36. Prototype struct ExecBase *SysBase;
  37. Prototype struct MsgPort *DosPort;
  38. Prototype struct DeviceNode *DevNode;
  39. Prototype struct DeviceList *VolNode;
  40. Prototype long        UnitNr;
  41. Prototype char       *DevName;
  42. Prototype ULONG     DevFlags;
  43. Prototype struct DosPacket *DosPacket;
  44. Prototype ULONG     error;
  45.  
  46. Local BPTR MakeFileLock(NetFileLock *netfl, struct FileLock *fl, long mode);
  47.  
  48. /*
  49.  * Since this code might be called several times in a row without being
  50.  * unloaded, you CANNOT ASSUME GLOBALS HAVE BEEN ZERO'D!!  This also goes
  51.  * for any global/static assignments that might be changed by running the
  52.  * code.
  53.  */
  54.  
  55. struct MsgPort    *DosPort;    /* Our DOS port... */
  56. struct DeviceNode *DevNode;    /* Our DOS node.. created by DOS for us */
  57. struct DeviceList *VolNode;    /* Device List structure for our volume
  58.                  * node */
  59.  
  60. struct DosLibrary *DOSBase;    /* DOS library base */
  61. long        WaitMask;    /* The signal mask to wait for */
  62. long        UnitNr;     /* From */
  63. char           *DevName;    /*   the */
  64. ULONG        DevFlags;    /*     mountlist */
  65. struct DosPacket *DosPacket;    /* For the SystemRequest pr_WindowPtr */
  66. long        OpenCount;    /* How many open files/locks there are */
  67. ULONG        error;
  68.  
  69.  
  70. /*
  71.  * Don't call the entry point main().  This way, if you make a mistake
  72.  * with the compile options you'll get a link error.
  73.  */
  74.  
  75. Prototype void netfilesyshandler(void);
  76.  
  77. void
  78. handlermain(void)
  79. {
  80.     register struct DosPacket *packet;
  81.     struct Message *msg;
  82.     short        done;
  83.  
  84.     /*
  85.      * Initialize all global variables.  SysBase MUST be initialized
  86.      * before we can make Exec calls.  AbsExecBase is a library symbol
  87.      * referencing absolute memory location 4.
  88.      */
  89.  
  90.     DOSBase = OpenLibrary("dos.library", 0L);
  91.  
  92. #ifdef DEBUG
  93.     /*
  94.      * Initialize debugging code as soon as possible. Only SysBase required.
  95.      */
  96.  
  97.     initsyslog();
  98. #endif                /* DEBUG */
  99.  
  100.     DosPort = &((struct Process *)FindTask(NULL))->pr_MsgPort;
  101.  
  102.     debug(("WaitPort DosPort for startup...\n"));
  103.     WaitPort(DosPort);      /* Get Startup Packet  */
  104.     debug(("WaitPort DosPort done\n"));
  105.     msg = GetMsg(DosPort);
  106.     packet = (struct DosPacket *) msg->mn_Node.ln_Name;
  107.  
  108.     DevNode = BTOC(PArg3);
  109.     {
  110.     struct FileSysStartupMsg *fssm;
  111.     struct DosEnvec *de;
  112.  
  113.     DevName = "parnet.device";
  114.     UnitNr = 0;
  115.     DevFlags = 0;
  116.  
  117.     if (fssm = (struct FileSysStartupMsg *)BTOC(DevNode->dn_Startup)) {
  118.                     /* Same as BTOC(packet->dp_Arg2) */
  119.         UnitNr = fssm->fssm_Unit;
  120.         if (fssm->fssm_Device)
  121.         DevName = (char *)BTOC(fssm->fssm_Device)+1;
  122.         DevFlags = fssm->fssm_Flags;
  123.         de = BTOC(fssm->fssm_Environ);
  124.  
  125.         ClientDefaults(de->de_BlocksPerTrack, de->de_Interleave);
  126.     }
  127.     }
  128.  
  129.     if (DOSBase && OpenNetFS() == 0) {
  130.     /*
  131.      * Loading DevNode->dn_Task causes DOS *NOT* to startup a new
  132.      * instance of the device driver for every reference.    E.G. if
  133.      * you were writing a CON: device you would want this field to be
  134.      * NULL.
  135.      */
  136.  
  137.     DevNode->dn_Task = DosPort;
  138.  
  139.     PRes1 = DOSTRUE;
  140.     PRes2 = 0;
  141.     } else {            /* couldn't open dos.library  */
  142.     PRes1 = DOSFALSE;
  143.     PRes2 = ERROR_DEVICE_NOT_MOUNTED;   /* no better message available */
  144.     returnpacket(packet);
  145.     goto exit;        /* exit process    */
  146.     }
  147.     returnpacket(packet);
  148.  
  149.     /*
  150.      * Get the first real packet.
  151.      * This seems to be necessary because adding our Volume node at
  152.      * this point causes some kind of deadlock. Which is kind
  153.      * of silly since we returned the startup packet. Even calling
  154.      * AttemptLockDosList does not seem to give any indication...
  155.      */
  156.     debug(("WaitPort DosPort for 1st real packet...\n"));
  157.     WaitPort(DosPort);
  158.     debug(("WaitPort DosPort done\n"));
  159.     msg = GetMsg(DosPort);
  160.  
  161.     {
  162.     struct DateStamp ds;
  163.  
  164.     DateStamp(&ds);
  165.     VolNode = NewVolNode("Network", &ds);
  166.     debug(("VolNode done\n"));
  167.     }
  168.     /* Initialize some more global variables    */
  169.  
  170.     OpenCount = 0;
  171.     WaitMask = (1L << DosPort->mp_SigBit) |
  172.            (1L << RdPort->mp_SigBit);
  173.  
  174.     done = -1;
  175.  
  176.     goto entry;
  177.  
  178.     /*
  179.      * Here begins the endless loop, waiting for requests over our message
  180.      * port and executing them.  Since requests are sent over the message
  181.      * port in our device and volume nodes, we must not use our Process
  182.      * message port for this: this precludes being able to call DOS
  183.      * functions ourselves.
  184.      */
  185.  
  186. top:
  187.     for (done = -1; done < 0;) {
  188.     Wait(WaitMask);
  189.     wakeup:
  190.     while (msg = GetMsg(RdPort)) {
  191.         /* Handle unsollicited network input */
  192.         DoProtocol(msg, ((struct IOStdReq *)msg)->io_Data);
  193.     }
  194.     while (msg = GetMsg(DosPort)) {
  195.     entry:
  196.  
  197.         packet = (PACKET *) msg->mn_Node.ln_Name;
  198.         PRes1 = DOSFALSE;
  199.         PRes2 = 0;
  200.         error = 0;
  201.         debug(("Packet: %4ld %08lx %08lx %08lx %s\n",
  202.              PType, PArg1, PArg2, PArg3, typetostr(PType)));
  203.  
  204.         DosPacket = packet;     /* For the System Requesters */
  205.         ReqPacket.p_Action = PType;
  206.  
  207.         switch (PType) {
  208.         case ACTION_DIE:        /* attempt to die?  */
  209.         done = (PArg1 == MSH_MAGIC) ? PArg2 : 0;   /* Argh! Hack! */
  210.         break;
  211.         case ACTION_CURRENT_VOLUME: /* -               VolNode,UnitNr*/
  212.         PRes1 = (long) CTOB(VolNode);
  213.         PRes2 = UnitNr;
  214.         break;
  215.         case ACTION_LOCATE_OBJECT:    /* Lock,Name,Mode    Lock         */
  216.         {
  217.             struct FileLock *lock;
  218.             NetFileLock     *netfl;
  219.             long        lockmode;
  220.  
  221.             lock = BTOC(PArg1);
  222.             if ((lockmode = PArg3) != EXCLUSIVE_LOCK)
  223.             lockmode = SHARED_LOCK;
  224.             netfl = NetLock(NETFL(lock ? lock->fl_Key : 0),
  225.                   BTOC(PArg2),
  226.                   lockmode);
  227.             PRes1 = MakeFileLock(netfl, lock, lockmode);
  228.         }
  229.         break;
  230.         case ACTION_RENAME_DISK:    /* BSTR:NewName        Bool      */
  231.         NewVolNodeName(BTOC(PArg1));
  232.         PRes1 = DOSTRUE;
  233.         break;
  234.         case ACTION_FREE_LOCK:    /* Lock            Bool      */
  235.         {
  236.             struct FileLock *lock;
  237.             NetFileLock    *netfl;
  238.  
  239.             PRes1 = DOSTRUE;
  240.             lock = BTOC(PArg1);
  241.             if (lock == NULL)
  242.             break;
  243.  
  244.             netfl = NETFL(lock->fl_Key);
  245.             FreeFileLock(lock);
  246.             NetUnLock(netfl);
  247.         }
  248.         break;
  249.         case ACTION_DELETE_OBJECT:    /* Lock,Name        Bool         */
  250.         {
  251.             struct FileLock *lock;
  252.  
  253.             lock = BTOC(PArg1);
  254.             PRes1 = NetDeleteFile(NETFL(lock ? lock->fl_Key : 0),
  255.                      BTOC(PArg2));
  256.         }
  257.         break;
  258.         case ACTION_RENAME_OBJECT:    /* SLock,SName,DLock,DName   Bool    */
  259.         {
  260.             struct FileLock *slock, *dlock;
  261.  
  262.             slock = BTOC(PArg1);
  263.             dlock = BTOC(PArg3);
  264.             PRes1 = NetRename(NETFL(slock ? slock->fl_Key : 0),
  265.                      BTOC(PArg2),
  266.                      NETFL(dlock ? dlock->fl_Key : 0),
  267.                      BTOC(PArg4));
  268.         }
  269.         break;
  270.         case ACTION_MORECACHE:    /* #BufsToAdd        bool,numbufs */
  271.         PRes1 = 0;        /* observed behaviour in std filesystem */
  272.         PRes2 = 0;        /* documented behaviour in manual */
  273.         break;
  274.         case ACTION_COPY_DIR:    /* Lock            Lock      */
  275.         {
  276.             struct FileLock *lock;
  277.             NetFileLock *netfl;
  278.  
  279.             lock = BTOC(PArg1);
  280.  
  281.             netfl = NetDupLock(NETFL(lock ? lock->fl_Key : 0));
  282.  
  283.             PRes1 = MakeFileLock(netfl, lock,
  284.                      lock ? lock->fl_Access : SHARED_LOCK);
  285.         }
  286.         break;
  287.         case ACTION_SET_PROTECT:    /* -,Lock,Name,Mask       Bool      */
  288.         {
  289.             struct FileLock *lock;
  290.  
  291.             lock = BTOC(PArg2);
  292.             PRes1 = NetSetProtect(NETFL(lock ? lock->fl_Key : 0),
  293.                     BTOC(PArg3), PArg4);
  294.         }
  295.         break;
  296.         case ACTION_CREATE_DIR:    /* Lock,Name        Lock         */
  297.         {
  298.             struct FileLock *lock;
  299.             NetFileLock *netfl;
  300.  
  301.             lock = BTOC(PArg1);
  302.  
  303.             netfl = NetCreateDir(NETFL(lock ? lock->fl_Key : 0),
  304.                        BTOC(PArg2));
  305.  
  306.             PRes1 = MakeFileLock(netfl, lock, SHARED_LOCK);
  307.         }
  308.         break;
  309.         case ACTION_EXAMINE_OBJECT: /* Lock,Fib           Bool         */
  310.         {
  311.             struct FileLock *lock;
  312.  
  313.             lock = BTOC(PArg1);
  314.             PRes1 = NetExamine(NETFL(lock ? lock->fl_Key : 0),
  315.                       BTOC(PArg2));
  316.         }
  317.         break;
  318.         case ACTION_EXAMINE_NEXT:    /* Lock,Fib           Bool         */
  319.         {
  320.             struct FileLock *lock;
  321.  
  322.             lock = BTOC(PArg1);
  323.             PRes1 = NetExNext(NETFL(lock ? lock->fl_Key : 0),
  324.                      BTOC(PArg2));
  325.         }
  326.         break;
  327.         case ACTION_DISK_INFO:    /* InfoData           Bool:TRUE     */
  328.         PRes1 = NetDiskInfo(BTOC(PArg1));
  329.         break;
  330.         case ACTION_INFO:    /* Lock,InfoData           Bool:TRUE     */
  331.         {
  332.             struct FileLock *lock;
  333.  
  334.             lock = BTOC(PArg1);
  335.             PRes1 = NetInfo(NETFL(lock ? lock->fl_Key : 0),
  336.                      BTOC(PArg2));
  337.         }
  338.         break;
  339. /*        case ACTION_FLUSH:        / * writeout bufs, disk motor off     */
  340.         case ACTION_SET_COMMENT:    /* -,Lock,Name,Comment       Bool      */
  341.         {
  342.             struct FileLock *lock;
  343.  
  344.             lock = BTOC(PArg2);
  345.             PRes1 = NetSetComment(NETFL(lock ? lock->fl_Key : 0),
  346.                       BTOC(PArg3), BTOC(PArg4));
  347.         }
  348.         break;
  349.         case ACTION_PARENT: /* Lock                ParentLock    */
  350.         {
  351.             struct FileLock *lock;
  352.             NetFileLock *netfl;
  353.  
  354.             lock = BTOC(PArg1);
  355.  
  356.             netfl = NetParentDir(NETFL(lock ? lock->fl_Key : 0));
  357.  
  358.             PRes1 = MakeFileLock(netfl, lock, SHARED_LOCK);
  359.         }
  360.         break;
  361.         case ACTION_INHIBIT:    /* Bool            Bool      */
  362.         PRes1 = DOSFALSE;
  363.         break;
  364.         case ACTION_SET_DATE: /* -,Lock,Name,CPTRDateStamp       Bool      */
  365.         {
  366.             struct FileLock *lock;
  367.  
  368.             lock = BTOC(PArg2);
  369.             PRes1 = NetSetDate(NETFL(lock ? lock->fl_Key : 0),
  370.                       BTOC(PArg3),
  371.                       (struct DateStamp *)PArg4);
  372.         }
  373.         break;
  374.         case ACTION_SAME_LOCK:  /* Lock1,Lock2           Result    */
  375.         {
  376.             struct FileLock *fl1, *fl2;
  377.  
  378.             fl1 = BTOC(PArg1);
  379.             fl2 = BTOC(PArg2);
  380.             if (fl1->fl_Volume == fl2->fl_Volume &&
  381.             BTOC(fl1->fl_Volume) == VolNode) {
  382.             PRes1 = NetSameLock(NETFL(fl1->fl_Key),
  383.                        NETFL(fl2->fl_Key));
  384.             } else {
  385.             PRes1 = DOSFALSE;
  386.             error = ERROR_INVALID_LOCK;
  387.             }
  388.         }
  389.         break;
  390.         case ACTION_READ:    /* FHArg1,CPTRBuffer,Length      ActLength  */
  391.         PRes1 = NetRead(NETFH(PArg1), (UBYTE *)PArg2, PArg3);
  392.         break;
  393.         case ACTION_WRITE:    /* FHArg1,CPTRBuffer,Length      ActLength  */
  394.         PRes1 = NetWrite(NETFH(PArg1), (UBYTE *)PArg2, PArg3);
  395.         break;
  396.         case ACTION_OPENRW:     /* FileHandle,Lock,Name    Bool      */
  397.         case ACTION_OPENOLD:    /* FileHandle,Lock,Name    Bool      */
  398.         case ACTION_OPENNEW:    /* FileHandle,Lock,Name    Bool      */
  399.         {
  400.             NetFileHandle *netfh;
  401.             struct FileHandle *fh;
  402.             struct FileLock *lock;
  403.  
  404.             fh = BTOC(PArg1);
  405.             lock = BTOC(PArg2);
  406.             netfh = NetOpen(NETFL(lock ? lock->fl_Key : 0),
  407.                   BTOC(PArg3),
  408.                   PType);
  409.             if (netfh) {
  410.             fh->fh_Arg1 = (long) netfh;
  411.             PRes1 = DOSTRUE;
  412.             OpenCount++;
  413.             }
  414.         }
  415.         break;
  416.         case ACTION_CLOSE:    /* FHArg1            Bool:Success */
  417.         PRes1 = NetClose(NETFH(PArg1));
  418.         OpenCount--;
  419.         break;
  420.         case ACTION_SEEK:    /* FHArg1,Position,Mode      OldPosition */
  421.         PRes1 = NetSeek(NETFH(PArg1), PArg2, PArg3);
  422.         break;
  423. #ifdef notdef
  424.         case ACTION_FORMAT: /* vol,type            Bool:success */
  425.         PRes1 = NetFormat(BTOC(PArg1), PArg2);
  426.         break;
  427. #endif
  428.         case ACTION_MAKE_LINK: /* parent,name,target,soft       Bool      */
  429.         {
  430.             struct FileLock *lock;
  431.             void        *dest;
  432.  
  433.             lock = BTOC(PArg1);
  434.             dest = PArg4 ? (char *)PArg3            /* C string! */
  435.                  : (void *)((struct FileLock *)BTOC(PArg3))->fl_Key;
  436.             PRes1 = NetMakeLink(NETFL(lock ? lock->fl_Key : 0),
  437.                     BTOC(PArg2),
  438.                     dest,
  439.                     PArg4);
  440.         }
  441.         break;
  442.         case ACTION_READ_LINK: /* parent,name,target,size       length    */
  443.         {
  444.             struct FileLock *lock;
  445.             lock = BTOC(PArg1);
  446.             PRes1 = NetReadLink(NETFL(lock ? lock->fl_Key : 0),
  447.                     (char *)PArg2,      /* C string! */
  448.                     (char *)PArg3,
  449.                     PArg4);
  450.         }
  451.         break;
  452.         case ACTION_SET_FILE_SIZE:
  453.         PRes1 = NetSetFileSize(NETFH(PArg1), PArg2, PArg3);
  454.         break;
  455. /*        case ACTION_WRITE_PROTECT: */
  456.                 /* FH,Lock                BOOL     */
  457.         case ACTION_FH_FROM_LOCK:
  458.         {
  459.             NetFileHandle *netfh;
  460.             struct FileHandle *fh;
  461.             struct FileLock *lock;
  462.  
  463.             fh = BTOC(PArg1);
  464.             lock = BTOC(PArg2);
  465.             netfh = NetOpenFromLock(NETFL(lock ? lock->fl_Key : 0));
  466.             if (netfh) {
  467.             fh->fh_Arg1 = (long) netfh;
  468.             PRes1 = DOSTRUE;
  469.             OpenCount++;
  470.             /* Discard the lock */
  471.             FreeFileLock(lock);
  472.             }
  473.         }
  474.         break;
  475.         case ACTION_IS_FILESYSTEM:
  476.         PRes1 = DOSTRUE;
  477.         break;
  478.         case ACTION_CHANGE_MODE:
  479.         {
  480.             void *object;
  481.  
  482.             switch (PArg1) {
  483.             case CHANGE_FH:
  484.             object = NETFH(((struct FileHandle *)BTOC(PArg2))->fh_Arg1);
  485.             break;
  486.             case CHANGE_LOCK:
  487.             object = NETFL(((struct FileLock *)BTOC(PArg2))->fl_Key);
  488.             break;
  489.             }
  490.             PRes1 = NetChangeMode(PArg1, object, PArg3);
  491.         }
  492.         break;
  493.         case ACTION_COPY_DIR_FH:    /* fh_Arg1           Lock      */
  494.         case ACTION_PARENT_FH:
  495.         {
  496.             NetFileLock *netfl;
  497.  
  498.             if (PType == ACTION_PARENT_FH)
  499.             netfl = NetParentOfFH(NETFH(PArg1));
  500.             else
  501.             netfl = NetDupLockFromFH(NETFH(PArg1));
  502.  
  503.             /* User has inserted disk by now, so we can use VolNode */
  504.             PRes1 = MakeFileLock(netfl, NULL, SHARED_LOCK);
  505.         }
  506.         break;
  507.         case ACTION_EXAMINE_FH:     /* fh_Arg1,Fib         Bool      */
  508.         PRes1 = NetExamineFH(NETFH(PArg1), BTOC(PArg2));
  509.         break;
  510.         /*
  511.          * A few other packet types which we do not support
  512.          */
  513.         case ACTION_LOCK_RECORD:    /* fh,pos,len,mode,time    Bool      */
  514.         {
  515.             debug(("fh(arg1) %x\n", PArg1));
  516.  
  517.             NetLockRecord(packet, NETFH(PArg1), PArg2, PArg3, PArg4, PArg5);
  518.             packet = NULL;
  519.         }
  520.         break;
  521.         case ACTION_FREE_RECORD:    /* fh,pos,len           Bool      */
  522.         {
  523.             debug(("fh(arg1) %x\n", PArg1));
  524. /*            NetFileHandle *netfh = NETFH(((struct FileHandle *)
  525.                           PArg1)->fh_Arg1); */
  526.  
  527.             PRes1 = NetFreeRecord(NETFH(PArg1), PArg2, PArg3);
  528.         }
  529.         break;
  530. /*        case ACTION_WAIT_CHAR:     / * Timeout, ticks       Bool      */
  531. /*        case ACTION_RAWMODE:       / * Bool(-1:RAW 0:CON)      OldState  */
  532.         default:
  533.         PRes1 = DOSFALSE;
  534.         error = ERROR_ACTION_NOT_KNOWN;
  535.         break;
  536.         } /* end switch */
  537.         if (packet) {
  538.         if (error)
  539.             PRes2 = error;
  540.         debug(("RES=%06lx, ERR=%ld\n", PRes1, error));
  541.         returnpacket(packet);
  542.         DosPacket = NULL;
  543.         }
  544. #ifdef DEBUG
  545.         else {
  546.         debug(("NOREP\n"));
  547.         }
  548. #endif
  549.     } /* end while (GetMsg()) */
  550.  
  551.     } /* end for (;done) */
  552.  
  553. #ifdef DEBUG
  554.     debug(("Can we remove ourselves? "));
  555. #endif                /* DEBUG */
  556.     Forbid();
  557.     if (OpenCount || packetsqueued()) {
  558.     Permit();
  559.     debug((" ..  not yet!\n"));
  560.     goto top;        /* sorry... can't exit     */
  561.     }
  562.     debug((" .. yes!\n"));
  563.  
  564.     /*
  565.      * Causes a new process to be created on next reference.
  566.      */
  567.  
  568.     DevNode->dn_Task = NULL;
  569.     CloseNetFS();
  570.     FreeVolNode(VolNode);
  571.     debug(("CloseNetFS() returned.\n"));
  572.  
  573.     /*
  574.      * Remove debug, closedown, fall of the end of the world.
  575.      */
  576. exit:
  577. #ifdef DEBUG
  578.     uninitsyslog();
  579. #endif                /* DEBUG */
  580.  
  581.     if (done & 2)
  582.     UnLoadSeg(DevNode->dn_SegList); /* This is real fun. We are still */
  583.     if (done & (2 | 1))
  584.     DevNode->dn_SegList = NULL;    /* Forbid()den, fortunately */
  585.  
  586.     CloseLibrary((struct Library *)DOSBase);
  587.  
  588.     /* Fall off the end of the world. Implicit Permit(). */
  589. }
  590.  
  591. /*
  592.  *  Make a new struct FileLock, for DOS use. It is put on a singly linked
  593.  *  list, which is attached to the same VolumeNode the old lock was on.
  594.  *
  595.  *  Also note that we must ALWAYS be prepared to UnLock() or DupLock()
  596.  *  any FileLocks we ever made, even if the volume in question has been
  597.  *  removed and/or inserted into another drive with another FileSystem
  598.  *  handler!
  599.  *
  600.  * DOS makes certain assumptions about LOCKS.    A lock must minimally be a
  601.  * FileLock structure, with additional private information after the
  602.  * FileLock structure.    The longword before the beginning of the structure
  603.  * must contain the length of structure + 4.
  604.  *
  605.  * NOTE!!!!! The workbench does not follow the rules and assumes it can copy
  606.  * lock structures.  This means that if you want to be workbench
  607.  * compatible, your lock structures must be EXACTLY sizeof(struct
  608.  * FileLock). Also, it sometimes uses uninitialized values for the lock mode...
  609.  */
  610.  
  611. Prototype struct FileLock *NewFileLock(NetFileLock *netfl, struct FileLock *fl);
  612.  
  613. struct FileLock *
  614. NewFileLock(NetFileLock *netfl, struct FileLock *fl)
  615. {
  616.     struct FileLock *newlock;
  617.     struct DeviceList *volnode = NULL;
  618.  
  619.     if (fl) {
  620.     volnode = BTOC(fl->fl_Volume);
  621.     }
  622.     if (volnode == NULL) {
  623.     volnode = VolNode;
  624.     debug(("volnode 0->%lx\n", volnode));
  625.     }
  626. #ifdef DEBUG
  627.     if (volnode != VolNode) {
  628.     debug(("volnode != VolNode %lx != %lx\n",
  629.         volnode, VolNode));
  630.     }
  631.     if (volnode->dl_Task != DosPort) {
  632.     debug(("volnode->dl_Task != DosPort %lx != %lx\n",
  633.         volnode->dl_Task, DosPort));
  634.     }
  635. #endif
  636.  
  637.     if (newlock = dosalloc((ULONG)sizeof (*newlock))) {
  638.     newlock->fl_Key = (ULONG) netfl;
  639.     newlock->fl_Task = DosPort;
  640.     newlock->fl_Volume = (BPTR) CTOB(volnode);
  641.     Forbid();
  642.     newlock->fl_Link = volnode->dl_LockList;
  643.     volnode->dl_LockList = (BPTR) CTOB(newlock);
  644.     Permit();
  645.     } else
  646.     error = ERROR_NO_FREE_STORE;
  647.  
  648.     return newlock;
  649. }
  650.  
  651. Prototype long FreeFileLock(struct FileLock *lock);
  652.  
  653. long
  654. FreeFileLock(struct FileLock *lock)
  655. {
  656.     register struct FileLock *fl;
  657.     register struct FileLock **flp;
  658.     struct DeviceList         *volnode;
  659.  
  660.     volnode = (struct DeviceList *)BTOC(lock->fl_Volume);
  661.     flp = (struct FileLock **) &volnode->dl_LockList;
  662.     for (fl = BTOC(*flp); fl && fl != lock; fl = BTOC(fl->fl_Link))
  663.     flp = (struct FileLock **)&fl->fl_Link;
  664.  
  665.     if (fl == lock) {
  666.     *(BPTR *)flp = fl->fl_Link;
  667.     dosfree((ULONG *)fl);
  668.     OpenCount--;
  669.     return DOSTRUE;
  670.     } else {
  671.     debug(("Huh?? Could not find filelock!\n"));
  672.     return DOSFALSE;
  673.     }
  674. }
  675.  
  676. /*
  677.  * MakeFileLock allocates and initializes a new FileLock, using info
  678.  * from an existing FileLock. It always consumes the NetFileLock, even
  679.  * in case of failure.
  680.  */
  681.  
  682. Prototype BPTR MakeFileLock(NetFileLock *netfl, struct FileLock *fl, long mode);
  683.  
  684. BPTR
  685. MakeFileLock(NetFileLock *netfl, struct FileLock *fl, long mode)
  686. {
  687.     struct FileLock *newlock;
  688.  
  689.     newlock = NULL;
  690.     if (netfl) {
  691.     if (newlock = NewFileLock(netfl, fl)) {
  692.         newlock->fl_Access = mode;
  693.         OpenCount++;
  694.     } else
  695.         NetUnLock(netfl);
  696.     }
  697.  
  698.     return CTOB(newlock);
  699. }
  700.  
  701. /*
  702.  * Create Volume node and add to the device list.   This will
  703.  * cause the WORKBENCH to recognize us as a disk.   If we
  704.  * don't create a Volume node, Wb will not recognize us.
  705.  * However, we are a NET: disk, Volume node or not.
  706.  */
  707.  
  708. Prototype struct DeviceList *NewVolNode(char *name, struct DateStamp *date);
  709.  
  710. struct DeviceList     *
  711. NewVolNode(char *name, struct DateStamp *date)
  712. {
  713.     struct DeviceList *volnode;
  714.     char       *volname;        /* This is my volume name */
  715.  
  716.     if (volnode = dosalloc((ULONG)sizeof (struct DeviceList))) {
  717.     if (volname = dosalloc(33L)) {
  718.         volname[0] = strlen(name);
  719.         strcpy(volname + 1, name);      /* Make sure \0 terminated */
  720.  
  721.         volnode->dl_Type = DLT_VOLUME;
  722.         volnode->dl_Task = DosPort;
  723.         volnode->dl_DiskType = ID_DOS_DISK;
  724.         volnode->dl_Name = (BSTR *)CTOB(volname);
  725.         volnode->dl_VolumeDate = *date;
  726.         volnode->dl_NetFileLockList = NULL;
  727.  
  728.         if (DOSBase->dl_lib.lib_Version >= 37) {
  729.         struct DosList *dl;
  730.         debug(("LockDosList...\n"));
  731.         dl = AttemptLockDosList(LDF_VOLUMES | LDF_DEVICES | LDF_WRITE);
  732.         if ((ULONG)dl <= 1) {
  733.             debug(("LockDosList NOT ok\n"));
  734.             goto brute_force;
  735.         }
  736.         UnLockDosList(LDF_VOLUMES | LDF_DEVICES | LDF_WRITE);
  737.  
  738.         debug(("AddDosEntry...\n"));
  739.         if (AddDosEntry((struct DosList *)volnode) == DOSFALSE) {
  740.             debug(("AddDosEntry for VolNode fails!\n"));
  741.             goto error;
  742.         }
  743.         debug(("AddDosEntry: done\n"));
  744.         } else {
  745.         struct DosInfo *di;
  746.  
  747.         brute_force:
  748.         di = BTOC(((struct RootNode *) DOSBase->dl_Root)->rn_Info);
  749.  
  750.         Forbid();
  751.         volnode->dl_Next = di->di_DevInfo;
  752.         di->di_DevInfo = (long) CTOB(volnode);
  753.         Permit();
  754.         }
  755.     } else {
  756.     error:
  757.         dosfree((ULONG *)volnode);
  758.         volnode = NULL;
  759.     }
  760.     } else {
  761.     error = ERROR_NO_FREE_STORE;
  762.     }
  763.  
  764.     return volnode;
  765. }
  766.  
  767. /*
  768.  *  Give the VolNode a new name (given as a BCPL string).
  769.  */
  770.  
  771. Prototype void NewVolNodeName(char *newname);
  772.  
  773. void
  774. NewVolNodeName(char *newname)
  775. {
  776.     if (VolNode) {
  777.     register char *volname = BTOC(VolNode->dl_Name);
  778.  
  779.     memcpy(volname, newname, 1 + newname[0]);
  780.     }
  781. }
  782.  
  783. /*
  784.  * Remove Volume entry.  Since DOS uses singly linked lists, we must
  785.  * (ugg) search it manually to find the link before our Volume entry.
  786.  */
  787.  
  788. Prototype void FreeVolNode(struct DeviceList *volnode);
  789.  
  790. void
  791. FreeVolNode(struct DeviceList *volnode)
  792. {
  793.     debug(("FreeVolNode %08lx\n", volnode));
  794.  
  795.     if (volnode == NULL)
  796.     return;
  797.  
  798.     if (DOSBase->dl_lib.lib_Version >= 37) {
  799.     struct DosList *dl;
  800.  
  801.     dl = LockDosList(LDF_VOLUMES | LDF_WRITE);
  802.     (void)RemDosEntry((struct DosList *)volnode);
  803.     UnLockDosList(LDF_VOLUMES | LDF_WRITE);
  804.     } else {
  805.     struct DosInfo *di = BTOC(((struct RootNode *) DOSBase->dl_Root)->rn_Info);
  806.     register struct DeviceList *dl;
  807.     register void  *dlp;
  808.  
  809.     dlp = &di->di_DevInfo;
  810.     Forbid();
  811.     for (dl = BTOC(di->di_DevInfo); dl && dl != volnode; dl = BTOC(dl->dl_Next))
  812.         dlp = &dl->dl_Next;
  813.     if (dl == volnode) {
  814.         *(BPTR *) dlp = dl->dl_Next;
  815.     }
  816. #ifdef DEBUG
  817.     else {
  818.         debug(("****PANIC: Unable to find volume node\n"));
  819.     }
  820. #endif                /* DEBUG */
  821.     Permit();
  822.     }
  823.  
  824.     dosfree(BTOC(volnode->dl_Name));
  825.     dosfree((ULONG *)volnode);
  826.  
  827.     if (volnode == VolNode)
  828.     VolNode = NULL;
  829. }
  830.