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

📄 nfsmount.c

📁 Util-linux 软件包包含许多工具。其中比较重要的是加载、卸载、格式化、分区和管理硬盘驱动器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * nfsmount.c -- Linux NFS mount * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * Wed Feb  8 12:51:48 1995, biro@yggdrasil.com (Ross Biro): allow all port * numbers to be specified on the command line. * * Fri, 8 Mar 1996 18:01:39, Swen Thuemmler <swen@uni-paderborn.de>: * Omit the call to connect() for Linux version 1.3.11 or later. * * Wed Oct  1 23:55:28 1997: Dick Streefland <dick_streefland@tasking.com> * Implemented the "bg", "fg" and "retry" mount options for NFS. * * 1999-02-22 Arkadiusz Mi秌iewicz <misiek@pld.ORG.PL> * - added Native Language Support *  * Modified by Olaf Kirch and Trond Myklebust for new NFS code, * plus NFSv3 stuff. *//* * nfsmount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp */#include "../defines.h"	/* for HAVE_rpcsvc_nfs_prot_h and HAVE_inet_aton */#include <unistd.h>#include <stdio.h>#include <string.h>#include <errno.h>#include <netdb.h>#include <time.h>#include <rpc/rpc.h>#include <rpc/pmap_prot.h>#include <rpc/pmap_clnt.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/utsname.h>#include <sys/stat.h>#include <netinet/in.h>#include <arpa/inet.h>#include "sundries.h"#include "nfsmount.h"#ifdef HAVE_rpcsvc_nfs_prot_h#include <rpcsvc/nfs_prot.h>#else#include <linux/nfs.h>#define nfsstat nfs_stat#endif#include "mount_constants.h"#include "nfs_mount4.h"#include "nls.h"#ifndef NFS_PORT#define NFS_PORT 2049#endif#ifndef NFS_FHSIZE#define NFS_FHSIZE 32#endifstatic char *nfs_strerror(int stat);#define MAKE_VERSION(p,q,r)	(65536*(p) + 256*(q) + (r))#define MAX_NFSPROT ((nfs_mount_version >= 4) ? 3 : 2)static intlinux_version_code(void) {	struct utsname my_utsname;	int p, q, r;	if (uname(&my_utsname) == 0) {		p = atoi(strtok(my_utsname.release, "."));		q = atoi(strtok(NULL, "."));		r = atoi(strtok(NULL, "."));		return MAKE_VERSION(p,q,r);	}	return 0;}/* * Unfortunately, the kernel prints annoying console messages * in case of an unexpected nfs mount version (instead of * just returning some error).  Therefore we'll have to try * and figure out what version the kernel expects. * * Variables: *	NFS_MOUNT_VERSION: these nfsmount sources at compile time *	nfs_mount_version: version this source and running kernel can handle */static intfind_kernel_nfs_mount_version(void) {	static int kernel_version = -1;	int nfs_mount_version = NFS_MOUNT_VERSION;	if (kernel_version == -1)		kernel_version = linux_version_code();	if (kernel_version) {	     if (kernel_version < MAKE_VERSION(2,1,32))		  nfs_mount_version = 1;	     else if (kernel_version < MAKE_VERSION(2,2,18))		  nfs_mount_version = 3;	     else if (kernel_version < MAKE_VERSION(2,3,0))		  nfs_mount_version = 4; /* since 2.2.18pre9 */	     else if (kernel_version < MAKE_VERSION(2,3,99))		  nfs_mount_version = 3;	     else		  nfs_mount_version = 4; /* since 2.3.99pre4 */	}	if (nfs_mount_version > NFS_MOUNT_VERSION)	     nfs_mount_version = NFS_MOUNT_VERSION;	return nfs_mount_version;}static struct pmap *get_mountport(struct sockaddr_in *server_addr,      long unsigned prog,      long unsigned version,      long unsigned proto,      long unsigned port,      int nfs_mount_version){	struct pmaplist *pmap;	static struct pmap p = {0, 0, 0, 0};	if (version > MAX_NFSPROT)		version = MAX_NFSPROT;	if (!prog)		prog = MOUNTPROG;	p.pm_prog = prog;	p.pm_vers = version;	p.pm_prot = proto;	p.pm_port = port;	server_addr->sin_port = PMAPPORT;	pmap = pmap_getmaps(server_addr);	while (pmap) {		if (pmap->pml_map.pm_prog != prog)			goto next;		if (!version && p.pm_vers > pmap->pml_map.pm_vers)			goto next;		if (version > 2 && pmap->pml_map.pm_vers != version)			goto next;		if (version && version <= 2 && pmap->pml_map.pm_vers > 2)			goto next;		if (pmap->pml_map.pm_vers > MAX_NFSPROT ||		    (proto && p.pm_prot && pmap->pml_map.pm_prot != proto) ||		    (port && pmap->pml_map.pm_port != port))			goto next;		memcpy(&p, &pmap->pml_map, sizeof(p));	next:		pmap = pmap->pml_next;	}	if (!p.pm_vers)		p.pm_vers = MOUNTVERS;	if (!p.pm_prot)		p.pm_prot = IPPROTO_TCP;#if 0	if (!p.pm_port) {		p.pm_port = pmap_getport(server_addr, p.pm_prog, p.pm_vers,					 p.pm_prot);	}#endif#if 0#define MOUNTPORT 635	/* HJLu wants to remove all traces of the old default port.	   Are there still people running a mount RPC service on this	   port without having a portmapper? */	if (!p.pm_port)		p.pm_port = MOUNTPORT;#endif	return &p;}int nfsmount(const char *spec, const char *node, int *flags,	     char **extra_opts, char **mount_opts, int *nfs_mount_vers,	     int running_bg){	static char *prev_bg_host;	char hostdir[1024];	CLIENT *mclient;	char *hostname, *dirname, *old_opts, *mounthost = NULL;	char new_opts[1024];	struct timeval total_timeout;	enum clnt_stat clnt_stat;	static struct nfs_mount_data data;	char *opt, *opteq;	int nfs_mount_version;	int val;	struct hostent *hp;	struct sockaddr_in server_addr;	struct sockaddr_in mount_server_addr;	struct pmap *pm_mnt;	int msock, fsock;	struct timeval retry_timeout;	union {		struct fhstatus nfsv2;		struct mountres3 nfsv3;	} status;	struct stat statbuf;	char *s;	int port, mountport, proto, bg, soft, intr;	int posix, nocto, noac, nolock, broken_suid;	int retry, tcp;	int mountprog, mountvers, nfsprog, nfsvers;	int retval;	time_t t;	time_t prevt;	time_t timeout;	/* The version to try is either specified or 0	   In case it is 0 we tell the caller what we tried */	if (!*nfs_mount_vers)		*nfs_mount_vers = find_kernel_nfs_mount_version();	nfs_mount_version = *nfs_mount_vers;	retval = EX_FAIL;	msock = fsock = -1;	mclient = NULL;	if (strlen(spec) >= sizeof(hostdir)) {		fprintf(stderr, _("mount: "				  "excessively long host:dir argument\n"));		goto fail;	}	strcpy(hostdir, spec);	if ((s = strchr(hostdir, ':'))) {		hostname = hostdir;		dirname = s + 1;		*s = '\0';		/* Ignore all but first hostname in replicated mounts		   until they can be fully supported. (mack@sgi.com) */		if ((s = strchr(hostdir, ','))) {			*s = '\0';			fprintf(stderr,				_("mount: warning: "				  "multiple hostnames not supported\n"));		}	} else {		fprintf(stderr,			_("mount: "			  "directory to mount not in host:dir format\n"));		goto fail;	}	server_addr.sin_family = AF_INET;#ifdef HAVE_inet_aton	if (!inet_aton(hostname, &server_addr.sin_addr))#endif	{		if ((hp = gethostbyname(hostname)) == NULL) {			fprintf(stderr, _("mount: can't get address for %s\n"),				hostname);			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);			}			memcpy(&server_addr.sin_addr,			       hp->h_addr, hp->h_length);		}	}	memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr));	/* add IP address to mtab options for use when unmounting */	s = inet_ntoa(server_addr.sin_addr);	old_opts = *extra_opts;	if (!old_opts)		old_opts = "";	if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {		fprintf(stderr, _("mount: "				  "excessively long option argument\n"));		goto fail;	}	sprintf(new_opts, "%s%saddr=%s",		old_opts, *old_opts ? "," : "", s);	*extra_opts = xstrdup(new_opts);	/* Set default options.	 * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to	 * let the kernel decide.	 * timeo is filled in after we know whether it'll be TCP or UDP. */	memset(&data, 0, sizeof(data));	data.retrans	= 3;	data.acregmin	= 3;	data.acregmax	= 60;	data.acdirmin	= 30;	data.acdirmax	= 60;#if NFS_MOUNT_VERSION >= 2	data.namlen	= NAME_MAX;#endif	bg = 0;	soft = 0;	intr = 0;	posix = 0;	nocto = 0;	nolock = 0;	broken_suid = 0;	noac = 0;	retry = 10000;		/* 10000 minutes ~ 1 week */	tcp = 0;	mountprog = MOUNTPROG;	mountvers = 0;	port = 0;	mountport = 0;	nfsprog = NFS_PROGRAM;	nfsvers = 0;	/* parse options */	for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {		if ((opteq = strchr(opt, '='))) {			val = atoi(opteq + 1);				*opteq = '\0';			if (!strcmp(opt, "rsize"))				data.rsize = val;			else if (!strcmp(opt, "wsize"))				data.wsize = val;			else if (!strcmp(opt, "timeo"))				data.timeo = val;			else if (!strcmp(opt, "retrans"))				data.retrans = val;			else if (!strcmp(opt, "acregmin"))				data.acregmin = val;			else if (!strcmp(opt, "acregmax"))				data.acregmax = val;			else if (!strcmp(opt, "acdirmin"))				data.acdirmin = val;			else if (!strcmp(opt, "acdirmax"))				data.acdirmax = val;			else if (!strcmp(opt, "actimeo")) {				data.acregmin = val;				data.acregmax = val;				data.acdirmin = val;				data.acdirmax = val;			}			else if (!strcmp(opt, "retry"))				retry = val;			else if (!strcmp(opt, "port"))				port = val;			else if (!strcmp(opt, "mountport"))			        mountport = val;			else if (!strcmp(opt, "mounthost"))			        mounthost=xstrndup(opteq+1,						   strcspn(opteq+1," \t\n\r,"));			else if (!strcmp(opt, "mountprog"))				mountprog = val;			else if (!strcmp(opt, "mountvers"))				mountvers = val;			else if (!strcmp(opt, "nfsprog"))				nfsprog = val;			else if (!strcmp(opt, "nfsvers") ||				 !strcmp(opt, "vers"))				nfsvers = val;			else if (!strcmp(opt, "proto")) {				if (!strncmp(opteq+1, "tcp", 3))					tcp = 1;				else if (!strncmp(opteq+1, "udp", 3))					tcp = 0;				else					printf(_("Warning: Unrecognized proto= option.\n"));			} else if (!strcmp(opt, "namlen")) {#if NFS_MOUNT_VERSION >= 2				if (nfs_mount_version >= 2)					data.namlen = val;				else#endif					printf(_("Warning: Option namlen is not supported.\n"));			} else if (!strcmp(opt, "addr")) {				/* ignore */;			} else {				printf(_("unknown nfs mount parameter: "					 "%s=%d\n"), opt, val);				goto fail;			}		} else {			val = 1;			if (!strncmp(opt, "no", 2)) {				val = 0;				opt += 2;			}			if (!strcmp(opt, "bg")) 				bg = val;			else if (!strcmp(opt, "fg")) 				bg = !val;			else if (!strcmp(opt, "soft"))				soft = val;			else if (!strcmp(opt, "hard"))				soft = !val;			else if (!strcmp(opt, "intr"))				intr = val;			else if (!strcmp(opt, "posix"))				posix = val;			else if (!strcmp(opt, "cto"))				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 if (!strcmp(opt, "broken_suid")) {				broken_suid = val;			} else {				if (!sloppy) {					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)

⌨️ 快捷键说明

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