9ns: move the symlink check after the mount check
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 24 Apr 2019 01:52:17 +0000 (21:52 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 24 Apr 2019 02:04:18 +0000 (22:04 -0400)
Although you can't bind a symlink (so that it is the domount side of a
mount point), the code is a bit cleaner if we do the symlink check after
the 'mount/nomount' spot.

Also, if we ever build in support for binding symlinks (src_path / WHAT)
onto the namespace, then we'll already have support for that on the
intermediate path names in a walk.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/src/ns/chan.c

index 459e532..26d812b 100644 (file)
@@ -894,27 +894,7 @@ int walk(struct chan **cp, char **names, int nnames, struct walk_helper *wh,
                                        return -1;
                                }
                                n = wq->nqid;
-                               if (wq->clone->qid.type & QTSYMLINK) {
-                                       nc = walk_symlink(wq->clone, wh, nnames
-                                                         - nhave - n);
-                                       if (!nc) {
-                                               /* walk_symlink() set error.
-                                                * This seems to be the standard
-                                                * walk() error-cleanup. */
-                                               if (nerror)
-                                                       *nerror = nhave +
-                                                               wq->nqid;
-                                               cclose(c);
-                                               cclose(wq->clone);
-                                               cnameclose(cname);
-                                               kfree(wq);
-                                               if (mh != NULL)
-                                                       putmhead(mh);
-                                               return -1;
-                                       }
-                               } else {
-                                       nc = wq->clone;
-                               }
+                               nc = wq->clone;
                        } else {        /* stopped early, at a mount point */
                                if (wq->clone != NULL) {
                                        cclose(wq->clone);
@@ -923,6 +903,26 @@ int walk(struct chan **cp, char **names, int nnames, struct walk_helper *wh,
                                lastmountpoint = nc;
                                n = i + 1;
                        }
+                       if (nc->qid.type & QTSYMLINK) {
+                               struct chan *old_nc = nc;
+
+                               nc = walk_symlink(old_nc, wh,
+                                                 nnames - nhave - n);
+                               if (!nc) {
+                                       /* walk_symlink() set error.
+                                        * This seems to be the standard
+                                        * walk() error-cleanup. */
+                                       if (nerror)
+                                               *nerror = nhave + n;
+                                       cclose(c);
+                                       cclose(old_nc);
+                                       cnameclose(cname);
+                                       kfree(wq);
+                                       if (mh != NULL)
+                                               putmhead(mh);
+                                       return -1;
+                               }
+                       }
                        for (i = 0; i < n; i++)
                                cname = addelem(cname, names[nhave + i]);
                }