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