~ubuntu-branches/ubuntu/lucid/9base/lucid

« back to all changes in this revision

Viewing changes to lib9/cleanname.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2006-01-25 15:33:00 UTC
  • Revision ID: james.westby@ubuntu.com-20060125153300-6hh4p9wx8iqqply5
Tags: upstream-2
ImportĀ upstreamĀ versionĀ 2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <u.h>
 
2
#include <libc.h>
 
3
 
 
4
/*
 
5
 * In place, rewrite name to compress multiple /, eliminate ., and process ..
 
6
 */
 
7
#define SEP(x)  ((x)=='/' || (x) == 0)
 
8
char*
 
9
cleanname(char *name)
 
10
{
 
11
        char *p, *q, *dotdot;
 
12
        int rooted;
 
13
 
 
14
        rooted = name[0] == '/';
 
15
 
 
16
        /*
 
17
         * invariants:
 
18
         *      p points at beginning of path element we're considering.
 
19
         *      q points just past the last path element we wrote (no slash).
 
20
         *      dotdot points just past the point where .. cannot backtrack
 
21
         *              any further (no slash).
 
22
         */
 
23
        p = q = dotdot = name+rooted;
 
24
        while(*p) {
 
25
                if(p[0] == '/') /* null element */
 
26
                        p++;
 
27
                else if(p[0] == '.' && SEP(p[1]))
 
28
                        p += 1; /* don't count the separator in case it is nul */
 
29
                else if(p[0] == '.' && p[1] == '.' && SEP(p[2])) {
 
30
                        p += 2;
 
31
                        if(q > dotdot) {        /* can backtrack */
 
32
                                while(--q > dotdot && *q != '/')
 
33
                                        ;
 
34
                        } else if(!rooted) {    /* /.. is / but ./../ is .. */
 
35
                                if(q != name)
 
36
                                        *q++ = '/';
 
37
                                *q++ = '.';
 
38
                                *q++ = '.';
 
39
                                dotdot = q;
 
40
                        }
 
41
                } else {        /* real path element */
 
42
                        if(q != name+rooted)
 
43
                                *q++ = '/';
 
44
                        while((*q = *p) != '/' && *q != 0)
 
45
                                p++, q++;
 
46
                }
 
47
        }
 
48
        if(q == name)   /* empty string is really ``.'' */
 
49
                *q++ = '.';
 
50
        *q = '\0';
 
51
        return name;
 
52
}