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 + -
显示快捷键?