summaryrefslogtreecommitdiffstats
path: root/sys/lib/libsa/nfs.c
diff options
context:
space:
mode:
authorniklas <niklas@openbsd.org>1996-12-08 15:15:44 +0000
committerniklas <niklas@openbsd.org>1996-12-08 15:15:44 +0000
commit79dbd5ceb790c1a6e35c11a8bfd3df05746466e4 (patch)
treecdd73304c6efb8b8c0a428ff7146d6f83a604d24 /sys/lib/libsa/nfs.c
parentinstall -> ${INSTALL}, -c -> ${COPY} (diff)
downloadwireguard-openbsd-79dbd5ceb790c1a6e35c11a8bfd3df05746466e4.tar.xz
wireguard-openbsd-79dbd5ceb790c1a6e35c11a8bfd3df05746466e4.zip
Merge to NetBSD 961207
Diffstat (limited to 'sys/lib/libsa/nfs.c')
-rw-r--r--sys/lib/libsa/nfs.c180
1 files changed, 165 insertions, 15 deletions
diff --git a/sys/lib/libsa/nfs.c b/sys/lib/libsa/nfs.c
index b31ecc8da50..a09d4698d0a 100644
--- a/sys/lib/libsa/nfs.c
+++ b/sys/lib/libsa/nfs.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: nfs.c,v 1.5 1996/10/15 09:58:34 mickey Exp $ */
-/* $NetBSD: nfs.c,v 1.15 1996/05/14 10:28:26 leo Exp $ */
+/* $OpenBSD: nfs.c,v 1.6 1996/12/08 15:15:52 niklas Exp $ */
+/* $NetBSD: nfs.c,v 1.19 1996/10/13 02:29:04 christos Exp $ */
/*-
* Copyright (c) 1993 John Brezak
@@ -38,8 +38,8 @@
#include <netinet/in.h>
#include <netinet/in_systm.h>
-#include <nfs/rpcv2.h>
-#include <nfs/nfsv2.h>
+#include "rpcv2.h"
+#include "nfsv2.h"
#include "stand.h"
#include "net.h"
@@ -82,6 +82,12 @@ struct nfs_read_repl {
u_char data[NFSREAD_SIZE];
};
+struct nfs_readlnk_repl {
+ n_long errno;
+ n_long len;
+ char path[NFS_MAXPATHLEN];
+};
+
struct nfs_iodesc {
struct iodesc *iodesc;
off_t off;
@@ -222,6 +228,51 @@ nfs_lookupfh(d, name, newfd)
}
/*
+ * Get the destination of a symbolic link.
+ */
+int
+nfs_readlink(d, buf)
+ struct nfs_iodesc *d;
+ char *buf;
+{
+ struct {
+ n_long h[RPC_HEADER_WORDS];
+ u_char fh[NFS_FHSIZE];
+ } sdata;
+ struct {
+ n_long h[RPC_HEADER_WORDS];
+ struct nfs_readlnk_repl d;
+ } rdata;
+ ssize_t cc;
+
+#ifdef NFS_DEBUG
+ if (debug)
+ printf("readlink: called\n");
+#endif
+
+ bcopy(d->fh, sdata.fh, NFS_FHSIZE);
+ cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READLINK,
+ sdata.fh, NFS_FHSIZE,
+ &rdata.d, sizeof(rdata.d));
+ if (cc == -1)
+ return (errno);
+
+ if (cc < 4)
+ return (EIO);
+
+ if (rdata.d.errno)
+ return (ntohl(rdata.d.errno));
+
+ rdata.d.len = ntohl(rdata.d.len);
+ if (rdata.d.len > NFS_MAXPATHLEN)
+ return (ENAMETOOLONG);
+
+ bcopy(rdata.d.path, buf, rdata.d.len);
+ buf[rdata.d.len] = 0;
+ return (0);
+}
+
+/*
* Read data from a file.
* Return transfer count or -1 (and set errno)
*/
@@ -330,7 +381,12 @@ nfs_open(path, f)
char *path;
struct open_file *f;
{
- struct nfs_iodesc *newfd;
+ struct nfs_iodesc *newfd, *currfd;
+ register char *cp, *ncp;
+ register int c;
+ char namebuf[NFS_MAXPATHLEN + 1];
+ char linkbuf[NFS_MAXPATHLEN + 1];
+ int nlinks = 0;
int error = 0;
#ifdef NFS_DEBUG
@@ -342,24 +398,118 @@ nfs_open(path, f)
return (ENXIO);
}
- /* allocate file system specific data structure */
- newfd = alloc(sizeof(*newfd));
- newfd->iodesc = nfs_root_node.iodesc;
- newfd->off = 0;
+ currfd = &nfs_root_node;
+ newfd = 0;
+
+ cp = path;
+ while (*cp) {
+ /*
+ * Remove extra separators
+ */
+ while (*cp == '/')
+ cp++;
+
+ if (*cp == '\0')
+ break;
+ /*
+ * Check that current node is a directory.
+ */
+ if (currfd->fa.fa_type != htonl(NFDIR)) {
+ error = ENOTDIR;
+ goto out;
+ }
+
+ /* allocate file system specific data structure */
+ newfd = alloc(sizeof(*newfd));
+ newfd->iodesc = currfd->iodesc;
+ newfd->off = 0;
+
+ /*
+ * Get next component of path name.
+ */
+ {
+ register int len = 0;
+
+ ncp = cp;
+ while ((c = *cp) != '\0' && c != '/') {
+ if (++len > NFS_MAXNAMLEN) {
+ error = ENOENT;
+ goto out;
+ }
+ cp++;
+ }
+ *cp = '\0';
+ }
+
+ /* lookup a file handle */
+ error = nfs_lookupfh(currfd, ncp, newfd);
+ *cp = c;
+ if (error)
+ goto out;
+
+ /*
+ * Check for symbolic link
+ */
+ if (newfd->fa.fa_type == htonl(NFLNK)) {
+ int link_len, len;
+
+ error = nfs_readlink(newfd, linkbuf);
+ if (error)
+ goto out;
+
+ link_len = strlen(linkbuf);
+ len = strlen(cp);
+
+ if (link_len + len > MAXPATHLEN
+ || ++nlinks > MAXSYMLINKS) {
+ error = ENOENT;
+ goto out;
+ }
+
+ bcopy(cp, &namebuf[link_len], len + 1);
+ bcopy(linkbuf, namebuf, link_len);
+
+ /*
+ * If absolute pathname, restart at root.
+ * If relative pathname, restart at parent directory.
+ */
+ cp = namebuf;
+ if (*cp == '/') {
+ if (currfd != &nfs_root_node)
+ free(currfd, sizeof(*currfd));
+ currfd = &nfs_root_node;
+ }
+
+ free(newfd, sizeof(*newfd));
+ newfd = 0;
+
+ continue;
+ }
+
+ if (currfd != &nfs_root_node)
+ free(currfd, sizeof(*currfd));
+ currfd = newfd;
+ newfd = 0;
+ }
+
+ error = 0;
- /* lookup a file handle */
- error = nfs_lookupfh(&nfs_root_node, path, newfd);
+out:
if (!error) {
- f->f_fsdata = (void *)newfd;
+ f->f_fsdata = (void *)currfd;
return (0);
}
-
+
#ifdef NFS_DEBUG
if (debug)
printf("nfs_open: %s lookupfh failed: %s\n",
- path, strerror(error));
+ path, strerror(error));
#endif
- free(newfd, sizeof(*newfd));
+ if (currfd != &nfs_root_node)
+ free(currfd, sizeof(*currfd));
+ if (newfd)
+ free(newfd, sizeof(*newfd));
+
return (error);
}