9ns: Add #gtfs
[akaros.git] / kern / src / ns / dev.c
index ffe3cfa..f041e67 100644 (file)
@@ -26,8 +26,6 @@
  * 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 <kmalloc.h>
 #include <kref.h>
 #include <cpio.h>
 #include <pmap.h>
 #include <smp.h>
-#include <ip.h>
+#include <net/ip.h>
 
 extern uint32_t kerndate;
-extern char *eve;
+extern struct username eve;
 
 void mkqid(struct qid *q, int64_t path, uint32_t vers, int type)
 {
@@ -68,6 +66,8 @@ void
 devdir(struct chan *c, struct qid qid, char *n,
           int64_t length, char *user, long perm, struct dir *db)
 {
+       struct timespec now = nsec2timespec(epoch_nsec());
+
        db->name = n;
        if (c->flag & CMSG)
                qid.type |= QTMOUNT;
@@ -76,12 +76,22 @@ devdir(struct chan *c, struct qid qid, char *n,
        db->dev = c->dev;
        db->mode = perm;
        db->mode |= qid.type << 24;
-       db->atime = seconds();
-       db->mtime = kerndate;
        db->length = length;
        db->uid = user;
-       db->gid = eve;
+       db->gid = eve.name;
        db->muid = user;
+       db->ext = NULL;
+       /* TODO: once we figure out what to do for uid/gid, then we can try to tie
+        * that to the n_uid.  Or just ignore it, and only use that as a
+        * pass-through for 9p2000.u. */
+       db->n_uid = 0;
+       db->n_gid = 0;
+       db->n_muid = 0;
+       /* TODO: what does devdir really want? */
+       db->atime = now;
+       db->btime = now;
+       db->ctime = now;
+       db->mtime = now;
 }
 
 /*
@@ -96,7 +106,15 @@ devdir(struct chan *c, struct qid qid, char *n,
  *
  * TODO(cross): Document devgen and clean this mess up. Devgen should probably
  * be removed and replaced with a smarter data structure.
- */
+ *
+ * Keep in mind that the expected behavior of gen functions that interoperate
+ * with dev functions (e.g. devdirread()) is that files are directly genned, but
+ * not directories.  Directories will fail to gen, and devstat() just makes
+ * something up.  See also:
+ * https://github.com/brho/plan9/blob/89d43d2262ad43eb4b26c2a8d6a27cfeddb33828/nix/sys/src/nix/port/dev.c#L74
+ *
+ * The comment about genning a file's siblings needs a grain of salt too.  Look
+ * through ipgen().  I think it's what I call "direct genning." */
 int
 devgen(struct chan *c, char *unused_name, struct dirtab *tab, int ntab,
        int i, struct dir *dp)
@@ -112,7 +130,7 @@ devgen(struct chan *c, char *unused_name, struct dirtab *tab, int ntab,
        }
        if (tab->qid.vers == -1)
                return 0;
-       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;
 }
 
@@ -250,9 +268,10 @@ Accept:
                                        printd("DEVWALK -1, i was %d, want path %p\n", i,
                                                   c->qid.path);
 Notfound:
+                                       set_error(ENOENT, "could not find name %s, dev %s", n,
+                                                     c->type == -1 ? "no dev" : devtab[c->type].name);
                                        if (j == 0)
-                                               error(ENOENT, ERROR_FIXME);
-                                       set_error(ENOENT, ERROR_FIXME);
+                                               error_jmp();
                                        goto Done;
                                case 0:
                                        printd("DEVWALK continue, i was %d\n", i);
@@ -283,13 +302,27 @@ Done:
        } else if (wq->clone) {
                /* attach cloned channel to same device */
                wq->clone->type = c->type;
+       } else {
+               /* Not sure this is possible, would like to know. */
+               warn_once("had enough names, but still no wq->clone");
        }
        return wq;
 }
 
