Added set_error() API to have a single point of entry for setting for errno and errstr.
[akaros.git] / kern / src / ns / dev.c
index 7c7b324..a2db8bf 100644 (file)
@@ -118,11 +118,23 @@ struct chan *devclone(struct chan *c)
 {
        struct chan *nc;
 
 {
        struct chan *nc;
 
-       if (c->flag & COPEN)
-               panic("clone of open file type %s\n", devtab[c->type].name);
+       /* In plan 9, you couldn't clone an open chan.  We're allowing it, possibly
+        * foolishly.  The new chan is a non-open, "kernel internal" chan.  Note
+        * that c->flag isn't set, for instance.  c->mode is, which might be a
+        * problem.  The newchan should eventually have a device's open called on
+        * it, at which point it upgrades from a kernel internal chan to one that
+        * can refer to an object in the device (e.g. grab a refcnt on a
+        * conversation in #ip).
+        *
+        * Either we allow devclones of open chans, or O_PATH walks do not open a
+        * file.  It's nice to allow the device to do something for O_PATH, but
+        * perhaps that is not critical.  However, if we can't clone an opened chan,
+        * then we can *only* openat from an FD that is O_PATH, which is not the
+        * spec (and not as useful). */
+       if ((c->flag & COPEN) && !(c->flag & O_PATH))
+               panic("clone of non-O_PATH open file type %s\n", devtab[c->type].name);
 
        nc = newchan();
 
        nc = newchan();
-
        nc->type = c->type;
        nc->dev = c->dev;
        nc->mode = c->mode;
        nc->type = c->type;
        nc->dev = c->dev;
        nc->mode = c->mode;
@@ -173,7 +185,7 @@ struct walkqid *devwalk(struct chan *c,
        for (j = 0; j < nname; j++) {
                if (!(nc->qid.type & QTDIR)) {
                        if (j == 0)
        for (j = 0; j < nname; j++) {
                if (!(nc->qid.type & QTDIR)) {
                        if (j == 0)
-                               error(Enotdir);
+                               error(ENOTDIR, NULL);
                        goto Done;
                }
                n = name[j];
                        goto Done;
                }
                n = name[j];
@@ -204,10 +216,9 @@ Accept:
                                        printd("DEVWALK -1, i was %d, want path %p\n", i,
                                                   c->qid.path);
 Notfound:
                                        printd("DEVWALK -1, i was %d, want path %p\n", i,
                                                   c->qid.path);
 Notfound:
-                                       set_errno(ENOENT);
                                        if (j == 0)
                                        if (j == 0)
-                                               error(Enonexist);
-                                       set_errstr(Enonexist);
+                                               error(ENODEV, NULL);
+                                       set_error(ENOENT, NULL);
                                        goto Done;
                                case 0:
                                        printd("DEVWALK continue, i was %d\n", i);
                                        goto Done;
                                case 0:
                                        printd("DEVWALK continue, i was %d\n", i);
@@ -267,13 +278,13 @@ devstat(struct chan *c, uint8_t * db, int n,
                                        devdir(c, c->qid, elem, 0, eve, DMDIR | 0555, &dir);
                                        n = convD2M(&dir, db, n);
                                        if (n == 0)
                                        devdir(c, c->qid, elem, 0, eve, DMDIR | 0555, &dir);
                                        n = convD2M(&dir, db, n);
                                        if (n == 0)
-                                               error(Ebadarg);
+                                               error(EINVAL, NULL);
                                        return n;
                                }
                                printd("DEVSTAT fails:%s %llu\n", devtab[c->type].name,
                                           c->qid.path);
                                set_errno(ENOENT);
                                        return n;
                                }
                                printd("DEVSTAT fails:%s %llu\n", devtab[c->type].name,
                                           c->qid.path);
                                set_errno(ENOENT);
-                               error(Enonexist);
+                               error(ENODEV, NULL);
                        case 0:
                                printd("DEVSTAT got 0\n");
                                break;
                        case 0:
                                printd("DEVSTAT got 0\n");
                                break;
@@ -285,7 +296,7 @@ devstat(struct chan *c, uint8_t * db, int n,
                                                dir.mode |= DMMOUNT;
                                        n = convD2M(&dir, db, n);
                                        if (n == 0)
                                                dir.mode |= DMMOUNT;
                                        n = convD2M(&dir, db, n);
                                        if (n == 0)
-                                               error(Ebadarg);
+                                               error(EINVAL, NULL);
                                        return n;
                                }
                                break;
                                        return n;
                                }
                                break;
@@ -318,7 +329,7 @@ devdirread(struct chan *c, char *d, long n,
                                dsz = convD2M(&dir[0], (uint8_t *) d, n - m);
                                if (dsz <= BIT16SZ) {   /* <= not < because this isn't stat; read is stuck */
                                        if (m == 0)
                                dsz = convD2M(&dir[0], (uint8_t *) d, n - m);
                                if (dsz <= BIT16SZ) {   /* <= not < because this isn't stat; read is stuck */
                                        if (m == 0)
-                                               error(Eshort);
+                                               error(ENODATA, NULL);
                                        return m;
                                }
                                m += dsz;
                                        return m;
                                }
                                m += dsz;
@@ -331,7 +342,7 @@ devdirread(struct chan *c, char *d, long n,
 }
 
 /*
 }
 
 /*
- * error(Eperm) if open permission not granted for up->env->user.
+ * error(EPERM, NULL) if open permission not granted for up->env->user.
  */
 void devpermcheck(char *fileuid, uint32_t perm, int omode)
 {
  */
 void devpermcheck(char *fileuid, uint32_t perm, int omode)
 {
@@ -349,8 +360,7 @@ void devpermcheck(char *fileuid, uint32_t perm, int omode)
         * seem to handle O_EXEC being mixed readable or writable. */
        rwx = omode_to_rwx(omode);
        if ((rwx & perm) != rwx)
         * seem to handle O_EXEC being mixed readable or writable. */
        rwx = omode_to_rwx(omode);
        if ((rwx & perm) != rwx)
-               error("%s: devpermcheck(%s,0x%x,0x%x) failed", Eperm, fileuid, perm,
-                         omode);
+               error(EPERM, "devpermcheck(%s, 0%o, 0%o) failed", fileuid, perm, omode);
 }
 
 struct chan *devopen(struct chan *c, int omode, struct dirtab *tab, int ntab,
 }
 
 struct chan *devopen(struct chan *c, int omode, struct dirtab *tab, int ntab,
@@ -377,7 +387,7 @@ struct chan *devopen(struct chan *c, int omode, struct dirtab *tab, int ntab,
 Return:
        c->offset = 0;
        if ((c->qid.type & QTDIR) && (omode & O_WRITE))
 Return:
        c->offset = 0;
        if ((c->qid.type & QTDIR) && (omode & O_WRITE))
-               error("Tried opening dir with non-read-only mode %o", omode);
+               error(EACCES, "Tried opening dir with non-read-only mode %o", omode);
        c->mode = openmode(omode);
        c->flag |= COPEN;
        return c;
        c->mode = openmode(omode);
        c->flag |= COPEN;
        return c;
@@ -386,7 +396,7 @@ Return:
 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)
 {
-       error(Eperm);
+       error(EPERM, NULL);
 }
 
 struct block *devbread(struct chan *c, long n, uint32_t offset)
 }
 
 struct block *devbread(struct chan *c, long n, uint32_t offset)
@@ -396,7 +406,7 @@ struct block *devbread(struct chan *c, long n, uint32_t offset)
 
        bp = allocb(n);
        if (bp == 0)
 
        bp = allocb(n);
        if (bp == 0)
-               error(Enomem);
+               error(ENOMEM, NULL);
        if (waserror()) {
                freeb(bp);
                nexterror();
        if (waserror()) {
                freeb(bp);
                nexterror();
@@ -424,24 +434,24 @@ long devbwrite(struct chan *c, struct block *bp, uint32_t offset)
 
 void devremove(struct chan *c)
 {
 
 void devremove(struct chan *c)
 {
-       error(Eperm);
+       error(EPERM, NULL);
 }
 
 int devwstat(struct chan *c, uint8_t * unused_uint8_p_t, int i)
 {
 }
 
 int devwstat(struct chan *c, uint8_t * unused_uint8_p_t, int i)
 {
-       error(Eperm);
+       error(EPERM, NULL);
        return 0;
 }
 
 void devpower(int i)
 {
        return 0;
 }
 
 void devpower(int i)
 {
-       error(Eperm);
+       error(EPERM, NULL);
 }
 
 #if 0
 int devconfig(int unused_int, char *c, DevConf *)
 {
 }
 
 #if 0
 int devconfig(int unused_int, char *c, DevConf *)
 {
-       error(Eperm);
+       error(EPERM, NULL);
        return 0;
 }
 #endif
        return 0;
 }
 #endif
@@ -460,7 +470,7 @@ void validwstatname(char *name)
 {
        validname(name, 0);
        if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
 {
        validname(name, 0);
        if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
-               error(Efilename);
+               error(EINVAL, NULL);
 }
 
 struct dev *devbyname(char *name)
 }
 
 struct dev *devbyname(char *name)