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

  1. /*
  2.  * $Id: netfs.c,v 1.1 1993/12/02 20:45:46 Rhialto Exp $
  3.  * $Log: netfs.c,v $
  4.  * Revision 1.1  1993/12/02  20:45:46  Rhialto
  5.  * Initial revision
  6.  *
  7.  * Actually convert file system actions into network packets.
  8.  * All functions assume that the packet type has been set already,
  9.  * so that the code for some packets can be shared.
  10.  * Read and Write are an exception because they may split the
  11.  * operation in multiple packets.
  12.  */
  13.  
  14. #include "netfs.h"
  15. #include <string.h>
  16.  
  17. #ifdef DEBUG
  18. #   include "syslog.h"
  19. #else
  20. #   define    debug(x)
  21. #endif
  22.  
  23. Prototype Packet      ReqPacket;
  24. Prototype ULONG       Validation;
  25. Prototype ULONG       MyValidation;
  26.  
  27. Packet        ReqPacket;
  28. ULONG        Validation;
  29. ULONG        MyValidation;
  30. NetFileLock    *RootLock;
  31. struct List    NameList;
  32.  
  33. struct Entry {
  34.     struct Node     e_Node;
  35. };
  36.  
  37. /*
  38.  * Remember device parts of names DH0:xx/yy,
  39.  * without the colons.
  40.  */
  41.  
  42. void
  43. AddRemoteName(char *bstr)
  44. {
  45.     struct Entry   *e;
  46.     int         len;
  47.     char       *n;
  48.     static int        nestcount;
  49.  
  50.     debug(("AddRemoteName %d '%.*s'\n", nestcount, bstr[0], bstr+1));
  51.     if (nestcount > 0)
  52.     return;
  53.  
  54.     nestcount++;
  55.  
  56.     n = memchr(bstr + 1, ':', (unsigned char)bstr[0]);
  57.     if (n == NULL) {
  58.     /* Can't happen */
  59.     len = bstr[0];
  60.     } else
  61.     len = n - (bstr + 1);
  62.  
  63.     e = (void *)&NameList;
  64.     while (e = NextNode((struct MinNode *)e)) {
  65.     n = e->e_Node.ln_Name;
  66.  
  67.     if (n[0] == len && strnicmp(n+1, bstr+1, len) == 0) {
  68.         debug(("AddName: Found it\n"));
  69.         goto end;        /* Found it */
  70.     }
  71.     }
  72.  
  73.     debug(("AddName: A new name\n"));
  74.  
  75.     e = dosalloc(sizeof(struct Entry) + 1 + len);
  76.     if (e == NULL)
  77.     goto end;
  78.     n = e + 1;
  79.     e->e_Node.ln_Name = n;
  80.     n[0] = len;
  81.     memcpy(n + 1, bstr + 1, len);
  82.  
  83.     AddTail(&NameList, &e->e_Node);
  84.  
  85.     /* Now check if it was a reasonable thing to do... */
  86.     {
  87.     NetFileLock    *nfl;
  88.     static Packet    save;
  89.  
  90.     save = ReqPacket;
  91.     ReqPacket.p_Action = ACTION_LOCATE_OBJECT;
  92.     if (nfl = NetLock(RootLock, n, SHARED_LOCK)) {
  93.         ReqPacket.p_Action = ACTION_FREE_LOCK;
  94.         NetUnLock(nfl);
  95.     } else {
  96.         Remove(e);
  97.         dosfree((void *)e);
  98.     }
  99.     ReqPacket = save;
  100.     }
  101.  
  102. end:
  103.     nestcount--;
  104. }
  105.  
  106. char *
  107. CopyString(char *to, char *from)
  108. {
  109.     int         len = from[0];
  110.  
  111.     debug(("CopyString '%.*s'\n", from[0], from+1));
  112.     memcpy(to, from, 1 + len);
  113.     to = to + 1 + len;
  114.     *to++ = '\0';
  115.     /* Align to longword for conversion to BPTR by the server */
  116.     to = (char *)(((ULONG)to + 3) & ~3);
  117.  
  118.     return to;
  119. }
  120.  
  121. /*
  122.  * Some packets use C style 0-terminated strings.
  123.  * Convert them to counted strings, for consisteny.
  124.  */
  125. char *
  126. CopyCString(char *to, char *from)
  127. {
  128.     int         len = strlen(from);
  129.  
  130.     to[0] = len;
  131.     memcpy(to + 1, from, len);
  132.     to = to + 1 + len;
  133.     *to++ = '\0';
  134.     /* Align to longword for conversion to BPTR by the server */
  135.     to = (char *)(((ULONG)to + 3) & ~3);
  136.  
  137.     return to;
  138. }
  139.  
  140. void *
  141. memchr(const void *cs, int c, size_t n)
  142. {
  143.     while (n > 0) {
  144.     if (*(unsigned char *)cs == (unsigned char)c)
  145.         return cs;
  146.     cs = (char *)cs + 1;
  147.     n--;
  148.     }
  149.     return NULL;
  150. }
  151.  
  152. void
  153. bstrcpy(unsigned char *d, unsigned char *s)
  154. {
  155.     memcpy(d, s, 1 + s[0]);
  156. }
  157.  
  158. int NameIsNetRoot;
  159. int NameIsRemoteDevice;
  160.  
  161. char *
  162. CopyName(char *to, char *from, NetFileLock *parent)
  163. {
  164.     int         len = from[0];
  165.     char       *p;
  166.  
  167.     debug(("CopyName '%.*s'\n", from[0], from+1));
  168.     NameIsNetRoot = 0;
  169.     NameIsRemoteDevice = 0;
  170.     if (p = memchr(from + 1, ':', len)) {
  171.     /* NET:something -> something */
  172.     p++;
  173.     len -= (p - (from + 1));
  174.     to[0] = len;
  175.     if (len)
  176.         memcpy(to + 1, p, len);
  177.     } else
  178.     memcpy(to, from, 1 + len);
  179.     if (parent == RootLock) {
  180.     NameIsNetRoot = (len == 0);
  181.     p = memchr(to + 1, '/', len);
  182.     if (p) {
  183.         /* dh0/something -> dh0:something */
  184.         p[0] = ':';
  185.     } else {
  186.         if (len > 5 && strncmp(&to[1+len-5], ".info", 5) == 0) {
  187.         /* NET:DH0.info -> DH0:Node.rinfo */
  188.         strcpy(&to[1+len-5], ":Node.rinfo");
  189.         len += 6;
  190.         to[0] = len;
  191.         } else {
  192.         /* dh0 -> dh0: */
  193.         to[0] = ++len;
  194.         to[len] = ':';
  195.         NameIsRemoteDevice = 1;
  196.         }
  197.     }
  198.     if (!NameIsNetRoot) {
  199.         AddRemoteName(to);
  200.     }
  201.     }
  202.     to = to + 1 + len;
  203.     *to++ = '\0';
  204.     /* Align to longword for conversion to BPTR by the server */
  205.     to = (char *)(((ULONG)to + 3) & ~3);
  206.  
  207.     return to;
  208. }
  209.  
  210. NetFileLock *
  211. ValidLock(NetFileLock *netfl)
  212. {
  213.     if (netfl == NULL)
  214.     return RootLock;
  215.  
  216.     if (netfl->nfl_Validation == Validation)
  217.     return netfl;
  218.  
  219.     if (netfl->nfl_Validation == 0)
  220.     return netfl;
  221.  
  222.     error = ERROR_DEVICE_NOT_MOUNTED;
  223.     return NULL;
  224. }
  225.  
  226. int
  227. ValidFile(NetFileHandle *netfh)
  228. {
  229.     return netfh && netfh->nfh_Validation == Validation;
  230. }
  231.  
  232. NetFileLock *
  233. MakeNetLock(ULONG fl)
  234. {
  235.     NetFileLock *netfl;
  236.  
  237.     if (netfl = AllocMem(sizeof(*netfl), MEMF_PUBLIC|MEMF_CLEAR)) {
  238.     netfl->nfl_FileLock = fl;
  239.     netfl->nfl_Validation = Validation;
  240.     }
  241. #ifdef DEBUG
  242.     debug(("MakeNetLock %x from %x\n", netfl, fl));
  243.     if (fl == 0)
  244.     debug(("!!! 0 remote lock !!!\n"));
  245. #endif
  246.     return netfl;
  247. }
  248.  
  249. void
  250. FreeNetLock(NetFileLock *netfl)
  251. {
  252.     if (netfl && netfl != RootLock)
  253.     FreeMem(netfl, sizeof(*netfl));
  254. }
  255.  
  256. NetFileHandle *
  257. MakeNetFile(ULONG fh)
  258. {
  259.     NetFileHandle *netfh;
  260.  
  261.     if (netfh = AllocMem(sizeof(*netfh), MEMF_PUBLIC|MEMF_CLEAR)) {
  262.     netfh->nfh_FileHandle = fh;
  263.     netfh->nfh_Validation = Validation;
  264.     }
  265.     debug(("MakeNetFile %x\n", netfh));
  266.     return netfh;
  267. }
  268.  
  269. void
  270. FreeNetFile(NetFileHandle *netfh)
  271. {
  272.     if (netfh)
  273.     FreeMem(netfh, sizeof(*netfh));
  274. }
  275.  
  276. /* ---------------------------------------------------------------------- */
  277.  
  278. Prototype NetFileLock *NetLock(NetFileLock *parent, char *name, ULONG mode);
  279.  
  280. NetFileLock *
  281. NetLock(NetFileLock *parent, char *name, ULONG mode)
  282. {
  283.     char       *end;
  284.  
  285.     if (parent = ValidLock(parent)) {
  286.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  287.     ReqPacket.p_Arg[1] = mode;
  288.     end = CopyName((char *)&ReqPacket.p_Arg[2], name, parent);
  289.  
  290.     debug(("NetLock: %x %s %d\n", parent, (char *)&ReqPacket.p_Arg[2]+1,
  291.         mode));
  292.  
  293.     if (NameIsNetRoot)
  294.         return RootLock;
  295.  
  296.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  297.         error = ReqPacket.p_Res2;
  298.         if (ReqPacket.p_Res1) {
  299.         return MakeNetLock(ReqPacket.p_Res1);
  300.         }
  301.     }
  302.     }
  303.     return NULL;
  304. }
  305.  
  306. Prototype void NetUnLock(NetFileLock *netfl);
  307.  
  308. void
  309. NetUnLock(NetFileLock *netfl)
  310. {
  311.     if (netfl) {
  312.     if ((netfl = ValidLock(netfl))) {
  313.         if (netfl == RootLock)
  314.         return;
  315.  
  316.         ReqPacket.p_Arg[0] = netfl->nfl_FileLock;
  317.  
  318.         (void)SendRecv(&ReqPacket, REQSIZE(1), &ReqPacket, STDREPLY);
  319.     }
  320.     FreeNetLock(netfl);
  321.     }
  322. }
  323.  
  324. Prototype NetFileLock *NetDupLock(NetFileLock *netfl);
  325.  
  326. NetFileLock *
  327. NetDupLock(NetFileLock *netfl)
  328. {
  329.     if (netfl = ValidLock(netfl)) {
  330.     if (netfl == RootLock)
  331.         return RootLock;
  332.  
  333.     ReqPacket.p_Arg[0] = netfl->nfl_FileLock;
  334.  
  335.     if (SendRecv(&ReqPacket, REQSIZE(1), &ReqPacket, STDREPLY) == 0) {
  336.         error = ReqPacket.p_Res2;
  337.         if (ReqPacket.p_Res1) {
  338.         return MakeNetLock(ReqPacket.p_Res1);
  339.         }
  340.     }
  341.     }
  342.     return NULL;
  343. }
  344.  
  345. Prototype NetFileLock *NetCreateDir(NetFileLock *parent, char *name);
  346.  
  347. NetFileLock *
  348. NetCreateDir(NetFileLock *parent, char *name)
  349. {
  350.     char       *end;
  351.  
  352.     if (parent = ValidLock(parent)) {
  353.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  354.     end = CopyName((char *)&ReqPacket.p_Arg[1], name, parent);
  355.  
  356.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  357.         error = ReqPacket.p_Res2;
  358.         if (ReqPacket.p_Res1) {
  359.         return MakeNetLock(ReqPacket.p_Res1);
  360.         }
  361.     }
  362.     }
  363.     return NULL;
  364. }
  365.  
  366. Prototype ULONG NetDeleteFile(NetFileLock *parent, char *name);
  367.  
  368. ULONG
  369. NetDeleteFile(NetFileLock *parent, char *name)
  370. {
  371.     char       *end;
  372.  
  373.     if (parent = ValidLock(parent)) {
  374.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  375.     end = CopyName((char *)&ReqPacket.p_Arg[1], name, parent);
  376.  
  377.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  378.         error = ReqPacket.p_Res2;
  379.         return ReqPacket.p_Res1;
  380.     }
  381.     }
  382.     return DOSFALSE;
  383. }
  384.  
  385. Prototype NetFileLock *NetParentDir(NetFileLock *netfl);
  386.  
  387. NetFileLock *
  388. NetParentDir(NetFileLock *netfl)
  389. {
  390.     if (netfl == NULL) {
  391.     error = ERROR_OBJECT_NOT_FOUND;
  392.     } else if (netfl = ValidLock(netfl)) {
  393.     if (netfl == RootLock)
  394.         return NULL;
  395.  
  396.     ReqPacket.p_Arg[0] = netfl->nfl_FileLock;
  397.  
  398.     if (SendRecv(&ReqPacket, REQSIZE(1), &ReqPacket, STDREPLY) == 0) {
  399.         error = ReqPacket.p_Res2;
  400.         if (ReqPacket.p_Res1)
  401.         return MakeNetLock(ReqPacket.p_Res1);
  402.         else if (error == 0)
  403.         return RootLock;
  404.     }
  405.     }
  406.     return NULL;
  407. }
  408.  
  409. Prototype ULONG NetSameLock(NetFileLock *lock1, NetFileLock *lock2);
  410.  
  411. ULONG
  412. NetSameLock(NetFileLock *lock1, NetFileLock *lock2)
  413. {
  414.     if ((lock1 = ValidLock(lock1)) && (lock2 = ValidLock(lock2))) {
  415.     if (lock1 == lock2) {
  416.         debug(("NetSameLock: same local ptr %x\n", lock1));
  417.         return DOSTRUE;
  418.     }
  419.  
  420. #if 1
  421.     if (lock1 == RootLock || lock2 == RootLock) {
  422.         /*error = ERROR_DEVICE_NOT_MOUNTED;*/
  423.         error = ERROR_INVALID_LOCK;
  424.         return DOSFALSE;
  425.     }
  426. #endif
  427.  
  428.     if (lock1->nfl_FileLock == lock2->nfl_FileLock) {
  429.         debug(("NetSameLock: same remote ptr %x\n", lock1->nfl_FileLock));
  430.         return DOSTRUE;
  431.     }
  432.  
  433.     debug(("NetSameLock: compare remote %x %x\n", lock1->nfl_FileLock, lock2->nfl_FileLock));
  434.     ReqPacket.p_Arg[0] = lock1->nfl_FileLock;
  435.     ReqPacket.p_Arg[1] = lock2->nfl_FileLock;
  436.  
  437.     if (SendRecv(&ReqPacket, REQSIZE(2), &ReqPacket, STDREPLY) == 0) {
  438.         error = ReqPacket.p_Res2;
  439.         return ReqPacket.p_Res1;
  440.     }
  441.     }
  442.     return DOSFALSE;
  443. }
  444.  
  445. ULONG
  446. NetRelabel(NetFileLock *slock, char *sname, NetFileLock *dlock, char *dname)
  447. {
  448.  
  449.     char       *end;
  450.     char       *colon;
  451.  
  452.     ReqPacket.p_Action = ACTION_RENAME_DISK;
  453.     end = CopyName((char *)&ReqPacket.p_Arg[0], sname, slock);
  454.     colon = end;
  455.     end = CopyName((char *)end,                 dname, dlock);
  456.  
  457.     /* Remove colon from new name */
  458.     if (colon[colon[0]] == ':') {
  459.     colon[colon[0]] = '\0';
  460.     colon[0]--;
  461.     }
  462.  
  463.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  464.     error = ReqPacket.p_Res2;
  465.     return ReqPacket.p_Res1;
  466.     }
  467. }
  468.  
  469. Prototype ULONG NetRename(NetFileLock *slock, char *sname, NetFileLock *dlock, char *dname);
  470.  
  471. ULONG
  472. NetRename(NetFileLock *slock, char *sname, NetFileLock *dlock, char *dname)
  473. {
  474.     char       *end;
  475.     char        root;
  476.     char        dev;
  477.  
  478.     if ((slock = ValidLock(slock)) && (dlock = ValidLock(dlock))) {
  479.     ReqPacket.p_Arg[0] = slock->nfl_FileLock;
  480.     ReqPacket.p_Arg[1] = dlock->nfl_FileLock;
  481.     end = CopyName((char *)&ReqPacket.p_Arg[2], sname, slock);
  482.     root = NameIsNetRoot;
  483.     dev  = NameIsRemoteDevice;
  484.     end = CopyName((char *)end,                 dname, dlock);
  485.     root += NameIsNetRoot;
  486.     dev  += NameIsRemoteDevice;
  487.  
  488.     if (dev == 2)
  489.         return NetRelabel(slock, sname, dlock, dname);
  490.     if (root || dev) {
  491.         error = ERROR_RENAME_ACROSS_DEVICES;
  492.         return DOSFALSE;
  493.     }
  494.  
  495.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  496.         error = ReqPacket.p_Res2;
  497.         return ReqPacket.p_Res1;
  498.     }
  499.     }
  500.     return DOSFALSE;
  501. }
  502.  
  503. Prototype ULONG NetSetProtect(NetFileLock *parent, char *name, ULONG protect);
  504.  
  505. ULONG
  506. NetSetProtect(NetFileLock *parent, char *name, ULONG protect)
  507. {
  508.     char       *end;
  509.  
  510.     if (parent = ValidLock(parent)) {
  511.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  512.     ReqPacket.p_Arg[1] = protect;
  513.     end = CopyName((char *)&ReqPacket.p_Arg[2], name, parent);
  514.  
  515.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  516.         error = ReqPacket.p_Res2;
  517.         return ReqPacket.p_Res1;
  518.     }
  519.     }
  520.     return DOSFALSE;
  521. }
  522.  
  523. Prototype ULONG NetExamine(NetFileLock *netfl, struct FileInfoBlock *fib);
  524.  
  525. ULONG
  526. NetExamine(NetFileLock *netfl, struct FileInfoBlock *fib)
  527. {
  528.     if (netfl = ValidLock(netfl)) {
  529.     if (netfl == RootLock) {
  530.         char       *p;
  531.  
  532.         memset(fib, 0, sizeof(*fib));
  533.         /* Includes fib_DiskKey = 0 */
  534.         fib->fib_DirEntryType =
  535.         fib->fib_EntryType = ST_ROOT;
  536.         p = BTOC(VolNode->dl_Name);
  537.         bstrcpy(&fib->fib_FileName[0], p);
  538.         fib->fib_Date = VolNode->dl_VolumeDate;
  539.  
  540.         return DOSTRUE;
  541.     }
  542.  
  543.     ReqPacket.p_Arg[0] = netfl->nfl_FileLock;
  544.  
  545.     if (SendRecv2(&ReqPacket, REQSIZE(1), NULL, 0,
  546.               &ReqPacket, STDREPLY, fib, sizeof(*fib)) == 0) {
  547. #ifdef DEBUG
  548.     {
  549.         debug(("key %x size %d name '%.*s'\n", fib->fib_DiskKey, fib->fib_Size,
  550.             fib->fib_FileName[0], &fib->fib_FileName[1]));
  551.     }
  552. #endif
  553.         error = ReqPacket.p_Res2;
  554.         return ReqPacket.p_Res1;
  555.     }
  556.     }
  557.     return DOSFALSE;
  558. }
  559.  
  560. Prototype ULONG NetExNext(NetFileLock *netfl, struct FileInfoBlock *fib);
  561.  
  562. /*
  563.  * For ExNext, (a part of) the FileInfoBlock must be sent
  564.  * with the request. To be flexible, here is a define for
  565.  * how much we actually transmit. In this case, everything
  566.  * up to the end of the file name plus a bit of slop to
  567.  * survive round-down errors.
  568.  * See also notes in the server.
  569.  */
  570.  
  571. #define EXNEXTFIBSIZE(f) (offsetof(struct FileInfoBlock, fib_FileName[0]) + \
  572.               f->fib_FileName[0] + 2)
  573.  
  574. ULONG
  575. NetExNext(NetFileLock *netfl, struct FileInfoBlock *fib)
  576. {
  577.     if (netfl = ValidLock(netfl)) {
  578.     if (netfl == RootLock) {
  579.         struct Entry   *e;
  580.         int         i;
  581.  
  582.         if (fib->fib_DiskKey > 0 && fib->fib_DirEntryType == ST_USERDIR) {
  583.         fib->fib_DirEntryType =
  584.         fib->fib_EntryType = ST_FILE;
  585.         i = fib->fib_FileName[0];
  586.         strcpy(&fib->fib_FileName[1+i], ".info");
  587.         fib->fib_FileName[0] = i + 5;
  588.  
  589.         return DOSTRUE;
  590.         }
  591.  
  592.         e = NextNode((struct MinNode *)&NameList);
  593.         for (i = fib->fib_DiskKey; e && i > 0; i--)
  594.         e = NextNode((struct MinNode *)e);
  595.  
  596.         if (e) {
  597.         fib->fib_DiskKey++;
  598.         fib->fib_DirEntryType =
  599.         fib->fib_EntryType = ST_USERDIR;
  600.         bstrcpy(&fib->fib_FileName[0], e->e_Node.ln_Name);
  601.  
  602.         return DOSTRUE;
  603.         }
  604.  
  605.         error = ERROR_NO_MORE_ENTRIES;
  606.         return DOSFALSE;
  607.     }
  608.  
  609.     ReqPacket.p_Arg[0] = netfl->nfl_FileLock;
  610.  
  611.     if (SendRecv2(&ReqPacket, REQSIZE(1), fib, EXNEXTFIBSIZE(fib),
  612.               &ReqPacket, STDREPLY, fib, sizeof(*fib)) == 0) {
  613.         error = ReqPacket.p_Res2;
  614.         return ReqPacket.p_Res1;
  615.     }
  616.     }
  617.     return DOSFALSE;
  618. }
  619. Prototype ULONG NetDiskInfo(struct InfoData *id);
  620.  
  621. ULONG
  622. NetDiskInfo(struct InfoData *id)
  623. {
  624.     memset(id, 0, sizeof(*id));
  625.     id->id_DiskState = ID_VALIDATED;
  626.     id->id_NumBlocks = 1;
  627.     id->id_NumBlocksUsed = 1;
  628.     id->id_BytesPerBlock = MAXDATA;
  629.     id->id_DiskType = ID_DOS_DISK;
  630.     id->id_VolumeNode = CTOB(VolNode);
  631.     id->id_InUse = 1;
  632.  
  633.     return DOSTRUE;
  634. }
  635.  
  636. Prototype ULONG NetInfo(NetFileLock *netfl, struct InfoData *id);
  637.  
  638. ULONG
  639. NetInfo(NetFileLock *netfl, struct InfoData *id)
  640. {
  641.     if (netfl == RootLock)
  642.     return NetDiskInfo(id);
  643.  
  644.     if (netfl = ValidLock(netfl)) {
  645.     ReqPacket.p_Arg[0] = netfl->nfl_FileLock;
  646.  
  647.     if (SendRecv2(&ReqPacket, REQSIZE(1), NULL, 0,
  648.               &ReqPacket, STDREPLY, id, sizeof(*id)) == 0) {
  649.         id->id_VolumeNode = NULL;
  650.         error = ReqPacket.p_Res2;
  651.         return ReqPacket.p_Res1;
  652.     }
  653.     }
  654.     return DOSFALSE;
  655. }
  656.  
  657. Prototype ULONG NetSetComment(NetFileLock *parent, char *name, char *comment);
  658.  
  659. ULONG
  660. NetSetComment(NetFileLock *parent, char *name, char *comment)
  661. {
  662.     char       *end;
  663.  
  664.     if (parent = ValidLock(parent)) {
  665.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  666.     end = CopyName((char *)&ReqPacket.p_Arg[1], name, parent);
  667.     end = CopyString(end,               comment);
  668.  
  669.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  670.         error = ReqPacket.p_Res2;
  671.         return ReqPacket.p_Res1;
  672.     }
  673.     }
  674.     return DOSFALSE;
  675. }
  676.  
  677. Prototype ULONG NetSetDate(NetFileLock *parent, char *name, struct DateStamp *ds);
  678.  
  679. ULONG
  680. NetSetDate(NetFileLock *parent, char *name, struct DateStamp *ds)
  681. {
  682.     char       *end;
  683.  
  684.     if (parent = ValidLock(parent)) {
  685.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  686.     ReqPacket.p_Arg[1] = ds->ds_Days;
  687.     ReqPacket.p_Arg[2] = ds->ds_Minute;
  688.     ReqPacket.p_Arg[3] = ds->ds_Tick;
  689.     end = CopyName((char *)&ReqPacket.p_Arg[4], name, parent);
  690.  
  691.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  692.         error = ReqPacket.p_Res2;
  693.         return ReqPacket.p_Res1;
  694.     }
  695.     }
  696.     return DOSFALSE;
  697. }
  698.  
  699. Prototype NetFileHandle *NetOpen(NetFileLock *parent, char *name, ULONG mode);
  700.  
  701. NetFileHandle *
  702. NetOpen(NetFileLock *parent, char *name, ULONG mode)
  703. {
  704.     char       *end;
  705.  
  706.     if (parent = ValidLock(parent)) {
  707.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  708.     end = CopyName((char *)&ReqPacket.p_Arg[1], name, parent);
  709.     /* mode is actually the packet type */
  710.  
  711.     debug(("NetOpen: %x %s %d\n", parent, (char *)&ReqPacket.p_Arg[1]+1,
  712.         mode));
  713.  
  714.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  715.         error = ReqPacket.p_Res2;
  716.         if (ReqPacket.p_Res1) {
  717.         return MakeNetFile(ReqPacket.p_Res1);
  718.         }
  719.     }
  720.     }
  721.     return NULL;
  722. }
  723.  
  724. Prototype LONG NetRead(NetFileHandle *netfh, char *buffer, LONG length);
  725.  
  726. LONG
  727. NetRead(NetFileHandle *netfh, char *buffer, LONG length)
  728. {
  729.     LONG        done = 0;
  730.  
  731.     if (ValidFile(netfh)) {
  732.     while (length > 0) {
  733.         ReqPacket.p_Action = ACTION_READ;
  734.         ReqPacket.p_Arg[0] = netfh->nfh_FileHandle;
  735.         ReqPacket.p_Arg[1] = min(length, MAXDATA);
  736.  
  737.         if (SendRecv2(&ReqPacket, REQSIZE(2), NULL, 0,
  738.               &ReqPacket, STDREPLY, buffer, ReqPacket.p_Arg[1]) != 0)
  739.         break;
  740.  
  741.         if ((long)ReqPacket.p_Res1 <= 0)
  742.         break;
  743.  
  744.         length -= ReqPacket.p_Res1;
  745.         buffer += ReqPacket.p_Res1;
  746.         done   += ReqPacket.p_Res1;
  747.     }
  748.  
  749.     error = ReqPacket.p_Res2;
  750.     return done;
  751.     }
  752.  
  753.     return -1;
  754. }
  755.  
  756. Prototype LONG NetWrite(NetFileHandle *netfh, char *buffer, LONG length);
  757.  
  758. LONG
  759. NetWrite(NetFileHandle *netfh, char *buffer, LONG length)
  760. {
  761.     LONG        done = 0;
  762.  
  763.     if (ValidFile(netfh)) {
  764.     while (length > 0) {
  765.         LONG        thislength = min(length, MAXDATA);
  766.  
  767.         ReqPacket.p_Action = ACTION_WRITE;
  768.         ReqPacket.p_Arg[0] = netfh->nfh_FileHandle;
  769.         ReqPacket.p_Arg[1] = thislength;
  770.  
  771.         if (SendRecv2(&ReqPacket, REQSIZE(2), buffer, thislength,
  772.               &ReqPacket, STDREPLY, NULL, 0) != 0)
  773.         break;
  774.  
  775.         if (ReqPacket.p_Res1 == -1)
  776.         break;
  777.  
  778.         done   += ReqPacket.p_Res1;
  779.  
  780.         if (ReqPacket.p_Res1 != thislength)
  781.         break;
  782.  
  783.         length -= ReqPacket.p_Res1;
  784.         buffer += ReqPacket.p_Res1;
  785.     }
  786.  
  787.     error = ReqPacket.p_Res2;
  788.     return done;
  789.     }
  790.  
  791.     return -1;
  792. }
  793.  
  794. Prototype ULONG NetClose(NetFileHandle *netfh);
  795.  
  796. ULONG
  797. NetClose(NetFileHandle *netfh)
  798. {
  799.     if (ValidFile(netfh)) {
  800.     ReqPacket.p_Arg[0] = netfh->nfh_FileHandle;
  801.  
  802.     if (SendRecv(&ReqPacket, REQSIZE(1), &ReqPacket, STDREPLY) == 0) {
  803.         if (ReqPacket.p_Res1 && (error = ReqPacket.p_Res2) == 0) {
  804.         FreeNetFile(netfh);
  805.         }
  806.         return ReqPacket.p_Res1;
  807.     }
  808.     }
  809.     return DOSFALSE;
  810. }
  811.  
  812. Prototype ULONG NetSeek(NetFileHandle *netfh, ULONG position, ULONG mode);
  813.  
  814. ULONG
  815. NetSeek(NetFileHandle *netfh, ULONG position, ULONG mode)
  816. {
  817.     if (ValidFile(netfh)) {
  818.     ReqPacket.p_Arg[0] = netfh->nfh_FileHandle;
  819.     ReqPacket.p_Arg[1] = position;
  820.     ReqPacket.p_Arg[2] = mode;
  821.  
  822.     if (SendRecv(&ReqPacket, REQSIZE(3), &ReqPacket, STDREPLY) == 0) {
  823.         error = ReqPacket.p_Res2;
  824.         return ReqPacket.p_Res1;
  825.     }
  826.     }
  827.     return DOSFALSE;
  828. }
  829.  
  830. /*
  831.  * Target can be eith
  832.  */
  833.  
  834. Prototype ULONG NetMakeLink(NetFileLock *parent, char *name, void *target, ULONG mode);
  835.  
  836. ULONG
  837. NetMakeLink(NetFileLock *parent, char *name, void *target, ULONG soft)
  838. {
  839.     char       *end;
  840.  
  841.     if (parent = ValidLock(parent)) {
  842.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  843.     ReqPacket.p_Arg[1] = soft;
  844.     if (soft) {
  845.         /* XXX Is this a BCPL or C string? */
  846.         end = CopyCString((char *)&ReqPacket.p_Arg[2], target);
  847.     } else {
  848.         NetFileLock *tlock = ValidLock((NetFileLock *)target);
  849.  
  850.         debug(("MakeLink hard %s -> %x\n", name, target));
  851.         if (tlock == 0) {
  852.         error = ERROR_INVALID_LOCK;
  853.         return DOSFALSE;
  854.         }
  855.         ReqPacket.p_Arg[2] = tlock->nfl_FileLock;
  856.         end = &ReqPacket.p_Arg[3];
  857.     }
  858.     end = CopyName(end, name, parent);
  859.  
  860.     if (SendRecv(&ReqPacket, end - &ReqPacket, &ReqPacket, STDREPLY) == 0) {
  861.         error = ReqPacket.p_Res2;
  862.         return ReqPacket.p_Res1;
  863.     }
  864.     }
  865.     return NULL;
  866. }
  867.  
  868. Prototype ULONG NetReadLink(NetFileLock *parent, char *name, char *target, ULONG length);
  869.  
  870. ULONG
  871. NetReadLink(NetFileLock *parent, char *name, char *target, ULONG length)
  872. {
  873.     char       *end;
  874.  
  875.     if (parent = ValidLock(parent)) {
  876.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  877.     ReqPacket.p_Arg[1] = length;
  878.     end = CopyCString((char *)&ReqPacket.p_Arg[2], name);   /* XXX should be CopyCName */
  879.  
  880.     if (SendRecv2(&ReqPacket, end - &ReqPacket, NULL, 0,
  881.               &ReqPacket, STDREPLY, target, length) == 0) {
  882.         error = ReqPacket.p_Res2;
  883.         return ReqPacket.p_Res1;
  884.     }
  885.     }
  886.     return NULL;
  887. }
  888. Prototype ULONG NetSetFileSize(NetFileHandle *netfh, ULONG position, ULONG mode);
  889.  
  890. ULONG
  891. NetSetFileSize(NetFileHandle *netfh, ULONG position, ULONG mode)
  892. {
  893.     /* Same arguments and result */
  894.     return NetSeek(netfh, position, mode);
  895. }
  896.  
  897. Prototype NetFileHandle *NetOpenFromLock(NetFileLock *parent);
  898.  
  899. NetFileHandle *
  900. NetOpenFromLock(NetFileLock *parent)
  901. {
  902.     if (parent = ValidLock(parent)) {
  903.     ReqPacket.p_Arg[0] = parent->nfl_FileLock;
  904.  
  905.     if (SendRecv(&ReqPacket, REQSIZE(1), &ReqPacket, STDREPLY) == 0) {
  906.         error = ReqPacket.p_Res2;
  907.         if (ReqPacket.p_Res1) {
  908.         return MakeNetFile(ReqPacket.p_Res1);
  909.         }
  910.     }
  911.     }
  912.     return NULL;
  913. }
  914.  
  915. Prototype NetFileLock *NetParentOfFH(NetFileHandle *netfh);
  916.  
  917. NetFileLock *
  918. NetParentOfFH(NetFileHandle *netfh)
  919. {
  920.     if (ValidFile(netfh)) {
  921.     ReqPacket.p_Arg[0] = netfh->nfh_FileHandle;
  922.  
  923.     if (SendRecv(&ReqPacket, REQSIZE(1), &ReqPacket, STDREPLY) == 0) {
  924.         error = ReqPacket.p_Res2;
  925.         if (ReqPacket.p_Res1) {
  926.         return MakeNetLock(ReqPacket.p_Res1);
  927.         }
  928.     }
  929.     }
  930.     return NULL;
  931. }
  932.  
  933. Prototype ULONG NetChangeMode(ULONG type, void *object, ULONG mode);
  934.  
  935. ULONG
  936. NetChangeMode(ULONG type, void *object, ULONG mode)
  937. {
  938.     ULONG        object2 = 0;
  939.  
  940.     switch (type) {
  941.     case CHANGE_FH:
  942.     if (object = ValidLock(object))
  943.         object2 = ((NetFileHandle *)object)->nfh_FileHandle;
  944.     break;
  945.     case CHANGE_LOCK:
  946.     if (ValidFile(object))
  947.         object2 = ((NetFileLock *)object)->nfl_FileLock;
  948.     break;
  949.     }
  950.     if (object2) {
  951.     ReqPacket.p_Arg[0] = type;
  952.     ReqPacket.p_Arg[1] = object2;
  953.     ReqPacket.p_Arg[2] = mode;
  954.  
  955.     if (SendRecv(&ReqPacket, REQSIZE(3), &ReqPacket, STDREPLY) == 0) {
  956.         error = ReqPacket.p_Res2;
  957.         return ReqPacket.p_Res1;
  958.     }
  959.     }
  960.  
  961.     error = ERROR_OBJECT_WRONG_TYPE;
  962.     return DOSFALSE;
  963.  
  964. }
  965.  
  966. Prototype NetFileLock *NetDupLockFromFH(NetFileHandle *netfh);
  967.  
  968. NetFileLock *
  969. NetDupLockFromFH(NetFileHandle *netfh)
  970. {
  971.     return NetParentOfFH(netfh);
  972. }
  973.  
  974. Prototype ULONG NetExamineFH(NetFileHandle *netfh, struct FileInfoBlock *fib);
  975.  
  976. ULONG
  977. NetExamineFH(NetFileHandle *netfh, struct FileInfoBlock *fib)
  978. {
  979.     if (ValidFile(netfh)) {
  980.     ReqPacket.p_Arg[0] = netfh->nfh_FileHandle;
  981.  
  982.     if (SendRecv2(&ReqPacket, REQSIZE(1), NULL, 0,
  983.               &ReqPacket, STDREPLY, fib, sizeof(*fib)) == 0) {
  984.         error = ReqPacket.p_Res2;
  985.         return ReqPacket.p_Res1;
  986.     }
  987.     }
  988.     return DOSFALSE;
  989. }
  990.  
  991. void
  992. NetLockRecordReply(struct DosPacket *dp, ULONG res1, ULONG res2)
  993. {
  994.     debug(("NetLockRecordReply %x %x\n", res1, res2));
  995.  
  996.     dp->dp_Res1 = res1;
  997.     dp->dp_Res2 = res2;
  998.     returnpacket(dp);
  999. }
  1000.  
  1001. Prototype void NetLockRecord(struct DosPacket *dp, NetFileHandle *netfh, LONG start, LONG length, LONG mode, LONG timeout);
  1002.  
  1003. void
  1004. NetLockRecord(struct DosPacket *dp, NetFileHandle *netfh, LONG start,
  1005.           LONG length, LONG mode, LONG timeout)
  1006. {
  1007.     debug(("NetLockRecord %x %x->%x\n", dp, netfh, netfh->nfh_FileHandle));
  1008.  
  1009.     if (ValidFile(netfh)) {
  1010.     ReqPacket.p_Arg[0] = netfh->nfh_FileHandle;
  1011.     ReqPacket.p_Arg[1] = start;
  1012.     ReqPacket.p_Arg[2] = length;
  1013.     ReqPacket.p_Arg[3] = mode;
  1014.     ReqPacket.p_Arg[4] = timeout;
  1015.     ReqPacket.p_Arg[5] = dp;        /* extra */
  1016.  
  1017.     if (Send2(&ReqPacket, REQSIZE(6), NULL, 0) != 0) {
  1018.         NetLockRecordReply(dp, DOSFALSE, ERROR_NO_FREE_STORE);
  1019.     }
  1020.     } else {
  1021.     debug(("Bad NetFH\n"));
  1022.     NetLockRecordReply(dp, DOSFALSE, ERROR_OBJECT_WRONG_TYPE);
  1023.     }
  1024. }
  1025.  
  1026. Prototype ULONG NetFreeRecord(NetFileHandle *netfh, LONG start, LONG length);
  1027.  
  1028. ULONG
  1029. NetFreeRecord(NetFileHandle *netfh, LONG start, LONG length)
  1030. {
  1031.     if (ValidFile(netfh)) {
  1032.     ReqPacket.p_Arg[0] = netfh->nfh_FileHandle;
  1033.     ReqPacket.p_Arg[1] = start;
  1034.     ReqPacket.p_Arg[2] = length;
  1035.  
  1036.     if (SendRecv(&ReqPacket, REQSIZE(3), &ReqPacket, STDREPLY) == 0) {
  1037.         error = ReqPacket.p_Res2;
  1038.         return ReqPacket.p_Res1;
  1039.     }
  1040.     }
  1041.     return NULL;
  1042. }
  1043.  
  1044. /* ---------------------------------------------------------------------- */
  1045.  
  1046. Prototype void DoAsyncReply(Packet *pkt);
  1047.  
  1048. void
  1049. DoAsyncReply(Packet *pkt)
  1050. {
  1051.     debug(("DoAsyncReply\n"));
  1052.  
  1053.     switch (pkt->p_Data[0]) {
  1054.     case ACTION_LOCK_RECORD:
  1055.     NetLockRecordReply((void *)pkt->p_Data[1], pkt->p_Res1, pkt->p_Res2);
  1056.     break;
  1057.     default:
  1058.     debug(("Weird AsyncReply, %d\n", pkt->p_Data[0]));
  1059.     }
  1060. }
  1061.  
  1062. /* ---------------------------------------------------------------------- */
  1063.  
  1064. Prototype ULONG OpenNetFS(void);
  1065.  
  1066. ULONG
  1067. OpenNetFS(void)
  1068. {
  1069.     ULONG        error;
  1070.  
  1071.     debug(("OpenNetFS\n"));
  1072.     error = OpenNetwork();
  1073.     if (error == 0) {
  1074.     RootLock = MakeNetLock(0);
  1075.     RootLock->nfl_Validation = 0;
  1076.     NewList(&NameList);
  1077.     }
  1078.     debug(("OpenNetFS done\n"));
  1079.     return error;
  1080. }
  1081.  
  1082. Prototype ULONG CloseNetFS(void);
  1083.  
  1084. ULONG
  1085. CloseNetFS(void)
  1086. {
  1087.     NetFileLock *nfl;
  1088.  
  1089.     debug(("CloseNetFS\n"));
  1090.     CloseNetwork();
  1091.  
  1092.     nfl = RootLock;
  1093.     RootLock = NULL;
  1094.     FreeNetLock(nfl);
  1095.  
  1096.     return 0;
  1097. }
  1098.