| /* Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. |
| * Portions Copyright © 1997-1999 Vita Nuova Limited |
| * Portions Copyright © 2000-2007 Vita Nuova Holdings Limited |
| * (www.vitanuova.com) |
| * Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others |
| * |
| * Modified for the Akaros operating system: |
| * Copyright (c) 2013-2014 The Regents of the University of California |
| * Copyright (c) 2013-2015 Google Inc. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a copy |
| * of this software and associated documentation files (the "Software"), to deal |
| * in the Software without restriction, including without limitation the rights |
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| * copies of the Software, and to permit persons to whom the Software is |
| * furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included in |
| * all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| * SOFTWARE. */ |
| |
| #include <slab.h> |
| #include <kmalloc.h> |
| #include <kref.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <assert.h> |
| #include <error.h> |
| #include <cpio.h> |
| #include <pmap.h> |
| #include <smp.h> |
| #include <net/ip.h> |
| |
| static uint8_t *pstring(uint8_t *p, char *s) |
| { |
| unsigned int n; |
| |
| if (s == NULL) { |
| PBIT16(p, 0); |
| p += BIT16SZ; |
| return p; |
| } |
| |
| n = strlen(s); |
| PBIT16(p, n); |
| p += BIT16SZ; |
| memmove(p, s, n); |
| p += n; |
| return p; |
| } |
| |
| static uint8_t *pqid(uint8_t *p, struct qid *q) |
| { |
| PBIT8(p, q->type); |
| p += BIT8SZ; |
| PBIT32(p, q->vers); |
| p += BIT32SZ; |
| PBIT64(p, q->path); |
| p += BIT64SZ; |
| return p; |
| } |
| |
| static unsigned int stringsz(char *s) |
| { |
| if (s == NULL) |
| return BIT16SZ; |
| |
| return BIT16SZ + strlen(s); |
| } |
| |
| unsigned int sizeS2M(struct fcall *f) |
| { |
| unsigned int n; |
| int i; |
| |
| n = 0; |
| n += BIT32SZ; /* size */ |
| n += BIT8SZ; /* type */ |
| n += BIT16SZ; /* tag */ |
| |
| switch (f->type) { |
| default: |
| return 0; |
| |
| case Tversion: |
| n += BIT32SZ; |
| n += stringsz(f->version); |
| break; |
| |
| case Tflush: |
| n += BIT16SZ; |
| break; |
| |
| case Tauth: |
| n += BIT32SZ; |
| n += stringsz(f->uname); |
| n += stringsz(f->aname); |
| break; |
| |
| case Tattach: |
| n += BIT32SZ; |
| n += BIT32SZ; |
| n += stringsz(f->uname); |
| n += stringsz(f->aname); |
| break; |
| |
| case Twalk: |
| n += BIT32SZ; |
| n += BIT32SZ; |
| n += BIT16SZ; |
| for (i = 0; i < f->nwname; i++) |
| n += stringsz(f->wname[i]); |
| break; |
| |
| case Topen: |
| n += BIT32SZ; |
| n += BIT8SZ; |
| break; |
| |
| case Tcreate: |
| n += BIT32SZ; |
| n += stringsz(f->name); |
| n += BIT32SZ; |
| n += BIT8SZ; |
| break; |
| |
| case Tread: |
| n += BIT32SZ; |
| n += BIT64SZ; |
| n += BIT32SZ; |
| break; |
| |
| case Twrite: |
| n += BIT32SZ; |
| n += BIT64SZ; |
| n += BIT32SZ; |
| n += f->count; |
| break; |
| |
| case Tclunk: |
| case Tremove: |
| n += BIT32SZ; |
| break; |
| |
| case Tstat: |
| n += BIT32SZ; |
| break; |
| |
| case Twstat: |
| n += BIT32SZ; |
| n += BIT16SZ; |
| n += f->nstat; |
| break; |
| |
| |
| |
| case Rversion: |
| n += BIT32SZ; |
| n += stringsz(f->version); |
| break; |
| |
| case Rerror: |
| n += stringsz(f->ename); |
| break; |
| |
| case Rflush: |
| break; |
| |
| case Rauth: |
| n += QIDSZ; |
| break; |
| |
| case Rattach: |
| n += QIDSZ; |
| break; |
| |
| case Rwalk: |
| n += BIT16SZ; |
| n += f->nwqid * QIDSZ; |
| break; |
| |
| case Ropen: |
| case Rcreate: |
| n += QIDSZ; |
| n += BIT32SZ; |
| break; |
| |
| case Rread: |
| n += BIT32SZ; |
| n += f->count; |
| break; |
| |
| case Rwrite: |
| n += BIT32SZ; |
| break; |
| |
| case Rclunk: |
| break; |
| |
| case Rremove: |
| break; |
| |
| case Rstat: |
| n += BIT16SZ; |
| n += f->nstat; |
| break; |
| |
| case Rwstat: |
| break; |
| } |
| return n; |
| } |
| |
| unsigned int convS2M(struct fcall *f, uint8_t * ap, unsigned int nap) |
| { |
| uint8_t *p; |
| unsigned int i, size; |
| |
| size = sizeS2M(f); |
| if (size == 0) |
| return 0; |
| if (size > nap) |
| return 0; |
| |
| p = (uint8_t *) ap; |
| |
| PBIT32(p, size); |
| p += BIT32SZ; |
| PBIT8(p, f->type); |
| p += BIT8SZ; |
| PBIT16(p, f->tag); |
| p += BIT16SZ; |
| |
| switch (f->type) { |
| default: |
| return 0; |
| |
| case Tversion: |
| PBIT32(p, f->msize); |
| p += BIT32SZ; |
| p = pstring(p, f->version); |
| break; |
| |
| case Tflush: |
| PBIT16(p, f->oldtag); |
| p += BIT16SZ; |
| break; |
| |
| case Tauth: |
| PBIT32(p, f->afid); |
| p += BIT32SZ; |
| p = pstring(p, f->uname); |
| p = pstring(p, f->aname); |
| break; |
| |
| case Tattach: |
| PBIT32(p, f->fid); |
| p += BIT32SZ; |
| PBIT32(p, f->afid); |
| p += BIT32SZ; |
| p = pstring(p, f->uname); |
| p = pstring(p, f->aname); |
| break; |
| |
| case Twalk: |
| PBIT32(p, f->fid); |
| p += BIT32SZ; |
| PBIT32(p, f->newfid); |
| p += BIT32SZ; |
| PBIT16(p, f->nwname); |
| p += BIT16SZ; |
| if (f->nwname > MAXWELEM) |
| return 0; |
| for (i = 0; i < f->nwname; i++) |
| p = pstring(p, f->wname[i]); |
| break; |
| |
| case Topen: |
| PBIT32(p, f->fid); |
| p += BIT32SZ; |
| PBIT8(p, f->mode); |
| p += BIT8SZ; |
| break; |
| |
| case Tcreate: |
| PBIT32(p, f->fid); |
| p += BIT32SZ; |
| p = pstring(p, f->name); |
| PBIT32(p, f->perm); |
| p += BIT32SZ; |
| PBIT8(p, f->mode); |
| p += BIT8SZ; |
| break; |
| |
| case Tread: |
| PBIT32(p, f->fid); |
| p += BIT32SZ; |
| PBIT64(p, f->offset); |
| p += BIT64SZ; |
| PBIT32(p, f->count); |
| p += BIT32SZ; |
| break; |
| |
| case Twrite: |
| PBIT32(p, f->fid); |
| p += BIT32SZ; |
| PBIT64(p, f->offset); |
| p += BIT64SZ; |
| PBIT32(p, f->count); |
| p += BIT32SZ; |
| memmove(p, f->data, f->count); |
| p += f->count; |
| break; |
| |
| case Tclunk: |
| case Tremove: |
| PBIT32(p, f->fid); |
| p += BIT32SZ; |
| break; |
| |
| case Tstat: |
| PBIT32(p, f->fid); |
| p += BIT32SZ; |
| break; |
| |
| case Twstat: |
| PBIT32(p, f->fid); |
| p += BIT32SZ; |
| PBIT16(p, f->nstat); |
| p += BIT16SZ; |
| memmove(p, f->stat, f->nstat); |
| p += f->nstat; |
| break; |
| |
| |
| |
| case Rversion: |
| PBIT32(p, f->msize); |
| p += BIT32SZ; |
| p = pstring(p, f->version); |
| break; |
| |
| case Rerror: |
| p = pstring(p, f->ename); |
| break; |
| |
| case Rflush: |
| break; |
| |
| case Rauth: |
| p = pqid(p, &f->aqid); |
| break; |
| |
| case Rattach: |
| p = pqid(p, &f->qid); |
| break; |
| |
| case Rwalk: |
| PBIT16(p, f->nwqid); |
| p += BIT16SZ; |
| if (f->nwqid > MAXWELEM) |
| return 0; |
| for (i = 0; i < f->nwqid; i++) |
| p = pqid(p, &f->wqid[i]); |
| break; |
| |
| case Ropen: |
| case Rcreate: |
| p = pqid(p, &f->qid); |
| PBIT32(p, f->iounit); |
| p += BIT32SZ; |
| break; |
| |
| case Rread: |
| PBIT32(p, f->count); |
| p += BIT32SZ; |
| memmove(p, f->data, f->count); |
| p += f->count; |
| break; |
| |
| case Rwrite: |
| PBIT32(p, f->count); |
| p += BIT32SZ; |
| break; |
| |
| case Rclunk: |
| break; |
| |
| case Rremove: |
| break; |
| |
| case Rstat: |
| PBIT16(p, f->nstat); |
| p += BIT16SZ; |
| memmove(p, f->stat, f->nstat); |
| p += f->nstat; |
| break; |
| |
| case Rwstat: |
| break; |
| } |
| if (size != p - ap) |
| return 0; |
| return size; |
| } |