]> git.tdb.fi Git - libs/core.git/blob - source/fs/utils.cpp
Remove Id tags and copyright notices from source files
[libs/core.git] / source / fs / utils.cpp
1 #include <cerrno>
2 #include <cstdio>
3 #include <msp/core/except.h>
4 #ifndef WIN32
5 #include <fnmatch.h>
6 #else
7 #include <msp/strings/glob.h>
8 #endif
9 #include <msp/strings/utils.h>
10 #include "dir.h"
11 #include "path.h"
12 #include "stat.h"
13 #include "utils.h"
14
15 using namespace std;
16
17 namespace Msp {
18 namespace FS {
19
20 string basename(const Path &p)
21 {
22         return p[-1];
23 }
24
25 Path dirname(const Path &p)
26 {
27         if(p.size()==1)
28         {
29                 if(p.is_absolute())
30                         return p;
31                 return ".";
32         }
33         return p.subpath(0, p.size()-1);
34 }
35
36 string basepart(const string &fn)
37 {
38         unsigned dot = fn.rfind('.');
39         return fn.substr(0, dot);
40 }
41
42 string extpart(const string &fn)
43 {
44         string::size_type dot = fn.rfind('.');
45         if(dot==string::npos)
46                 return string();
47         return fn.substr(dot);
48 }
49
50 Path fix_case(const Path &path)
51 {
52         bool found = true;
53         Path result;
54         for(Path::Iterator i=path.begin(); i!=path.end(); ++i)
55         {
56                 if(!found || *i=="/")
57                         result /= *i;
58                 else
59                 {
60                         list<string> files;
61                         if(result.size())
62                                 files = list_files(result);
63                         else
64                                 files = list_files(".");
65
66                         found = false;
67                         for(list<string>::iterator j=files.begin(); (j!=files.end() && !found); ++j)
68                                 if(!strcasecmp(*j,*i))
69                                 {
70                                         result /= *j;
71                                         found = true;
72                                 }
73
74                         if(!found)
75                                 result /= *i;
76                 }
77         }
78
79         return result;
80 }
81
82 Path readlink(const Path &link)
83 {
84 #ifdef WIN32
85         (void)link;
86         throw Exception("No symbolic links on win32");
87 #else
88         char buf[4096];
89         int len = ::readlink(link.str().c_str(), buf, sizeof(buf));
90         if(len==-1)
91                 throw SystemError("readlink failed", errno);
92         return string(buf, len);
93 #endif
94 }
95
96 Path realpath(const Path &path)
97 {
98 #ifdef WIN32
99         if(path.is_absolute())
100                 return path;
101         else
102                 return getcwd()/path;
103 #else
104         list<string> queue(path.begin(), path.end());
105         if(!path.is_absolute())
106         {
107                 Path cwd = getcwd();
108                 queue.insert(queue.begin(), cwd.begin(), cwd.end());
109         }
110
111         Path real;
112         unsigned n_links = 0;
113         while(!queue.empty())
114         {
115                 Path next = real/queue.front();
116                 queue.pop_front();
117
118                 struct stat st = lstat(next);
119                 if(S_ISLNK(st.st_mode))
120                 {
121                         if(++n_links>64)
122                                 throw Exception("Ludicrous amount of symlinks detected in realpath, giving up");
123                         Path link = readlink(next);
124                         queue.insert(queue.begin(), link.begin(), link.end());
125                 }
126                 else
127                         real = next;
128         }
129
130         return real;
131 #endif
132 }
133
134 void rename(const Path &from, const Path &to)
135 {
136         if(::rename(from.str().c_str(), to.str().c_str())==-1)
137                 throw SystemError("rename failed", errno);
138 }
139
140 void unlink(const Path &path)
141 {
142         if(::unlink(path.str().c_str())==-1)
143                 throw SystemError("unlink failed", errno);
144 }
145
146 Path relative(const Path &path, const Path &base)
147 {
148         Path::Iterator i = path.begin();
149         Path::Iterator j = base.begin();
150         for(; (i!=path.end() && j!=base.end() && *i==*j); ++i, ++j) ;
151
152         Path result;
153         for(; j!=base.end(); ++j)
154                 result /= "..";
155         for(; i!=path.end(); ++i)
156                 result /= *i;
157
158         return result;
159 }
160
161 int descendant_depth(const Path &path, const Path &parent)
162 {
163         Path::Iterator i = path.begin();
164         Path::Iterator j = parent.begin();
165         for(; (i!=path.end() && j!=parent.end() && *i==*j); ++i, ++j) ;
166
167         if(j!=parent.end())
168                 return -1;
169         
170         int result = 0;
171         for(; i!=path.end(); ++i)
172                 ++result;
173
174         return result;
175 }
176
177 } // namespace FS
178 } // namespace Msp