]> git.tdb.fi Git - libs/core.git/blob - source/utils.cpp
a0c2486f17402593b2e48199fc9d689923098809
[libs/core.git] / source / utils.cpp
1 /* $Id$
2
3 This file is part of libmspfs
4 Copyright © 2006-2008  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <cerrno>
9 #include <msp/core/except.h>
10 #ifndef WIN32
11 #include <fnmatch.h>
12 #else
13 #include <msp/strings/glob.h>
14 #endif
15 #include <msp/strings/utils.h>
16 #include "dir.h"
17 #include "path.h"
18 #include "stat.h"
19 #include "utils.h"
20
21 using namespace std;
22
23 namespace Msp {
24 namespace FS {
25
26 string basename(const Path &p)
27 {
28         return p[-1];
29 }
30
31 Path dirname(const Path &p)
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         unsigned 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         throw Exception("No symbolic links on win32");
86 #else
87         char buf[4096];
88         int len=::readlink(link.str().c_str(), buf, sizeof(buf));
89         if(len==-1)
90                 throw SystemError("readlink failed", errno);
91         return string(buf, len);
92 #endif
93 }
94
95 Path realpath(const Path &path)
96 {
97 #ifdef WIN32
98         if(path.is_absolute())
99                 return path;
100         else
101                 return getcwd()/path;
102 #else
103         list<string> queue(path.begin(), path.end());
104         if(!path.is_absolute())
105         {
106                 Path cwd=getcwd();
107                 queue.insert(queue.begin(), cwd.begin(), cwd.end());
108         }
109
110         Path real;
111         unsigned n_links=0;
112         while(!queue.empty())
113         {
114                 Path next=real/queue.front();
115                 queue.pop_front();
116
117                 struct stat st=lstat(next);
118                 if(S_ISLNK(st.st_mode))
119                 {
120                         if(++n_links>64)
121                                 throw Exception("Ludicrous amount of symlinks detected in realpath, giving up");
122                         Path link=readlink(next);
123                         queue.insert(queue.begin(), link.begin(), link.end());
124                 }
125                 else
126                         real=next;
127         }
128
129         return real;
130 #endif
131 }
132
133 void unlink(const Path &path)
134 {
135         if(::unlink(path.str().c_str())==-1)
136                 throw SystemError("unlink failed", errno);
137 }
138
139 Path relative(const Path &path, const Path &base)
140 {
141         Path::Iterator i=path.begin();
142         Path::Iterator j=base.begin();
143         for(; (i!=path.end() && j!=base.end() && *i==*j); ++i, ++j) ;
144
145         Path result;
146         for(; j!=base.end(); ++j)
147                 result/="..";
148         for(; i!=path.end(); ++i)
149                 result/=*i;
150
151         return result;
152 }
153
154 } // namespace FS
155 } // namespace Msp