home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / comms / network / dnet.lzh / dnet / snfs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-04  |  13.5 KB  |  649 lines

  1.  
  2. /*
  3.  *  SNFS.C     V1.1
  4.  *
  5.  *  DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
  6.  *
  7.  *  NETWORK FILE SYSTEM SERVER
  8.  *
  9.  *  Accepts connections to files or directories & read-write or dir-scan calls.
  10.  */
  11.  
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <sys/wait.h>
  15. #include <sys/time.h>
  16. #include <sys/dir.h>
  17. #include <sys/file.h>
  18. #include <sys/resource.h>
  19. #include <stdio.h>
  20. #include <errno.h>
  21. #include <signal.h>
  22.  
  23. #include "servers.h"
  24. #include "snfs.h"
  25.  
  26. /* #define DEBUG */
  27.  
  28. #define MAXHANDLES    256
  29.  
  30. char *FDName();
  31. extern void AmigaToUnixPath();
  32. extern void ConcatPath();
  33. extern char *malloc();
  34. extern char *TailPart();
  35. extern char *strcpy();
  36.  
  37. int Chan;
  38.  
  39. typedef struct {
  40.     short isopen;
  41.     short fd;
  42.     int   modes;
  43.     int   remodes;
  44.     long  pos;
  45.     char  *name;
  46. } HANDLE;
  47.  
  48. HANDLE Handle[MAXHANDLES];
  49.  
  50.  
  51. chandler()
  52. {
  53.     union wait stat;
  54.     struct rusage rus;
  55.     while (wait3(&stat, WNOHANG, &rus) > 0);
  56. }
  57.  
  58. void NFs();
  59.  
  60. main(ac,av)
  61. char *av[];
  62. {
  63.     long chann = DListen(PORT_NFS);
  64.     int fd;
  65.     int n;
  66.     char buf[1024];
  67.     extern int errno;
  68.  
  69.     if (av[1])
  70.     chdir(av[1]);
  71. #ifdef DEBUG
  72.     freopen("NFS", "w", stderr);
  73.     fprintf(stderr, "RUNNING\n");
  74.     fflush(stderr);
  75. #endif
  76.     signal(SIGCHLD, chandler);
  77.     signal(SIGPIPE, SIG_IGN);
  78.     for (;;) {
  79.     fd = DAccept(chann);
  80.     if (fd < 0) {
  81.         if (errno == EINTR)
  82.         continue;
  83.         break;
  84.     }
  85.     if (fork() == NULL) {
  86.         NFs(fd);
  87. #ifdef DEBUG
  88.         fprintf(stderr, "CLOSING\n");
  89.         fflush(stderr);
  90. #endif
  91.         _exit(1);
  92.     }
  93.     close(fd);
  94.     }
  95.     perror("NFS");
  96. }
  97.  
  98. void
  99. NFs(chan)
  100. int chan;
  101. {
  102.     OpenHandle("/", "", O_RDONLY); /* root */
  103.     for (;;) {
  104.     unsigned char basebuf[6];
  105.     struct {
  106.         char    cmd;
  107.         unsigned char blen;
  108.         unsigned long dlen;
  109.     } Base;
  110.     long bytes;
  111.     union {
  112.         OpOpen    Open;
  113.         OpRead    Read;
  114.         OpWrite    Write;
  115.         OpClose    Close;
  116.         OpSeek    Seek;
  117.         OpParent    Parent;
  118.         OpDelete    Delete;
  119.         OpCreateDir CreateDir;
  120.         OpDup    Dup;
  121.         OpNextDir   NextDir;
  122.         OpRename    Rename;
  123.     } R;
  124.     union {
  125.         RtOpen    Open;
  126.         RtRead    Read;
  127.         RtWrite    Write;
  128.         RtSeek    Seek;
  129.         RtParent    Parent;
  130.         RtDelete    Delete;
  131.         RtCreateDir CreateDir;
  132.         RtDup    Dup;
  133.         RtNextDir   NextDir;
  134.         RtRename    Rename;
  135.     } W;
  136.     long h;
  137.     char buf[256];
  138.  
  139.     if (ggread(chan, basebuf, 6) != 6)
  140.         break;
  141.     Base.cmd  = basebuf[0];
  142.     Base.blen = basebuf[1];
  143.     Base.dlen = (basebuf[2] << 24) | (basebuf[3] << 16) |(basebuf[4] << 8)|
  144.         basebuf[5];
  145. #ifdef DEBUG
  146.         fprintf(stderr, "command %02x %ld %ld\n", 
  147.         Base.cmd, Base.blen, Base.dlen
  148.     );
  149.     fflush(stderr);
  150. #endif
  151.     if (ggread(chan, &R, Base.blen) != Base.blen)
  152.         break;
  153.     switch(Base.cmd) {
  154.     case 'M':    /* create directory */
  155.         {
  156.             ggread(chan, buf, Base.dlen);
  157.         AmigaToUnixPath(buf);
  158.         mkdir(buf, 0777);
  159. #ifdef DEBUG
  160.         fprintf(stderr, "MakeDir %s\n", buf);
  161.             fflush(stderr);
  162. #endif
  163.         }
  164.         R.Open.DirHandle = R.CreateDir.DirHandle;
  165.         /* FALL THROUGH */
  166.     case 'P':
  167.         if (Base.cmd == 'P') {
  168.         char *name = FDName(ntol(R.Parent.Handle));
  169.         short i = strlen(name)-1;
  170.  
  171. #ifdef DEBUG
  172.         fprintf(stderr, "Parent Dir of: %s\n", name);
  173.         fflush(stderr);
  174. #endif
  175.  
  176.         if (i >= 0 && name[i] == '/')    /* remove tailing /'s */
  177.             --i;
  178.         if (i < 0) {
  179.             W.Open.Handle = lton(-1);
  180.                 gwrite(chan, &W.Open, sizeof(W.Open));
  181. #ifdef DEBUG
  182.             fprintf(stderr, "NO PARENT\n");
  183.             fflush(stderr);
  184. #endif
  185.             break;
  186.         }
  187.         while (i >= 0 && name[i] != '/')  /* remove name */
  188.             --i;
  189.         while (i >= 0 && name[i] == '/')  /* remove tailing /'s */
  190.             --i;
  191.         ++i;
  192.         if (i == 0) {    /* at root */
  193.             buf[i++] = '/';
  194.         } 
  195.         strncpy(buf, name, i);
  196.         buf[i] = 0;
  197. #ifdef DEBUG
  198.         fprintf(stderr, "Parent Exists: %s\n", buf);
  199.             fflush(stderr);
  200. #endif
  201.             R.Open.DirHandle = lton(0);
  202.         }
  203.         R.Open.Modes = lton(1005);
  204.         /* FALL THROUGH */
  205.     case 'O':    /*    open    */
  206.         if (Base.cmd == 'O')  {
  207.             ggread(chan, buf, Base.dlen);
  208.         AmigaToUnixPath(buf);
  209. #ifdef DEBUG
  210.         fprintf(stderr, "OPEN: %s %d\n", buf, Base.dlen);
  211.         fflush(stderr);
  212. #endif
  213.         }
  214.         if (ntol(R.Open.Modes) == 1006)
  215.             h = OpenHandle(FDName(ntol(R.Open.DirHandle)),buf, 
  216.             O_CREAT|O_TRUNC|O_RDWR
  217.         );
  218.         else
  219.         h = OpenHandle(FDName(ntol(R.Open.DirHandle)),buf, O_RDWR);
  220. #ifdef DEBUG
  221.         fprintf(stderr, "Open h = %d name = %s  modes=%d\n", 
  222.         h, buf, R.Open.Modes
  223.         );
  224.         fflush(stderr);
  225. #endif
  226.         if (h >= 0) {
  227.         struct stat stat;
  228.         if (fstat(FDHandle(h), &stat) < 0)
  229.             perror("fstat");
  230.             W.Open.Handle = lton(h);
  231.             W.Open.Prot = lton(0);
  232.             W.Open.Type = lton((stat.st_mode & S_IFDIR) ? 1 : -1);
  233. #ifdef DEBUG
  234.         fprintf(stderr, "fstat type %d\n", W.Open.Type);
  235.         fflush(stderr);
  236. #endif
  237.             W.Open.Size = lton(stat.st_size);
  238.         SetDate(&W.Open.Date, stat.st_mtime);
  239.             gwrite(chan, &W.Open, sizeof(W.Open));
  240.         if (Base.cmd == 'P') {    /* tag name */
  241.             char *tail = TailPart(buf);
  242.             unsigned char c = strlen(tail) + 1;
  243.  
  244.             gwrite(chan, &c, 1);
  245.             gwrite(chan, tail, c);
  246.         }
  247.         } else {
  248.         W.Open.Handle = lton(-1);
  249.             gwrite(chan, &W.Open, sizeof(W.Open));
  250.         }
  251.         break;
  252.     case 'N':    /* next directory.  Scan beg. at index    */
  253.         {
  254.         DIR *dir = opendir(FDName(ntol(R.NextDir.Handle)));
  255.         struct stat sbuf;
  256.         struct direct *dp;
  257.         long index = 0;
  258.         char buf[1024];
  259.  
  260.         while (dir && index <= ntol(R.NextDir.Index) + 2) {
  261.             if ((dp = readdir(dir)) == NULL)
  262.             break;
  263.             ++index;
  264.         }
  265.         if (dir)
  266.             closedir(dir);
  267.         if (index <= ntol(R.NextDir.Index) + 2) {
  268.             W.Open.Handle = lton(-1);
  269.         } else {
  270.             W.Open.Handle = lton(index);
  271.             strcpy(buf, FDName(ntol(R.NextDir.Handle)));
  272.             strcat(buf, "/");
  273.             strcat(buf, dp->d_name);
  274.             stat(buf, &sbuf);
  275.                 W.Open.Prot = lton(0);
  276.                 W.Open.Type = lton((sbuf.st_mode & S_IFDIR) ? 1 : -1);
  277. #ifdef DEBUG
  278.             fprintf(stderr, "fstat type %d\n", W.Open.Type);
  279.             fflush(stderr);
  280. #endif
  281.                 W.Open.Size = lton(sbuf.st_size);
  282.             SetDate(&W.Open.Date, sbuf.st_mtime);
  283.         }
  284.         gwrite(chan, &W.Open, sizeof(W.Open));
  285.         if (ntol(W.Open.Handle) >= 0) {
  286.             unsigned char len = strlen(dp->d_name) + 1;
  287.             gwrite(chan, &len, 1);
  288.             gwrite(chan, dp->d_name, len);
  289.         }
  290.         }
  291.         break;
  292.     case 'r':    /*    RENAME    */
  293.         {
  294.         char tmp1[512];
  295.         char tmp2[512];
  296.         char buf1[1024];
  297.         char buf2[1024];
  298.  
  299.             ggread(chan, buf, Base.dlen);
  300.         strcpy(tmp1, buf);
  301.         strcpy(tmp2, buf + strlen(buf) + 1);
  302.         AmigaToUnixPath(tmp1);
  303.         AmigaToUnixPath(tmp2);
  304.         ConcatPath(FDName(ntol(R.Rename.DirHandle1)), tmp1, buf1);
  305.         ConcatPath(FDName(ntol(R.Rename.DirHandle2)), tmp2, buf2);
  306. #ifdef DEBUG
  307.         fprintf(stderr, "Rename %s to %s\n", buf1, buf2);
  308.         fflush(stderr);
  309. #endif
  310.         if (rename(buf1, buf2) < 0)
  311.             W.Rename.Error = lton(1);
  312.         else
  313.             W.Rename.Error = lton(0);
  314.         gwrite(chan, &W.Rename.Error, sizeof(W.Rename.Error));
  315.         }
  316.         break;
  317.     case 'd':    /*    DUP    */
  318.         h = DupHandle(ntol(R.Dup.Handle));
  319.         if (h >= 0) {
  320.         struct stat stat;
  321.         if (fstat(FDHandle(h), &stat) < 0)
  322.             perror("fstat");
  323.             W.Open.Handle = lton(h);
  324.             W.Open.Prot = lton(0);
  325.             W.Open.Type = lton((stat.st_mode & S_IFDIR) ? 1 : -1);
  326. #ifdef DEBUG
  327.         fprintf(stderr, "fstat type %d\n", W.Open.Type);
  328.         fflush(stderr);
  329. #endif
  330.             W.Open.Size = lton(stat.st_size);
  331.         SetDate(&W.Open.Date, stat.st_mtime);
  332.         } else {
  333.         W.Open.Handle = lton(-1);
  334.         }
  335.         gwrite(chan, &W.Dup, sizeof(W.Dup));
  336.         break;
  337.     case 'R':    /*    READ    */
  338.         {
  339.         int fd = FDHandle(ntol(R.Read.Handle));
  340.         char *buf = malloc(ntol(R.Read.Bytes));
  341.  
  342.         W.Read.Bytes = lton(read(fd, buf, ntol(R.Read.Bytes)));
  343. #ifdef DEBUG
  344.         fprintf(stderr, "h=%d fd %d Read %d  Result=%d\n", 
  345.             R.Read.Handle, fd, R.Read.Bytes, W.Read.Bytes
  346.         );
  347.             fflush(stderr);
  348. #endif
  349.         gwrite(chan, &W.Read, sizeof(W.Read));
  350.         if (ntol(W.Read.Bytes) > 0)
  351.             gwrite(chan, buf, ntol(W.Read.Bytes));
  352.         free(buf);
  353.         }
  354.         break;
  355.     case 'W':
  356.         {
  357.         int fd = FDHandle(ntol(R.Write.Handle));
  358.         char *buf = malloc(ntol(R.Write.Bytes));
  359.         if (ggread(chan,buf,ntol(R.Write.Bytes))!=ntol(R.Write.Bytes))
  360.             break;
  361.         W.Write.Bytes = lton(write(fd, buf, ntol(R.Write.Bytes)));
  362. #ifdef DEBUG
  363.         fprintf(stderr, "h=%d fd %d Write %d  Result=%d\n", 
  364.             R.Write.Handle, fd, R.Write.Bytes, W.Write.Bytes
  365.         );
  366.             fflush(stderr);
  367. #endif
  368.         gwrite(chan, &W.Write, sizeof(W.Write));
  369.         free(buf);
  370.         }
  371.         break;
  372.     case 'C':
  373.         {
  374.         CloseHandle(ntol(R.Close.Handle));
  375.         }
  376.         break;
  377.     case 'S':
  378.         {
  379.         int fd = FDHandle(ntol(R.Seek.Handle));
  380.         W.Seek.OldOffset = lton(lseek(fd, 0, 1));
  381.         W.Seek.NewOffset = lton(lseek(fd, ntol(R.Seek.Offset), 
  382.             ntol(R.Seek.How)));
  383. #ifdef DEBUG
  384.         fprintf(stderr, "h %d SEEK %d %d %d result = %d\n",
  385.             R.Seek.Handle, fd, R.Seek.Offset, R.Seek.How,
  386.             W.Seek.NewOffset
  387.         );
  388.             fflush(stderr);
  389. #endif
  390.         gwrite(chan, &W.Seek, sizeof(W.Seek));
  391.         }
  392.         break;
  393.     case 'D':
  394.         {
  395.         char buf2[1024];
  396.  
  397.             ggread(chan, buf, Base.dlen);    /* get name to delete */
  398.         AmigaToUnixPath(buf);
  399.         ConcatPath(FDName(ntol(R.Delete.DirHandle)), buf, buf2);
  400.  
  401.         unlink(buf2);
  402.         rmdir(buf2);
  403. #ifdef DEBUG
  404.         fprintf(stderr, "Delete %s\n", buf2);
  405.             fflush(stderr);
  406. #endif
  407.         W.Delete.Error = lton(0);
  408.         gwrite(chan, &W.Delete, sizeof(W.Delete));
  409.         }
  410.         break;
  411.     default:
  412.         exit(1);
  413.         break;
  414.     }
  415.     }
  416. }
  417.  
  418. OpenHandle(base, tail, modes)
  419. char *base;
  420. char *tail;
  421. int modes;
  422. {
  423.     short i;
  424.     int fd;
  425.     char name[1024];
  426.  
  427.     ConcatPath(base, tail, name);
  428.     for (i = 0; i < MAXHANDLES; ++i) {
  429.     if (Handle[i].isopen == 0)
  430.         break;
  431.     }
  432.     if (i == MAXHANDLES)
  433.     return(-1);
  434.     fd = open(name, modes, 0666);
  435.     if (fd < 0 && (modes & O_RDWR) && !(modes & O_CREAT)) {
  436.     modes &= ~O_RDWR;
  437.     fd = open(name, modes);
  438.     }
  439.     Handle[i].name = strcpy(malloc(strlen(name)+1), name);
  440.     Handle[i].fd = fd;
  441. #ifdef DEBUG
  442.     fprintf(stderr, "OpenHandle: %d = open %s %d\n", Handle[i].fd, name,modes);
  443.     fflush(stderr);
  444. #endif
  445.     if (Handle[i].fd < 0)
  446.     return(-1);
  447.     Handle[i].modes = modes;
  448.     Handle[i].remodes= modes & ~(O_TRUNC|O_CREAT);
  449.     Handle[i].isopen = 1;
  450.     return(i);
  451. }
  452.  
  453. CloseHandle(h)
  454. {
  455. #ifdef DEBUG
  456.     fprintf(stderr, " Close Handle %d\n", h);
  457.     fflush(stderr);
  458. #endif
  459.     if (h >= 0 && h < MAXHANDLES && Handle[h].isopen) {
  460.     if (Handle[h].fd >= 0)
  461.         close(Handle[h].fd);
  462.     Handle[h].fd = -1;
  463.     Handle[h].isopen = 0;
  464.     free(Handle[h].name);
  465.     }
  466. }
  467.  
  468. /*
  469.  *  Insert ../ for / at beginning.
  470.  */
  471.  
  472. void
  473. AmigaToUnixPath(buf)
  474. char *buf;
  475. {
  476.     char *base = buf;
  477. #ifdef DEBUG
  478.     fprintf(stderr, "AmigaToUnixPath %s", buf);
  479. #endif
  480.     if (*buf == ':')
  481.     *buf++ = '/';
  482.     while (*buf == '/') {
  483.     bcopy(buf, buf + 2, strlen(buf)+1);
  484.     buf[0] = buf[1] = '.';
  485.     buf += 3;
  486.     }
  487. #ifdef DEBUG
  488.     fprintf(stderr, " TO %s\n", base);
  489.     fflush(stderr);
  490. #endif
  491. }
  492.  
  493. void
  494. ConcatPath(s1, s2, buf)
  495. char *s1, *s2;
  496. char *buf;
  497. {
  498. #ifdef DEBUG
  499.     fprintf(stderr, "ConCatPaths From '%s' '%s'\n", s1, s2);
  500. #endif
  501.     while (strncmp(s2, "../", 3) == 0) {    /* parent */
  502.     ;
  503.     break;
  504.     }
  505.     while (strncmp(s2, "./", 2) == 0) {        /* current */
  506.     s2 += 2;
  507.     }
  508.     if (s2[0] == '/') {
  509.     strcpy(buf, s2);
  510.     return;
  511.     }
  512.     if (s1[0] == 0 && s2[0] == 0) {
  513.     strcpy(buf, ".");
  514.     return;
  515.     }
  516.     if (s1[0] == 0)
  517.     s1 = ".";
  518.     strcpy(buf, s1);
  519.     if (s1[strlen(s1)-1] != '/')
  520.         strcat(buf, "/");
  521.     strcat(buf, s2);
  522. #ifdef DEBUG
  523.     fprintf(stderr, "ConCatPaths to %s\n", buf);
  524.     fflush(stderr);
  525. #endif
  526. }
  527.  
  528. char *
  529. FDName(h)
  530. {
  531. #ifdef DEBUG
  532.     fprintf(stderr, "FDName(%d) =", h);
  533. #endif
  534.     if (h >= 0 && h < MAXHANDLES && Handle[h].isopen) {
  535. #ifdef DEBUG
  536.     fprintf(stderr, "%s\n", Handle[h].name);
  537.         fflush(stderr);
  538. #endif
  539.     return(Handle[h].name);
  540.     }
  541. #ifdef DEBUG
  542.     fprintf(stderr, "??\n");
  543.     fflush(stderr);
  544. #endif
  545.     return(".");
  546. }
  547.  
  548. DupHandle(h)
  549. {
  550.     short n = -1;
  551.     if (h >= 0 && h < MAXHANDLES && Handle[h].isopen)
  552.     n = OpenHandle(".",Handle[h].name, Handle[h].remodes & ~O_RDWR);
  553.     return(n);
  554. }
  555.  
  556. FDHandle(h)
  557. {
  558.     int fd = -1;
  559.     if (h >= 0 && h < MAXHANDLES && Handle[h].isopen) {
  560.     fd = Handle[h].fd;
  561.     if (fd < 0) {
  562.         Handle[h].fd = fd = open(Handle[h].name, Handle[h].remodes, 0666);
  563.         if (fd >= 0 && !(Handle[h].modes & O_APPEND))
  564.         lseek(fd, Handle[h].pos, 0);
  565.     }
  566.     }
  567.     return(fd);
  568. }
  569.  
  570. char *
  571. TailPart(path)
  572. char *path;
  573. {
  574.     register char *ptr = path + strlen(path) - 1;
  575.  
  576.     while (ptr >= path && *ptr != '/')
  577.     --ptr;
  578.     ++ptr;
  579. #ifdef DEBUG
  580.     fprintf(stderr, "TAILPART '%s' -> %s\n", path, ptr);
  581.     fflush(stderr);
  582. #endif
  583.     return(ptr);
  584. }
  585.  
  586. SetDate(date, mtime)
  587. STAMP *date;
  588. time_t mtime;
  589. {
  590.     struct tm *tm = localtime(&mtime);
  591.     long years = tm->tm_year;    /* since 1900    */
  592.     long days;
  593.  
  594.     years += 300;            /* since 1600           */
  595.     days = (years / 400) * 146097;    /* # days every four cents    */
  596.  
  597.     years = years % 400;
  598.  
  599.     /*
  600.      *    First assume a leap year every 4 years, then correct for centuries.
  601.      *    never include the 'current' year in the calculations.  Thus, year 0
  602.      *      (a leap year) is included only if years > 0.
  603.      */
  604.  
  605.     days += years * 365 + ((years+3) / 4);
  606.     
  607.     if (years <= 100)
  608.     ;
  609.     else if (years <= 200)        /* no leap 3 of 4 cent. marks    */
  610.     days -= 1;
  611.     else if (years <= 300)
  612.     days -= 2;
  613.     else
  614.     days -= 3;
  615.     days -= 138062;            /* 1600 -> 1978            */
  616.     date->ds_Days  = lton(days + tm->tm_yday);
  617.     date->ds_Minute= lton(tm->tm_min + tm->tm_hour * 60);
  618.     date->ds_Tick  = lton(tm->tm_sec * 50);
  619. }
  620.  
  621. long
  622. ntol(n)
  623. unsigned long n;
  624. {
  625.     unsigned char n0, n1, n2, n3;
  626.  
  627.     n0 = n >> 24;
  628.     n1 = n >> 16;
  629.     n2 = n >> 8;
  630.     n3 = n;
  631.  
  632.     return(n0 | (n1 << 8) | (n2 << 16) | (n3 << 24));
  633. }
  634.  
  635. long
  636. lton(n)
  637. unsigned long n;
  638. {
  639.     unsigned char n0, n1, n2, n3;
  640.  
  641.     n0 = n >> 24;
  642.     n1 = n >> 16;
  643.     n2 = n >> 8;
  644.     n3 = n;
  645.  
  646.     return(n0 | (n1 << 8) | (n2 << 16) | (n3 << 24));
  647. }
  648.  
  649.