devproc: change user from char* to struct username
[akaros.git] / kern / drivers / dev / root.c
index 5edd579..12f35e5 100644 (file)
@@ -1,4 +1,31 @@
-// INFERNO
+/* 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 <vfs.h>
 #include <kfs.h>
 #include <slab.h>
 #include <ip.h>
 #include <umem.h>
 
+struct dev rootdevtab;
+
+static char *devname(void)
+{
+       return rootdevtab.name;
+}
+
 /* make it a power of 2 and nobody gets hurt */
 #define MAXFILE 1024
 int rootmaxq = MAXFILE;
 int inumber = 13;
 
 /* TODO:
- *  - fix DOTDOT in gen.
  *  - synchronization!  what needs protection from concurrent use, etc.
  *     - clean up documentation and whatnot
  *     - does remove, mkdir, rmdir work?
@@ -42,21 +75,41 @@ int inumber = 13;
  * dotdot is .., ptr is data (for files)
  * size is # elements (for dirs)
  * *sizep is a pointer for reasons not understood.
- * next is the sibling. For a dir, it's the first element after '.'.
+ * child is the qid.path of the first child of a directory.
+ * Possibly 0 == no child.
+ * To find the next sibling (in a directory), look at roottab[i].qid.vers.
+ *
  *     int     dotdot;
- *      int     child; 
+ *      int     child;
  *     void    *ptr;
  *     int     size;
  *     int     *sizep;
- * 
- * entry is empty if type is 0. We look in roottab to determine that. 
+ *
+ * entry is empty if type is 0. We look in roottab to determine that.
 */
 /* we pack the qid as follows: path is the index, vers is ., and type is type */
 
 /* Inferno seems to want to: perm |= DMDIR.  It gets checked in other places.
  * NxM didn't want this, IIRC.
  *
- * Also note that "" (/, #r, whatever) has no vers/next/sibling. */
+ * Also note that "" (/, #root, whatever) has no vers/next/sibling.
+ *
+ * If you want to add new entries, add it to the roottab such that the linked
+ * list of indexes is a cycle (change the last current one), then add an entry
+ * to rootdata, and then change the first rootdata entry to have another entry.
+ * Yeah, it's a pain in the ass.
+ *
+ * To add subdirectories, or any child of a directory, the files (e.g. env_dir1)
+ * go in roottab.  Children of a parent are linked with their vers (note
+ * env_dir1 points to env_dir2), and the last item's vers = 0.  These files need
+ * their dotdot set in rootdata to the qid of their parent.  The directory that
+ * has children needs its child pointer set to the first qid in the list, and
+ * its data pointer must point to the roottab entry for the child.  This also
+ * means that all child entries in roottab for a parent must be contiguous.
+ *
+ * Yeah, it's a pain in the ass.  And, given this structure, it probably can't
+ * grow dynamically (I think we assume roottab[i] = entry for qid.path all over
+ * the place - imagine what happens if we wanted to squeeze in a new entry). */
 struct dirtab roottab[MAXFILE] = {
        {"", {0, 0, QTDIR}, 0, DMDIR | 0777},
        {"chan", {1, 2, QTDIR}, 0, DMDIR | 0777},
@@ -70,7 +123,10 @@ struct dirtab roottab[MAXFILE] = {
        {"env", {9, 10, QTDIR}, 0, DMDIR | 0777},
        {"root", {10, 11, QTDIR}, 0, DMDIR | 0777},
        {"srv", {11, 12, QTDIR}, 0, DMDIR | 0777},
-       {"mnt", {12, 0, QTDIR}, 0, DMDIR | 0777},
+       {"mnt", {12, 13, QTDIR}, 0, DMDIR | 0777},
+       {"proc", {13, 0, QTDIR}, 0, DMDIR | 0777},
+       {"env_dir1", {14, 15, QTDIR}, 0, DMDIR | 0777},
+       {"env_dir2", {15, 0, QTDIR}, 0, DMDIR | 0777},
 };
 
 struct rootdata {
@@ -82,7 +138,7 @@ struct rootdata {
 };
 
 struct rootdata rootdata[MAXFILE] = {
-       {0,     1,       &roottab[1],    12,    NULL},
+       {0,     1,       &roottab[1],    13,    NULL},
        {0,     0,       NULL,   0,      NULL},
        {0,     0,       NULL,   0,      NULL},
        {0,     0,       NULL,   0,      NULL},
@@ -91,10 +147,13 @@ struct rootdata rootdata[MAXFILE] = {
        {0,     0,       NULL,   0,      NULL},
        {0,     0,       NULL,   0,      NULL},
        {0,     0,       NULL,   0,      NULL},
+       {0,     14,      &roottab[14],   2,      NULL},
        {0,     0,       NULL,   0,      NULL},
        {0,     0,       NULL,   0,      NULL},
        {0,     0,       NULL,   0,      NULL},
        {0,     0,       NULL,   0,      NULL},
+       {9,     0,       NULL,   0,      NULL},
+       {9,     0,       NULL,   0,      NULL},
 };
 
 /* this is super useful */
@@ -140,7 +199,7 @@ static int newentry(int parent)
        int n = findempty();
        int sib;
        if (n < 0)
-               error("#r. No more");
+               error(EFAIL, "#root. No more");
        printd("new entry is %d\n", n);
        /* add the new one to the head of the linked list.  vers is 'next' */
        roottab[n].qid.vers = rootdata[parent].child;
@@ -189,8 +248,8 @@ static struct chan *rootattach(char *spec)
 {
        struct chan *c;
        if (*spec)
-               error(Ebadspec);
-       c = devattach('r', spec);
+               error(EINVAL, ERROR_FIXME);
+       c = devattach(devname(), spec);
        mkqid(&c->qid, roottab[0].qid.path, roottab[0].qid.vers, QTDIR);
        return c;
 }
@@ -206,26 +265,10 @@ rootgen(struct chan *c, char *name,
               tab, nd, s, name);
 
        if (s == DEVDOTDOT) {
-               panic("this is busted");
                p = rootdata[c->qid.path].dotdot;
-               // XXX we need to set the vers too.  equiv to mkqid(&c->qid, ...)
-               c->qid.path = p;
-               c->qid.type = QTDIR;
-               name = "#r";
-               if (p != 0) {
-                       /* TODO: what is this doing?  do we want to walk the entire table,
-                        * or are we just walking the siblings of our parent? */
-                       for (i = p;;) {
-                               if (roottab[i].qid.path == c->qid.path) {
-                                       name = roottab[i].name;
-                                       break;
-                               }
-                               i = roottab[i].qid.vers;
-                               if (!i)
-                                       break;
-                       }
-               }
-               devdir(c, c->qid, name, 0, eve, 0777, dp);
+               c->qid = roottab[p].qid;
+               name = roottab[p].name;
+               devdir(c, c->qid, name, 0, eve.name, 0777, dp);
                return 1;
        }
 
@@ -234,7 +277,7 @@ rootgen(struct chan *c, char *name,
                if (s)
                        return -1;
                tab = &roottab[c->qid.path];
-               devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
+               devdir(c, tab->qid, tab->name, tab->length, eve.name, tab->perm, dp);
                return 1;
        }
 
@@ -244,9 +287,10 @@ rootgen(struct chan *c, char *name,
                tab = &roottab[rootdata[path].child];
                /* we're starting at a directory. It might be '.' */
                for (iter = 0, i = rootdata[path].child; /* break */; iter++) {
-                       if(strcmp(tab->name, name) == 0){
+                       if (strncmp(tab->name, name, KNAMELEN) == 0) {
                                printd("Rootgen returns 1 for %s\n", name);
-                               devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
+                               devdir(c, tab->qid, tab->name, tab->length, eve.name, tab->perm,
+                                      dp);
                                printd("return 1 with [%d, %d, %d]\n", dp->qid.path,
                                       dp->qid.vers, dp->qid.type);
                                return 1;
@@ -283,7 +327,7 @@ rootgen(struct chan *c, char *name,
                return -1;
        }
        printd("root scan find returns path %p name %s\n", tab->qid.path, tab->name);
-       devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
+       devdir(c, tab->qid, tab->name, tab->length, eve.name, tab->perm, dp);
        return 1;
 }
 
@@ -326,7 +370,7 @@ static void rootcreate(struct chan *c, char *name, int omode, uint32_t perm)
        /* need to filter openmode so that it gets only the access-type bits */
        omode = openmode(omode);
        c->mode = openmode(omode);
-       printd("rootcreate: c %p, name %s, omode %o, perm %x\n", 
+       printd("rootcreate: c %p, name %s, omode %o, perm %x\n",
               c, name, omode, perm);
        /* find an empty slot */
        int path = c->qid.path;
@@ -366,7 +410,7 @@ static long rootread(struct chan *c, void *buf, long n, int64_t offset)
                n = len - offset;
        data = rootdata[p].ptr;
        /* we can't really claim it has to be a user address. Lots of
-        * kernel things read directly, e.g. /dev/reboot, #V, etc.
+        * kernel things read directly, e.g. /dev/reboot, #nix, etc.
         * Address validation should be done in the syscall layer.
         */
        memcpy(buf, data + offset, n);
@@ -384,19 +428,20 @@ static long rootwrite(struct chan *c, void *a, long n, int64_t off)
        struct dirtab *r = &roottab[c->qid.path];
 
        if (off < 0)
-               error("rootwrite: offset < 0!");
+               error(EFAIL, "rootwrite: offset < 0!");
 
        if (off + n > rd->size){
                void *p;
-               p = krealloc(rd->ptr, off + n, KMALLOC_WAIT);
+               p = krealloc(rd->ptr, off + n, MEM_WAIT);
                if (! p)
-                       error("rootwrite: could not grow the file to %d bytes", off + n);
+                       error(EFAIL, "rootwrite: could not grow the file to %d bytes",
+                                 off + n);
                rd->ptr = p;
                rd->size = off + n;
        }
        assert(current);
        if (memcpy_from_user_errno(current, rd->ptr + off, a, n) < 0)
-               error("%s: bad user addr %p", __FUNCTION__, a);
+               error(EFAIL, "%s: bad user addr %p", __FUNCTION__, a);
 
        return n;
 }
@@ -412,11 +457,11 @@ static int rootwstat(struct chan *c, uint8_t *m_buf, int m_buf_sz)
        /* common trick in wstats.  we want the dir and any strings in the M.  the
         * strings are smaller than entire M (strings plus other M).  the strings
         * will be placed right after the dir (dir[1]) */
-       dir = kzmalloc(sizeof(struct dir) + m_buf_sz, KMALLOC_WAIT);
+       dir = kzmalloc(sizeof(struct dir) + m_buf_sz, MEM_WAIT);
        m_sz = convM2D(m_buf, m_buf_sz, &dir[0], (char*)&dir[1]);
        if (!m_sz) {
                kfree(dir);
-               error(Eshortstat);
+               error(ENODATA, ERROR_FIXME);
        }
        /* TODO: handle more things than just the mode */
        if (!emptystr(dir->name))
@@ -429,23 +474,22 @@ static int rootwstat(struct chan *c, uint8_t *m_buf, int m_buf_sz)
 }
 
 struct dev rootdevtab __devtab = {
-       'r',
-       "root",
-       devreset,
-       rootinit,
-       devshutdown,
-       rootattach,
-       rootwalk,
-       rootstat,
-       rootopen,
-       rootcreate,
-       rootclose,
-       rootread,
-       devbread,
-       rootwrite,
-       devbwrite,
-       devremove,
-       rootwstat,
-       devpower,
-       devchaninfo,
+       .name = "root",
+       .reset = devreset,
+       .init = rootinit,
+       .shutdown = devshutdown,
+       .attach = rootattach,
+       .walk = rootwalk,
+       .stat = rootstat,
+       .open = rootopen,
+       .create = rootcreate,
+       .close = rootclose,
+       .read = rootread,
+       .bread = devbread,
+       .write = rootwrite,
+       .bwrite = devbwrite,
+       .remove = devremove,
+       .wstat = rootwstat,
+       .power = devpower,
+       .chaninfo = devchaninfo,
 };