auto_mount.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 893 行 · 第 1/2 页

C
893
字号
#ifndef lintstatic char *sccsid = "@(#)auto_mount.c	4.6      (ULTRIX)        4/11/91";#endif lint/************************************************************************ *									* *			Copyright (c) 1986 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* *	Portions of this software have been licensed to  *	Digital Equipment Company, Maynard, MA. *	Copyright (c) 1987 Sun Microsystems, Inc.  ALL RIGHTS RESERVED. *//* *	Modification History: *  *	9 Mar 91 -- condylis *		Brought in nfssrc4.1 do_mount() code to solve  *		subdirectory bugs. * *	27 Dec 90 -- condylis *		Fixed bug in creating symbolic link to file system already  *		mounted.  Added storing dev number in filsys structure at *		mount time to prevent having to call getmnt to get it at *		umount time. *		 *	4 Sep 90 -- condylis *		Changed calls to rpc client error routines to use newer *		interface. * *	24 May 90 -- condylis *		Fixed bugs in passing of option flags to mount system *		call. * *      10 Nov 89 -- lebel *              Incorporated direct maps, bugfixes, metacharacter handling  *              and other fun stuff from the reference tape. * 	14 Jun 89 -- condylis *		Added copyright header. * */#include <stdio.h>#include <ctype.h>#include <syslog.h>#include <sys/param.h>#include <sys/errno.h>#include <sys/time.h>#include <sys/stat.h>#include <sys/wait.h>#include <sys/socket.h>#include <sys/signal.h>#include <rpc/rpc.h>#include <rpc/pmap_clnt.h>#include <netdb.h>#include <errno.h>#include "nfs_prot.h"typedef nfs_fh fhandle_t;#include <rpcsvc/mount.h>#define NFSCLIENT#include <sys/mount.h>#include <nfs/nfs_gfs.h>#include <nfs/nfs_clnt.h>#include <nfs/vfs.h>#include "automount.h"#include "mntent.h"#define MAXHOSTS  20struct mapfs *find_server();struct filsys *already_mounted();void addtomtab();char *inet_ntoa();extern int trace;extern int verbose;nfsstatdo_mount(dir, me, rootfs, linkpath)	struct autodir *dir;	struct mapent *me;	struct filsys **rootfs;	char **linkpath;{	char mntpnt[MAXPATHLEN];	static char linkbuf[MAXPATHLEN];	enum clnt_stat pingmount();	struct filsys *fs, *tfs;	struct mapfs *mfs, *rmfs;	struct mapent *m, *mapnext;	nfsstat status = NFSERR_NOENT;	struct in_addr prevhost;	int imadeit;	struct stat stbuf;	char *roothost = "";	*rootfs = NULL;	*linkpath = "";	prevhost.s_addr = (u_long)0;        for (m = me ; m ; m = mapnext) {                mapnext = m->map_next;                tfs = NULL;                mfs = find_server(m, &tfs, m == me, prevhost);                if (mfs == NULL)                        continue;		if (m == me) {                        for (fs = HEAD(struct filsys, fs_q); fs;                                fs = NEXT(struct filsys, fs)) {				for (rmfs = me->map_fs; rmfs; rmfs = rmfs->mfs_next) {					(void) sprintf(mntpnt, "%s%s/%s%s%s", 					tmpdir, dir->dir_name, rmfs->mfs_host, 					me->map_root, m->map_mntpnt);                                	if (strcmp(mntpnt, fs->fs_mntpnt) == 0) {                                        	(void) sprintf(linkbuf, 							"%s%s/%s%s%s",                                                	tmpdir,                                                	dir->dir_name,							rmfs->mfs_host,                                                	me->map_root,                                                	me->map_fs->mfs_subdir);                                        	if (trace > 1)                                                	(void) fprintf(stderr,                                                	"renew link for %s\n",                                                	linkbuf);                                        	*linkpath = linkbuf;                                        	return (NFS_OK);                                	}				}                        }			roothost = mfs->mfs_host;			(void) sprintf(mntpnt, "%s%s/%s%s%s", tmpdir,                        dir->dir_name, mfs->mfs_host, me->map_root, m->map_mntpnt);		} else {			(void) sprintf(mntpnt, "%s%s/%s%s%s", tmpdir,			dir->dir_name, roothost, me->map_root, m->map_mntpnt);		}                /*                 * It may be possible to return a symlink                 * to an existing mount point without                 * actually having to do a mount.                 */                if (me->map_next == NULL && *me->map_mntpnt == '\0') {                        /* Is it my host ? */                        if (mfs->mfs_addr.s_addr == my_addr.s_addr) {                                (void) strcpy(linkbuf, mfs->mfs_dir);                                (void) strcat(linkbuf, mfs->mfs_subdir);                                *linkpath = linkbuf;                                if (trace > 1)                                        (void) fprintf(stderr,                                                "It's on my host\n");                                return (NFS_OK);                        }                        /*                         * An existing mount point ?                         * XXX Note: this is a bit risky - the                         * mount may belong to another automount                         * daemon - it could unmount it anytime and                         * this symlink would then point to an empty                         * or non-existent mount point.                         */                        if (tfs != NULL) {                                if (trace > 1)                                        (void) fprintf(stderr,                                        "already mounted %s:%s on %s (%s)\n",                                        tfs->fs_host, tfs->fs_dir,                                        tfs->fs_mntpnt, tfs->fs_opts);                                (void) strcpy(linkbuf, tfs->fs_mntpnt);                                (void) strcat(linkbuf, mfs->mfs_subdir);                                *linkpath = linkbuf;                                *rootfs = tfs;                                return (NFS_OK);                        }                }                if (nomounts)                        return (NFSERR_PERM);                 /* Create the mount point if necessary */                imadeit = 0;                if (stat(mntpnt, &stbuf) != 0) {                        if (mkdir_r(mntpnt) == 0) {                                imadeit = 1;                        } else {                                if (verbose)                                        syslog(LOG_ERR,                                        "Couldn't create mountpoint %s: %m",                                        mntpnt);                                if (trace > 1)                                        (void) fprintf(stderr,                                        "couldn't create mntpnt %s\n",                                        mntpnt);                                continue;                        }                }                if (pingmount(mfs->mfs_addr) != RPC_SUCCESS) {                        syslog(LOG_ERR, "host %s not responding", mfs->mfs_host) ;			prevhost.s_addr = (u_long)0;                        continue;                }                /*  Now do the mount */                tfs = NULL;                status = nfsmount(mfs->mfs_host, mfs->mfs_addr, mfs->mfs_dir,                                mntpnt, m->map_mntopts, &tfs);                if (status == NFS_OK) {                        if (*rootfs == NULL) {                                *rootfs = tfs;                                (void) sprintf(linkbuf, "%s%s/%s%s%s",                                        tmpdir, dir->dir_name,                                        mfs->mfs_host, me->map_root,                                        mfs->mfs_subdir);                                *linkpath = linkbuf;                        }                        tfs->fs_rootfs = *rootfs;                        prevhost.s_addr = mfs->mfs_addr.s_addr;                } else {                        if (imadeit)                                safe_rmdir(mntpnt);                }        }        if (*rootfs != NULL) {                return (NFS_OK);        }        return (status);}struct mapfs *find_server(me, fsp, rootmount, preferred)	struct mapent *me;	struct filsys **fsp;	int rootmount;	struct in_addr preferred;{	int entrycount, localcount;	struct mapfs *mfs;	struct hostent *hp;	struct in_addr addrs[MAXHOSTS], addr, *addrp, trymany();	/*	 * get addresses & see if any are myself	 * or were mounted from previously in a	 * hierarchical mount.	 */	entrycount = localcount = 0;	for (mfs = me->map_fs; mfs; mfs = mfs->mfs_next) {		if (mfs->mfs_addr.s_addr == 0) {			hp = gethostbyname(mfs->mfs_host);			if (hp)				bcopy(hp->h_addr, (char *)&mfs->mfs_addr,					hp->h_length);		}		if (mfs->mfs_addr.s_addr) {			entrycount++;			if (mfs->mfs_addr.s_addr == my_addr.s_addr)				return mfs;			if (mfs->mfs_addr.s_addr == preferred.s_addr)				return mfs;		}	}	if (entrycount == 0)		return NULL;	/* see if any already mounted */	if (rootmount)	    for (mfs = me->map_fs; mfs; mfs = mfs->mfs_next) {		    if (*fsp = already_mounted(mfs->mfs_host, mfs->mfs_dir,			me->map_mntopts, mfs->mfs_addr)) 			    return mfs;	    }	if (entrycount == 1) 	/* no replication involved */		return me->map_fs;	/* try local net */	addrp = addrs;	for (mfs = me->map_fs; mfs; mfs = mfs->mfs_next) {		if (inet_netof(mfs->mfs_addr) == inet_netof(my_addr)) {			localcount++;			*addrp++ = mfs->mfs_addr;		}	}	if (localcount > 0) {	/* got some */		(*addrp).s_addr = 0;	/* terminate list */		addr = trymany(addrs, mount_timeout / 2);		if (addr.s_addr) {	/* got one */			for (mfs = me->map_fs; mfs; mfs = mfs->mfs_next)			if (addr.s_addr == mfs->mfs_addr.s_addr)				return mfs;		}	}	if (entrycount == localcount)		return NULL;	/* now try them all */	addrp = addrs;	for (mfs = me->map_fs; mfs; mfs = mfs->mfs_next)		*addrp++ = mfs->mfs_addr;	(*addrp).s_addr = 0;	/* terminate list */	addr = trymany(addrs, mount_timeout / 2);	if (addr.s_addr) {	/* got one */		for (mfs = me->map_fs; mfs; mfs = mfs->mfs_next)		if (addr.s_addr == mfs->mfs_addr.s_addr)				return mfs;	}	return NULL;}/* *  If mount table has changed update internal fs info */voidcheck_mtab(){	struct stat stbuf;	struct filsys *fs, *fsnext;	char *index();	int found, has1, has2;	struct hostent *hp;	struct v_fs_data tfs;	struct v_fs_data *buffer = &tfs;	int rtn, start=0;	/* reset the present flags */	for (fs = HEAD(struct filsys, fs_q); fs;	    fs = NEXT(struct filsys, fs))		    fs->fs_present = 0;	/* now see what's been mounted */	while ((rtn = getmnt(&start, buffer, sizeof(struct fs_data),NOSTAT_MANY, NULL)) > 0) {		char *tmphost, *tmppath, *p, tmpc;/* XXX will fix later */		if (buffer->fd_fstype != 0x05)			continue;		p = index(buffer->fd_devname, ':');		if (p == NULL)			continue;		tmpc = *p;		*p = '\0';		tmphost = buffer->fd_devname;		tmppath = p+1;		if (tmppath[0] != '/')			continue;		found = 0;/* lebel - compare other opts too */		for (fs = HEAD(struct filsys, fs_q); fs;			fs = NEXT(struct filsys, fs)) {			if (strcmp(buffer->fd_path, fs->fs_mntpnt) == 0 &&			    strcmp(tmphost, fs->fs_host) == 0 &&			    strcmp(tmppath, fs->fs_dir) == 0 &&			    same_opts(buffer->fd_un.gvfs.mi.mi_optstr, fs->fs_opts)) { 				fs->fs_present = 1;				found++;				break;			}		}		if (!found) {			fs = alloc_fs(tmphost, tmppath,				buffer->fd_path, buffer->fd_un.gvfs.mi.mi_optstr);			if (fs == NULL)				return;			fs->fs_present = 1;			hp = gethostbyname(tmphost);			if (hp != NULL) {				bcopy(hp->h_addr, &fs->fs_addr.sin_addr, hp->h_length);			}		}		*p = tmpc;	}	/* free fs's that are no longer present */	for (fs = HEAD(struct filsys, fs_q); fs; fs = fsnext) {		fsnext = NEXT(struct filsys, fs);		if (!fs->fs_present) {			flush_links(fs);			free_filsys(fs);		}	}}/* * Search the mount table to see if the given file system is already * mounted.  */struct filsys *already_mounted(host, fsname, opts, hostaddr)	char *host;	char *fsname;	char *opts;	struct in_addr hostaddr;{	struct filsys *fs;	struct mntent m1, m2;	int has1, has2;	struct autodir *dir;	int mydir;	check_mtab();	m1.mnt_opts = opts;	for (fs = HEAD(struct filsys, fs_q); fs; fs = NEXT(struct filsys, fs)){		if (strcmp(fsname, fs->fs_dir) != 0)			continue;		if (hostaddr.s_addr != fs->fs_addr.sin_addr.s_addr)			continue;		/*		 * Check it's not on one of my mount points.		 * I might be mounted on top of a previous 

⌨️ 快捷键说明

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