Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/* 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();
}