blob: c4387b4a02be414ab955ed5f06a87ce222214570 [file] [log] [blame]
Guido van Rossume3cafbe1992-12-14 23:25:04 +00001# NFS RPC client -- RFC 1094
2
Guido van Rossumfa83c7b1992-12-17 17:12:38 +00003# XXX This is not yet complete.
4# XXX Only GETATTR, SETTTR, LOOKUP and READDIR are supported.
5
Guido van Rossume3cafbe1992-12-14 23:25:04 +00006# (See mountclient.py for some hints on how to write RPC clients in
7# Python in general)
8
Guido van Rossum195a4f71992-12-15 20:52:31 +00009import rpc
Guido van Rossume3cafbe1992-12-14 23:25:04 +000010from rpc import UDPClient, TCPClient
11from mountclient import FHSIZE, MountPacker, MountUnpacker
12
13NFS_PROGRAM = 100003
14NFS_VERSION = 2
15
16# enum stat
17NFS_OK = 0
18# (...many error values...)
19
20# enum ftype
21NFNON = 0
22NFREG = 1
23NFDIR = 2
24NFBLK = 3
25NFCHR = 4
26NFLNK = 5
27
28
29class NFSPacker(MountPacker):
30
Tim Peterse6ddc8b2004-07-18 05:56:09 +000031 def pack_sattrargs(self, sa):
32 file, attributes = sa
33 self.pack_fhandle(file)
34 self.pack_sattr(attributes)
Guido van Rossume3cafbe1992-12-14 23:25:04 +000035
Tim Peterse6ddc8b2004-07-18 05:56:09 +000036 def pack_sattr(self, sa):
37 mode, uid, gid, size, atime, mtime = sa
38 self.pack_uint(mode)
39 self.pack_uint(uid)
40 self.pack_uint(gid)
41 self.pack_uint(size)
42 self.pack_timeval(atime)
43 self.pack_timeval(mtime)
Guido van Rossume3cafbe1992-12-14 23:25:04 +000044
Tim Peterse6ddc8b2004-07-18 05:56:09 +000045 def pack_diropargs(self, da):
46 dir, name = da
47 self.pack_fhandle(dir)
48 self.pack_string(name)
Guido van Rossume3cafbe1992-12-14 23:25:04 +000049
Tim Peterse6ddc8b2004-07-18 05:56:09 +000050 def pack_readdirargs(self, ra):
51 dir, cookie, count = ra
52 self.pack_fhandle(dir)
53 self.pack_uint(cookie)
54 self.pack_uint(count)
Guido van Rossume3cafbe1992-12-14 23:25:04 +000055
Tim Peterse6ddc8b2004-07-18 05:56:09 +000056 def pack_timeval(self, tv):
57 secs, usecs = tv
58 self.pack_uint(secs)
59 self.pack_uint(usecs)
Guido van Rossume3cafbe1992-12-14 23:25:04 +000060
61
62class NFSUnpacker(MountUnpacker):
63
Tim Peterse6ddc8b2004-07-18 05:56:09 +000064 def unpack_readdirres(self):
65 status = self.unpack_enum()
66 if status == NFS_OK:
67 entries = self.unpack_list(self.unpack_entry)
68 eof = self.unpack_bool()
69 rest = (entries, eof)
70 else:
71 rest = None
72 return (status, rest)
Guido van Rossume3cafbe1992-12-14 23:25:04 +000073
Tim Peterse6ddc8b2004-07-18 05:56:09 +000074 def unpack_entry(self):
75 fileid = self.unpack_uint()
76 name = self.unpack_string()
77 cookie = self.unpack_uint()
78 return (fileid, name, cookie)
Guido van Rossume3cafbe1992-12-14 23:25:04 +000079
Tim Peterse6ddc8b2004-07-18 05:56:09 +000080 def unpack_diropres(self):
81 status = self.unpack_enum()
82 if status == NFS_OK:
83 fh = self.unpack_fhandle()
84 fa = self.unpack_fattr()
85 rest = (fh, fa)
86 else:
87 rest = None
88 return (status, rest)
Guido van Rossume3cafbe1992-12-14 23:25:04 +000089
Tim Peterse6ddc8b2004-07-18 05:56:09 +000090 def unpack_attrstat(self):
91 status = self.unpack_enum()
92 if status == NFS_OK:
93 attributes = self.unpack_fattr()
94 else:
95 attributes = None
96 return status, attributes
Guido van Rossume3cafbe1992-12-14 23:25:04 +000097
Tim Peterse6ddc8b2004-07-18 05:56:09 +000098 def unpack_fattr(self):
99 type = self.unpack_enum()
100 mode = self.unpack_uint()
101 nlink = self.unpack_uint()
102 uid = self.unpack_uint()
103 gid = self.unpack_uint()
104 size = self.unpack_uint()
105 blocksize = self.unpack_uint()
106 rdev = self.unpack_uint()
107 blocks = self.unpack_uint()
108 fsid = self.unpack_uint()
109 fileid = self.unpack_uint()
110 atime = self.unpack_timeval()
111 mtime = self.unpack_timeval()
112 ctime = self.unpack_timeval()
113 return (type, mode, nlink, uid, gid, size, blocksize, \
114 rdev, blocks, fsid, fileid, atime, mtime, ctime)
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000115
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000116 def unpack_timeval(self):
117 secs = self.unpack_uint()
118 usecs = self.unpack_uint()
119 return (secs, usecs)
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000120
121
122class NFSClient(UDPClient):
123
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000124 def __init__(self, host):
125 UDPClient.__init__(self, host, NFS_PROGRAM, NFS_VERSION)
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000126
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000127 def addpackers(self):
128 self.packer = NFSPacker()
129 self.unpacker = NFSUnpacker('')
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000130
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000131 def mkcred(self):
132 if self.cred == None:
133 self.cred = rpc.AUTH_UNIX, rpc.make_auth_unix_default()
134 return self.cred
Guido van Rossum195a4f71992-12-15 20:52:31 +0000135
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000136 def Getattr(self, fh):
137 return self.make_call(1, fh, \
138 self.packer.pack_fhandle, \
139 self.unpacker.unpack_attrstat)
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000140
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000141 def Setattr(self, sa):
142 return self.make_call(2, sa, \
143 self.packer.pack_sattrargs, \
144 self.unpacker.unpack_attrstat)
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000145
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000146 # Root() is obsolete
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000147
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000148 def Lookup(self, da):
149 return self.make_call(4, da, \
150 self.packer.pack_diropargs, \
151 self.unpacker.unpack_diropres)
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000152
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000153 # ...
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000154
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000155 def Readdir(self, ra):
156 return self.make_call(16, ra, \
157 self.packer.pack_readdirargs, \
158 self.unpacker.unpack_readdirres)
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000159
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000160 # Shorthand to get the entire contents of a directory
161 def Listdir(self, dir):
162 list = []
163 ra = (dir, 0, 2000)
164 while 1:
165 (status, rest) = self.Readdir(ra)
166 if status <> NFS_OK:
167 break
168 entries, eof = rest
169 last_cookie = None
170 for fileid, name, cookie in entries:
171 list.append((fileid, name))
172 last_cookie = cookie
173 if eof or last_cookie == None:
174 break
175 ra = (ra[0], last_cookie, ra[2])
176 return list
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000177
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000178
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000179def test():
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000180 import sys
181 if sys.argv[1:]: host = sys.argv[1]
182 else: host = ''
183 if sys.argv[2:]: filesys = sys.argv[2]
184 else: filesys = None
185 from mountclient import UDPMountClient, TCPMountClient
186 mcl = TCPMountClient(host)
187 if filesys == None:
188 list = mcl.Export()
189 for item in list:
190 print item
191 return
192 sf = mcl.Mnt(filesys)
193 print sf
194 fh = sf[1]
195 if fh:
196 ncl = NFSClient(host)
197 as = ncl.Getattr(fh)
198 print as
199 list = ncl.Listdir(fh)
200 for item in list: print item
201 mcl.Umnt(filesys)