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