📄 adm.c
字号:
/* $Id: adm.C,v 1.6 2001/09/20 06:21:25 dm Exp $ *//* * * Copyright (C) 2001 David Mazieres (dm@uun.org) * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * */#include "getfh3.h"#include "classfs_prot.h"#include "nfsmounter.h"#include "classfsd.h"#include "rxx.h"int ping_timeout = 600;class cfsadm;qhash<str, ref<cfsadm> > &fstab = *New qhash<str, ref<cfsadm> >;ptr<asrv> rootsrv;AUTH *myauth = authunix_create_realids ();struct pinger { const sockaddr_in sin; cfsadm *const cfsp; time_t lastping; timecb_t *wait; callbase *cbase; pinger (cfsadm *cfsp, const sockaddr_in &sin); ~pinger (); void pinged (clnt_stat stat); void waitcb ();};class cfsadm : public virtual refcount { authunix_parms *aup; ptr <axprt_unix> x; ptr <asrv> s; void mount (svccb *sbp); void mounted (svccb *sbp, ref<mountres> resp, sockaddr_in sin, clnt_stat err); void dispatch (svccb *sbp);protected: cfsadm (ref<axprt_unix> x, const authunix_parms *aup); PRIVDEST ~cfsadm ();public: qhash<str, ref<pinger> > mps; void kill () { if (x) dispatch (NULL); } static void alloc (ptr<axprt_unix> x, const authunix_parms *aup) { if (x) vNew refcounted<cfsadm> (x, aup); }};pinger::pinger (cfsadm *c, const sockaddr_in &s) : sin (s), cfsp (c), wait (NULL), cbase (NULL){ pinged (RPC_SUCCESS);}pinger::~pinger (){ timecb_remove (wait); if (cbase) cbase->cancel ();}voidpinger::pinged (clnt_stat stat){ cbase = NULL; if (!stat) lastping = timenow; if (ping_timeout && timenow > lastping + ping_timeout) cfsp->kill (); else wait = delaycb (60, wrap (this, &pinger::waitcb));}voidpinger::waitcb (){ wait = NULL; cbase = udpclnt->call (NFSPROC3_NULL, NULL, NULL, wrap (this, &pinger::pinged), myauth, xdr_void, xdr_void, nfs_program_3.progno, nfs_program_3.versno, (sockaddr *) &sin);}cfsadm::cfsadm (ref<axprt_unix> xx, const authunix_parms *au) : x (xx), s (asrv::alloc (x, classfs_prog_1, wrap (this, &cfsadm::dispatch))){ x->allow_recvfd = true; aup = static_cast<authunix_parms *> (xmalloc (sizeof (*aup))); *aup = *au; *reinterpret_cast<void **> (&aup->aup_gids) = xmalloc (aup->aup_len * sizeof (aup->aup_gids[0])); memcpy (aup->aup_gids, au->aup_gids, aup->aup_len * sizeof (aup->aup_gids[0])); aup->aup_machname = "localhost"; refcount_inc ();}cfsadm::~cfsadm (){ xfree (aup->aup_gids); xfree (aup);}voidcfsadm::mount (svccb *sbp){ static rxx nameok ("\\w[\\w\\.\\-]*"); classfs_mount_arg *arg = sbp->template getarg<classfs_mount_arg> (); int fd = x->recvfd (); if (fd < 0) { sbp->replyref (EBADF); return; } sockaddr_in sin; socklen_t len = sizeof (sin); if (getsockname (fd, (sockaddr *) &sin, &len) < 0) { close (fd); sbp->replyref (ENOTSOCK); return; } int n; len = sizeof (n); if (sin.sin_family != AF_INET || getsockopt (fd, SOL_SOCKET, SO_TYPE, (char *) &n, &len) < 0 || n != SOCK_DGRAM) { close (fd); sbp->replyref (ESOCKTNOSUPPORT); return; } if (!nameok.match (arg->name)) { close (fd); sbp->replyref (EINVAL); return; } if (!uid_mkdir (aup2aid (aup), arg->name)) { close (fd); sbp->replyref (EEXIST); return; } // uid_rmdir (aup2aid (aup), arg->name); mountarg ma; ma.hostname = strbuf () << "*" << aup2aid (aup) << "!" << arg->name; ma.path = mountpoint (aup, arg->name); ma.flags = NMOPT_NFS3|NMOPT_SOFT; ma.handle = arg->fh; ref<mountres> mrp (New refcounted<mountres>); nmx->sendfd (fd); nmc->call (NFSMOUNTER_MOUNT, &ma, mrp, wrap (mkref(this), &cfsadm::mounted, sbp, mrp, sin));}voidcfsadm::mounted (svccb *sbp, ref<mountres> resp, sockaddr_in sin, clnt_stat err){ classfs_mount_arg *arg = sbp->template getarg<classfs_mount_arg> (); if (err) fatal << "nfsmounter: " << err << "\n"; if (resp->status) { uid_rmdir (aup2aid (aup), arg->name); warn << "*" << aup2aid (aup) << "!" << arg->name << ": " << strerror (resp->status) << "\n"; } else { str mp = mountpoint (aup, arg->name); mps.insert (mp, New refcounted<pinger> (this, sin)); fstab.insert (mp, mkref (this)); } sbp->replyref (resp->status);}voidcfsadm::dispatch (svccb *sbp){ if (!sbp) { if (x) { sfs_aid aid = aup2aid (aup); warn << "EOF from aid " << aid << "\n"; s = NULL; x = NULL; qhash_slot<str, ref<pinger> > *sp, *nsp; for (sp = mps.first (); sp; sp = nsp) { static rxx basenamerx ("[^/]*$"); nsp = mps.next (sp); basenamerx.search (sp->key); warn << "unmounting " << basenamerx[0] << "\n"; detach (aid, basenamerx[0]); } refcount_dec (); } return; } switch (sbp->proc ()) { case CLASSFSPROC_NULL: sbp->reply (NULL); break; case CLASSFSPROC_MOUNT: mount (sbp); break; default: sbp->reject (PROC_UNAVAIL); break; }}static void unmount_send (sfs_aid aid, str name, bool logit);static voidunmount_cb (sfs_aid aid, str name, ref<int> res, clnt_stat err){ if (err) fatal << "nfsmounter: " << err << "\n"; if (*res) delaycb (5, wrap (unmount_send, aid, name, false)); else uid_rmdir (aid, name);}static voidunmount_send (sfs_aid aid, str name, bool logit){ umountarg arg; arg.path = mountpoint (aid, name); if (logit) arg.flags = NUOPT_FORCE|NUOPT_STALE; else arg.flags = NUOPT_FORCE|NUOPT_STALE|NUOPT_NLOG; ref<int> res = New refcounted<int> (EBUSY); nmc->call (NFSMOUNTER_UMOUNT, &arg, res, wrap (unmount_cb, aid, name, res));}boolkillserv (sfs_aid aid, str name){ str fsname = mountpoint (aid, name); cfsadm *cfsp = fstab[fsname]; if (!cfsp) return false; cfsp->kill (); return true;}booldetach (sfs_aid aid, str name){ str fsname = mountpoint (aid, name); cfsadm *cfsp = fstab[fsname]; if (!cfsp) return false; cfsp->mps.remove (fsname); fstab.remove (fsname); rootdir->aidunlink (aid, name); unmount_send (aid, name, true); return true;}static voidadm_mounted (ref<mountres> resp, clnt_stat err){ if (err) fatal << "nfsmounter: " << err << "\n"; if (resp->status) fatal << mntpath << ": " << strerror (resp->status) << "\n"; sfs_suidserv ("classfs", wrap (&cfsadm::alloc));}voidadm_init (void){ int nfsfd = inetsocket (SOCK_DGRAM, 0, INADDR_LOOPBACK); rootsrv = asrv::alloc (axprt_dgram::alloc (nfsfd), nfs_program_3, wrap (&afsnode::dispatch3)); nfs_fh3 fh; rootdir->mkfh3 (&fh); mountarg arg; arg.hostname = strbuf ("(%s)", progname.cstr ()); arg.path = mntpath; arg.flags = NMOPT_NFS3|NMOPT_SOFT|NMOPT_NOAC; arg.handle.set (const_cast<char *> (fh.data.base ()), fh.data.size ()); ref<mountres> mrp (New refcounted<mountres>); nmx->sendfd (nfsfd, false); nmc->call (NFSMOUNTER_MOUNT, &arg, mrp, wrap (adm_mounted, mrp));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -