blob: 645a2a70dc8d1e0653858a3bd4b263979d9240da [file] [log] [blame]
Guido van Rossume3cafbe1992-12-14 23:25:04 +00001# NFS RPC client -- RFC 1094
2
3# (See mountclient.py for some hints on how to write RPC clients in
4# Python in general)
5
Guido van Rossum195a4f71992-12-15 20:52:31 +00006import rpc
Guido van Rossume3cafbe1992-12-14 23:25:04 +00007from rpc import UDPClient, TCPClient
8from mountclient import FHSIZE, MountPacker, MountUnpacker
9
10NFS_PROGRAM = 100003
11NFS_VERSION = 2
12
13# enum stat
14NFS_OK = 0
15# (...many error values...)
16
17# enum ftype
18NFNON = 0
19NFREG = 1
20NFDIR = 2
21NFBLK = 3
22NFCHR = 4
23NFLNK = 5
24
25
26class NFSPacker(MountPacker):
27
28 def pack_sattrargs(self, sa):
29 file, attributes = sa
30 self.pack_fhandle(file)
31 self.pack_sattr(attributes)
32
33 def pack_sattr(self, sa):
34 mode, uid, gid, size, atime, mtime = sa
35 self.pack_uint(mode)
36 self.pack_uint(uid)
37 self.pack_uint(gid)
38 self.pack_uint(size)
39 self.pack_timeval(atime)
40 self.pack_timeval(mtime)
41
42 def pack_diropargs(self, da):
43 dir, name = da
44 self.pack_fhandle(dir)
45 self.pack_string(name)
46
47 def pack_readdirargs(self, ra):
48 dir, cookie, count = ra
49 self.pack_fhandle(dir)
50 self.pack_uint(cookie)
51 self.pack_uint(count)
52
53 def pack_timeval(self, tv):
54 secs, usecs = tv
55 self.pack_uint(secs)
56 self.pack_uint(usecs)
57
58
59class NFSUnpacker(MountUnpacker):
60
61 def unpack_readdirres(self):
62 status = self.unpack_enum()
63 if status == NFS_OK:
64 entries = self.unpack_list(self.unpack_entry)
65 eof = self.unpack_bool()
66 rest = (entries, eof)
67 else:
68 rest = None
69 return (status, rest)
70
71 def unpack_entry(self):
72 fileid = self.unpack_uint()
73 name = self.unpack_string()
74 cookie = self.unpack_uint()
75 return (fileid, name, cookie)
76
77 def unpack_diropres(self):
78 status = self.unpack_enum()
79 if status == NFS_OK:
80 fh = self.unpack_fhandle()
81 fa = self.unpack_fattr()
82 rest = (fh, fa)
83 else:
84 rest = None
85 return (status, rest)
86
87 def unpack_attrstat(self):
88 status = self.unpack_enum()
89 if status == NFS_OK:
90 attributes = self.unpack_fattr()
91 else:
92 attributes = None
93 return status, attributes
94
95 def unpack_fattr(self):
96 type = self.unpack_enum()
97 mode = self.unpack_uint()
98 nlink = self.unpack_uint()
99 uid = self.unpack_uint()
100 gid = self.unpack_uint()
101 size = self.unpack_uint()
102 blocksize = self.unpack_uint()
103 rdev = self.unpack_uint()
104 blocks = self.unpack_uint()
105 fsid = self.unpack_uint()
106 fileid = self.unpack_uint()
107 atime = self.unpack_timeval()
108 mtime = self.unpack_timeval()
109 ctime = self.unpack_timeval()
110 return (type, mode, nlink, uid, gid, size, blocksize, \
111 rdev, blocks, fsid, fileid, atime, mtime, ctime)
112
113 def unpack_timeval(self):
114 secs = self.unpack_uint()
115 usecs = self.unpack_uint()
116 return (secs, usecs)
117
118
119class NFSClient(UDPClient):
120
121 def init(self, host):
122 return UDPClient.init(self, host, NFS_PROGRAM, NFS_VERSION)
123
124 def addpackers(self):
125 self.packer = NFSPacker().init()
126 self.unpacker = NFSUnpacker().init('')
127
Guido van Rossum195a4f71992-12-15 20:52:31 +0000128 def mkcred(self, proc):
129 if self.cred == None:
130 self.cred = rpc.AUTH_UNIX, rpc.make_auth_unix_default()
131 return self.cred
132
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000133 def Getattr(self, fh):
134 self.start_call(1)
135 self.packer.pack_fhandle(fh)
136 self.do_call()
137 as = self.unpacker.unpack_attrstat()
138 self.end_call()
139 return as
140
141 def Setattr(self, sa):
142 self.start_call(2)
143 self.packer.pack_sattrargs(sa)
144 self.do_call()
145 as = self.unpacker.unpack_attrstat()
146 self.end_call()
147 return as
148
149 # Root() is obsolete
150
151 def Lookup(self, da):
152 self.start_call(4)
153 self.packer.pack_diropargs(da)
154 self.do_call()
155 dr = self.unpacker.unpack_diropres()
156 self.end_call()
157 return dr
158
159 # ...
160
161 def Readdir(self, ra):
162 self.start_call(16)
163 self.packer.pack_readdirargs(ra)
164 self.do_call()
165 rr = self.unpacker.unpack_readdirres()
166 self.end_call()
167 return rr
168
169 # Shorthand to get the entire contents of a directory
170 def Listdir(self, dir):
171 list = []
172 ra = (dir, 0, 16)
173 while 1:
174 (status, rest) = self.Readdir(ra)
175 if status <> NFS_OK:
176 break
177 entries, eof = rest
178 last_cookie = None
179 for fileid, name, cookie in entries:
180 print (fileid, name, cookie) # XXX
181 list.append(fileid, name)
182 last_cookie = cookie
183 if eof or not last_cookie:
184 break
185 ra = (ra[0], last_cookie, ra[2])
186 return list
187
188
189def test():
190 import sys
191 if sys.argv[1:]: host = sys.argv[1]
192 else: host = ''
193 if sys.argv[2:]: filesys = sys.argv[2]
194 else: filesys = None
195 from mountclient import UDPMountClient, TCPMountClient
196 mcl = TCPMountClient().init(host)
197 if filesys == None:
198 list = mcl.Export()
199 for item in list:
200 print item
201 return
202 sf = mcl.Mnt(filesys)
203 print sf
204 fh = sf[1]
205 if fh:
206 ncl = NFSClient().init(host)
207 as = ncl.Getattr(fh)
208 print as
209 list = ncl.Listdir(fh)
210 for item in list: print item
211 mcl.Unmnt(filesys)
212
213test()