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