home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff294.lzh / DNet / unix / server / snfs.c < prev    next >
C/C++ Source or Header  |  1989-12-11  |  13KB  |  615 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.     struct {
  105.         char    cmd;
  106.         unsigned char blen;
  107.         unsigned long dlen;
  108.     } Base;
  109.     long bytes;
  110.     union {
  111.         OpOpen    Open;
  112.         OpRead    Read;
  113.         OpWrite    Write;
  114.         OpClose    Close;
  115.         OpSeek    Seek;
  116.         OpParent    Parent;
  117.         OpDelete    Delete;
  118.         OpCreateDir CreateDir;
  119.         OpDup    Dup;
  120.         OpNextDir   NextDir;
  121.         OpRename    Rename;
  122.     } R;
  123.     union {
  124.         RtOpen    Open;
  125.         RtRead    Read;
  126.         RtWrite    Write;
  127.         RtSeek    Seek;
  128.         RtParent    Parent;
  129.         RtDelete    Delete;
  130.         RtCreateDir CreateDir;
  131.         RtDup    Dup;
  132.         RtNextDir   NextDir;
  133.         RtRename    Rename;
  134.     } W;
  135.     long h;
  136.     char buf[256];
  137.  
  138.     if (ggread(chan, &Base, sizeof(Base)) != sizeof(Base))
  139.         break;
  140. #ifdef DEBUG
  141.         fprintf(stderr, "command %02x %ld %ld\n", 
  142.         Base.cmd, Base.blen, Base.dlen
  143.     );
  144.     fflush(stderr);
  145. #endif
  146.     if (ggread(chan, &R, Base.blen) != Base.blen)
  147.         break;
  148.     switch(Base.cmd) {
  149.     case 'M':    /* create directory */
  150.         {
  151.             ggread(chan, buf, Base.dlen);
  152.         AmigaToUnixPath(buf);
  153.         mkdir(buf, 0777);
  154. #ifdef DEBUG
  155.         fprintf(stderr, "MakeDir %s\n", buf);
  156.             fflush(stderr);
  157. #endif
  158.         }
  159.         R.Open.DirHandle = R.CreateDir.DirHandle;
  160.         /* FALL THROUGH */
  161.     case 'P':
  162.         if (Base.cmd == 'P') {
  163.         char *name = FDName(R.Parent.Handle);
  164.         short i = strlen(name)-1;
  165.  
  166. #ifdef DEBUG
  167.         fprintf(stderr, "Parent Dir of: %s\n", name);
  168.         fflush(stderr);
  169. #endif
  170.  
  171.         if (i >= 0 && name[i] == '/')    /* remove tailing /'s */
  172.             --i;
  173.         if (i < 0) {
  174.             W.Open.Handle = -1;
  175.                 gwrite(chan, &W.Open, sizeof(W.Open));
  176. #ifdef DEBUG
  177.             fprintf(stderr, "NO PARENT\n");
  178.             fflush(stderr);
  179. #endif
  180.             break;
  181.         }
  182.         while (i >= 0 && name[i] != '/')  /* remove name */
  183.             --i;
  184.         while (i >= 0 && name[i] == '/')  /* remove tailing /'s */
  185.             --i;
  186.         ++i;
  187.         if (i == 0) {    /* at root */
  188.             buf[i++] = '/';
  189.         } 
  190.         strncpy(buf, name, i);
  191.         buf[i] = 0;
  192. #ifdef DEBUG
  193.         fprintf(stderr, "Parent Exists: %s\n", buf);
  194.             fflush(stderr);
  195. #endif
  196.             R.Open.DirHandle = 0;
  197.         }
  198.         R.Open.Modes = 1005;
  199.         /* FALL THROUGH */
  200.     case 'O':    /*    open    */
  201.         if (Base.cmd == 'O')  {
  202.             ggread(chan, buf, Base.dlen);
  203.         AmigaToUnixPath(buf);
  204. #ifdef DEBUG
  205.         fprintf(stderr, "OPEN: %s %d\n", buf, Base.dlen);
  206.         fflush(stderr);
  207. #endif
  208.         }
  209.         if (R.Open.Modes == 1006)
  210.             h = OpenHandle(FDName(R.Open.DirHandle),buf, 
  211.             O_CREAT|O_TRUNC|O_RDWR
  212.         );
  213.         else
  214.         h = OpenHandle(FDName(R.Open.DirHandle),buf, O_RDWR);
  215. #ifdef DEBUG
  216.         fprintf(stderr, "Open h = %d name = %s  modes=%d\n", 
  217.         h, buf, R.Open.Modes
  218.         );
  219.         fflush(stderr);
  220. #endif
  221.         if (h >= 0) {
  222.         struct stat stat;
  223.         if (fstat(FDHandle(h), &stat) < 0)
  224.             perror("fstat");
  225.             W.Open.Handle = h;
  226.             W.Open.Prot = 0;
  227.             W.Open.Type = (stat.st_mode & S_IFDIR) ? 1 : -1;
  228. #ifdef DEBUG
  229.         fprintf(stderr, "fstat type %d\n", W.Open.Type);
  230.         fflush(stderr);
  231. #endif
  232.             W.Open.Size = stat.st_size;
  233.         SetDate(&W.Open.Date, stat.st_mtime);
  234.             gwrite(chan, &W.Open, sizeof(W.Open));
  235.         if (Base.cmd == 'P') {    /* tag name */
  236.             char *tail = TailPart(buf);
  237.             unsigned char c = strlen(tail) + 1;
  238.  
  239.             gwrite(chan, &c, 1);
  240.             gwrite(chan, tail, c);
  241.         }
  242.         } else {
  243.         W.Open.Handle = -1;
  244.             gwrite(chan, &W.Open, sizeof(W.Open));
  245.         }
  246.         break;
  247.     case 'N':    /* next directory.  Scan beg. at index    */
  248.         {
  249.         DIR *dir = opendir(FDName(R.NextDir.Handle));
  250.         struct stat sbuf;
  251.         struct direct *dp;
  252.         long index = 0;
  253.         char buf[1024];
  254.  
  255.         while (dir && index <= R.NextDir.Index + 2) {
  256.             if ((dp = readdir(dir)) == NULL)
  257.             break;
  258.             ++index;
  259.         }
  260.         if (dir)
  261.             closedir(dir);
  262.         if (index <= R.NextDir.Index + 2) {
  263.             W.Open.Handle = -1;
  264.         } else {
  265.             W.Open.Handle = index;
  266.             strcpy(buf, FDName(R.NextDir.Handle));
  267.             strcat(buf, "/");
  268.             strcat(buf, dp->d_name);
  269.             stat(buf, &sbuf);
  270.                 W.Open.Prot = 0;
  271.                 W.Open.Type = (sbuf.st_mode & S_IFDIR) ? 1 : -1;
  272. #ifdef DEBUG
  273.             fprintf(stderr, "fstat type %d\n", W.Open.Type);
  274.             fflush(stderr);
  275. #endif
  276.                 W.Open.Size = sbuf.st_size;
  277.             SetDate(&W.Open.Date, sbuf.st_mtime);
  278.         }
  279.         gwrite(chan, &W.Open, sizeof(W.Open));
  280.         if (W.Open.Handle >= 0) {
  281.             unsigned char len = strlen(dp->d_name) + 1;
  282.             gwrite(chan, &len, 1);
  283.             gwrite(chan, dp->d_name, len);
  284.         }
  285.         }
  286.         break;
  287.     case 'r':    /*    RENAME    */
  288.         {
  289.         char tmp1[512];
  290.         char tmp2[512];
  291.         char buf1[1024];
  292.         char buf2[1024];
  293.  
  294.             ggread(chan, buf, Base.dlen);
  295.         strcpy(tmp1, buf);
  296.         strcpy(tmp2, buf + strlen(buf) + 1);
  297.         AmigaToUnixPath(tmp1);
  298.         AmigaToUnixPath(tmp2);
  299.         ConcatPath(FDName(R.Rename.DirHandle1), tmp1, buf1);
  300.         ConcatPath(FDName(R.Rename.DirHandle2), tmp2, buf2);
  301. #ifdef DEBUG
  302.         fprintf(stderr, "Rename %s to %s\n", buf1, buf2);
  303.         fflush(stderr);
  304. #endif
  305.         if (rename(buf1, buf2) < 0)
  306.             W.Rename.Error = 1;
  307.         else
  308.             W.Rename.Error = 0;
  309.         gwrite(chan, &W.Rename.Error, sizeof(W.Rename.Error));
  310.         }
  311.         break;
  312.     case 'd':    /*    DUP    */
  313.         h = DupHandle(R.Dup.Handle);
  314.         if (h >= 0) {
  315.         struct stat stat;
  316.         if (fstat(FDHandle(h), &stat) < 0)
  317.             perror("fstat");
  318.             W.Open.Handle = h;
  319.             W.Open.Prot = 0;
  320.             W.Open.Type = (stat.st_mode & S_IFDIR) ? 1 : -1;
  321. #ifdef DEBUG
  322.         fprintf(stderr, "fstat type %d\n", W.Open.Type);
  323.         fflush(stderr);
  324. #endif
  325.             W.Open.Size = stat.st_size;
  326.         SetDate(&W.Open.Date, stat.st_mtime);
  327.         } else {
  328.         W.Open.Handle = -1;
  329.         }
  330.         gwrite(chan, &W.Dup, sizeof(W.Dup));
  331.         break;
  332.     case 'R':    /*    READ    */
  333.         {
  334.         int fd = FDHandle(R.Read.Handle);
  335.         char *buf = malloc(R.Read.Bytes);
  336.  
  337.         W.Read.Bytes = read(fd, buf, R.Read.Bytes);
  338. #ifdef DEBUG
  339.         fprintf(stderr, "h=%d fd %d Read %d  Result=%d\n", 
  340.             R.Read.Handle, fd, R.Read.Bytes, W.Read.Bytes
  341.         );
  342.             fflush(stderr);
  343. #endif
  344.         gwrite(chan, &W.Read, sizeof(W.Read));
  345.         if (W.Read.Bytes > 0)
  346.             gwrite(chan, buf, W.Read.Bytes);
  347.         free(buf);
  348.         }
  349.         break;
  350.     case 'W':
  351.         {
  352.         int fd = FDHandle(R.Write.Handle);
  353.         char *buf = malloc(R.Write.Bytes);
  354.         if (ggread(chan, buf, R.Write.Bytes) != R.Write.Bytes)
  355.             break;
  356.         W.Write.Bytes = write(fd, buf, R.Write.Bytes);
  357. #ifdef DEBUG
  358.         fprintf(stderr, "h=%d fd %d Write %d  Result=%d\n", 
  359.             R.Write.Handle, fd, R.Write.Bytes, W.Write.Bytes
  360.         );
  361.             fflush(stderr);
  362. #endif
  363.         gwrite(chan, &W.Write, sizeof(W.Write));
  364.         free(buf);
  365.         }
  366.         break;
  367.     case 'C':
  368.         {
  369.         CloseHandle(R.Close.Handle);
  370.         }
  371.         break;
  372.     case 'S':
  373.         {
  374.         int fd = FDHandle(R.Seek.Handle);
  375.         W.Seek.OldOffset = lseek(fd, 0, 1);
  376.         W.Seek.NewOffset = lseek(fd, R.Seek.Offset, R.Seek.How);
  377. #ifdef DEBUG
  378.         fprintf(stderr, "h %d SEEK %d %d %d result = %d\n",
  379.             R.Seek.Handle, fd, R.Seek.Offset, R.Seek.How,
  380.             W.Seek.NewOffset
  381.         );
  382.             fflush(stderr);
  383. #endif
  384.         gwrite(chan, &W.Seek, sizeof(W.Seek));
  385.         }
  386.         break;
  387.     case 'D':
  388.         {
  389.         char buf2[1024];
  390.  
  391.             ggread(chan, buf, Base.dlen);    /* get name to delete */
  392.         AmigaToUnixPath(buf);
  393.         ConcatPath(FDName(R.Delete.DirHandle), buf, buf2);
  394.  
  395.         unlink(buf2);
  396.         rmdir(buf2);
  397. #ifdef DEBUG
  398.         fprintf(stderr, "Delete %s\n", buf2);
  399.             fflush(stderr);
  400. #endif
  401.         W.Delete.Error = 0;
  402.         gwrite(chan, &W.Delete, sizeof(W.Delete));
  403.         }
  404.         break;
  405.     default:
  406.         exit(1);
  407.         break;
  408.     }
  409.     }
  410. }
  411.  
  412. OpenHandle(base, tail, modes)
  413. char *base;
  414. char *tail;
  415. int modes;
  416. {
  417.     short i;
  418.     int fd;
  419.     char name[1024];
  420.  
  421.     ConcatPath(base, tail, name);
  422.     for (i = 0; i < MAXHANDLES; ++i) {
  423.     if (Handle[i].isopen == 0)
  424.         break;
  425.     }
  426.     if (i == MAXHANDLES)
  427.     return(-1);
  428.     fd = open(name, modes, 0666);
  429.     if (fd < 0 && (modes & O_RDWR) && !(modes & O_CREAT)) {
  430.     modes &= ~O_RDWR;
  431.     fd = open(name, modes);
  432.     }
  433.     Handle[i].name = strcpy(malloc(strlen(name)+1), name);
  434.     Handle[i].fd = fd;
  435. #ifdef DEBUG
  436.     fprintf(stderr, "OpenHandle: %d = open %s %d\n", Handle[i].fd, name,modes);
  437.     fflush(stderr);
  438. #endif
  439.     if (Handle[i].fd < 0)
  440.     return(-1);
  441.     Handle[i].modes = modes;
  442.     Handle[i].remodes= modes & ~(O_TRUNC|O_CREAT);
  443.     Handle[i].isopen = 1;
  444.     return(i);
  445. }
  446.  
  447. CloseHandle(h)
  448. {
  449. #ifdef DEBUG
  450.     fprintf(stderr, " Close Handle %d\n", h);
  451.     fflush(stderr);
  452. #endif
  453.     if (h >= 0 && h < MAXHANDLES && Handle[h].isopen) {
  454.     if (Handle[h].fd >= 0)
  455.         close(Handle[h].fd);
  456.     Handle[h].fd = -1;
  457.     Handle[h].isopen = 0;
  458.     free(Handle[h].name);
  459.     }
  460. }
  461.  
  462. /*
  463.  *  Insert ../ for / at beginning.
  464.  */
  465.  
  466. void
  467. AmigaToUnixPath(buf)
  468. char *buf;
  469. {
  470.     char *base = buf;
  471. #ifdef DEBUG
  472.     fprintf(stderr, "AmigaToUnixPath %s", buf);
  473. #endif
  474.     if (*buf == ':')
  475.     *buf++ = '/';
  476.     while (*buf == '/') {
  477.     bcopy(buf, buf + 2, strlen(buf)+1);
  478.     buf[0] = buf[1] = '.';
  479.     buf += 3;
  480.     }
  481. #ifdef DEBUG
  482.     fprintf(stderr, " TO %s\n", base);
  483.     fflush(stderr);
  484. #endif
  485. }
  486.  
  487. void
  488. ConcatPath(s1, s2, buf)
  489. char *s1, *s2;
  490. char *buf;
  491. {
  492. #ifdef DEBUG
  493.     fprintf(stderr, "ConCatPaths From '%s' '%s'\n", s1, s2);
  494. #endif
  495.     while (strncmp(s2, "../", 3) == 0) {    /* parent */
  496.     ;
  497.     break;
  498.     }
  499.     while (strncmp(s2, "./", 2) == 0) {        /* current */
  500.     s2 += 2;
  501.     }
  502.     if (s2[0] == '/') {
  503.     strcpy(buf, s2);
  504.     return;
  505.     }
  506.     if (s1[0] == 0 && s2[0] == 0) {
  507.     strcpy(buf, ".");
  508.     return;
  509.     }
  510.     if (s1[0] == 0)
  511.     s1 = ".";
  512.     strcpy(buf, s1);
  513.     if (s1[strlen(s1)-1] != '/')
  514.         strcat(buf, "/");
  515.     strcat(buf, s2);
  516. #ifdef DEBUG
  517.     fprintf(stderr, "ConCatPaths to %s\n", buf);
  518.     fflush(stderr);
  519. #endif
  520. }
  521.  
  522. char *
  523. FDName(h)
  524. {
  525. #ifdef DEBUG
  526.     fprintf(stderr, "FDName(%d) =", h);
  527. #endif
  528.     if (h >= 0 && h < MAXHANDLES && Handle[h].isopen) {
  529. #ifdef DEBUG
  530.     fprintf(stderr, "%s\n", Handle[h].name);
  531.         fflush(stderr);
  532. #endif
  533.     return(Handle[h].name);
  534.     }
  535. #ifdef DEBUG
  536.     fprintf(stderr, "??\n");
  537.     fflush(stderr);
  538. #endif
  539.     return(".");
  540. }
  541.  
  542. DupHandle(h)
  543. {
  544.     short n = -1;
  545.     if (h >= 0 && h < MAXHANDLES && Handle[h].isopen)
  546.     n = OpenHandle(".",Handle[h].name, Handle[h].remodes & ~O_RDWR);
  547.     return(n);
  548. }
  549.  
  550. FDHandle(h)
  551. {
  552.     int fd = -1;
  553.     if (h >= 0 && h < MAXHANDLES && Handle[h].isopen) {
  554.     fd = Handle[h].fd;
  555.     if (fd < 0) {
  556.         Handle[h].fd = fd = open(Handle[h].name, Handle[h].remodes, 0666);
  557.         if (fd >= 0 && !(Handle[h].modes & O_APPEND))
  558.         lseek(fd, Handle[h].pos, 0);
  559.     }
  560.     }
  561.     return(fd);
  562. }
  563.  
  564. char *
  565. TailPart(path)
  566. char *path;
  567. {
  568.     register char *ptr = path + strlen(path) - 1;
  569.  
  570.     while (ptr >= path && *ptr != '/')
  571.     --ptr;
  572.     ++ptr;
  573. #ifdef DEBUG
  574.     fprintf(stderr, "TAILPART '%s' -> %s\n", path, ptr);
  575.     fflush(stderr);
  576. #endif
  577.     return(ptr);
  578. }
  579.  
  580. SetDate(date, mtime)
  581. STAMP *date;
  582. time_t mtime;
  583. {
  584.     struct tm *tm = localtime(&mtime);
  585.     long years = tm->tm_year;    /* since 1900    */
  586.     long days;
  587.  
  588.     years += 300;            /* since 1600           */
  589.     days = (years / 400) * 146097;    /* # days every four cents    */
  590.  
  591.     years = years % 400;
  592.  
  593.     /*
  594.      *    First assume a leap year every 4 years, then correct for centuries.
  595.      *    never include the 'current' year in the calculations.  Thus, year 0
  596.      *      (a leap year) is included only if years > 0.
  597.      */
  598.  
  599.     days += years * 365 + ((years+3) / 4);
  600.     
  601.     if (years <= 100)
  602.     ;
  603.     else if (years <= 200)        /* no leap 3 of 4 cent. marks    */
  604.     days -= 1;
  605.     else if (years <= 300)
  606.     days -= 2;
  607.     else
  608.     days -= 3;
  609.     days -= 138062;            /* 1600 -> 1978            */
  610.     date->ds_Days  = days + tm->tm_yday;
  611.     date->ds_Minute= tm->tm_min + tm->tm_hour * 60;
  612.     date->ds_Tick  = tm->tm_sec * 50;
  613. }
  614.  
  615.