fcallfmt.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
git clone git://git.suckless.org/9base | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
fcallfmt.c (6265B) | |
--- | |
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 | |
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'… | |
29 break; | |
30 case Rversion: | |
31 seprint(buf, e, "Rversion tag %ud msize %ud version '%s'… | |
32 break; | |
33 case Tauth: /* 102 */ | |
34 seprint(buf, e, "Tauth tag %ud afid %d uname %s aname %s… | |
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… | |
40 break; | |
41 case Tattach: /* 104 */ | |
42 seprint(buf, e, "Tattach tag %ud fid %d afid %d uname %s… | |
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.ty… | |
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->old… | |
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 nwna… | |
60 if(f->nwname <= MAXWELEM) | |
61 for(i=0; i<f->nwname; i++) | |
62 p = seprint(p, e, "%d:%s ", i, f->wname[… | |
63 break; | |
64 case Rwalk: | |
65 p = seprint(buf, e, "Rwalk tag %ud nwqid %ud ", tag, f->… | |
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… | |
71 } | |
72 break; | |
73 case Topen: /* 112 */ | |
74 seprint(buf, e, "Topen tag %ud fid %ud mode %d", tag, fi… | |
75 break; | |
76 case Ropen: | |
77 seprint(buf, e, "Ropen tag %ud qid " QIDFMT " iounit %ud… | |
78 f->qid.path, f->qid.vers, qidtype(tmp, f->qid.ty… | |
79 break; | |
80 case Topenfd: /* 98 */ | |
81 seprint(buf, e, "Topenfd tag %ud fid %ud mode %d", tag, … | |
82 break; | |
83 case Ropenfd: | |
84 seprint(buf, e, "Ropenfd tag %ud qid " QIDFMT " iounit %… | |
85 f->qid.path, f->qid.vers, qidtype(tmp, f->qid.ty… | |
86 break; | |
87 case Tcreate: /* 114 */ | |
88 seprint(buf, e, "Tcreate tag %ud fid %ud name %s perm %M… | |
89 break; | |
90 case Rcreate: | |
91 seprint(buf, e, "Rcreate tag %ud qid " QIDFMT " iounit %… | |
92 f->qid.path, f->qid.vers, qidtype(tmp, f->qid.ty… | |
93 break; | |
94 case Tread: /* 116 */ | |
95 seprint(buf, e, "Tread tag %ud fid %d offset %lld count … | |
96 tag, fid, f->offset, f->count); | |
97 break; | |
98 case Rread: | |
99 p = seprint(buf, e, "Rread tag %ud count %ud ", tag, f->… | |
100 dumpsome(p, e, f->data, f->count); | |
101 break; | |
102 case Twrite: /* 118 */ | |
103 p = seprint(buf, e, "Twrite tag %ud fid %d offset %lld c… | |
104 tag, fid, f->offset, f->count); | |
105 dumpsome(p, e, f->data, f->count); | |
106 break; | |
107 case Rwrite: | |
108 seprint(buf, e, "Rwrite tag %ud count %ud", tag, f->coun… | |
109 break; | |
110 case Tclunk: /* 120 */ | |
111 seprint(buf, e, "Tclunk tag %ud fid %ud", tag, fid); | |
112 break; | |
113 case Rclunk: | |
114 seprint(buf, e, "Rclunk tag %ud", tag); | |
115 break; | |
116 case Tremove: /* 122 */ | |
117 seprint(buf, e, "Tremove tag %ud fid %ud", tag, fid); | |
118 break; | |
119 case Rremove: | |
120 seprint(buf, e, "Rremove tag %ud", tag); | |
121 break; | |
122 case Tstat: /* 124 */ | |
123 seprint(buf, e, "Tstat tag %ud fid %ud", tag, fid); | |
124 break; | |
125 case Rstat: | |
126 p = seprint(buf, e, "Rstat tag %ud ", tag); | |
127 if(f->stat == nil || f->nstat > sizeof tmp) | |
128 seprint(p, e, " stat(%d bytes)", f->nstat); | |
129 else{ | |
130 d = (Dir*)tmp; | |
131 convM2D(f->stat, f->nstat, d, (char*)(d+1)); | |
132 seprint(p, e, " stat "); | |
133 fdirconv(p+6, e, d); | |
134 } | |
135 break; | |
136 case Twstat: /* 126 */ | |
137 p = seprint(buf, e, "Twstat tag %ud fid %ud", tag, fid); | |
138 if(f->stat == nil || f->nstat > sizeof tmp) | |
139 seprint(p, e, " stat(%d bytes)", f->nstat); | |
140 else{ | |
141 d = (Dir*)tmp; | |
142 convM2D(f->stat, f->nstat, d, (char*)(d+1)); | |
143 seprint(p, e, " stat "); | |
144 fdirconv(p+6, e, d); | |
145 } | |
146 break; | |
147 case Rwstat: | |
148 seprint(buf, e, "Rwstat tag %ud", tag); | |
149 break; | |
150 default: | |
151 seprint(buf, e, "unknown type %d", type); | |
152 } | |
153 return fmtstrcpy(fmt, buf); | |
154 } | |
155 | |
156 static char* | |
157 qidtype(char *s, uchar t) | |
158 { | |
159 char *p; | |
160 | |
161 p = s; | |
162 if(t & QTDIR) | |
163 *p++ = 'd'; | |
164 if(t & QTAPPEND) | |
165 *p++ = 'a'; | |
166 if(t & QTEXCL) | |
167 *p++ = 'l'; | |
168 if(t & QTAUTH) | |
169 *p++ = 'A'; | |
170 *p = '\0'; | |
171 return s; | |
172 } | |
173 | |
174 int | |
175 dirfmt(Fmt *fmt) | |
176 { | |
177 char buf[160]; | |
178 | |
179 fdirconv(buf, buf+sizeof buf, va_arg(fmt->args, Dir*)); | |
180 return fmtstrcpy(fmt, buf); | |
181 } | |
182 | |
183 static void | |
184 fdirconv(char *buf, char *e, Dir *d) | |
185 { | |
186 char tmp[16]; | |
187 | |
188 seprint(buf, e, "'%s' '%s' '%s' '%s' " | |
189 "q " QIDFMT " m %#luo " | |
190 "at %ld mt %ld l %lld " | |
191 "t %d d %d", | |
192 d->name, d->uid, d->gid, d->muid, | |
193 d->qid.path, d->qid.vers, qidtype(tmp, d->qid.ty… | |
194 d->atime, d->mtime, d->length, | |
195 d->type, d->dev); | |
196 } | |
197 | |
198 /* | |
199 * dump out count (or DUMPL, if count is bigger) bytes from | |
200 * buf to ans, as a string if they are all printable, | |
201 * else as a series of hex bytes | |
202 */ | |
203 #define DUMPL 64 | |
204 | |
205 static uint | |
206 dumpsome(char *ans, char *e, char *buf, long count) | |
207 { | |
208 int i, printable; | |
209 char *p; | |
210 | |
211 if(buf == nil){ | |
212 seprint(ans, e, "<no data>"); | |
213 return strlen(ans); | |
214 } | |
215 printable = 1; | |
216 if(count > DUMPL) | |
217 count = DUMPL; | |
218 for(i=0; i<count && printable; i++) | |
219 if((buf[i]!=0 && buf[i]<32) || (uchar)buf[i]>127) | |
220 printable = 0; | |
221 p = ans; | |
222 *p++ = '\''; | |
223 if(printable){ | |
224 if(2*count > e-p-2) | |
225 count = (e-p-2)/2; | |
226 for(i=0; i<count; i++){ | |
227 if(buf[i] == 0){ | |
228 *p++ = '\\'; | |
229 *p++ = '0'; | |
230 }else if(buf[i] == '\t'){ | |
231 *p++ = '\\'; | |
232 *p++ = 't'; | |
233 }else if(buf[i] == '\n'){ | |
234 *p++ = '\\'; | |
235 *p++ = 'n'; | |
236 }else | |
237 *p++ = buf[i]; | |
238 } | |
239 }else{ | |
240 if(2*count > e-p-2) | |
241 count = (e-p-2)/2; | |
242 for(i=0; i<count; i++){ | |
243 if(i>0 && i%4==0) | |
244 *p++ = ' '; | |
245 sprint(p, "%2.2ux", (uchar)buf[i]); | |
246 p += 2; | |
247 } | |
248 } | |
249 *p++ = '\''; | |
250 *p = 0; | |
251 assert(p < e); | |
252 return p - ans; | |
253 } |