⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nfsmount.c

📁 Util-linux 软件包包含许多工具。其中比较重要的是加载、卸载、格式化、分区和管理硬盘驱动器
💻 C
📖 第 1 页 / 共 2 页
字号:
		| (nocto ? NFS_MOUNT_NOCTO : 0)		| (noac ? NFS_MOUNT_NOAC : 0);#if NFS_MOUNT_VERSION >= 2	if (nfs_mount_version >= 2)		data.flags |= (tcp ? NFS_MOUNT_TCP : 0);#endif#if NFS_MOUNT_VERSION >= 3	if (nfs_mount_version >= 3)		data.flags |= (nolock ? NFS_MOUNT_NONLM : 0);#endif#if NFS_MOUNT_VERSION >= 4	if (nfs_mount_version >= 4)		data.flags |= (broken_suid ? NFS_MOUNT_BROKEN_SUID : 0);#endif	if (nfsvers > MAX_NFSPROT) {		fprintf(stderr, "NFSv%d not supported!\n", nfsvers);		return 0;	}	if (mountvers > MAX_NFSPROT) {		fprintf(stderr, "NFSv%d not supported!\n", nfsvers);		return 0;	}	if (nfsvers && !mountvers)		mountvers = (nfsvers < 3) ? 1 : nfsvers;	if (nfsvers && nfsvers < mountvers)		mountvers = nfsvers;	/* Adjust options if none specified */	if (!data.timeo)		data.timeo = tcp ? 70 : 7;#ifdef NFS_MOUNT_DEBUG	printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",	       data.rsize, data.wsize, data.timeo, data.retrans);	printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n",	       data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);	printf("port = %d, bg = %d, retry = %d, flags = %.8x\n",	       port, bg, retry, data.flags);	printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n",	       mountprog, mountvers, nfsprog, nfsvers);	printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n",	       (data.flags & NFS_MOUNT_SOFT) != 0,	       (data.flags & NFS_MOUNT_INTR) != 0,	       (data.flags & NFS_MOUNT_POSIX) != 0,	       (data.flags & NFS_MOUNT_NOCTO) != 0,	       (data.flags & NFS_MOUNT_NOAC) != 0);#if NFS_MOUNT_VERSION >= 2	printf("tcp = %d\n",	       (data.flags & NFS_MOUNT_TCP) != 0);#endif#endif	data.version = nfs_mount_version;	*mount_opts = (char *) &data;	if (*flags & MS_REMOUNT)		return 0;	/*	 * If the previous mount operation on the same host was	 * backgrounded, and the "bg" for this mount is also set,	 * give up immediately, to avoid the initial timeout.	 */	if (bg && !running_bg &&	    prev_bg_host && strcmp(hostname, prev_bg_host) == 0) {		if (retry > 0)			retval = EX_BG;		return retval;	}	/* create mount deamon client */	/* See if the nfs host = mount host. */	if (mounthost) {		if (mounthost[0] >= '0' && mounthost[0] <= '9') {			mount_server_addr.sin_family = AF_INET;			mount_server_addr.sin_addr.s_addr = inet_addr(hostname);		} else {			if ((hp = gethostbyname(mounthost)) == NULL) {				fprintf(stderr, _("mount: can't get address for %s\n"),					mounthost);				goto fail;			} else {				if (hp->h_length > sizeof(struct in_addr)) {					fprintf(stderr,						_("mount: got bad hp->h_length?\n"));					hp->h_length = sizeof(struct in_addr);				}				mount_server_addr.sin_family = AF_INET;				memcpy(&mount_server_addr.sin_addr,				       hp->h_addr, hp->h_length);			}		}	}	/*	 * The following loop implements the mount retries. On the first	 * call, "running_bg" is 0. When the mount times out, and the	 * "bg" option is set, the exit status EX_BG will be returned.	 * For a backgrounded mount, there will be a second call by the	 * child process with "running_bg" set to 1.	 *	 * The case where the mount point is not present and the "bg"	 * option is set, is treated as a timeout. This is done to	 * support nested mounts.	 *	 * The "retry" count specified by the user is the number of	 * minutes to retry before giving up.	 *	 * Only the first error message will be displayed.	 */	retry_timeout.tv_sec = 3;	retry_timeout.tv_usec = 0;	total_timeout.tv_sec = 20;	total_timeout.tv_usec = 0;	timeout = time(NULL) + 60 * retry;	prevt = 0;	t = 30;	val = 1;	for (;;) {		if (bg && stat(node, &statbuf) == -1) {			/* no mount point yet - sleep */			if (running_bg) {				sleep(val);	/* 1, 2, 4, 8, 16, 30, ... */				val *= 2;				if (val > 30)					val = 30;			}		} else {			/* be careful not to use too many CPU cycles */			if (t - prevt < 30)				sleep(30);			pm_mnt = get_mountport(&mount_server_addr,					       mountprog,					       mountvers,					       proto,					       mountport,					       nfs_mount_version);			/* contact the mount daemon via TCP */			mount_server_addr.sin_port = htons(pm_mnt->pm_port);			msock = RPC_ANYSOCK;			switch (pm_mnt->pm_prot) {			case IPPROTO_UDP:				mclient = clntudp_create(&mount_server_addr,							 pm_mnt->pm_prog,							 pm_mnt->pm_vers,							 retry_timeout,							 &msock);				if (mclient)					break;				mount_server_addr.sin_port =					htons(pm_mnt->pm_port);				msock = RPC_ANYSOCK;			case IPPROTO_TCP:				mclient = clnttcp_create(&mount_server_addr,							 pm_mnt->pm_prog,							 pm_mnt->pm_vers,							 &msock, 0, 0);				break;			default:				mclient = 0;			}			if (mclient) {				/* try to mount hostname:dirname */				mclient->cl_auth = authunix_create_default();				/* make pointers in xdr_mountres3 NULL so				 * that xdr_array allocates memory for us				 */				memset(&status, 0, sizeof(status));				if (pm_mnt->pm_vers == 3)					clnt_stat = clnt_call(mclient,						     MOUNTPROC3_MNT,						     (xdrproc_t) xdr_dirpath,						     (caddr_t) &dirname,						     (xdrproc_t) xdr_mountres3,						     (caddr_t) &status,						     total_timeout);				else					clnt_stat = clnt_call(mclient,						     MOUNTPROC_MNT,						     (xdrproc_t) xdr_dirpath,						     (caddr_t) &dirname,						     (xdrproc_t) xdr_fhstatus,						     (caddr_t) &status,						     total_timeout);				if (clnt_stat == RPC_SUCCESS)					break;		/* we're done */#if 0				/* errno? who sets errno? */				/* this fragment breaks bg mounting */				if (errno != ECONNREFUSED) {					clnt_perror(mclient, "mount");					goto fail;	/* don't retry */				}#endif				if (!running_bg && prevt == 0)					clnt_perror(mclient, "mount");				auth_destroy(mclient->cl_auth);				clnt_destroy(mclient);				mclient = 0;				close(msock);			} else {				if (!running_bg && prevt == 0)					clnt_pcreateerror("mount");			}			prevt = t;		}		if (!bg)		        goto fail;		if (!running_bg) {			prev_bg_host = xstrdup(hostname);			if (retry > 0)				retval = EX_BG;			goto fail;		}		t = time(NULL);		if (t >= timeout)			goto fail;	}	nfsvers = (pm_mnt->pm_vers < 2) ? 2 : pm_mnt->pm_vers;	if (nfsvers == 2) {		if (status.nfsv2.fhs_status != 0) {			fprintf(stderr,				"mount: %s:%s failed, reason given by server: %s\n",				hostname, dirname,				nfs_strerror(status.nfsv2.fhs_status));			goto fail;		}		memcpy(data.root.data,		       (char *) status.nfsv2.fhstatus_u.fhs_fhandle,		       NFS_FHSIZE);#if NFS_MOUNT_VERSION >= 4		data.root.size = NFS_FHSIZE;		memcpy(data.old_root.data,		       (char *) status.nfsv2.fhstatus_u.fhs_fhandle,		       NFS_FHSIZE);#endif	} else {#if NFS_MOUNT_VERSION >= 4		fhandle3 *fhandle;		if (status.nfsv3.fhs_status != 0) {			fprintf(stderr,				"mount: %s:%s failed, reason given by server: %s\n",				hostname, dirname,				nfs_strerror(status.nfsv3.fhs_status));			goto fail;		}		fhandle = &status.nfsv3.mountres3_u.mountinfo.fhandle;		memset(data.old_root.data, 0, NFS_FHSIZE);		memset(&data.root, 0, sizeof(data.root));		data.root.size = fhandle->fhandle3_len;		memcpy(data.root.data,		       (char *) fhandle->fhandle3_val,		       fhandle->fhandle3_len);		data.flags |= NFS_MOUNT_VER3;#endif	}	/* create nfs socket for kernel */	if (tcp) {		if (nfs_mount_version < 3) {	     		printf(_("NFS over TCP is not supported.\n"));			goto fail;		}		fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);	} else		fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);	if (fsock < 0) {		perror(_("nfs socket"));		goto fail;	}	if (bindresvport(fsock, 0) < 0) {		perror(_("nfs bindresvport"));		goto fail;	}	if (port == 0) {		server_addr.sin_port = PMAPPORT;		port = pmap_getport(&server_addr, nfsprog, nfsvers,				    tcp ? IPPROTO_TCP : IPPROTO_UDP);#if 1		/* Here we check to see if user is mounting with the		 * tcp option.  If so, and if the portmap returns a		 * '0' for port (service unavailable), we then exit,		 * notifying the user, rather than hanging up mount.		 */		if (port == 0 && tcp == 1) {			perror(_("nfs server reported service unavailable"));			goto fail;		}#endif		if (port == 0)			port = NFS_PORT;#ifdef NFS_MOUNT_DEBUG		else			printf(_("used portmapper to find NFS port\n"));#endif	}#ifdef NFS_MOUNT_DEBUG	printf(_("using port %d for nfs deamon\n"), port);#endif	server_addr.sin_port = htons(port);	/*	 * connect() the socket for kernels 1.3.10 and below only,	 * to avoid problems with multihomed hosts.	 * --Swen	 */	if (linux_version_code() <= 66314	    && connect(fsock, (struct sockaddr *) &server_addr,		       sizeof (server_addr)) < 0) {		perror(_("nfs connect"));		goto fail;	}	/* prepare data structure for kernel */	data.fd = fsock;	memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr));	strncpy(data.hostname, hostname, sizeof(data.hostname));	/* clean up */	auth_destroy(mclient->cl_auth);	clnt_destroy(mclient);	close(msock);	return 0;	/* abort */ fail:	if (msock != -1) {		if (mclient) {			auth_destroy(mclient->cl_auth);			clnt_destroy(mclient);		}		close(msock);	}	if (fsock != -1)		close(fsock);	return retval;}	/* * We need to translate between nfs status return values and * the local errno values which may not be the same. * * Andreas Schwab <schwab@LS5.informatik.uni-dortmund.de>: change errno: * "after #include <errno.h> the symbol errno is reserved for any use, *  it cannot even be used as a struct tag or field name". */#ifndef EDQUOT#define EDQUOT	ENOSPC#endifstatic struct {	enum nfsstat stat;	int errnum;} nfs_errtbl[] = {	{ NFS_OK,		0		},	{ NFSERR_PERM,		EPERM		},	{ NFSERR_NOENT,		ENOENT		},	{ NFSERR_IO,		EIO		},	{ NFSERR_NXIO,		ENXIO		},	{ NFSERR_ACCES,		EACCES		},	{ NFSERR_EXIST,		EEXIST		},	{ NFSERR_NODEV,		ENODEV		},	{ NFSERR_NOTDIR,	ENOTDIR		},	{ NFSERR_ISDIR,		EISDIR		},#ifdef NFSERR_INVAL	{ NFSERR_INVAL,		EINVAL		},	/* that Sun forgot */#endif	{ NFSERR_FBIG,		EFBIG		},	{ NFSERR_NOSPC,		ENOSPC		},	{ NFSERR_ROFS,		EROFS		},	{ NFSERR_NAMETOOLONG,	ENAMETOOLONG	},	{ NFSERR_NOTEMPTY,	ENOTEMPTY	},	{ NFSERR_DQUOT,		EDQUOT		},	{ NFSERR_STALE,		ESTALE		},#ifdef EWFLUSH	{ NFSERR_WFLUSH,	EWFLUSH		},#endif	/* Throw in some NFSv3 values for even more fun (HP returns these) */	{ 71,			EREMOTE		},	{ -1,			EIO		}};static char *nfs_strerror(int stat){	int i;	static char buf[256];	for (i = 0; nfs_errtbl[i].stat != -1; i++) {		if (nfs_errtbl[i].stat == stat)			return strerror(nfs_errtbl[i].errnum);	}	sprintf(buf, _("unknown nfs status return value: %d"), stat);	return buf;}#if 0intmy_getport(struct in_addr server, struct timeval *timeo, ...){        struct sockaddr_in sin;        struct pmap     pmap;        CLIENT          *clnt;        int             sock = RPC_ANYSOCK, port;        pmap.pm_prog = prog;        pmap.pm_vers = vers;        pmap.pm_prot = prot;        pmap.pm_port = 0;        sin.sin_family = AF_INET;        sin.sin_addr = server;        sin.sin_port = htons(111);        clnt = clntudp_create(&sin, 100000, 2, *timeo, &sock);        status = clnt_call(clnt, PMAP_GETPORT,                                &pmap, (xdrproc_t) xdr_pmap,                                &port, (xdrproc_t) xdr_uint);        if (status != SUCCESS) {	     /* natter */                port = 0;        }        clnt_destroy(clnt);        close(sock);        return port;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -