Kprof uses an IRQ alarm
[akaros.git] / kern / drivers / dev / root.c
index 6b5b7d0..5edd579 100644 (file)
@@ -365,13 +365,11 @@ static long rootread(struct chan *c, void *buf, long n, int64_t offset)
        if (offset + n > len)
                n = len - offset;
        data = rootdata[p].ptr;
-       /* we might call read from the kernel (load_elf()) */
-       if (current) {
-               if (memcpy_to_user_errno(current, buf, data + offset, n) < 0)
-                       error("%s: bad user addr %p", __FUNCTION__, buf);
-       } else {
-               memcpy(buf, data + offset, n);
-       }
+       /* we can't really claim it has to be a user address. Lots of
+        * kernel things read directly, e.g. /dev/reboot, #V, etc.
+        * Address validation should be done in the syscall layer.
+        */
+       memcpy(buf, data + offset, n);
        return n;
 }
 
@@ -403,6 +401,33 @@ static long rootwrite(struct chan *c, void *a, long n, int64_t off)
        return n;
 }
 
+static int rootwstat(struct chan *c, uint8_t *m_buf, int m_buf_sz)
+{
+       struct dirtab *file = &roottab[c->qid.path];
+       struct dir *dir;
+       int m_sz;
+
+       /* TODO: some security check, Eperm on error */
+
+       /* 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);
+       m_sz = convM2D(m_buf, m_buf_sz, &dir[0], (char*)&dir[1]);
+       if (!m_sz) {
+               kfree(dir);
+               error(Eshortstat);
+       }
+       /* TODO: handle more things than just the mode */
+       if (!emptystr(dir->name))
+               printk("[%s] attempted rename of %s to %s\n", __FUNCTION__,
+                      file->name, dir->name);  /* strncpy for this btw */
+       if (dir->mode != ~0UL)
+               file->perm = dir->mode | (file->qid.type == QTDIR ? DMDIR : 0);
+       kfree(dir);
+       return m_sz;
+}
+
 struct dev rootdevtab __devtab = {
        'r',
        "root",
@@ -420,7 +445,7 @@ struct dev rootdevtab __devtab = {
        rootwrite,
        devbwrite,
        devremove,
-       devwstat,
+       rootwstat,
        devpower,
        devchaninfo,
 };