335 lines
6.1 KiB
C
335 lines
6.1 KiB
C
/* Copyright © 2003 Russ Cox, MIT; see /sys/src/libsunrpc/COPYING */
|
|
#include <u.h>
|
|
#include <libc.h>
|
|
#include <thread.h>
|
|
#include <sunrpc.h>
|
|
#include <nfs3.h>
|
|
|
|
int chatty;
|
|
SunClient *client;
|
|
|
|
void
|
|
usage(void)
|
|
{
|
|
fprint(2, "usage: nfsmount address [cmd]\n"
|
|
"cmd is one of:\n"
|
|
"\tnull\n"
|
|
"\tmnt path\n"
|
|
"\tdump\n"
|
|
"\tumnt path\n"
|
|
"\tumntall\n"
|
|
"\texport (default)\n");
|
|
threadexitsall("usage");
|
|
}
|
|
|
|
void
|
|
portCall(SunCall *c, PortCallType type)
|
|
{
|
|
c->rpc.prog = PortProgram;
|
|
c->rpc.vers = PortVersion;
|
|
c->rpc.proc = type>>1;
|
|
c->rpc.iscall = !(type&1);
|
|
c->type = type;
|
|
}
|
|
|
|
int
|
|
getport(SunClient *client, uint prog, uint vers, uint prot, uint *port)
|
|
{
|
|
PortTGetport tx;
|
|
PortRGetport rx;
|
|
|
|
memset(&tx, 0, sizeof tx);
|
|
portCall(&tx.call, PortCallTGetport);
|
|
tx.map.prog = prog;
|
|
tx.map.vers = vers;
|
|
tx.map.prot = prot;
|
|
|
|
memset(&rx, 0, sizeof rx);
|
|
portCall(&rx.call, PortCallRGetport);
|
|
|
|
if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
|
|
return -1;
|
|
*port = rx.port;
|
|
return 0;
|
|
}
|
|
|
|
uchar unixauth[] = {
|
|
0x12, 0x23, 0x34, 0x45, /* stamp */
|
|
0x00, 0x00, 0x00, 0x04, /* gnot */
|
|
0x67, 0x6e, 0x6f, 0x74,
|
|
0x00, 0x00, 0x03, 0xE9, /* 1001 */
|
|
0x00, 0x00, 0x03, 0xE9, /* 1001 */
|
|
0x00, 0x00, 0x00, 0x00, /* gid list */
|
|
};
|
|
void
|
|
mountCall(SunCall *c, NfsMount3CallType type)
|
|
{
|
|
c->rpc.prog = NfsMount3Program;
|
|
c->rpc.vers = NfsMount3Version;
|
|
c->rpc.proc = type>>1;
|
|
c->rpc.iscall = !(type&1);
|
|
if(c->rpc.iscall){
|
|
c->rpc.cred.flavor = SunAuthSys;
|
|
c->rpc.cred.data = unixauth;
|
|
c->rpc.cred.ndata = sizeof unixauth;
|
|
}
|
|
c->type = type;
|
|
}
|
|
|
|
void
|
|
tnull(char **argv)
|
|
{
|
|
NfsMount3TNull tx;
|
|
NfsMount3RNull rx;
|
|
|
|
USED(argv);
|
|
|
|
memset(&tx, 0, sizeof tx);
|
|
mountCall(&tx.call, NfsMount3CallTNull);
|
|
|
|
memset(&rx, 0, sizeof rx);
|
|
mountCall(&rx.call, NfsMount3CallRNull);
|
|
|
|
if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
|
|
sysfatal("rpc: %r");
|
|
}
|
|
|
|
void
|
|
tmnt(char **argv)
|
|
{
|
|
int i;
|
|
NfsMount3TMnt tx;
|
|
NfsMount3RMnt rx;
|
|
|
|
memset(&tx, 0, sizeof tx);
|
|
mountCall(&tx.call, NfsMount3CallTMnt);
|
|
tx.path = argv[0];
|
|
|
|
memset(&rx, 0, sizeof rx);
|
|
mountCall(&rx.call, NfsMount3CallRMnt);
|
|
|
|
if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
|
|
sysfatal("rpc: %r");
|
|
|
|
if(rx.status != 0){
|
|
nfs3Errstr(rx.status);
|
|
sysfatal("mnt: %r");
|
|
}
|
|
|
|
print("handle %.*H\n", rx.len, rx.handle);
|
|
print("auth:");
|
|
for(i=0; i<rx.nauth; i++)
|
|
print(" %ud", (uint)rx.auth[i]);
|
|
print("\n");
|
|
}
|
|
|
|
void
|
|
tdump(char **argv)
|
|
{
|
|
uchar *p, *ep;
|
|
NfsMount3TDump tx;
|
|
NfsMount3RDump rx;
|
|
NfsMount3Entry e;
|
|
|
|
memset(&tx, 0, sizeof tx);
|
|
mountCall(&tx.call, NfsMount3CallTDump);
|
|
USED(argv);
|
|
|
|
memset(&rx, 0, sizeof rx);
|
|
mountCall(&rx.call, NfsMount3CallRDump);
|
|
|
|
if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
|
|
sysfatal("rpc: %r");
|
|
|
|
p = rx.data;
|
|
ep = p+rx.count;
|
|
while(p < ep){
|
|
if(nfsMount3EntryUnpack(p, ep, &p, &e) < 0)
|
|
sysfatal("unpack entry structure failed");
|
|
print("%s %s\n", e.host, e.path);
|
|
}
|
|
}
|
|
|
|
void
|
|
tumnt(char **argv)
|
|
{
|
|
NfsMount3TUmnt tx;
|
|
NfsMount3RUmnt rx;
|
|
|
|
memset(&tx, 0, sizeof tx);
|
|
mountCall(&tx.call, NfsMount3CallTUmnt);
|
|
tx.path = argv[0];
|
|
|
|
memset(&rx, 0, sizeof rx);
|
|
mountCall(&rx.call, NfsMount3CallRUmnt);
|
|
|
|
if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
|
|
sysfatal("rpc: %r");
|
|
|
|
print("\n");
|
|
}
|
|
|
|
void
|
|
tumntall(char **argv)
|
|
{
|
|
NfsMount3TUmntall tx;
|
|
NfsMount3RUmntall rx;
|
|
|
|
memset(&tx, 0, sizeof tx);
|
|
mountCall(&tx.call, NfsMount3CallTUmntall);
|
|
USED(argv);
|
|
|
|
memset(&rx, 0, sizeof rx);
|
|
mountCall(&rx.call, NfsMount3CallRUmntall);
|
|
|
|
if(sunClientRpc(client, 0, &tx.call, &rx.call, nil) < 0)
|
|
sysfatal("rpc: %r");
|
|
|
|
print("\n");
|
|
}
|
|
|
|
void
|
|
texport(char **argv)
|
|
{
|
|
uchar *p, *ep, *tofree;
|
|
char **g, **gg;
|
|
int ng, i, n;
|
|
NfsMount3TDump tx;
|
|
NfsMount3RDump rx;
|
|
NfsMount3Export e;
|
|
|
|
memset(&tx, 0, sizeof tx);
|
|
mountCall(&tx.call, NfsMount3CallTExport);
|
|
USED(argv);
|
|
|
|
memset(&rx, 0, sizeof rx);
|
|
mountCall(&rx.call, NfsMount3CallRExport);
|
|
|
|
if(sunClientRpc(client, 0, &tx.call, &rx.call, &tofree) < 0)
|
|
sysfatal("rpc: %r");
|
|
|
|
p = rx.data;
|
|
ep = p+rx.count;
|
|
g = nil;
|
|
ng = 0;
|
|
while(p < ep){
|
|
n = nfsMount3ExportGroupSize(p);
|
|
if(n > ng){
|
|
ng = n;
|
|
g = erealloc(g, sizeof(g[0])*ng);
|
|
}
|
|
if(nfsMount3ExportUnpack(p, ep, &p, g, &gg, &e) < 0)
|
|
sysfatal("unpack export structure failed");
|
|
print("%s", e.path);
|
|
for(i=0; i<e.ng; i++)
|
|
print(" %s", e.g[i]);
|
|
print("\n");
|
|
}
|
|
free(tofree);
|
|
}
|
|
|
|
static struct {
|
|
char *cmd;
|
|
int narg;
|
|
void (*fn)(char**);
|
|
} tab[] = {
|
|
"null", 0, tnull,
|
|
"mnt", 1, tmnt,
|
|
"dump", 0, tdump,
|
|
"umnt", 1, tumnt,
|
|
"umntall", 1, tumntall,
|
|
"export", 0, texport,
|
|
};
|
|
|
|
char*
|
|
netchangeport(char *addr, char *port)
|
|
{
|
|
static char buf[256];
|
|
char *r;
|
|
|
|
strecpy(buf, buf+sizeof buf, addr);
|
|
r = strrchr(buf, '!');
|
|
if(r == nil)
|
|
return nil;
|
|
r++;
|
|
strecpy(r, buf+sizeof buf, port);
|
|
return buf;
|
|
}
|
|
|
|
void
|
|
threadmain(int argc, char **argv)
|
|
{
|
|
char *dflt[] = { "export", };
|
|
char *addr, *cmd;
|
|
int i, proto;
|
|
uint port;
|
|
char buf[32];
|
|
int mapit;
|
|
|
|
mapit = 1;
|
|
ARGBEGIN{
|
|
case 'R':
|
|
chatty++;
|
|
break;
|
|
case 'm':
|
|
mapit = 0;
|
|
break;
|
|
}ARGEND
|
|
|
|
if(argc < 1)
|
|
usage();
|
|
|
|
fmtinstall('B', sunRpcFmt);
|
|
fmtinstall('C', sunCallFmt);
|
|
fmtinstall('H', encodefmt);
|
|
sunFmtInstall(&portProg);
|
|
sunFmtInstall(&nfsMount3Prog);
|
|
|
|
addr = netmkaddr(argv[0], "udp", "portmap");
|
|
if(mapit){
|
|
/* translate with port mapper */
|
|
fprint(2, "connecting to %s\n", addr);
|
|
if((client = sunDial(addr)) == nil)
|
|
sysfatal("dial %s: %r", addr);
|
|
client->chatty = chatty;
|
|
sunClientProg(client, &portProg);
|
|
if(strstr(addr, "udp!"))
|
|
proto = PortProtoUdp;
|
|
else
|
|
proto = PortProtoTcp;
|
|
if(getport(client, NfsMount3Program, NfsMount3Version, proto, &port) < 0)
|
|
sysfatal("getport: %r");
|
|
snprint(buf, sizeof buf, "%ud!r", port);
|
|
addr = netchangeport(addr, buf);
|
|
sunClientClose(client);
|
|
}
|
|
|
|
fprint(2, "connecting to %s\n", addr);
|
|
if((client = sunDial(addr)) == nil)
|
|
sysfatal("dial %s: %r", addr);
|
|
|
|
client->chatty = chatty;
|
|
sunClientProg(client, &nfsMount3Prog);
|
|
|
|
argv++;
|
|
argc--;
|
|
|
|
if(argc == 0){
|
|
argc = 1;
|
|
argv = dflt;
|
|
}
|
|
cmd = argv[0];
|
|
argv++;
|
|
argc--;
|
|
|
|
for(i=0; i<nelem(tab); i++){
|
|
if(strcmp(tab[i].cmd, cmd) == 0){
|
|
if(tab[i].narg != argc)
|
|
usage();
|
|
(*tab[i].fn)(argv);
|
|
threadexitsall(nil);
|
|
}
|
|
}
|
|
usage();
|
|
}
|