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

📄 nfsmount.c

📁 watchdog source watchdog source
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Header: /cvsroot/watchdog/watchdog/src/nfsmount.c,v 1.2 2006/07/31 09:39:23 meskes Exp $ *//* * 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 <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"#include <linux/nfs.h>#include "mount_constants.h"#include "nfs_mount4.h"#define HAVE_inet_aton#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;}/* * nfs_mount_version according to the sources seen at compile time. */int nfs_mount_version = 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: *	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;	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;}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 broken_suid;	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)) {		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;

⌨️ 快捷键说明

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