Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_posix/sys/src/libc/port/cleanname.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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 *s;	/* source of copy */
12
	char *d;	/* destination of copy */
13
	char *d0;	/* start of path afer the root name */
14
	Rune r;
15
	int rooted;
16
 
17
	if(name[0] == 0)
18
		return strcpy(name, ".");
19
	rooted = 0;
20
	d0 = name;
21
	if(d0[0] == '#'){
22
		if(d0[1] == 0)
23
			return d0;
24
		d0  += 1 + chartorune(&r, d0+1); /* ignore slash: #/ */
25
		while(!SEP(*d0))
26
			d0 += chartorune(&r, d0);
27
		if(d0 == 0)
28
			return name;
29
		d0++;	/* keep / after #<name> */
30
		rooted = 1;
31
	}else if(d0[0] == '/'){
32
		rooted = 1;
33
		d0++;
34
	}
35
 
36
	s = d0;
37
	if(rooted){
38
		/* skip extra '/' at root name */
39
		for(; *s == '/'; s++)
40
			;
41
	}
42
	/* remove dup slashes */
43
	for(d = d0; *s != 0; s++){
44
		*d++ = *s;
45
		if(*s == '/')
46
			while(s[1] == '/')
47
				s++;
48
	}
49
	*d = 0;
50
 
51
	d = d0;
52
	s = d0;
53
	while(*s != 0){
54
		if(s[0] == '.' && SEP(s[1])){
55
			if(s[1] == 0)
56
				break;
57
			s+= 2;
58
			continue;
59
		}
60
		if(s[0] == '.' && s[1] == '.' && SEP(s[2])){
61
			if(d == d0){
62
				if(rooted){
63
					/* /../x -> /x */
64
					if(s[2] == 0)
65
						break;
66
					s += 3;
67
					continue;
68
				}else{
69
					/* ../x -> ../x; and never collect ../ */
70
					d0 += 3;
71
				}
72
			}
73
			if(d > d0){
74
				/* a/../x -> x */
75
				assert(d-2 >= d0 && d[-1] == '/');
76
				for(d -= 2; d > d0 && d[-1] != '/'; d--)
77
						;
78
				if(s[2] == 0)
79
					break;
80
				s += 3;
81
				continue;
82
			}
83
		}
84
		while(!SEP(*s))
85
			*d++ = *s++;
86
		if(*s == 0)
87
			break;
88
 
89
		*d++ = *s++;
90
	}
91
	*d = 0;
92
	if(d-1 > name && d[-1] == '/')	/* thanks to #/ */
93
		*--d = 0;
94
	if(name[0] == 0)
95
		strcpy(name, ".");
96
	return name;
97
}