1 #include <u.h>
2 #include <libc.h>
3 #include <fcall.h>
4
5 static uint dumpsome(char*, char*, char*, long);
6 static void fdirconv(char*, char*, Dir*);
7 static char *qidtype(char*, uchar);
8
9 #define QIDFMT "(%.16llux %lud %s)"
10
11 int
fcallfmt(Fmt * fmt)12 fcallfmt(Fmt *fmt)
13 {
14 Fcall *f;
15 int fid, type, tag, i;
16 char buf[512], tmp[200];
17 char *p, *e;
18 Dir *d;
19 Qid *q;
20
21 e = buf+sizeof(buf);
22 f = va_arg(fmt->args, Fcall*);
23 type = f->type;
24 fid = f->fid;
25 tag = f->tag;
26 switch(type){
27 case Tversion: /* 100 */
28 seprint(buf, e, "Tversion tag %ud msize %ud version '%s'", tag, f->msize, f->version);
29 break;
30 case Rversion:
31 seprint(buf, e, "Rversion tag %ud msize %ud version '%s'", tag, f->msize, f->version);
32 break;
33 case Tauth: /* 102 */
34 seprint(buf, e, "Tauth tag %ud afid %d uname %s aname %s", tag,
35 f->afid, f->uname, f->aname);
36 break;
37 case Rauth:
38 seprint(buf, e, "Rauth tag %ud qid " QIDFMT, tag,
39 f->aqid.path, f->aqid.vers, qidtype(tmp, f->aqid.type));
40 break;
41 case Tattach: /* 104 */
42 seprint(buf, e, "Tattach tag %ud fid %d afid %d uname %s aname %s", tag,
43 fid, f->afid, f->uname, f->aname);
44 break;
45 case Rattach:
46 seprint(buf, e, "Rattach tag %ud qid " QIDFMT, tag,
47 f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type));
48 break;
49 case Rerror: /* 107; 106 (Terror) illegal */
50 seprint(buf, e, "Rerror tag %ud ename %s", tag, f->ename);
51 break;
52 case Tflush: /* 108 */
53 seprint(buf, e, "Tflush tag %ud oldtag %ud", tag, f->oldtag);
54 break;
55 case Rflush:
56 seprint(buf, e, "Rflush tag %ud", tag);
57 break;
58 case Twalk: /* 110 */
59 p = seprint(buf, e, "Twalk tag %ud fid %d newfid %d nwname %d ", tag, fid, f->newfid, f->nwname);
60 if(f->nwname <= MAXWELEM)
61 for(i=0; i<f->nwname; i++)
62 p = seprint(p, e, "%d:%s ", i, f->wname[i]);
63 break;
64 case Rwalk:
65 p = seprint(buf, e, "Rwalk tag %ud nwqid %ud ", tag, f->nwqid);
66 if(f->nwqid <= MAXWELEM)
67 for(i=0; i<f->nwqid; i++){
68 q = &f->wqid[i];
69 p = seprint(p, e, "%d:" QIDFMT " ", i,
70 q->path, q->vers, qidtype(tmp, q->type));
71 }
72 break;
73 case Topen: /* 112 */
74 seprint(buf, e, "Topen tag %ud fid %ud mode %d", tag, fid, f->mode);
75 break;
76 case Ropen:
77 seprint(buf, e, "Ropen tag %ud qid " QIDFMT " iounit %ud ", tag,
78 f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type), f->iounit);
79 break;
80 case Tcreate: /* 114 */
81 seprint(buf, e, "Tcreate tag %ud fid %ud name %s perm %M mode %d", tag, fid, f->name, (ulong)f->perm, f->mode);
82 break;
83 case Rcreate:
84 seprint(buf, e, "Rcreate tag %ud qid " QIDFMT " iounit %ud ", tag,
85 f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type), f->iounit);
86 break;
87 case Tread: /* 116 */
88 seprint(buf, e, "Tread tag %ud fid %d offset %lld count %ud",
89 tag, fid, f->offset, f->count);
90 break;
91 case Rread:
92 p = seprint(buf, e, "Rread tag %ud count %ud ", tag, f->count);
93 dumpsome(p, e, f->data, f->count);
94 break;
95 case Twrite: /* 118 */
96 p = seprint(buf, e, "Twrite tag %ud fid %d offset %lld count %ud ",
97 tag, fid, f->offset, f->count);
98 dumpsome(p, e, f->data, f->count);
99 break;
100 case Rwrite:
101 seprint(buf, e, "Rwrite tag %ud count %ud", tag, f->count);
102 break;
103 case Tclunk: /* 120 */
104 seprint(buf, e, "Tclunk tag %ud fid %ud", tag, fid);
105 break;
106 case Rclunk:
107 seprint(buf, e, "Rclunk tag %ud", tag);
108 break;
109 case Tremove: /* 122 */
110 seprint(buf, e, "Tremove tag %ud fid %ud", tag, fid);
111 break;
112 case Rremove:
113 seprint(buf, e, "Rremove tag %ud", tag);
114 break;
115 case Tstat: /* 124 */
116 seprint(buf, e, "Tstat tag %ud fid %ud", tag, fid);
117 break;
118 case Rstat:
119 p = seprint(buf, e, "Rstat tag %ud ", tag);
120 if(f->nstat > sizeof tmp)
121 seprint(p, e, " stat(%d bytes)", f->nstat);
122 else{
123 d = (Dir*)tmp;
124 convM2D(f->stat, f->nstat, d, (char*)(d+1));
125 seprint(p, e, " stat ");
126 fdirconv(p+6, e, d);
127 }
128 break;
129 case Twstat: /* 126 */
130 p = seprint(buf, e, "Twstat tag %ud fid %ud", tag, fid);
131 if(f->nstat > sizeof tmp)
132 seprint(p, e, " stat(%d bytes)", f->nstat);
133 else{
134 d = (Dir*)tmp;
135 convM2D(f->stat, f->nstat, d, (char*)(d+1));
136 seprint(p, e, " stat ");
137 fdirconv(p+6, e, d);
138 }
139 break;
140 case Rwstat:
141 seprint(buf, e, "Rwstat tag %ud", tag);
142 break;
143 default:
144 seprint(buf, e, "unknown type %d", type);
145 }
146 return fmtstrcpy(fmt, buf);
147 }
148
149 static char*
qidtype(char * s,uchar t)150 qidtype(char *s, uchar t)
151 {
152 char *p;
153
154 p = s;
155 if(t & QTDIR)
156 *p++ = 'd';
157 if(t & QTAPPEND)
158 *p++ = 'a';
159 if(t & QTEXCL)
160 *p++ = 'l';
161 if(t & QTAUTH)
162 *p++ = 'A';
163 *p = '\0';
164 return s;
165 }
166
167 int
dirfmt(Fmt * fmt)168 dirfmt(Fmt *fmt)
169 {
170 char buf[160];
171
172 fdirconv(buf, buf+sizeof buf, va_arg(fmt->args, Dir*));
173 return fmtstrcpy(fmt, buf);
174 }
175
176 static void
fdirconv(char * buf,char * e,Dir * d)177 fdirconv(char *buf, char *e, Dir *d)
178 {
179 char tmp[16];
180
181 seprint(buf, e, "'%s' '%s' '%s' '%s' "
182 "q " QIDFMT " m %#luo "
183 "at %ld mt %ld l %lld "
184 "t %d d %d",
185 d->name, d->uid, d->gid, d->muid,
186 d->qid.path, d->qid.vers, qidtype(tmp, d->qid.type), d->mode,
187 d->atime, d->mtime, d->length,
188 d->type, d->dev);
189 }
190
191 /*
192 * dump out count (or DUMPL, if count is bigger) bytes from
193 * buf to ans, as a string if they are all printable,
194 * else as a series of hex bytes
195 */
196 #define DUMPL 64
197
198 static uint
dumpsome(char * ans,char * e,char * buf,long count)199 dumpsome(char *ans, char *e, char *buf, long count)
200 {
201 int i, printable;
202 char *p;
203
204 if(buf == nil){
205 seprint(ans, e, "<no data>");
206 return strlen(ans);
207 }
208 printable = 1;
209 if(count > DUMPL)
210 count = DUMPL;
211 for(i=0; i<count && printable; i++)
212 if((buf[i]<32 && buf[i] !='\n' && buf[i] !='\t') || (uchar)buf[i]>127)
213 printable = 0;
214 p = ans;
215 *p++ = '\'';
216 if(printable){
217 if(count > e-p-2)
218 count = e-p-2;
219 memmove(p, buf, count);
220 p += count;
221 }else{
222 if(2*count > e-p-2)
223 count = (e-p-2)/2;
224 for(i=0; i<count; i++){
225 if(i>0 && i%4==0)
226 *p++ = ' ';
227 sprint(p, "%2.2ux", buf[i]);
228 p += 2;
229 }
230 }
231 *p++ = '\'';
232 *p = 0;
233 return p - ans;
234 }
235