Exemplo n.º 1
0
static void
exports_update_one(nfs_export *exp, int verbose)
{
		/* check mountpoint option */
	if (exp->m_mayexport &&
	    exp->m_export.e_mountpoint &&
	    !is_mountpoint(exp->m_export.e_mountpoint[0]?
			   exp->m_export.e_mountpoint:
			   exp->m_export.e_path)) {
		printf("%s not exported as %s not a mountpoint.\n",
		       exp->m_export.e_path, exp->m_export.e_mountpoint);
		exp->m_mayexport = 0;
	}
	if (exp->m_mayexport && ((exp->m_exported<1) || exp->m_changed)) {
		if (verbose)
			printf("%sexporting %s:%s to kernel\n",
			       exp->m_exported ?"re":"",
			       exp->m_client->m_hostname,
			       exp->m_export.e_path);
		if (!export_export(exp))
			error(exp, errno);
	}
	if (exp->m_exported && ! exp->m_mayexport) {
		if (verbose)
			printf("unexporting %s:%s from kernel\n",
			       exp->m_client->m_hostname,
			       exp->m_export.e_path);
		if (!export_unexport(exp))
			error(exp, errno);
	}
}
Exemplo n.º 2
0
static struct nfs_fh_len *
get_rootfh(struct svc_req *rqstp, dirpath *path, nfs_export **expret,
		mountstat3 *error, int v3)
{
	struct sockaddr_in *sin = nfs_getrpccaller_in(rqstp->rq_xprt);
	struct stat	stb, estb;
	nfs_export	*exp;
	struct nfs_fh_len *fh;
	char		rpath[MAXPATHLEN+1];
	char		*p = *path;

	if (*p == '\0')
		p = "/";

	/* Reload /var/lib/nfs/etab if necessary */
	auth_reload();

	/* Resolve symlinks */
	if (realpath(p, rpath) != NULL) {
		rpath[sizeof (rpath) - 1] = '\0';
		p = rpath;
	}

	/* Now authenticate the intruder... */
	exp = auth_authenticate("mount", sin, p);
	if (!exp) {
		*error = NFSERR_ACCES;
		return NULL;
	}
	if (stat(p, &stb) < 0) {
		xlog(L_WARNING, "can't stat exported dir %s: %s",
				p, strerror(errno));
		if (errno == ENOENT)
			*error = NFSERR_NOENT;
		else
			*error = NFSERR_ACCES;
		return NULL;
	}
	if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) {
		xlog(L_WARNING, "%s is not a directory or regular file", p);
		*error = NFSERR_NOTDIR;
		return NULL;
	}
	if (stat(exp->m_export.e_path, &estb) < 0) {
		xlog(L_WARNING, "can't stat export point %s: %s",
		     p, strerror(errno));
		*error = NFSERR_NOENT;
		return NULL;
	}
	if (estb.st_dev != stb.st_dev
		   && (!new_cache
			   || !(exp->m_export.e_flags & NFSEXP_CROSSMOUNT))) {
		xlog(L_WARNING, "request to export directory %s below nearest filesystem %s",
		     p, exp->m_export.e_path);
		*error = NFSERR_ACCES;
		return NULL;
	}
	if (exp->m_export.e_mountpoint &&
		   !is_mountpoint(exp->m_export.e_mountpoint[0]?
				  exp->m_export.e_mountpoint:
				  exp->m_export.e_path)) {
		xlog(L_WARNING, "request to export an unmounted filesystem: %s",
		     p);
		*error = NFSERR_NOENT;
		return NULL;
	}

	if (new_cache) {
		/* This will be a static private nfs_export with just one
		 * address.  We feed it to kernel then extract the filehandle,
		 * 
		 */

		if (cache_export(exp, p)) {
			*error = NFSERR_ACCES;
			return NULL;
		}
		fh = cache_get_filehandle(exp, v3?64:32, p);
		if (fh == NULL) {
			*error = NFSERR_ACCES;
			return NULL;
		}
	} else {
		int did_export = 0;
	retry:
		if (exp->m_exported<1) {
			export_export(exp);
			did_export = 1;
		}
		if (!exp->m_xtabent)
			xtab_append(exp);

		if (v3)
			fh = getfh_size ((struct sockaddr *) sin, p, 64);
		if (!v3 || (fh == NULL && errno == EINVAL)) {
			/* We first try the new nfs syscall. */
			fh = getfh ((struct sockaddr *) sin, p);
			if (fh == NULL && errno == EINVAL)
				/* Let's try the old one. */
				fh = getfh_old ((struct sockaddr *) sin,
						stb.st_dev, stb.st_ino);
		}
		if (fh == NULL && !did_export) {
			exp->m_exported = 0;
			goto retry;
		}

		if (fh == NULL) {
			xlog(L_WARNING, "getfh failed: %s", strerror(errno));
			*error = NFSERR_ACCES;
			return NULL;
		}
	}
	*error = NFS_OK;
	mountlist_add(inet_ntoa(sin->sin_addr), p);
	if (expret)
		*expret = exp;
	return fh;
}