Commit | Line | Data |
---|---|---|
5174fdab LI |
1 | /* |
2 | * linux/fs/9p/fcprint.c | |
3 | * | |
4 | * Print 9P call. | |
5 | * | |
6 | * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
42e8c509 EVH |
9 | * it under the terms of the GNU General Public License version 2 |
10 | * as published by the Free Software Foundation. | |
5174fdab LI |
11 | * |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to: | |
19 | * Free Software Foundation | |
20 | * 51 Franklin Street, Fifth Floor | |
21 | * Boston, MA 02111-1301 USA | |
22 | * | |
23 | */ | |
5174fdab LI |
24 | #include <linux/module.h> |
25 | #include <linux/errno.h> | |
26 | #include <linux/fs.h> | |
27 | #include <linux/idr.h> | |
28 | ||
29 | #include "debug.h" | |
30 | #include "v9fs.h" | |
31 | #include "9p.h" | |
32 | #include "mux.h" | |
33 | ||
34 | static int | |
35 | v9fs_printqid(char *buf, int buflen, struct v9fs_qid *q) | |
36 | { | |
37 | int n; | |
38 | char b[10]; | |
39 | ||
40 | n = 0; | |
41 | if (q->type & V9FS_QTDIR) | |
42 | b[n++] = 'd'; | |
43 | if (q->type & V9FS_QTAPPEND) | |
44 | b[n++] = 'a'; | |
45 | if (q->type & V9FS_QTAUTH) | |
46 | b[n++] = 'A'; | |
47 | if (q->type & V9FS_QTEXCL) | |
48 | b[n++] = 'l'; | |
49 | if (q->type & V9FS_QTTMP) | |
50 | b[n++] = 't'; | |
51 | if (q->type & V9FS_QTSYMLINK) | |
52 | b[n++] = 'L'; | |
53 | b[n] = '\0'; | |
54 | ||
55 | return scnprintf(buf, buflen, "(%.16llx %x %s)", (long long int) q->path, | |
56 | q->version, b); | |
57 | } | |
58 | ||
59 | static int | |
60 | v9fs_printperm(char *buf, int buflen, int perm) | |
61 | { | |
62 | int n; | |
63 | char b[15]; | |
64 | ||
65 | n = 0; | |
66 | if (perm & V9FS_DMDIR) | |
67 | b[n++] = 'd'; | |
68 | if (perm & V9FS_DMAPPEND) | |
69 | b[n++] = 'a'; | |
70 | if (perm & V9FS_DMAUTH) | |
71 | b[n++] = 'A'; | |
72 | if (perm & V9FS_DMEXCL) | |
73 | b[n++] = 'l'; | |
74 | if (perm & V9FS_DMTMP) | |
75 | b[n++] = 't'; | |
76 | if (perm & V9FS_DMDEVICE) | |
77 | b[n++] = 'D'; | |
78 | if (perm & V9FS_DMSOCKET) | |
79 | b[n++] = 'S'; | |
80 | if (perm & V9FS_DMNAMEDPIPE) | |
81 | b[n++] = 'P'; | |
82 | if (perm & V9FS_DMSYMLINK) | |
83 | b[n++] = 'L'; | |
84 | b[n] = '\0'; | |
85 | ||
86 | return scnprintf(buf, buflen, "%s%03o", b, perm&077); | |
87 | } | |
88 | ||
89 | static int | |
90 | v9fs_printstat(char *buf, int buflen, struct v9fs_stat *st, int extended) | |
91 | { | |
92 | int n; | |
93 | ||
94 | n = scnprintf(buf, buflen, "'%.*s' '%.*s'", st->name.len, | |
95 | st->name.str, st->uid.len, st->uid.str); | |
96 | if (extended) | |
97 | n += scnprintf(buf+n, buflen-n, "(%d)", st->n_uid); | |
98 | ||
99 | n += scnprintf(buf+n, buflen-n, " '%.*s'", st->gid.len, st->gid.str); | |
100 | if (extended) | |
101 | n += scnprintf(buf+n, buflen-n, "(%d)", st->n_gid); | |
102 | ||
103 | n += scnprintf(buf+n, buflen-n, " '%.*s'", st->muid.len, st->muid.str); | |
104 | if (extended) | |
105 | n += scnprintf(buf+n, buflen-n, "(%d)", st->n_muid); | |
106 | ||
107 | n += scnprintf(buf+n, buflen-n, " q "); | |
108 | n += v9fs_printqid(buf+n, buflen-n, &st->qid); | |
109 | n += scnprintf(buf+n, buflen-n, " m "); | |
110 | n += v9fs_printperm(buf+n, buflen-n, st->mode); | |
111 | n += scnprintf(buf+n, buflen-n, " at %d mt %d l %lld", | |
112 | st->atime, st->mtime, (long long int) st->length); | |
113 | ||
114 | if (extended) | |
115 | n += scnprintf(buf+n, buflen-n, " ext '%.*s'", | |
116 | st->extension.len, st->extension.str); | |
117 | ||
118 | return n; | |
119 | } | |
120 | ||
121 | static int | |
122 | v9fs_dumpdata(char *buf, int buflen, u8 *data, int datalen) | |
123 | { | |
124 | int i, n; | |
125 | ||
126 | i = n = 0; | |
127 | while (i < datalen) { | |
128 | n += scnprintf(buf + n, buflen - n, "%02x", data[i]); | |
129 | if (i%4 == 3) | |
130 | n += scnprintf(buf + n, buflen - n, " "); | |
131 | if (i%32 == 31) | |
132 | n += scnprintf(buf + n, buflen - n, "\n"); | |
133 | ||
134 | i++; | |
135 | } | |
136 | n += scnprintf(buf + n, buflen - n, "\n"); | |
137 | ||
138 | return n; | |
139 | } | |
140 | ||
141 | static int | |
142 | v9fs_printdata(char *buf, int buflen, u8 *data, int datalen) | |
143 | { | |
144 | return v9fs_dumpdata(buf, buflen, data, datalen<16?datalen:16); | |
145 | } | |
146 | ||
147 | int | |
148 | v9fs_printfcall(char *buf, int buflen, struct v9fs_fcall *fc, int extended) | |
149 | { | |
150 | int i, ret, type, tag; | |
151 | ||
152 | if (!fc) | |
153 | return scnprintf(buf, buflen, "<NULL>"); | |
154 | ||
155 | type = fc->id; | |
156 | tag = fc->tag; | |
157 | ||
158 | ret = 0; | |
159 | switch (type) { | |
160 | case TVERSION: | |
161 | ret += scnprintf(buf+ret, buflen-ret, | |
162 | "Tversion tag %u msize %u version '%.*s'", tag, | |
163 | fc->params.tversion.msize, fc->params.tversion.version.len, | |
164 | fc->params.tversion.version.str); | |
165 | break; | |
166 | ||
167 | case RVERSION: | |
168 | ret += scnprintf(buf+ret, buflen-ret, | |
169 | "Rversion tag %u msize %u version '%.*s'", tag, | |
170 | fc->params.rversion.msize, fc->params.rversion.version.len, | |
171 | fc->params.rversion.version.str); | |
172 | break; | |
173 | ||
174 | case TAUTH: | |
175 | ret += scnprintf(buf+ret, buflen-ret, | |
176 | "Tauth tag %u afid %d uname '%.*s' aname '%.*s'", tag, | |
177 | fc->params.tauth.afid, fc->params.tauth.uname.len, | |
178 | fc->params.tauth.uname.str, fc->params.tauth.aname.len, | |
179 | fc->params.tauth.aname.str); | |
180 | break; | |
181 | ||
182 | case RAUTH: | |
183 | ret += scnprintf(buf+ret, buflen-ret, "Rauth tag %u qid ", tag); | |
184 | v9fs_printqid(buf+ret, buflen-ret, &fc->params.rauth.qid); | |
185 | break; | |
186 | ||
187 | case TATTACH: | |
188 | ret += scnprintf(buf+ret, buflen-ret, | |
189 | "Tattach tag %u fid %d afid %d uname '%.*s' aname '%.*s'", | |
190 | tag, fc->params.tattach.fid, fc->params.tattach.afid, | |
191 | fc->params.tattach.uname.len, fc->params.tattach.uname.str, | |
192 | fc->params.tattach.aname.len, fc->params.tattach.aname.str); | |
193 | break; | |
194 | ||
195 | case RATTACH: | |
196 | ret += scnprintf(buf+ret, buflen-ret, "Rattach tag %u qid ", tag); | |
197 | v9fs_printqid(buf+ret, buflen-ret, &fc->params.rattach.qid); | |
198 | break; | |
199 | ||
200 | case RERROR: | |
201 | ret += scnprintf(buf+ret, buflen-ret, "Rerror tag %u ename '%.*s'", | |
202 | tag, fc->params.rerror.error.len, | |
203 | fc->params.rerror.error.str); | |
204 | if (extended) | |
205 | ret += scnprintf(buf+ret, buflen-ret, " ecode %d\n", | |
206 | fc->params.rerror.errno); | |
207 | break; | |
208 | ||
209 | case TFLUSH: | |
210 | ret += scnprintf(buf+ret, buflen-ret, "Tflush tag %u oldtag %u", | |
211 | tag, fc->params.tflush.oldtag); | |
212 | break; | |
213 | ||
214 | case RFLUSH: | |
215 | ret += scnprintf(buf+ret, buflen-ret, "Rflush tag %u", tag); | |
216 | break; | |
217 | ||
218 | case TWALK: | |
219 | ret += scnprintf(buf+ret, buflen-ret, | |
220 | "Twalk tag %u fid %d newfid %d nwname %d", tag, | |
221 | fc->params.twalk.fid, fc->params.twalk.newfid, | |
222 | fc->params.twalk.nwname); | |
223 | for(i = 0; i < fc->params.twalk.nwname; i++) | |
224 | ret += scnprintf(buf+ret, buflen-ret," '%.*s'", | |
225 | fc->params.twalk.wnames[i].len, | |
226 | fc->params.twalk.wnames[i].str); | |
227 | break; | |
228 | ||
229 | case RWALK: | |
230 | ret += scnprintf(buf+ret, buflen-ret, "Rwalk tag %u nwqid %d", | |
231 | tag, fc->params.rwalk.nwqid); | |
232 | for(i = 0; i < fc->params.rwalk.nwqid; i++) | |
233 | ret += v9fs_printqid(buf+ret, buflen-ret, | |
234 | &fc->params.rwalk.wqids[i]); | |
235 | break; | |
236 | ||
237 | case TOPEN: | |
238 | ret += scnprintf(buf+ret, buflen-ret, | |
239 | "Topen tag %u fid %d mode %d", tag, | |
240 | fc->params.topen.fid, fc->params.topen.mode); | |
241 | break; | |
242 | ||
243 | case ROPEN: | |
244 | ret += scnprintf(buf+ret, buflen-ret, "Ropen tag %u", tag); | |
245 | ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.ropen.qid); | |
246 | ret += scnprintf(buf+ret, buflen-ret," iounit %d", | |
247 | fc->params.ropen.iounit); | |
248 | break; | |
249 | ||
250 | case TCREATE: | |
251 | ret += scnprintf(buf+ret, buflen-ret, | |
252 | "Tcreate tag %u fid %d name '%.*s' perm ", tag, | |
253 | fc->params.tcreate.fid, fc->params.tcreate.name.len, | |
254 | fc->params.tcreate.name.str); | |
255 | ||
256 | ret += v9fs_printperm(buf+ret, buflen-ret, fc->params.tcreate.perm); | |
257 | ret += scnprintf(buf+ret, buflen-ret, " mode %d", | |
258 | fc->params.tcreate.mode); | |
259 | break; | |
260 | ||
261 | case RCREATE: | |
262 | ret += scnprintf(buf+ret, buflen-ret, "Rcreate tag %u", tag); | |
263 | ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.rcreate.qid); | |
264 | ret += scnprintf(buf+ret, buflen-ret, " iounit %d", | |
265 | fc->params.rcreate.iounit); | |
266 | break; | |
267 | ||
268 | case TREAD: | |
269 | ret += scnprintf(buf+ret, buflen-ret, | |
270 | "Tread tag %u fid %d offset %lld count %u", tag, | |
271 | fc->params.tread.fid, | |
272 | (long long int) fc->params.tread.offset, | |
273 | fc->params.tread.count); | |
274 | break; | |
275 | ||
276 | case RREAD: | |
277 | ret += scnprintf(buf+ret, buflen-ret, | |
278 | "Rread tag %u count %u data ", tag, | |
279 | fc->params.rread.count); | |
280 | ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.rread.data, | |
281 | fc->params.rread.count); | |
282 | break; | |
283 | ||
284 | case TWRITE: | |
285 | ret += scnprintf(buf+ret, buflen-ret, | |
286 | "Twrite tag %u fid %d offset %lld count %u data ", | |
287 | tag, fc->params.twrite.fid, | |
288 | (long long int) fc->params.twrite.offset, | |
289 | fc->params.twrite.count); | |
290 | ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.twrite.data, | |
291 | fc->params.twrite.count); | |
292 | break; | |
293 | ||
294 | case RWRITE: | |
295 | ret += scnprintf(buf+ret, buflen-ret, "Rwrite tag %u count %u", | |
296 | tag, fc->params.rwrite.count); | |
297 | break; | |
298 | ||
299 | case TCLUNK: | |
300 | ret += scnprintf(buf+ret, buflen-ret, "Tclunk tag %u fid %d", | |
301 | tag, fc->params.tclunk.fid); | |
302 | break; | |
303 | ||
304 | case RCLUNK: | |
305 | ret += scnprintf(buf+ret, buflen-ret, "Rclunk tag %u", tag); | |
306 | break; | |
307 | ||
308 | case TREMOVE: | |
309 | ret += scnprintf(buf+ret, buflen-ret, "Tremove tag %u fid %d", | |
310 | tag, fc->params.tremove.fid); | |
311 | break; | |
312 | ||
313 | case RREMOVE: | |
314 | ret += scnprintf(buf+ret, buflen-ret, "Rremove tag %u", tag); | |
315 | break; | |
316 | ||
317 | case TSTAT: | |
318 | ret += scnprintf(buf+ret, buflen-ret, "Tstat tag %u fid %d", | |
319 | tag, fc->params.tstat.fid); | |
320 | break; | |
321 | ||
322 | case RSTAT: | |
323 | ret += scnprintf(buf+ret, buflen-ret, "Rstat tag %u ", tag); | |
324 | ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.rstat.stat, | |
325 | extended); | |
326 | break; | |
327 | ||
328 | case TWSTAT: | |
329 | ret += scnprintf(buf+ret, buflen-ret, "Twstat tag %u fid %d ", | |
330 | tag, fc->params.twstat.fid); | |
331 | ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.twstat.stat, | |
332 | extended); | |
333 | break; | |
334 | ||
335 | case RWSTAT: | |
336 | ret += scnprintf(buf+ret, buflen-ret, "Rwstat tag %u", tag); | |
337 | break; | |
338 | ||
339 | default: | |
340 | ret += scnprintf(buf+ret, buflen-ret, "unknown type %d", type); | |
341 | break; | |
342 | } | |
343 | ||
344 | return ret; | |
345 | } |