9 char *make_abs_path(const char *s)
12 int slen = s ? strlen(s) : 0;
17 getcwd(wd, sizeof wd);
18 int wdlen = strlen(wd);
19 len = wdlen + 1 + slen;
21 res = new char[len + 1];
23 sprintf(res, "%s/%s", wd, s);
25 memcpy(res, wd, len + 1);
28 res = new char[len + 1];
29 memcpy(res, s, len + 1);
37 abs_path = name = suffix = parent = 0;
40 FSPath::FSPath(const char *s)
42 abs_path = name = suffix = parent = 0;
52 FSPath::FSPath(const FSPath &p)
54 abs_path = name = suffix = parent = 0;
57 int len = strlen(p.abs_path);
58 abs_path = new char[len + 1];
59 memcpy(abs_path, p.abs_path, len + 1);
62 name = abs_path + (p.name - p.abs_path);
65 suffix = abs_path + (p.suffix - p.abs_path);
69 int len = strlen(p.parent);
70 parent = new char[len + 1];
71 memcpy(parent, p.parent, len + 1);
75 FSPath &FSPath::operator =(const FSPath &p)
80 abs_path = name = suffix = parent = 0;
83 int len = strlen(p.abs_path);
84 abs_path = new char[len + 1];
85 memcpy(abs_path, p.abs_path, len + 1);
88 name = abs_path + (p.name - p.abs_path);
91 suffix = abs_path + (p.suffix - p.abs_path);
95 int len = strlen(p.parent);
96 parent = new char[len + 1];
97 memcpy(parent, p.parent, len + 1);
103 FSPath::FSPath(FSPath &&p)
105 abs_path = p.abs_path;
110 p.abs_path = p.name = p.suffix = p.parent = 0;
113 FSPath &FSPath::operator =(FSPath &&p)
119 abs_path = p.abs_path;
124 p.abs_path = p.name = p.suffix = p.parent = 0;
129 void FSPath::sanitize()
131 printf("sanitize: \"%s\"\n", abs_path);
133 // first pass, convert and backslashes to slashes
142 // second pass, remove any "./" and "foo/.." parts
145 while((s = strstr(s, "./"))) {
147 memmove(s, s + 2, len + 1);
149 assert(len == (int)strlen(abs_path));
152 while((s = strstr(s, "/.."))) {
154 while(start > abs_path && *--start != '/');
156 memmove(start, s + 3, len - 2);
157 len -= (s + 3) - start;
160 assert(len == (int)strlen(abs_path));
162 // remove double slashes
163 while((s = strstr(abs_path, "//"))) {
164 memmove(s, s + 1, len-- - (s - abs_path));
166 assert(len == (int)strlen(abs_path));
168 // remove trailing slash if abs_path is not just a slash (root)
169 if(len > 1 && abs_path[len - 1] == '/') {
172 assert(len == (int)strlen(abs_path));
174 // setup name and prefix pointers as necessary
178 if(*s == '/') name = s + 1;
179 if(*s == '.') suffix = s;
184 name = abs_path; // shouldn't happen, all paths start with a slash
185 fprintf(stderr, "FSPath::sanitize: absolute path \"%s\" isn't absolute!\n", abs_path);
188 if(suffix == abs_path || suffix <= name) {
192 // create parent name string
193 if(abs_path[0] == '/' && abs_path[1] == 0) {
194 parent = 0; // root dir has no parent
196 int plen = name - 1 - abs_path;
200 plen = 1; // our parent is root, so we need the slash
203 parent = new char[plen + 1];
204 memcpy(parent, abs_path, plen);
209 bool FSPath::set_path(const char *s)
211 char *tmp = make_abs_path(s);
225 const char *FSPath::get_path() const
230 const char *FSPath::get_name() const
235 const char *FSPath::get_suffix() const
240 const char *FSPath::get_parent() const
245 bool FSPath::append_path(const char *s)
247 if(!s || !*s) return false;
254 return false; // can't append an absolute path
257 int len = strlen(abs_path) + 1 + strlen(s);
259 char *tmp = new char[len + 1];
274 bool FSPath::exists() const
277 return abs_path && stat(abs_path, &st) != -1;
280 bool FSPath::is_file() const
283 return abs_path && stat(abs_path, &st) != -1 && S_ISREG(st.st_mode);
286 bool FSPath::is_dir() const
289 return abs_path && stat(abs_path, &st) != -1 && S_ISDIR(st.st_mode);
292 bool FSPath::is_dev() const
295 unsigned int devmask = S_IFBLK | S_IFCHR;
296 return abs_path && stat(abs_path, &st) != -1 && (st.st_mode & devmask);
299 FSPath::operator const char* () const