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

📄 nfsmount.c

📁 linux mount的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* vi: set sw=4 ts=4: *//* * 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@misiek.eu.org> * - 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 <unistd.h>#include <stdio.h>#include <string.h>#include <errno.h>#include <netdb.h>#include <sys/socket.h>#include <time.h>#include <sys/utsname.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdlib.h>#include <sys/stat.h>#undef TRUE#undef FALSE#include <rpc/rpc.h>#include <rpc/pmap_prot.h>#include <rpc/pmap_clnt.h>#include <linux/nfs.h>  /* For the kernels nfs stuff */#include "nfsmount.h"#define error_msg(arg...)	fprintf(stderr, arg)#ifndef NFS_FHSIZEstatic const int NFS_FHSIZE = 32;#endif#ifndef NFS_PORTstatic const int NFS_PORT = 2049;#endif/* the bug of tool chain */#define  TOOL_CHAIN#ifdef   TOOL_CHAIN#include <rpc/types.h>#include <rpc/xdr.h>/* * constants specific to the xdr "protocol" */#define XDR_FALSE       ((long) 0)#define XDR_TRUE        ((long) 1)#define LASTUNSIGNED    ((u_int) 0-1)/* * These are the "generic" xdr routines. */bool_t   _xdr_int();#endif     /*TOOL_CHAIN*//* Disable the nls stuff */# undef bindtextdomain# define bindtextdomain(Domain, Directory) /* empty */# undef textdomain# define textdomain(Domain) /* empty */# define _(Text) (Text)# define N_(Text) (Text)static const int MS_MGC_VAL = 0xc0ed0000; /* Magic number indicatng "new" flags */static const int MS_RDONLY = 1;      /* Mount read-only */static const int MS_NOSUID = 2;      /* Ignore suid and sgid bits */static const int MS_NODEV = 4;      /* Disallow access to device special files */static const int MS_NOEXEC = 8;      /* Disallow program execution */static const int MS_SYNCHRONOUS = 16;      /* Writes are synced at once */static const int MS_REMOUNT = 32;      /* Alter flags of a mounted FS */static const int MS_MANDLOCK = 64;      /* Allow mandatory locks on an FS */static const int S_QUOTA = 128;     /* Quota initialized for file/directory/symlink */static const int S_APPEND = 256;     /* Append-only file */static const int S_IMMUTABLE = 512;     /* Immutable file */static const int MS_NOATIME = 1024;    /* Do not update access times. */static const int MS_NODIRATIME = 2048;    /* Do not update directory access times *//* * We want to be able to compile mount on old kernels in such a way * that the binary will work well on more recent kernels. * Thus, if necessary we teach nfsmount.c the structure of new fields * that will come later. * * Moreover, the new kernel includes conflict with glibc includes * so it is easiest to ignore the kernel altogether (at compile time). *//* NOTE: Do not make this into a 'static const int' because the pre-processor * needs to test this value in some #if statements. */#define NFS_MOUNT_VERSION 4struct nfs2_fh {        char                    data[32];};struct nfs3_fh {        unsigned short          size;        unsigned char           data[64];};struct nfs_mount_data {	int		version;		/* 1 */	int		fd;			/* 1 */	struct nfs2_fh	old_root;		/* 1 */	int		flags;			/* 1 */	int		rsize;			/* 1 */	int		wsize;			/* 1 */	int		timeo;			/* 1 */	int		retrans;		/* 1 */	int		acregmin;		/* 1 */	int		acregmax;		/* 1 */	int		acdirmin;		/* 1 */	int		acdirmax;		/* 1 */	struct sockaddr_in addr;		/* 1 */	char		hostname[256];		/* 1 */	int		namlen;			/* 2 */	unsigned int	bsize;			/* 3 */	struct nfs3_fh	root;			/* 4 */};/* bits in the flags field */static const int NFS_MOUNT_SOFT = 0x0001;	/* 1 */static const int NFS_MOUNT_INTR = 0x0002;	/* 1 */static const int NFS_MOUNT_SECURE = 0x0004;	/* 1 */static const int NFS_MOUNT_POSIX = 0x0008;	/* 1 */static const int NFS_MOUNT_NOCTO = 0x0010;	/* 1 */static const int NFS_MOUNT_NOAC = 0x0020;	/* 1 */static const int NFS_MOUNT_TCP = 0x0040;	/* 2 */static const int NFS_MOUNT_VER3 = 0x0080;	/* 3 */static const int NFS_MOUNT_KERBEROS = 0x0100;	/* 3 */static const int NFS_MOUNT_NONLM = 0x0200;	/* 3 */#define UTIL_LINUX_VERSION "2.10m"#define util_linux_version "util-linux-2.10m"#define HAVE_inet_aton#define HAVE_scsi_h#define HAVE_blkpg_h#define HAVE_kd_h#define HAVE_termcap#define HAVE_locale_h#define HAVE_libintl_h#define ENABLE_NLS#define HAVE_langinfo_h#define HAVE_progname#define HAVE_openpty#define HAVE_nanosleep#define HAVE_personality#define HAVE_tm_gmtoffstatic char *nfs_strerror(int status);#define MAKE_VERSION(p,q,r)	(65536*(p) + 256*(q) + (r))#define MAX_NFSPROT ((nfs_mount_version >= 4) ? 3 : 2)static const int EX_FAIL = 32;       /* mount failure */static const int EX_BG = 256;       /* retry in background (internal only) */char *xstrdup (const char *s);char *xstrndup (const char *s, int n);#define MAKE_VERSION(p,q,r)	(65536*(p) + 256*(q) + (r))static intget_kernel_revision(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;}/* * nfs_mount_version according to the sources seen at compile time. */static int nfs_mount_version;/* * 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: *	KERNEL_NFS_MOUNT_VERSION: kernel sources at compile time *	NFS_MOUNT_VERSION: these nfsmount sources at compile time *	nfs_mount_version: version this source and running kernel can handle */static voidfind_kernel_nfs_mount_version(void){	static int kernel_version = 0;	if (kernel_version)		return;	nfs_mount_version = NFS_MOUNT_VERSION; /* default */	kernel_version = get_kernel_revision();	if (kernel_version) {		if (kernel_version < MAKE_VERSION(2,1,32))			nfs_mount_version = 1;		else if (kernel_version < MAKE_VERSION(2,2,18) ||				(kernel_version >=   MAKE_VERSION(2,3,0) &&				 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;}static struct pmap *get_mountport(struct sockaddr_in *server_addr,      long unsigned prog,      long unsigned version,      long unsigned proto,      long unsigned port){struct pmaplist *pmap;static struct pmap p = {0, 0, 0, 0};server_addr->sin_port = PMAPPORT;pmap = pmap_getmaps(server_addr);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;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_port)	p.pm_port = MOUNTPORT;if (!p.pm_prot)	p.pm_prot = IPPROTO_TCP;return &p;}int nfsmount(const char *spec, const char *node, int *flags,	     char **extra_opts, char **mount_opts, int running_bg){	static char *prev_bg_host;	char hostdir[1024];	CLIENT *mclient;	char *hostname;	char *dirname;	char *old_opts;	char *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 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;	int mountport;	int proto;	int bg;	int soft;	int intr;	int posix;	int nocto;	int noac;	int nolock;	int retry;	int tcp;	int mountprog;	int mountvers;	int nfsprog;	int nfsvers;	int retval;	time_t t;	time_t prevt;	time_t timeout;	find_kernel_nfs_mount_version();	retval = EX_FAIL;	msock = fsock = -1;	mclient = NULL;	if (strlen(spec) >= sizeof(hostdir)) {		error_msg("excessively long host:dir argument");		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';			error_msg("warning: multiple hostnames not supported");		}	} else {		error_msg("directory to mount not in host:dir format");		goto fail;	}	server_addr.sin_family = AF_INET;#ifdef HAVE_inet_aton	if (!inet_aton(hostname, &server_addr.sin_addr))#endif	{#ifdef NO_GETHOSTBYNAME		fprintf(stderr, "ERROR (%d): no gethostbyname()\n", __LINE__);#else		if ((hp = gethostbyname(hostname)) == 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);			}			memcpy(&server_addr.sin_addr,			       hp->h_addr, hp->h_length);		}#endif	}	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)) {		error_msg("excessively long option argument");		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;	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"))

⌨️ 快捷键说明

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