fcallfmt.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) 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'", 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 Topenfd:        /* 98 */
           81                 seprint(buf, e, "Topenfd tag %ud fid %ud mode %d", tag, fid, f->mode);
           82                 break;
           83         case Ropenfd:
           84                 seprint(buf, e, "Ropenfd tag %ud qid " QIDFMT " iounit %ud unixfd %d", tag,
           85                         f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type), f->iounit, f->unixfd);
           86                 break;
           87         case Tcreate:        /* 114 */
           88                 seprint(buf, e, "Tcreate tag %ud fid %ud name %s perm %M mode %d", tag, fid, f->name, (ulong)f->perm, f->mode);
           89                 break;
           90         case Rcreate:
           91                 seprint(buf, e, "Rcreate tag %ud qid " QIDFMT " iounit %ud ", tag,
           92                         f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type), f->iounit);
           93                 break;
           94         case Tread:        /* 116 */
           95                 seprint(buf, e, "Tread tag %ud fid %d offset %lld count %ud",
           96                         tag, fid, f->offset, f->count);
           97                 break;
           98         case Rread:
           99                 p = seprint(buf, e, "Rread tag %ud count %ud ", tag, f->count);
          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 count %ud ",
          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->count);
          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.type), d->mode,
          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 }