-int
-devstat(struct chan *c, uint8_t * db, int n,
-               struct dirtab *tab, int ntab, Devgen * gen)
+/* Helper, makes a stat in @dp, given @n bytes, from chan @c's contents in @dir.
+ * Throws on error, returns the size used on success. */
+size_t dev_make_stat(struct chan *c, struct dir *dir, uint8_t *dp, size_t n)
+{
+       if (c->flag & CMSG)
+               dir->mode |= DMMOUNT;
+       n = convD2M(dir, dp, n);
+       if (n == 0)
+               error(EINVAL, ERROR_FIXME);
+       return n;
+}
+
+size_t devstat(struct chan *c, uint8_t *db, size_t n, struct dirtab *tab,
+               int ntab, Devgen *gen)
 {
        int i;
        struct dir dir;
@@ -309,7 +342,7 @@ devstat(struct chan *c, uint8_t * db, int n,
                                                for (elem = p = c->name->s; *p; p++)
                                                        if (*p == '/')
                                                                elem = p + 1;
-                                       devdir(c, c->qid, elem, 0, eve, DMDIR | 0555, &dir);
+                                       devdir(c, c->qid, elem, 0, eve.name, DMDIR | 0555, &dir);
                                        n = convD2M(&dir, db, n);
                                        if (n == 0)
                                                error(EINVAL, ERROR_FIXME);
@@ -324,14 +357,8 @@ devstat(struct chan *c, uint8_t * db, int n,
                        case 1:
                                printd("DEVSTAT gen returns path %p name %s, want path %p\n",
                                           dir.qid.path, dir.name, c->qid.path);
-                               if (c->qid.path == dir.qid.path) {
-                                       if (c->flag & CMSG)
-                                               dir.mode |= DMMOUNT;
-                                       n = convD2M(&dir, db, n);
-                                       if (n == 0)
-                                               error(EINVAL, ERROR_FIXME);
-                                       return n;
-                               }
+                               if (c->qid.path == dir.qid.path)
+                                       return dev_make_stat(c, &dir, db, n);
                                break;
                }
 }
@@ -375,25 +402,13 @@ devdirread(struct chan *c, char *d, long n,
 }
 
 /*
- * error(EPERM, ERROR_FIXME) if open permission not granted for up->env->user.
+ * Throws an error if open permission not granted for current->user.name
  */
 void devpermcheck(char *fileuid, uint32_t perm, int omode)
 {
-       int rwx;
-       /* select user, group, or other from the traditional rwxrwxrwx, shifting
-        * into the upper-most position */
-       if (strcmp(current->user, fileuid) == 0)
-               perm <<= 0;
-       else if (strcmp(current->user, eve) == 0)
-               perm <<= 3;
-       else
-               perm <<= 6;
-       /* translate omode into things like S_IRUSR (just one set of rwx------).
-        * Plan 9 originally only returned 0400 0200 0600 and 0100 here; it didn't
-        * seem to handle O_EXEC being mixed readable or writable. */
-       rwx = omode_to_rwx(omode);
-       if ((rwx & perm) != rwx)
-               error(EPERM, "devpermcheck(%s, 0%o, 0%o) failed", fileuid, perm, omode);
+       if (!caller_has_perms(fileuid, perm, omode))
+               error(EPERM, "permcheck(user: %s, rwx: 0%o, omode 0%o) failed",
+                     fileuid, perm, omode);
 }
 
 struct chan *devopen(struct chan *c, int omode, struct dirtab *tab, int ntab,
@@ -426,13 +441,13 @@ Return:
        return c;
 }
 
-void
-devcreate(struct chan *c, char *unused_char_p_t, int unused_int, uint32_t u)
+void devcreate(struct chan *c, char *unused_char_p_t, int unused_int,
+               uint32_t u, char *ext)
 {
        error(EPERM, ERROR_FIXME);
 }
 
-struct block *devbread(struct chan *c, long n, uint32_t offset)
+struct block *devbread(struct chan *c, size_t n, off64_t offset)
 {
        ERRSTACK(1);
        struct block *bp;
@@ -449,7 +464,7 @@ struct block *devbread(struct chan *c, long n, uint32_t offset)
        return bp;
 }
 
-long devbwrite(struct chan *c, struct block *bp, uint32_t offset)
+size_t devbwrite(struct chan *c, struct block *bp, off64_t offset)
 {
        ERRSTACK(1);
        long n;
@@ -470,7 +485,7 @@ void devremove(struct chan *c)
        error(EPERM, ERROR_FIXME);
 }
 
-int devwstat(struct chan *c, uint8_t * unused_uint8_p_t, int i)
+size_t devwstat(struct chan *c, uint8_t *unused_uint8_p_t, size_t i)
 {
        error(EPERM, ERROR_FIXME);
        return 0;