sysrename: fix to take full paths. Currently not quite there
authorRonald G. Minnich <rminnich@google.com>
Fri, 25 Jul 2014 19:50:47 +0000 (19:50 +0000)
committerRonald G. Minnich <rminnich@google.com>
Fri, 25 Jul 2014 19:50:47 +0000 (19:50 +0000)
This includes the changes to make sys_rename work for arbitrary paths.
There's also a bit of prototype cleanup.

Doesn't quite work yet but that may be a go9p bug. The wstat is correct
when sent now.

I'm fairly sure the chan tests are right, I talked to the guys at BL
about them.

Signed-off-by: Ronald G. Minnich <rminnich@google.com>
kern/drivers/dev/mnt.c
kern/include/ns.h
kern/src/ns/chan.c
kern/src/ns/sysfile.c
kern/src/syscall.c
scripts/tagging/MAKETAGS

index 825ffc5..9f41be7 100644 (file)
@@ -506,7 +506,7 @@ static int mntstat(struct chan *c, uint8_t * dp, int n)
        } else {
                n = r->reply.nstat;
                memmove(dp, r->reply.stat, n);
-               validstat(dp, n);
+               validstat(dp, n, 0);
                mntdirfix(dp, c);
        }
        poperror();
@@ -696,7 +696,7 @@ static long mntread(struct chan *c, void *buf, long n, int64_t off)
                        if (p + dirlen > e){
                                break;
                        }
-                       validstat(p, dirlen);
+                       validstat(p, dirlen, 0);
                        mntdirfix(p, c);
                        numdirent += dirlen;
                }
index 955129a..0755e3b 100644 (file)
@@ -868,9 +868,8 @@ long unionread(struct chan *, void *, long);
 void unlock(spinlock_t *);
 void userinit(void);
 uint32_t userpc(void);
-void validname(char *unused_char_p_t, int);
-void validstat(uint8_t * unused_uint8_p_t, int);
-void validwstatname(char *unused_char_p_t);
+void validname(char *, int);
+void validwstatname(char *);
 int walk(struct chan **, char **unused_char_pp_t, int unused_int, int, int *);
 void werrstr(char *unused_char_p_t, ...);
 void *xalloc(uint32_t);
@@ -1001,7 +1000,7 @@ long sysread(int fd, void *va, long n);
 long syspread(int fd, void *va, long n, int64_t off);
 int sysremove(char *path);
 int64_t sysseek(int fd, int64_t off, int whence);
-void validstat(uint8_t * s, int n);
+void validstat(uint8_t * s, int n, int slashok);
 int sysstat(char *path, uint8_t*, int n);
 int sysstatakaros(char *path, struct kstat *);
 long syswrite(int fd, void *va, long n);
index b54bc59..9aa7975 100644 (file)
@@ -396,7 +396,7 @@ int cmount(struct chan *new, struct chan *old, int flag, char *spec)
         * work.  The check of mount->mflag catches things like
         *  mount fd /root
         *  bind -c /root /
-        * 
+        *
         * This is far more complicated than it should be, but I don't
         * see an easier way at the moment.     -rsc
         */
