home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * SNFS.C V1.1
- *
- * DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
- *
- * NETWORK FILE SYSTEM SERVER
- *
- * Accepts connections to files or directories & read-write or dir-scan calls.
- */
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/wait.h>
- #include <sys/time.h>
- #include <sys/dir.h>
- #include <sys/file.h>
- #include <sys/resource.h>
- #include <stdio.h>
- #include <errno.h>
- #include <signal.h>
-
- #include "servers.h"
- #include "snfs.h"
-
- /* #define DEBUG */
-
- #define MAXHANDLES 256
-
- char *FDName();
- extern void AmigaToUnixPath();
- extern void ConcatPath();
- extern char *malloc();
- extern char *TailPart();
- extern char *strcpy();
-
- int Chan;
-
- typedef struct {
- short isopen;
- short fd;
- int modes;
- int remodes;
- long pos;
- char *name;
- } HANDLE;
-
- HANDLE Handle[MAXHANDLES];
-
-
- chandler()
- {
- union wait stat;
- struct rusage rus;
- while (wait3(&stat, WNOHANG, &rus) > 0);
- }
-
- void NFs();
-
- main(ac,av)
- char *av[];
- {
- long chann = DListen(PORT_NFS);
- int fd;
- int n;
- char buf[1024];
- extern int errno;
-
- if (av[1])
- chdir(av[1]);
- #ifdef DEBUG
- freopen("NFS", "w", stderr);
- fprintf(stderr, "RUNNING\n");
- fflush(stderr);
- #endif
- signal(SIGCHLD, chandler);
- signal(SIGPIPE, SIG_IGN);
- for (;;) {
- fd = DAccept(chann);
- if (fd < 0) {
- if (errno == EINTR)
- continue;
- break;
- }
- if (fork() == NULL) {
- NFs(fd);
- #ifdef DEBUG
- fprintf(stderr, "CLOSING\n");
- fflush(stderr);
- #endif
- _exit(1);
- }
- close(fd);
- }
- perror("NFS");
- }
-
- void
- NFs(chan)
- int chan;
- {
- OpenHandle("/", "", O_RDONLY); /* root */
- for (;;) {
- unsigned char basebuf[6];
- struct {
- char cmd;
- unsigned char blen;
- unsigned long dlen;
- } Base;
- long bytes;
- union {
- OpOpen Open;
- OpRead Read;
- OpWrite Write;
- OpClose Close;
- OpSeek Seek;
- OpParent Parent;
- OpDelete Delete;
- OpCreateDir CreateDir;
- OpDup Dup;
- OpNextDir NextDir;
- OpRename Rename;
- } R;
- union {
- RtOpen Open;
- RtRead Read;
- RtWrite Write;
- RtSeek Seek;
- RtParent Parent;
- RtDelete Delete;
- RtCreateDir CreateDir;
- RtDup Dup;
- RtNextDir NextDir;
- RtRename Rename;
- } W;
- long h;
- char buf[256];
-
- if (ggread(chan, basebuf, 6) != 6)
- break;
- Base.cmd = basebuf[0];
- Base.blen = basebuf[1];
- Base.dlen = (basebuf[2] << 24) | (basebuf[3] << 16) |(basebuf[4] << 8)|
- basebuf[5];
- #ifdef DEBUG
- fprintf(stderr, "command %02x %ld %ld\n",
- Base.cmd, Base.blen, Base.dlen
- );
- fflush(stderr);
- #endif
- if (ggread(chan, &R, Base.blen) != Base.blen)
- break;
- switch(Base.cmd) {
- case 'M': /* create directory */
- {
- ggread(chan, buf, Base.dlen);
- AmigaToUnixPath(buf);
- mkdir(buf, 0777);
- #ifdef DEBUG
- fprintf(stderr, "MakeDir %s\n", buf);
- fflush(stderr);
- #endif
- }
- R.Open.DirHandle = R.CreateDir.DirHandle;
- /* FALL THROUGH */
- case 'P':
- if (Base.cmd == 'P') {
- char *name = FDName(ntol(R.Parent.Handle));
- short i = strlen(name)-1;
-
- #ifdef DEBUG
- fprintf(stderr, "Parent Dir of: %s\n", name);
- fflush(stderr);
- #endif
-
- if (i >= 0 && name[i] == '/') /* remove tailing /'s */
- --i;
- if (i < 0) {
- W.Open.Handle = lton(-1);
- gwrite(chan, &W.Open, sizeof(W.Open));
- #ifdef DEBUG
- fprintf(stderr, "NO PARENT\n");
- fflush(stderr);
- #endif
- break;
- }
- while (i >= 0 && name[i] != '/') /* remove name */
- --i;
- while (i >= 0 && name[i] == '/') /* remove tailing /'s */
- --i;
- ++i;
- if (i == 0) { /* at root */
- buf[i++] = '/';
- }
- strncpy(buf, name, i);
- buf[i] = 0;
- #ifdef DEBUG
- fprintf(stderr, "Parent Exists: %s\n", buf);
- fflush(stderr);
- #endif
- R.Open.DirHandle = lton(0);
- }
- R.Open.Modes = lton(1005);
- /* FALL THROUGH */
- case 'O': /* open */
- if (Base.cmd == 'O') {
- ggread(chan, buf, Base.dlen);
- AmigaToUnixPath(buf);
- #ifdef DEBUG
- fprintf(stderr, "OPEN: %s %d\n", buf, Base.dlen);
- fflush(stderr);
- #endif
- }
- if (ntol(R.Open.Modes) == 1006)
- h = OpenHandle(FDName(ntol(R.Open.DirHandle)),buf,
- O_CREAT|O_TRUNC|O_RDWR
- );
- else
- h = OpenHandle(FDName(ntol(R.Open.DirHandle)),buf, O_RDWR);
- #ifdef DEBUG
- fprintf(stderr, "Open h = %d name = %s modes=%d\n",
- h, buf, R.Open.Modes
- );
- fflush(stderr);
- #endif
- if (h >= 0) {
- struct stat stat;
- if (fstat(FDHandle(h), &stat) < 0)
- perror("fstat");
- W.Open.Handle = lton(h);
- W.Open.Prot = lton(0);
- W.Open.Type = lton((stat.st_mode & S_IFDIR) ? 1 : -1);
- #ifdef DEBUG
- fprintf(stderr, "fstat type %d\n", W.Open.Type);
- fflush(stderr);
- #endif
- W.Open.Size = lton(stat.st_size);
- SetDate(&W.Open.Date, stat.st_mtime);
- gwrite(chan, &W.Open, sizeof(W.Open));
- if (Base.cmd == 'P') { /* tag name */
- char *tail = TailPart(buf);
- unsigned char c = strlen(tail) + 1;
-
- gwrite(chan, &c, 1);
- gwrite(chan, tail, c);
- }
- } else {
- W.Open.Handle = lton(-1);
- gwrite(chan, &W.Open, sizeof(W.Open));
- }
- break;
- case 'N': /* next directory. Scan beg. at index */
- {
- DIR *dir = opendir(FDName(ntol(R.NextDir.Handle)));
- struct stat sbuf;
- struct direct *dp;
- long index = 0;
- char buf[1024];
-
- while (dir && index <= ntol(R.NextDir.Index) + 2) {
- if ((dp = readdir(dir)) == NULL)
- break;
- ++index;
- }
- if (dir)
- closedir(dir);
- if (index <= ntol(R.NextDir.Index) + 2) {
- W.Open.Handle = lton(-1);
- } else {
- W.Open.Handle = lton(index);
- strcpy(buf, FDName(ntol(R.NextDir.Handle)));
- strcat(buf, "/");
- strcat(buf, dp->d_name);
- stat(buf, &sbuf);
- W.Open.Prot = lton(0);
- W.Open.Type = lton((sbuf.st_mode & S_IFDIR) ? 1 : -1);
- #ifdef DEBUG
- fprintf(stderr, "fstat type %d\n", W.Open.Type);
- fflush(stderr);
- #endif
- W.Open.Size = lton(sbuf.st_size);
- SetDate(&W.Open.Date, sbuf.st_mtime);
- }
- gwrite(chan, &W.Open, sizeof(W.Open));
- if (ntol(W.Open.Handle) >= 0) {
- unsigned char len = strlen(dp->d_name) + 1;
- gwrite(chan, &len, 1);
- gwrite(chan, dp->d_name, len);
- }
- }
- break;
- case 'r': /* RENAME */
- {
- char tmp1[512];
- char tmp2[512];
- char buf1[1024];
- char buf2[1024];
-
- ggread(chan, buf, Base.dlen);
- strcpy(tmp1, buf);
- strcpy(tmp2, buf + strlen(buf) + 1);
- AmigaToUnixPath(tmp1);
- AmigaToUnixPath(tmp2);
- ConcatPath(FDName(ntol(R.Rename.DirHandle1)), tmp1, buf1);
- ConcatPath(FDName(ntol(R.Rename.DirHandle2)), tmp2, buf2);
- #ifdef DEBUG
- fprintf(stderr, "Rename %s to %s\n", buf1, buf2);
- fflush(stderr);
- #endif
- if (rename(buf1, buf2) < 0)
- W.Rename.Error = lton(1);
- else
- W.Rename.Error = lton(0);
- gwrite(chan, &W.Rename.Error, sizeof(W.Rename.Error));
- }
- break;
- case 'd': /* DUP */
- h = DupHandle(ntol(R.Dup.Handle));
- if (h >= 0) {
- struct stat stat;
- if (fstat(FDHandle(h), &stat) < 0)
- perror("fstat");
- W.Open.Handle = lton(h);
- W.Open.Prot = lton(0);
- W.Open.Type = lton((stat.st_mode & S_IFDIR) ? 1 : -1);
- #ifdef DEBUG
- fprintf(stderr, "fstat type %d\n", W.Open.Type);
- fflush(stderr);
- #endif
- W.Open.Size = lton(stat.st_size);
- SetDate(&W.Open.Date, stat.st_mtime);
- } else {
- W.Open.Handle = lton(-1);
- }
- gwrite(chan, &W.Dup, sizeof(W.Dup));
- break;
- case 'R': /* READ */
- {
- int fd = FDHandle(ntol(R.Read.Handle));
- char *buf = malloc(ntol(R.Read.Bytes));
-
- W.Read.Bytes = lton(read(fd, buf, ntol(R.Read.Bytes)));
- #ifdef DEBUG
- fprintf(stderr, "h=%d fd %d Read %d Result=%d\n",
- R.Read.Handle, fd, R.Read.Bytes, W.Read.Bytes
- );
- fflush(stderr);
- #endif
- gwrite(chan, &W.Read, sizeof(W.Read));
- if (ntol(W.Read.Bytes) > 0)
- gwrite(chan, buf, ntol(W.Read.Bytes));
- free(buf);
- }
- break;
- case 'W':
- {
- int fd = FDHandle(ntol(R.Write.Handle));
- char *buf = malloc(ntol(R.Write.Bytes));
- if (ggread(chan,buf,ntol(R.Write.Bytes))!=ntol(R.Write.Bytes))
- break;
- W.Write.Bytes = lton(write(fd, buf, ntol(R.Write.Bytes)));
- #ifdef DEBUG
- fprintf(stderr, "h=%d fd %d Write %d Result=%d\n",
- R.Write.Handle, fd, R.Write.Bytes, W.Write.Bytes
- );
- fflush(stderr);
- #endif
- gwrite(chan, &W.Write, sizeof(W.Write));
- free(buf);
- }
- break;
- case 'C':
- {
- CloseHandle(ntol(R.Close.Handle));
- }
- break;
- case 'S':
- {
- int fd = FDHandle(ntol(R.Seek.Handle));
- W.Seek.OldOffset = lton(lseek(fd, 0, 1));
- W.Seek.NewOffset = lton(lseek(fd, ntol(R.Seek.Offset),
- ntol(R.Seek.How)));
- #ifdef DEBUG
- fprintf(stderr, "h %d SEEK %d %d %d result = %d\n",
- R.Seek.Handle, fd, R.Seek.Offset, R.Seek.How,
- W.Seek.NewOffset
- );
- fflush(stderr);
- #endif
- gwrite(chan, &W.Seek, sizeof(W.Seek));
- }
- break;
- case 'D':
- {
- char buf2[1024];
-
- ggread(chan, buf, Base.dlen); /* get name to delete */
- AmigaToUnixPath(buf);
- ConcatPath(FDName(ntol(R.Delete.DirHandle)), buf, buf2);
-
- unlink(buf2);
- rmdir(buf2);
- #ifdef DEBUG
- fprintf(stderr, "Delete %s\n", buf2);
- fflush(stderr);
- #endif
- W.Delete.Error = lton(0);
- gwrite(chan, &W.Delete, sizeof(W.Delete));
- }
- break;
- default:
- exit(1);
- break;
- }
- }
- }
-
- OpenHandle(base, tail, modes)
- char *base;
- char *tail;
- int modes;
- {
- short i;
- int fd;
- char name[1024];
-
- ConcatPath(base, tail, name);
- for (i = 0; i < MAXHANDLES; ++i) {
- if (Handle[i].isopen == 0)
- break;
- }
- if (i == MAXHANDLES)
- return(-1);
- fd = open(name, modes, 0666);
- if (fd < 0 && (modes & O_RDWR) && !(modes & O_CREAT)) {
- modes &= ~O_RDWR;
- fd = open(name, modes);
- }
- Handle[i].name = strcpy(malloc(strlen(name)+1), name);
- Handle[i].fd = fd;
- #ifdef DEBUG
- fprintf(stderr, "OpenHandle: %d = open %s %d\n", Handle[i].fd, name,modes);
- fflush(stderr);
- #endif
- if (Handle[i].fd < 0)
- return(-1);
- Handle[i].modes = modes;
- Handle[i].remodes= modes & ~(O_TRUNC|O_CREAT);
- Handle[i].isopen = 1;
- return(i);
- }
-
- CloseHandle(h)
- {
- #ifdef DEBUG
- fprintf(stderr, " Close Handle %d\n", h);
- fflush(stderr);
- #endif
- if (h >= 0 && h < MAXHANDLES && Handle[h].isopen) {
- if (Handle[h].fd >= 0)
- close(Handle[h].fd);
- Handle[h].fd = -1;
- Handle[h].isopen = 0;
- free(Handle[h].name);
- }
- }
-
- /*
- * Insert ../ for / at beginning.
- */
-
- void
- AmigaToUnixPath(buf)
- char *buf;
- {
- char *base = buf;
- #ifdef DEBUG
- fprintf(stderr, "AmigaToUnixPath %s", buf);
- #endif
- if (*buf == ':')
- *buf++ = '/';
- while (*buf == '/') {
- bcopy(buf, buf + 2, strlen(buf)+1);
- buf[0] = buf[1] = '.';
- buf += 3;
- }
- #ifdef DEBUG
- fprintf(stderr, " TO %s\n", base);
- fflush(stderr);
- #endif
- }
-
- void
- ConcatPath(s1, s2, buf)
- char *s1, *s2;
- char *buf;
- {
- #ifdef DEBUG
- fprintf(stderr, "ConCatPaths From '%s' '%s'\n", s1, s2);
- #endif
- while (strncmp(s2, "../", 3) == 0) { /* parent */
- ;
- break;
- }
- while (strncmp(s2, "./", 2) == 0) { /* current */
- s2 += 2;
- }
- if (s2[0] == '/') {
- strcpy(buf, s2);
- return;
- }
- if (s1[0] == 0 && s2[0] == 0) {
- strcpy(buf, ".");
- return;
- }
- if (s1[0] == 0)
- s1 = ".";
- strcpy(buf, s1);
- if (s1[strlen(s1)-1] != '/')
- strcat(buf, "/");
- strcat(buf, s2);
- #ifdef DEBUG
- fprintf(stderr, "ConCatPaths to %s\n", buf);
- fflush(stderr);
- #endif
- }
-
- char *
- FDName(h)
- {
- #ifdef DEBUG
- fprintf(stderr, "FDName(%d) =", h);
- #endif
- if (h >= 0 && h < MAXHANDLES && Handle[h].isopen) {
- #ifdef DEBUG
- fprintf(stderr, "%s\n", Handle[h].name);
- fflush(stderr);
- #endif
- return(Handle[h].name);
- }
- #ifdef DEBUG
- fprintf(stderr, "??\n");
- fflush(stderr);
- #endif
- return(".");
- }
-
- DupHandle(h)
- {
- short n = -1;
- if (h >= 0 && h < MAXHANDLES && Handle[h].isopen)
- n = OpenHandle(".",Handle[h].name, Handle[h].remodes & ~O_RDWR);
- return(n);
- }
-
- FDHandle(h)
- {
- int fd = -1;
- if (h >= 0 && h < MAXHANDLES && Handle[h].isopen) {
- fd = Handle[h].fd;
- if (fd < 0) {
- Handle[h].fd = fd = open(Handle[h].name, Handle[h].remodes, 0666);
- if (fd >= 0 && !(Handle[h].modes & O_APPEND))
- lseek(fd, Handle[h].pos, 0);
- }
- }
- return(fd);
- }
-
- char *
- TailPart(path)
- char *path;
- {
- register char *ptr = path + strlen(path) - 1;
-
- while (ptr >= path && *ptr != '/')
- --ptr;
- ++ptr;
- #ifdef DEBUG
- fprintf(stderr, "TAILPART '%s' -> %s\n", path, ptr);
- fflush(stderr);
- #endif
- return(ptr);
- }
-
- SetDate(date, mtime)
- STAMP *date;
- time_t mtime;
- {
- struct tm *tm = localtime(&mtime);
- long years = tm->tm_year; /* since 1900 */
- long days;
-
- years += 300; /* since 1600 */
- days = (years / 400) * 146097; /* # days every four cents */
-
- years = years % 400;
-
- /*
- * First assume a leap year every 4 years, then correct for centuries.
- * never include the 'current' year in the calculations. Thus, year 0
- * (a leap year) is included only if years > 0.
- */
-
- days += years * 365 + ((years+3) / 4);
-
- if (years <= 100)
- ;
- else if (years <= 200) /* no leap 3 of 4 cent. marks */
- days -= 1;
- else if (years <= 300)
- days -= 2;
- else
- days -= 3;
- days -= 138062; /* 1600 -> 1978 */
- date->ds_Days = lton(days + tm->tm_yday);
- date->ds_Minute= lton(tm->tm_min + tm->tm_hour * 60);
- date->ds_Tick = lton(tm->tm_sec * 50);
- }
-
- long
- ntol(n)
- unsigned long n;
- {
- unsigned char n0, n1, n2, n3;
-
- n0 = n >> 24;
- n1 = n >> 16;
- n2 = n >> 8;
- n3 = n;
-
- return(n0 | (n1 << 8) | (n2 << 16) | (n3 << 24));
- }
-
- long
- lton(n)
- unsigned long n;
- {
- unsigned char n0, n1, n2, n3;
-
- n0 = n >> 24;
- n1 = n >> 16;
- n2 = n >> 8;
- n3 = n;
-
- return(n0 | (n1 << 8) | (n2 << 16) | (n3 << 24));
- }
-
-