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

📄 sfsuclnt.c

📁 A part of LFS.This is a server software.
💻 C
字号:
/* $Id: sfsuclnt.C,v 1.10 2003/02/26 07:13:49 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 "classfscli.h"#include "nfstrans.h"#include "nfs3_nonnul.h"#include "getfh3.h"#include "rxx.h"#include "sfs_prot.h"#include "sfsagent.h"#include "parseopt.h"static list<sfsuclnt, &sfsuclnt::link> clist;static rxx devdbrx ("(0x[0-9a-f]+)\\s+(@[\\w\\.,%\\-]+)\\s+([\\w\\-]+)");static voiddevdbcat (int out){  if (!sfsdevdb) {    if (char *p = getenv ("SFS_ROOT"))      sfsdevdb = strbuf () << p << "/.devdb";    else      sfsdevdb = "/sfs/.devdb";  }  str devdb;  do {    devdb = file2str (sfsdevdb);  } while (!devdb && errno == ESTALE);  if (devdb)    write (out, devdb, devdb.len ());  else    warn << sfsdevdb << ": " << strerror (errno) << "\n";}sfsuclnt::sfsuclnt ()  : authlock (false), seqno (0), authno (0), auth (NULL){  clist.insert_head (this);}sfsuclnt::~sfsuclnt (){  clist.remove (this);  setauth (0);  if (nfsc)    nfsc->seteofcb (NULL);}voidsfsuclnt::eof (){  str srvname = sc->path;  sc = NULL;  nfsc = NULL;  sfsc = NULL;  nfscbs = NULL;  seqno = 0;  setauth (0);  warn << "EOF from " << srvname << "\n";  delaycb (10, wrap (mkref (this), &sfsuclnt::connect, srvname));}voidsfsuclnt::nfscbdispatch (svccb *sbp){  if (!sbp) {    eof ();    return;  }  switch (sbp->proc ()) {  case ex_NFSCBPROC3_NULL:  case ex_NFSCBPROC3_INVALIDATE:    sbp->reply (NULL);    break;  default:    sbp->reject (PROC_UNAVAIL);    break;  }}voidsfsuclnt::setauth (u_int32_t an){  if (auth) {    auth_destroy (auth);    if (sfsc)      sfsc->call (SFSPROC_LOGOUT, &authno, NULL, aclnt_cb_null);  }  authno = an;  if (authno)    auth = authuint_create (authno);  else    auth = NULL;  authlock = false;}voidsfsuclnt::setattrs (u_int32_t proc, void *resp, ref<ex_getattr3res> ap,		    ex_post_op_attr *poap, aclnt_cb cb, clnt_stat stat){  if (stat) {    (*cb) (stat);    return;  }  if (ap->status) {#define seterr(proc, arg, res)					\    case proc:							\      static_cast<res *> (resp)->set_status (ap->status);    switch (proc) {      NFS_PROGRAM_3_APPLY_NONULL (seterr);    default:      panic ("sfsuclnt::setattrs: invalid proc %d\n", proc);    }#undef seterr  }  else {    poap->set_present (true);    *poap->attributes = *ap->attributes;  }     getreply (proc, NULL, resp, cb, stat);}voidsfsuclnt::getreply (u_int32_t proc, ptr<nfs_fh3> fhp, void *resp,		    aclnt_cb cb, clnt_stat stat){  if (stat) {    (*cb) (stat);    return;  }  if (proc && !*static_cast<nfsstat3 *> (resp) && fhp)    switch (proc) {    case NFSPROC3_READ:      {	ex_read3res *rr = static_cast<ex_read3res *> (resp);	//rr->resok->file_attributes.set_present (false);	if (!rr->resok->file_attributes.present) {	  ref<ex_getattr3res> ap (New refcounted<ex_getattr3res>);	  nfsc->call (NFSPROC3_GETATTR, fhp, ap,		      wrap (this, &sfsuclnt::setattrs, proc, resp, ap,			    &rr->resok->file_attributes, cb),		      auth);	  return;	}      }      break;    case NFSPROC3_WRITE:      {	ex_write3res *wr = static_cast<ex_write3res *> (resp);	//wr->resok->file_wcc.after.set_present (false);	if (!wr->resok->file_wcc.after.present) {	  ref<ex_getattr3res> ap (New refcounted<ex_getattr3res>);	  nfsc->call (NFSPROC3_GETATTR, fhp, ap,		      wrap (this, &sfsuclnt::setattrs, proc, resp, ap,			    &wr->resok->file_wcc.after, cb),		      auth);	  return;	}      }      break;    default:      break;    }  nfs3_exp_disable (proc, resp);  (*cb) (stat);}voidsfsuclnt::call (u_int32_t proc, const void *argp, void *resp, aclnt_cb cb){  nfs3_exp_enable (proc, resp);  if (!nfsc)    (*cb) (RPC_CANTSEND);  else if (proc != NFSPROC3_NULL)    nfsc->call (proc, argp, resp,		wrap (this, &sfsuclnt::getreply, proc,		      New refcounted<nfs_fh3> (*static_cast<nfs_fh3 *> (argp)),		      resp, cb),		auth);  else    nfsc->call (proc, argp, resp, cb, auth);}static ptr<aclnt> agentclnt;static ptr<asrv> agentserv;inline voidreauth (){  for (sfsuclnt *c = clist.first; c; c = clist.next (c))    c->doauth (NULL);}inline stragentname (){  if (progname)    return progname;  return "classfs-client";}static voidsagent_dispatch (svccb *sbp){  if (!sbp) {    agentclnt = NULL;    agentserv = NULL;    reauth ();    return;  }  switch (sbp->proc ()) {  case AGENT_START:    reauth ();    break;  default:    sbp->reject (PROC_UNAVAIL);    break;  }}static ptr<aclnt>cagent (){  if (agentclnt)    return agentclnt;  str agentsock = getenv ("SFS_AGENTSOCK");  static rxx sockfdre ("^-(\\d+)?$");  int fd;  if (agentsock && sockfdre.search (agentsock)) {      if (sockfdre[1])	fd = atoi (sockfdre[1]);      else	fd = 0;      if (!isunixsocket (fd)) {	warn << "fd specified with '-S' not unix domain socket\n";	return NULL;      }  }  else if (agentsock) {    fd = unixsocket_connect (agentsock);    if (fd < 0) {      warn ("%s: %m\n", agentsock.cstr ());      return NULL;    }  }  else {    int sfscdfd = suidgetfd_required ("agent");    ref<axprt_unix> sfscdxprt = axprt_unix::alloc (sfscdfd);    ref<aclnt> sfscdclnt = aclnt::alloc (sfscdxprt, agent_prog_1);    int32_t res;    if (clnt_stat err = sfscdclnt->scall (AGENT_GETAGENT, NULL, &res)) {      warn << "sfscd: " << err << "\n";      return NULL;    }    if (res) {      warn << "connecting to agent via sfscd: " << strerror (res) << "\n";      return NULL;    }    if ((fd = sfscdxprt->recvfd ()) < 0) {      warn << "connecting to agent via sfscd: could not get file desriptor\n";      return NULL;    }  }  ref<axprt> x = axprt_stream::alloc (fd);  sfs_hostname prog = agentname ();  ref<aclnt> c = aclnt::alloc (x, agentctl_prog_1);  c->call (AGENTCTL_FORWARD, &prog, NULL, aclnt_cb_null, NULL, NULL, xdr_void);  agentclnt = aclnt::alloc (x, agentcb_prog_1);  agentserv = asrv::alloc (x, agent_prog_1, wrap (sagent_dispatch));  return agentclnt;}struct authrelay {  ref<sfsuclnt> sci;  const sfsuclnt::alloccb_t::ptr cb;  sfsagent_authinit_arg aiarg;  sfsagent_authmore_arg amarg;  sfsagent_auth_res ares;  sfs_loginarg sarg;  sfs_loginres sres;  authrelay (ref<sfsuclnt> sci, sfsuclnt::alloccb_t::ptr cb, u_int64_t seqno)    : sci (sci), cb (cb) {    aiarg.ntries = 0;    aiarg.requestor = agentname ();    aiarg.authinfo.type = SFS_AUTHINFO;    aiarg.authinfo.service = SFS_SFS;    sfs_parsepath (sci->sc->path, &aiarg.authinfo.name,		   &aiarg.authinfo.hostid);    aiarg.authinfo.hostid = sci->sc->hostid;    aiarg.authinfo.sessid = sci->sc->sessid;    aiarg.seqno = seqno;    amarg.authinfo = aiarg.authinfo;    cagent ()->call (AGENTCB_AUTHINIT, &aiarg, &ares,		     wrap (this, &authrelay::acb));  }  void done (bool ok = false) {    if (ok)      sci->setauth (*sres.authno);    else      sci->setauth (0);    if (cb)      (*cb) (sci, NULL);    delete this;  }  void acb (clnt_stat stat) {    if (stat) {      warn << "agent: " << stat << "\n";      done ();    }    else if (!ares.authenticate) {      done ();      return;    }    else {      sarg.seqno = aiarg.seqno;      sarg.certificate = *ares.certificate;      sci->sfsc->call (SFSPROC_LOGIN, &sarg, &sres,		       wrap (this, &authrelay::scb));    }  }  void scb (clnt_stat stat) {    if (stat) {      warn << "SFS server: " << stat << "\n";      done ();    }    else      switch (sres.status) {      case SFSLOGIN_OK:	done (true);	break;      case SFSLOGIN_MORE:	amarg.seqno = aiarg.seqno;	amarg.challenge = *sres.resmore;	cagent ()->call (AGENTCB_AUTHMORE, &amarg, &ares,			 wrap (this, &authrelay::acb));	break;      case SFSLOGIN_BAD:	aiarg.ntries++;	aiarg.seqno++;	/* cascade */      case SFSLOGIN_AGAIN:	cagent ()->call (AGENTCB_AUTHINIT, &aiarg, &ares,			 wrap (this, &authrelay::acb));	break;      default:	done ();	break;      }  }};voidsfsuclnt::doauth (sfsuclnt::alloccb_t::ptr cb){  if (authlock)    return;  if (!cagent ())    return;  authlock = true;  vNew authrelay (mkref (this), cb, seqno++);}voidsfsuclnt::connect_1 (sfsuclnt::alloccb_t::ptr cb, ptr<sfscon> c, str err){  if (!c) {    (*cb) (NULL, err);    return;  }  sc = c;  nfsc = aclnt::alloc (sc->x, ex_nfs_program_3);  sfsc = aclnt::alloc (sc->x, sfs_program_1);  nfscbs = asrv::alloc (sc->x, ex_nfscb_program_3,			wrap (this, &sfsuclnt::nfscbdispatch));  if (!cb)    warn << "reconnected to " << sc->path << "\n";  doauth (cb);}voidsfsuclnt::connect (str srvname){  sfs_connect_path (srvname, SFS_SFS,		    wrap (mkref (this), &sfsuclnt::connect_1,			  alloccb_t::ptr (NULL)));}voidsfsuclnt::alloc_2 (u_int64_t devno, sfsuclnt::alloccb_t cb, str devdb)		   {  if (!devdb) {    (*cb) (NULL, "could not read " << sfsdevdb);    return;  }  u_int64_t d2;  strbuf sb;  sb << devdb;  while (str line = suio_getline (sb.tosuio ()))    if (devdbrx.match (line) && convertint (devdbrx[1], &d2) && d2 == devno) {      sfs_connect_path (devdbrx[2], SFS_SFS,			wrap (mkref (this), &sfsuclnt::connect_1, cb));      return;    }  (*cb) (NULL, "could not find device in " << sfsdevdb);}voidsfsuclnt::alloc_1 (str path, sfsuclnt::alloccb_t cb,		   u_int64_t devno, str srvname, str rpath){  if (!srvname) {    (*cb) (NULL, path << ": pathinfo failed");    return;  }  chldrun (wrap (devdbcat),	   wrap (mkref (this), &sfsuclnt::alloc_2, devno, cb));}inline boolhexconv (int &out, const char in){  if (in >= '0' && in <= '9')    out = in - '0';  else if (in >= 'a' && in <= 'f')    out = in - ('a' - 10);  else if (in >= 'A' && in <= 'F')    out = in - ('A' - 10);  else    return false;  return true;}template<size_t max> inline boola2bytes (rpc_bytes<max> &b, str a){  int i = 0;  b.setsize (a.len () / 2);  for (const char *p = a.cstr (), *e = p + a.len (); p < e; p += 2) {    int h, l;    if (!hexconv (h, p[0]) || !hexconv (l, p[1]))      return false;    b[i++] = h << 4 | l;  }  return true;} voidsfsuclnt::alloc (str path, sfsuclnt::alloccb_t cb){  ref<sfsuclnt> sci (New refcounted<sfsuclnt>);  char buf[65];  str fhpath = path << "/.SFS \177FH";  int n = readlink (fhpath, buf, sizeof (buf) - 1);  if (n < 0 || n & 1 || !a2bytes (sci->rootfh.data, str (buf, n))) {    (*cb) (NULL, path << ": not an SFS file system");    return;  }  pathinfofetch (NULL, path, wrap (sci, &sfsuclnt::alloc_1, path, cb));}

⌨️ 快捷键说明

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