# NFS RPC client -- RFC 1094

# XXX This is not yet complete.
# XXX Only GETATTR, SETTTR, LOOKUP and READDIR are supported.

# (See mountclient.py for some hints on how to write RPC clients in
# Python in general)

import rpc
from rpc import UDPClient, TCPClient
from mountclient import FHSIZE, MountPacker, MountUnpacker

NFS_PROGRAM = 100003
NFS_VERSION = 2

# enum stat
NFS_OK = 0
# (...many error values...)

# enum ftype
NFNON = 0
NFREG = 1
NFDIR = 2
NFBLK = 3
NFCHR = 4
NFLNK = 5


class NFSPacker(MountPacker):

    def pack_sattrargs(self, sa):
        file, attributes = sa
        self.pack_fhandle(file)
        self.pack_sattr(attributes)

    def pack_sattr(self, sa):
        mode, uid, gid, size, atime, mtime = sa
        self.pack_uint(mode)
        self.pack_uint(uid)
        self.pack_uint(gid)
        self.pack_uint(size)
        self.pack_timeval(atime)
        self.pack_timeval(mtime)

    def pack_diropargs(self, da):
        dir, name = da
        self.pack_fhandle(dir)
        self.pack_string(name)

    def pack_readdirargs(self, ra):
        dir, cookie, count = ra
        self.pack_fhandle(dir)
        self.pack_uint(cookie)
        self.pack_uint(count)

    def pack_timeval(self, tv):
        secs, usecs = tv
        self.pack_uint(secs)
        self.pack_uint(usecs)


class NFSUnpacker(MountUnpacker):

    def unpack_readdirres(self):
        status = self.unpack_enum()
        if status == NFS_OK:
            entries = self.unpack_list(self.unpack_entry)
            eof = self.unpack_bool()
            rest = (entries, eof)
        else:
            rest = None
        return (status, rest)

    def unpack_entry(self):
        fileid = self.unpack_uint()
        name = self.unpack_string()
        cookie = self.unpack_uint()
        return (fileid, name, cookie)

    def unpack_diropres(self):
        status = self.unpack_enum()
        if status == NFS_OK:
            fh = self.unpack_fhandle()
            fa = self.unpack_fattr()
            rest = (fh, fa)
        else:
            rest = None
        return (status, rest)

    def unpack_attrstat(self):
        status = self.unpack_enum()
        if status == NFS_OK:
            attributes = self.unpack_fattr()
        else:
            attributes = None
        return status, attributes

    def unpack_fattr(self):
        type = self.unpack_enum()
        mode = self.unpack_uint()
        nlink = self.unpack_uint()
        uid = self.unpack_uint()
        gid = self.unpack_uint()
        size = self.unpack_uint()
        blocksize = self.unpack_uint()
        rdev = self.unpack_uint()
        blocks = self.unpack_uint()
        fsid = self.unpack_uint()
        fileid = self.unpack_uint()
        atime = self.unpack_timeval()
        mtime = self.unpack_timeval()
        ctime = self.unpack_timeval()
        return (type, mode, nlink, uid, gid, size, blocksize, \
                rdev, blocks, fsid, fileid, atime, mtime, ctime)

    def unpack_timeval(self):
        secs = self.unpack_uint()
        usecs = self.unpack_uint()
        return (secs, usecs)


class NFSClient(UDPClient):

    def __init__(self, host):
        UDPClient.__init__(self, host, NFS_PROGRAM, NFS_VERSION)

    def addpackers(self):
        self.packer = NFSPacker()
        self.unpacker = NFSUnpacker('')

    def mkcred(self):
        if self.cred is None:
            self.cred = rpc.AUTH_UNIX, rpc.make_auth_unix_default()
        return self.cred

    def Getattr(self, fh):
        return self.make_call(1, fh, \
                self.packer.pack_fhandle, \
                self.unpacker.unpack_attrstat)

    def Setattr(self, sa):
        return self.make_call(2, sa, \
                self.packer.pack_sattrargs, \
                self.unpacker.unpack_attrstat)

    # Root() is obsolete

    def Lookup(self, da):
        return self.make_call(4, da, \
                self.packer.pack_diropargs, \
                self.unpacker.unpack_diropres)

    # ...

    def Readdir(self, ra):
        return self.make_call(16, ra, \
                self.packer.pack_readdirargs, \
                self.unpacker.unpack_readdirres)

    # Shorthand to get the entire contents of a directory
    def Listdir(self, dir):
        list = []
        ra = (dir, 0, 2000)
        while 1:
            (status, rest) = self.Readdir(ra)
            if status <> NFS_OK:
                break
            entries, eof = rest
            last_cookie = None
            for fileid, name, cookie in entries:
                list.append((fileid, name))
                last_cookie = cookie
            if eof or last_cookie is None:
                break
            ra = (ra[0], last_cookie, ra[2])
        return list


def test():
    import sys
    if sys.argv[1:]: host = sys.argv[1]
    else: host = ''
    if sys.argv[2:]: filesys = sys.argv[2]
    else: filesys = None
    from mountclient import UDPMountClient, TCPMountClient
    mcl = TCPMountClient(host)
    if filesys is None:
        list = mcl.Export()
        for item in list:
            print item
        return
    sf = mcl.Mnt(filesys)
    print sf
    fh = sf[1]
    if fh:
        ncl = NFSClient(host)
        attrstat = ncl.Getattr(fh)
        print attrstat
        list = ncl.Listdir(fh)
        for item in list: print item
        mcl.Umnt(filesys)
