waserror() audit
[akaros.git] / kern / src / ns / cleanname.c
1 // INFERNO
2 #include <vfs.h>
3 #include <kfs.h>
4 #include <slab.h>
5 #include <kmalloc.h>
6 #include <kref.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <error.h>
11 #include <cpio.h>
12 #include <pmap.h>
13 #include <smp.h>
14 #include <ip.h>
15
16 /*
17  * In place, rewrite name to compress multiple /, eliminate ., and process ..
18  */
19 #define SEP(x)  ((x)=='/' || (x) == 0)
20 char*
21 cleanname(char *name)
22 {
23         char *p, *q, *dotdot;
24         int rooted, erasedprefix;
25
26         rooted = name[0] == '/';
27         erasedprefix = 0;
28
29         /*
30          * invariants:
31          *      p points at beginning of path element we're considering.
32          *      q points just past the last path element we wrote (no slash).
33          *      dotdot points just past the point where .. cannot backtrack
34          *              any further (no slash).
35          */
36         p = q = dotdot = name+rooted;
37         while(*p) {
38                 if(p[0] == '/') /* null element */
39                         p++;
40                 else if(p[0] == '.' && SEP(p[1])) {
41                         if(p == name)
42                                 erasedprefix = 1;
43                         p += 1; /* don't count the separator in case it is nul */
44                 } else if(p[0] == '.' && p[1] == '.' && SEP(p[2])) {
45                         p += 2;
46                         if(q > dotdot) {        /* can backtrack */
47                                 while(--q > dotdot && *q != '/')
48                                         ;
49                         } else if(!rooted) {    /* /.. is / but ./../ is .. */
50                                 if(q != name)
51                                         *q++ = '/';
52                                 *q++ = '.';
53                                 *q++ = '.';
54                                 dotdot = q;
55                         }
56                         if(q == name)
57                                 erasedprefix = 1;       /* erased entire path via dotdot */
58                 } else {        /* real path element */
59                         if(q != name+rooted)
60                                 *q++ = '/';
61                         while((*q = *p) != '/' && *q != 0)
62                                 p++, q++;
63                 }
64         }
65         if(q == name)   /* empty string is really ``.'' */
66                 *q++ = '.';
67         *q = '\0';
68         if(erasedprefix && name[0] == '#'){     
69                 /* this was not a #x device path originally - make it not one now */
70                 memmove(name+2, name, strlen(name)+1);
71                 name[0] = '.';
72                 name[1] = '/';
73         }
74         return name;
75 }