Пример #1
0
/*
 * Open a file.
 * return zero or error number
 */
int
nfs_open(char *path, struct open_file *f)
{
	struct nfs_iodesc *newfd, *currfd;
	char namebuf[NFS_MAXPATHLEN + 1], *cp, *ncp;
	char linkbuf[NFS_MAXPATHLEN + 1];
	int nlinks = 0, error = 0, c;

#ifdef NFS_DEBUG
	if (debug)
		printf("nfs_open: %s\n", path);
#endif
	if (nfs_root_node.iodesc == NULL) {
		printf("nfs_open: must mount first.\n");
		return (ENXIO);
	}

	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.
		 */
		{
			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;

out:
	if (!error) {
		f->f_fsdata = (void *)currfd;
		return (0);
	}

#ifdef NFS_DEBUG
	if (debug)
		printf("nfs_open: %s lookupfh failed: %s\n",
		    path, strerror(error));
#endif
	if (currfd != &nfs_root_node)
		free(currfd, sizeof(*currfd));
	if (newfd)
		free(newfd, sizeof(*newfd));

	return (error);
}
Пример #2
0
/*
 * Open a file.
 * return zero or error number
 */
int
nfs_open(const char *upath, struct open_file *f)
{
	struct iodesc *desc;
	struct nfs_iodesc *currfd;
	char buf[2 * NFS_FHSIZE + 3];
	u_char *fh;
	char *cp;
	int i;
#ifndef NFS_NOSYMLINK
	struct nfs_iodesc *newfd;
	struct nfsv2_fattrs *fa;
	char *ncp;
	int c;
	char namebuf[NFS_MAXPATHLEN + 1];
	char linkbuf[NFS_MAXPATHLEN + 1];
	int nlinks = 0;
#endif
	int error;
	char *path;

#ifdef NFS_DEBUG
 	if (debug)
 	    printf("nfs_open: %s (rootpath=%s)\n", upath, rootpath);
#endif
	if (!rootpath[0]) {
		printf("no rootpath, no nfs\n");
		return (ENXIO);
	}

	/*
	 * This is silly - we should look at dv_type but that value is
	 * arch dependant and we can't use it here.
	 */
#ifndef __i386__
	if (strcmp(f->f_dev->dv_name, "net") != 0)
		return(EINVAL);
#else
	if (strcmp(f->f_dev->dv_name, "pxe") != 0)
		return(EINVAL);
#endif

	if (!(desc = socktodesc(*(int *)(f->f_devdata))))
		return(EINVAL);

	/* Bind to a reserved port. */
	desc->myport = htons(--rpc_port);
	desc->destip = rootip;
	if ((error = nfs_getrootfh(desc, rootpath, nfs_root_node.fh)))
		return (error);
	nfs_root_node.fa.fa_type  = htonl(NFDIR);
	nfs_root_node.fa.fa_mode  = htonl(0755);
	nfs_root_node.fa.fa_nlink = htonl(2);
	nfs_root_node.iodesc = desc;

	fh = &nfs_root_node.fh[0];
	buf[0] = 'X';
	cp = &buf[1];
	for (i = 0; i < NFS_FHSIZE; i++, cp += 2)
		sprintf(cp, "%02x", fh[i]);
	sprintf(cp, "X");
	setenv("boot.nfsroot.server", inet_ntoa(rootip), 1);
	setenv("boot.nfsroot.path", rootpath, 1);
	setenv("boot.nfsroot.nfshandle", buf, 1);

	/* Allocate file system specific data structure */
	currfd = malloc(sizeof(*newfd));
	if (currfd == NULL) {
		error = ENOMEM;
		goto out;
	}

#ifndef NFS_NOSYMLINK
	bcopy(&nfs_root_node, currfd, sizeof(*currfd));
	newfd = 0;

	cp = path = strdup(upath);
	if (path == NULL) {
	    error = ENOMEM;
	    goto out;
	}
	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 = malloc(sizeof(*newfd));
		newfd->iodesc = currfd->iodesc;

		/*
		 * Get next component of path name.
		 */
		{
			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 == '/')
				bcopy(&nfs_root_node, currfd, sizeof(*currfd));

			free(newfd);
			newfd = 0;

			continue;
		}

		free(currfd);
		currfd = newfd;
		newfd = 0;
	}

	error = 0;

out:
	free(newfd);
	free(path);
#else
        currfd->iodesc = desc;

        error = nfs_lookupfh(&nfs_root_node, upath, currfd);
#endif
	if (!error) {
		currfd->off = 0;
		f->f_fsdata = (void *)currfd;
		return (0);
	}

#ifdef NFS_DEBUG
	if (debug)
		printf("nfs_open: %s lookupfh failed: %s\n",
		    path, strerror(error));
#endif
	free(currfd);

	return (error);
}