@@ -485,7 +485,7 @@ void cunmount(struct chan *mnt, struct chan *mounted)
                printd("cunmount newp extra umh %p has %p\n", mnt, mnt->umh);
 
        /*
-        * It _can_ happen that mounted->umh is non-NULL, 
+        * It _can_ happen that mounted->umh is non-NULL,
         * because mounted is the result of namec(Aopen)
         * (see sysfile.c:/^sysunmount).
         * If we open a union directory, it will have a umh.
@@ -951,6 +951,9 @@ void *memrchr(void *va, int c, long n)
  * correct Chan* but with an incorrect struct cname attached.
  * Since the functions that open Aaccess (sysstat, syswstat, sys_stat)
  * do not use the struct cname*, this avoids an unnecessary clone.
+ *
+ * Acreatechan will never open. It will do all the tests and return a chan
+ * for the directory where an open will succeed.
  */
 struct chan *namec(char *aname, int amode, int omode, uint32_t perm)
 {
@@ -1052,7 +1055,7 @@ struct chan *namec(char *aname, int amode, int omode, uint32_t perm)
        /*
         * On create, ....
         */
-       if (amode == Acreate) {
+       if ((amode == Acreate) || (amode == Acreatechan)) {
                /* perm must have DMDIR if last element is / or /. */
                if (e.mustbedir && !(perm & DMDIR)) {
                        npath = e.ARRAY_SIZEs;
@@ -1190,6 +1193,14 @@ Open:
                         */
                        break;
 
+               case Acreatechan:
+                       /*
+                        * We've walked to the place where it *could* be created.
+                        * Return that chan.
+                        */
+                       printk("Acreatechan: all but last? c is %p\n", c);
+                       break;
+
                case Acreate:
                        /*
                         * We've already walked all but the last element.
@@ -1208,11 +1219,11 @@ Open:
                         * The semantics of the create(2) system call are that if the
                         * file exists and can be written, it is to be opened with truncation.
                         * On the other hand, the create(5) message fails if the file exists.
-                        * If we get two create(2) calls happening simultaneously, 
-                        * they might both get here and send create(5) messages, but only 
+                        * If we get two create(2) calls happening simultaneously,
+                        * they might both get here and send create(5) messages, but only
                         * one of the messages will succeed.  To provide the expected create(2)
                         * semantics, the call with the failed message needs to try the above
-                        * walk again, opening for truncation.  This correctly solves the 
+                        * walk again, opening for truncation.  This correctly solves the
                         * create/create race, in the sense that any observable outcome can
                         * be explained as one happening before the other.
                         * The create/create race is quite common.  For example, it happens
@@ -1222,7 +1233,7 @@ Open:
                         * The implementation still admits a create/create/remove race:
                         * (A) walk to file, fails
                         * (B) walk to file, fails
-                        * (A) create file, succeeds, returns 
+                        * (A) create file, succeeds, returns
                         * (B) create file, fails
                         * (A) remove file, succeeds, returns
                         * (B) walk to file, return failure.
@@ -1402,7 +1413,7 @@ void isdir(struct chan *c)
  * The mount list is deleted when we cunmount.
  * The RWlock ensures that nothing is using the mount list at that time.
  *
- * It is okay to replace c->mh with whatever you want as 
+ * It is okay to replace c->mh with whatever you want as
  * long as you are sure you have a unique reference to it.
  *
  * This comment might belong somewhere else.
index 634b108..6061347 100644 (file)
@@ -498,7 +498,7 @@ int sysfwstat(int fd, uint8_t * buf, int n)
                return -1;
        }
 
-       validstat(buf, n);
+       validstat(buf, n, 0);
        c = fdtochan(current->fgrp, fd, -1, 1, 1);
        if (waserror()) {
                cclose(c);
@@ -951,7 +951,7 @@ int64_t sysseek(int fd, int64_t off, int whence)
        return off;
 }
 
-void validstat(uint8_t * s, int n)
+void validstat(uint8_t * s, int n, int slashok)
 {
        
        int m;
@@ -976,7 +976,7 @@ void validstat(uint8_t * s, int n)
        buf[m] = '\0';
        /* name could be '/' */
        if (strcmp(buf, "/") != 0)
-               validname(buf, 0);
+               validname(buf, slashok);
 }
 
 int sysfstat(int fd, uint8_t *buf, int n)
@@ -1145,7 +1145,7 @@ int syswstat(char *path, uint8_t * buf, int n)
                return -1;
        }
 
-       validstat(buf, n);
+       validstat(buf, n, 0);
        c = namec(path, Aaccess, 0, 0);
        if (waserror()) {
                cclose(c);
index 0d13c1e..078f036 100644 (file)
@@ -1858,10 +1858,79 @@ intreg_t sys_fwstat(struct proc *p, int fd, uint8_t *stat_m, size_t stat_sz,
 intreg_t sys_rename(struct proc *p, char *old_path, size_t old_path_l,
                     char *new_path, size_t new_path_l)
 {
-       printk("got rename from %s to %s\n", old_path, new_path);
-       /* this might trick userspace code to fallback to copying, for now */
-       set_errno(EXDEV);
-       return -1;
+       ERRSTACK(1);
+       char *from_path = user_strdup_errno(p, old_path, old_path_l);
+       char *to_path = user_strdup_errno(p, new_path, new_path_l);
+       struct chan *oldchan, *newchan = NULL;
+       int retval = -1;
+
+       if ((!from_path) || (!to_path))
+               return -1;
+       printk("sys_rename :%s: to :%s: : ", from_path, to_path);
+
+       /* we need a fid for the wstat. */
+       oldchan = namec(from_path, Aaccess, 0, 0);
+       printk("Oldchan: %C\n", oldchan);
+       if (! oldchan) {
+               printk("Could not get a chan for %s\n", from_path);
+               set_errno(ENOENT);
+               goto done;
+       }
+       /* the omode and perm are of no importance, we think. */
+       newchan = namec(to_path, Acreatechan, 0, 0);
+       if (newchan == NULL) {
+               printd("sys_rename %s to %s found no chan\n", from_path, to_path);
+               set_errno(EPERM);
+               goto done;
+       }
+       if ((newchan->dev != oldchan->dev) || 
+               (newchan->type != oldchan->type)) {
+               printk("Old chan and new chan do not match\n");
+               set_errno(ENODEV);
+               goto done;
+       }
+
+       printk("let's do it. ");
+       struct dir dir;
+       size_t mlen;
+       uint8_t mbuf[STATFIXLEN + MAX_PATH_LEN + 1];
+
+       init_empty_dir(&dir);
+       dir.name = to_path;
+       mlen = convD2M(&dir, mbuf, sizeof(mbuf));
+       if (! mlen) {
+               printk("convD2M failed\n");
+               set_errno(EINVAL);
+               goto done;
+       }
+       if (waserror()) {
+               printk("validstat failed: %s\n", current_errstr());
+               goto done;
+       }
+       validstat(mbuf, mlen, 1);
+       poperror();
+
+       if (waserror()) {
+               //cclose(oldchan);
+               nexterror();
+       }
+
+       retval = devtab[oldchan->type].wstat(oldchan, mbuf, mlen);
+
+       if (retval == mlen) {
+               retval = mlen;
+       } else {
+               printk("syswstat did not go well\n");
+               set_errno(EXDEV);
+       };
+       printk("syswstat returns %d\n", retval);
+
+done: 
+       user_memdup_free(p, to_path);
+       user_memdup_free(p, to_path);
+       //cclose(oldchan);
+       //cclose(newchan);
+       return retval;
 }
 
 /************** Syscall Invokation **************/
index fe1a395..8be52e7 100644 (file)
@@ -4,3 +4,9 @@ kern/include \
 kern/kfs \
 kern/src \
 kern/arch/x86 | awk '/\.[ch]$/{print $2}'`
+etags `du -a  \
+kern/drivers \
+kern/include \
+kern/kfs \
+kern/src \
+kern/arch/x86 | awk '/\.[ch]$/{print $2}'`