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

📄 nfsmount.c

📁 linux mount的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
				nocto = !val;			else if (!strcmp(opt, "ac"))				noac = !val;			else if (!strcmp(opt, "tcp"))				tcp = val;			else if (!strcmp(opt, "udp"))				tcp = !val;			else if (!strcmp(opt, "lock")) {				if (nfs_mount_version >= 3)					nolock = !val;				else					printf(_("Warning: option nolock is not supported.\n"));			} else {				printf(_("unknown nfs mount option: "					   "%s%s\n"), val ? "" : "no", opt);				goto fail;			}		}	}	proto = (tcp) ? IPPROTO_TCP : IPPROTO_UDP;	data.flags = (soft ? NFS_MOUNT_SOFT : 0)		| (intr ? NFS_MOUNT_INTR : 0)		| (posix ? NFS_MOUNT_POSIX : 0)		| (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 (nfsvers > MAX_NFSPROT) {		error_msg("NFSv%d not supported!", nfsvers);		return 0;	}	if (mountvers > MAX_NFSPROT) {		error_msg("NFSv%d not supported!", 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 {#ifdef NO_GETHOSTBYNAME		  fprintf(stderr, "ERROR (%d): no gethostbyname()\n", __LINE__);#else		  if ((hp = gethostbyname(mounthost)) == NULL) {			  error_msg("can't get address for %s", hostname);			  goto fail;		  } else {			  if (hp->h_length > sizeof(struct in_addr)) {				  error_msg("got bad hp->h_length?");				  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);		  }#endif	  }	}	/*	 * 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) {			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);			/* 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 (errno != ECONNREFUSED) {					clnt_perror(mclient, "mount");					goto fail;	/* don't retry */				}				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) {			error_msg("%s:%s failed, reason given by server: %s",				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 *my_fhandle;		if (status.nfsv3.fhs_status != 0) {			error_msg("%s:%s failed, reason given by server: %s",				hostname, dirname,				nfs_strerror(status.nfsv3.fhs_status));			goto fail;		}		my_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 = my_fhandle->fhandle3_len;		memcpy(data.root.data,		       (char *) my_fhandle->fhandle3_val,		       my_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 (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 (get_kernel_revision() <= 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 nfs_stat 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 status){	int i;	static char buf[256];	for (i = 0; nfs_errtbl[i].stat != -1; i++) {		if (nfs_errtbl[i].stat == status)			return strerror(nfs_errtbl[i].errnum);	}	sprintf(buf, _("unknown nfs status return value: %d"), status);	return buf;}static bool_txdr_fhandle (XDR *xdrs, fhandle objp){	//register int32_t *buf;	 if (!xdr_opaque (xdrs, objp, FHSIZE))		 return FALSE;	return TRUE;}bool_txdr_fhstatus (XDR *xdrs, fhstatus *objp){	//register int32_t *buf;	 if (!xdr_u_int (xdrs, &objp->fhs_status))		 return FALSE;	switch (objp->fhs_status) {	case 0:		 if (!xdr_fhandle (xdrs, objp->fhstatus_u.fhs_fhandle))			 return FALSE;		break;	default:		break;	}	return TRUE;}bool_txdr_dirpath (XDR *xdrs, dirpath *objp){	//register int32_t *buf;	 if (!xdr_string (xdrs, objp, MNTPATHLEN))		 return FALSE;	return TRUE;}bool_txdr_fhandle3 (XDR *xdrs, fhandle3 *objp){	//register int32_t *buf;	 if (!xdr_bytes (xdrs, (char **)&objp->fhandle3_val, (u_int *) &objp->fhandle3_len, FHSIZE3))		 return FALSE;	return TRUE;}#ifdef TOOL_CHAIN/* * XDR integers */bool_t_xdr_int(xdrs, ip)     XDR *xdrs;     int *ip;{#ifdef lint  (void) (xdr_short(xdrs, (short *)ip));  return (xdr_long(xdrs, (long *)ip));#else  if (sizeof (int) == sizeof (long)) {    return (xdr_long(xdrs, (long *)ip));  } else {    return (xdr_short(xdrs, (short *)ip));  }#endif}#endif   /* TOOL_CHAIN */bool_txdr_mountres3_ok (XDR *xdrs, mountres3_ok *objp){	//register int32_t *buf;	 if (!xdr_fhandle3 (xdrs, &objp->fhandle))		 return FALSE;	 if (!xdr_array (xdrs, (char **)&objp->auth_flavours.auth_flavours_val, (u_int *) &objp->auth_flavours.auth_flavours_len, ~0,			 sizeof (int), (xdrproc_t) _xdr_int))   /* xdr_int --> _xdr_int */		 return FALSE;	return TRUE;}bool_txdr_mountstat3 (XDR *xdrs, mountstat3 *objp){	//register int32_t *buf;	 if (!xdr_enum (xdrs, (enum_t *) objp))		 return FALSE;	return TRUE;}bool_txdr_mountres3 (XDR *xdrs, mountres3 *objp){	//register int32_t *buf;	 if (!xdr_mountstat3 (xdrs, &objp->fhs_status))		 return FALSE;	switch (objp->fhs_status) {	case MNT_OK:		 if (!xdr_mountres3_ok (xdrs, &objp->mountres3_u.mountinfo))			 return FALSE;		break;	default:		break;	}	return TRUE;}

⌨️ 快捷键说明

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