convM2S.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
       ---
       convM2S.c (5598B)
       ---
            1 #include        <u.h>
            2 #include        <libc.h>
            3 #include        <fcall.h>
            4 
            5 static
            6 uchar*
            7 gstring(uchar *p, uchar *ep, char **s)
            8 {
            9         uint n;
           10 
           11         if(p+BIT16SZ > ep)
           12                 return nil;
           13         n = GBIT16(p);
           14         p += BIT16SZ - 1;
           15         if(p+n+1 > ep)
           16                 return nil;
           17         /* move it down, on top of count, to make room for '\0' */
           18         memmove(p, p + 1, n);
           19         p[n] = '\0';
           20         *s = (char*)p;
           21         p += n+1;
           22         return p;
           23 }
           24 
           25 static
           26 uchar*
           27 gqid(uchar *p, uchar *ep, Qid *q)
           28 {
           29         if(p+QIDSZ > ep)
           30                 return nil;
           31         q->type = GBIT8(p);
           32         p += BIT8SZ;
           33         q->vers = GBIT32(p);
           34         p += BIT32SZ;
           35         q->path = GBIT64(p);
           36         p += BIT64SZ;
           37         return p;
           38 }
           39 
           40 /*
           41  * no syntactic checks.
           42  * three causes for error:
           43  *  1. message size field is incorrect
           44  *  2. input buffer too short for its own data (counts too long, etc.)
           45  *  3. too many names or qids
           46  * gqid() and gstring() return nil if they would reach beyond buffer.
           47  * main switch statement checks range and also can fall through
           48  * to test at end of routine.
           49  */
           50 uint
           51 convM2Su(uchar *ap, uint nap, Fcall *f, int dotu)
           52 {
           53         uchar *p, *ep;
           54         uint i, size;
           55 
           56         p = ap;
           57         ep = p + nap;
           58 
           59         if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep)
           60                 return 0;
           61         size = GBIT32(p);
           62         p += BIT32SZ;
           63 
           64         if(size < BIT32SZ+BIT8SZ+BIT16SZ)
           65                 return 0;
           66 
           67         f->type = GBIT8(p);
           68         p += BIT8SZ;
           69         f->tag = GBIT16(p);
           70         p += BIT16SZ;
           71 
           72         switch(f->type)
           73         {
           74         default:
           75                 return 0;
           76 
           77         case Tversion:
           78                 if(p+BIT32SZ > ep)
           79                         return 0;
           80                 f->msize = GBIT32(p);
           81                 p += BIT32SZ;
           82                 p = gstring(p, ep, &f->version);
           83                 break;
           84 
           85         case Tflush:
           86                 if(p+BIT16SZ > ep)
           87                         return 0;
           88                 f->oldtag = GBIT16(p);
           89                 p += BIT16SZ;
           90                 break;
           91 
           92         case Tauth:
           93                 if(p+BIT32SZ > ep)
           94                         return 0;
           95                 f->afid = GBIT32(p);
           96                 p += BIT32SZ;
           97                 p = gstring(p, ep, &f->uname);
           98                 if(p == nil)
           99                         break;
          100                 p = gstring(p, ep, &f->aname);
          101                 if(p == nil)
          102                         break;
          103                 f->uidnum = NOUID;
          104                 if(dotu){
          105                         if(p+BIT32SZ > ep)
          106                                 return 0;
          107                         f->uidnum = GBIT32(p);
          108                         p += BIT32SZ;
          109                 }
          110                 break;
          111 
          112         case Tattach:
          113                 if(p+BIT32SZ > ep)
          114                         return 0;
          115                 f->fid = GBIT32(p);
          116                 p += BIT32SZ;
          117                 if(p+BIT32SZ > ep)
          118                         return 0;
          119                 f->afid = GBIT32(p);
          120                 p += BIT32SZ;
          121                 p = gstring(p, ep, &f->uname);
          122                 if(p == nil)
          123                         break;
          124                 p = gstring(p, ep, &f->aname);
          125                 if(p == nil)
          126                         break;
          127                 f->uidnum = NOUID;
          128                 if(dotu){
          129                         if(p+BIT32SZ > ep)
          130                                 return 0;
          131                         f->uidnum = GBIT32(p);
          132                         p += BIT32SZ;
          133                 }
          134                 break;
          135 
          136         case Twalk:
          137                 if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep)
          138                         return 0;
          139                 f->fid = GBIT32(p);
          140                 p += BIT32SZ;
          141                 f->newfid = GBIT32(p);
          142                 p += BIT32SZ;
          143                 f->nwname = GBIT16(p);
          144                 p += BIT16SZ;
          145                 if(f->nwname > MAXWELEM)
          146                         return 0;
          147                 for(i=0; i<f->nwname; i++){
          148                         p = gstring(p, ep, &f->wname[i]);
          149                         if(p == nil)
          150                                 break;
          151                 }
          152                 break;
          153 
          154         case Topen:
          155         case Topenfd:
          156                 if(p+BIT32SZ+BIT8SZ > ep)
          157                         return 0;
          158                 f->fid = GBIT32(p);
          159                 p += BIT32SZ;
          160                 f->mode = GBIT8(p);
          161                 p += BIT8SZ;
          162                 break;
          163 
          164         case Tcreate:
          165                 if(p+BIT32SZ > ep)
          166                         return 0;
          167                 f->fid = GBIT32(p);
          168                 p += BIT32SZ;
          169                 p = gstring(p, ep, &f->name);
          170                 if(p == nil)
          171                         break;
          172                 if(p+BIT32SZ+BIT8SZ > ep)
          173                         return 0;
          174                 f->perm = GBIT32(p);
          175                 p += BIT32SZ;
          176                 f->mode = GBIT8(p);
          177                 p += BIT8SZ;
          178                 if(dotu)
          179                         p = gstring(p, ep, &f->extension);
          180                 break;
          181 
          182         case Tread:
          183                 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
          184                         return 0;
          185                 f->fid = GBIT32(p);
          186                 p += BIT32SZ;
          187                 f->offset = GBIT64(p);
          188                 p += BIT64SZ;
          189                 f->count = GBIT32(p);
          190                 p += BIT32SZ;
          191                 break;
          192 
          193         case Twrite:
          194                 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
          195                         return 0;
          196                 f->fid = GBIT32(p);
          197                 p += BIT32SZ;
          198                 f->offset = GBIT64(p);
          199                 p += BIT64SZ;
          200                 f->count = GBIT32(p);
          201                 p += BIT32SZ;
          202                 if(p+f->count > ep)
          203                         return 0;
          204                 f->data = (char*)p;
          205                 p += f->count;
          206                 break;
          207 
          208         case Tclunk:
          209         case Tremove:
          210                 if(p+BIT32SZ > ep)
          211                         return 0;
          212                 f->fid = GBIT32(p);
          213                 p += BIT32SZ;
          214                 break;
          215 
          216         case Tstat:
          217                 if(p+BIT32SZ > ep)
          218                         return 0;
          219                 f->fid = GBIT32(p);
          220                 p += BIT32SZ;
          221                 break;
          222 
          223         case Twstat:
          224                 if(p+BIT32SZ+BIT16SZ > ep)
          225                         return 0;
          226                 f->fid = GBIT32(p);
          227                 p += BIT32SZ;
          228                 f->nstat = GBIT16(p);
          229                 p += BIT16SZ;
          230                 if(p+f->nstat > ep)
          231                         return 0;
          232                 f->stat = p;
          233                 p += f->nstat;
          234                 break;
          235 
          236 /*
          237  */
          238         case Rversion:
          239                 if(p+BIT32SZ > ep)
          240                         return 0;
          241                 f->msize = GBIT32(p);
          242                 p += BIT32SZ;
          243                 p = gstring(p, ep, &f->version);
          244                 break;
          245 
          246         case Rerror:
          247                 p = gstring(p, ep, &f->ename);
          248                 f->errornum = 0;
          249                 if(dotu){
          250                         if(p+BIT32SZ > ep)
          251                                 return 0;
          252                         f->errornum = GBIT32(p);
          253                         p += BIT32SZ;
          254                 }
          255                 break;
          256 
          257         case Rflush:
          258                 break;
          259 
          260         case Rauth:
          261                 p = gqid(p, ep, &f->aqid);
          262                 if(p == nil)
          263                         break;
          264                 break;
          265 
          266         case Rattach:
          267                 p = gqid(p, ep, &f->qid);
          268                 if(p == nil)
          269                         break;
          270                 break;
          271 
          272         case Rwalk:
          273                 if(p+BIT16SZ > ep)
          274                         return 0;
          275                 f->nwqid = GBIT16(p);
          276                 p += BIT16SZ;
          277                 if(f->nwqid > MAXWELEM)
          278                         return 0;
          279                 for(i=0; i<f->nwqid; i++){
          280                         p = gqid(p, ep, &f->wqid[i]);
          281                         if(p == nil)
          282                                 break;
          283                 }
          284                 break;
          285 
          286         case Ropen:
          287         case Ropenfd:
          288         case Rcreate:
          289                 p = gqid(p, ep, &f->qid);
          290                 if(p == nil)
          291                         break;
          292                 if(p+BIT32SZ > ep)
          293                         return 0;
          294                 f->iounit = GBIT32(p);
          295                 p += BIT32SZ;
          296                 if(f->type == Ropenfd){
          297                         if(p+BIT32SZ > ep)
          298                                 return 0;
          299                         f->unixfd = GBIT32(p);
          300                         p += BIT32SZ;
          301                 }
          302                 break;
          303 
          304         case Rread:
          305                 if(p+BIT32SZ > ep)
          306                         return 0;
          307                 f->count = GBIT32(p);
          308                 p += BIT32SZ;
          309                 if(p+f->count > ep)
          310                         return 0;
          311                 f->data = (char*)p;
          312                 p += f->count;
          313                 break;
          314 
          315         case Rwrite:
          316                 if(p+BIT32SZ > ep)
          317                         return 0;
          318                 f->count = GBIT32(p);
          319                 p += BIT32SZ;
          320                 break;
          321 
          322         case Rclunk:
          323         case Rremove:
          324                 break;
          325 
          326         case Rstat:
          327                 if(p+BIT16SZ > ep)
          328                         return 0;
          329                 f->nstat = GBIT16(p);
          330                 p += BIT16SZ;
          331                 if(p+f->nstat > ep)
          332                         return 0;
          333                 f->stat = p;
          334                 p += f->nstat;
          335                 break;
          336 
          337         case Rwstat:
          338                 break;
          339         }
          340 
          341         if(p==nil || p>ep)
          342                 return 0;
          343         if(ap+size == p)
          344                 return size;
          345         return 0;
          346 }
          347 
          348 uint
          349 convM2S(uchar *ap, uint nap, Fcall *f)
          350 {
          351         return convM2Su(ap, nap, f, 0);
          352 }