blob: 82e5b175bd897eb722b6414040aa6f4be09ad786 [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
31 def pack_sattrargs(self, sa):
32 file, attributes = sa
33 self.pack_fhandle(file)
34 self.pack_sattr(attributes)
35
36 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)
44
45 def pack_diropargs(self, da):
46 dir, name = da
47 self.pack_fhandle(dir)
48 self.pack_string(name)
49
50 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)
55
56 def pack_timeval(self, tv):
57 secs, usecs = tv
58 self.pack_uint(secs)
59 self.pack_uint(usecs)
60
61
62class NFSUnpacker(MountUnpacker):
63
64 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)
73
74 def unpack_entry(self):
75 fileid = self.unpack_uint()
76 name = self.unpack_string()
77 cookie = self.unpack_uint()
78 return (fileid, name, cookie)
79
80 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)
89
90 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
97
98 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)
115
116 def unpack_timeval(self):
117 secs = self.unpack_uint()
118 usecs = self.unpack_uint()
119 return (secs, usecs)
120
121
122class NFSClient(UDPClient):
123
124 def init(self, host):
125 return UDPClient.init(self, host, NFS_PROGRAM, NFS_VERSION)
126
127 def addpackers(self):
128 self.packer = NFSPacker().init()
129 self.unpacker = NFSUnpacker().init('')
130
Guido van Rossum195a4f71992-12-15 20:52:31 +0000131 def mkcred(self, proc):
132 if self.cred == None:
133 self.cred = rpc.AUTH_UNIX, rpc.make_auth_unix_default()
134 return self.cred
135
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000136 def Getattr(self, fh):
137 self.start_call(1)
138 self.packer.pack_fhandle(fh)
139 self.do_call()
140 as = self.unpacker.unpack_attrstat()
141 self.end_call()
142 return as
143
144 def Setattr(self, sa):
145 self.start_call(2)
146 self.packer.pack_sattrargs(sa)
147 self.do_call()
148 as = self.unpacker.unpack_attrstat()
149 self.end_call()
150 return as
151
152 # Root() is obsolete
153
154 def Lookup(self, da):
155 self.start_call(4)
156 self.packer.pack_diropargs(da)
157 self.do_call()
158 dr = self.unpacker.unpack_diropres()
159 self.end_call()
160 return dr
161
162 # ...
163
164 def Readdir(self, ra):
165 self.start_call(16)
166 self.packer.pack_readdirargs(ra)
167 self.do_call()
168 rr = self.unpacker.unpack_readdirres()
169 self.end_call()
170 return rr
171
172 # Shorthand to get the entire contents of a directory
173 def Listdir(self, dir):
174 list = []
Guido van Rossumad5f8621992-12-15 21:43:04 +0000175 ra = (dir, 0, 2000)
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000176 while 1:
177 (status, rest) = self.Readdir(ra)
178 if status <> NFS_OK:
179 break
180 entries, eof = rest
181 last_cookie = None
182 for fileid, name, cookie in entries:
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000183 list.append(fileid, name)
184 last_cookie = cookie
Guido van Rossumad5f8621992-12-15 21:43:04 +0000185 if eof or last_cookie == None:
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000186 break
187 ra = (ra[0], last_cookie, ra[2])
188 return list
189
190
191def test():
192 import sys
193 if sys.argv[1:]: host = sys.argv[1]
194 else: host = ''
195 if sys.argv[2:]: filesys = sys.argv[2]
196 else: filesys = None
197 from mountclient import UDPMountClient, TCPMountClient
198 mcl = TCPMountClient().init(host)
199 if filesys == None:
200 list = mcl.Export()
201 for item in list:
202 print item
203 return
204 sf = mcl.Mnt(filesys)
205 print sf
206 fh = sf[1]
207 if fh:
208 ncl = NFSClient().init(host)
209 as = ncl.Getattr(fh)
210 print as
211 list = ncl.Listdir(fh)
212 for item in list: print item
Guido van Rossumad5f8621992-12-15 21:43:04 +0000213 mcl.Umnt(filesys)
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000214
215test()