]> git.tdb.fi Git - libs/core.git/blob - source/utils.cpp
Add files
[libs/core.git] / source / utils.cpp
1 #include <dirent.h>
2 #include <sys/stat.h>
3 #include <errno.h>
4 #include <fnmatch.h>
5 #include <msp/strutils.h>
6 #include "path.h"
7 #include "utils.h"
8
9 using namespace std;
10
11 namespace Msp {
12 namespace Path {
13
14 /**
15 Fixes the case of the given path to match files / directories on the
16 filesystem.  Intended to be used in programs that need to interact with
17 emulated Windows programs.
18 */
19 Path fix_case(const Path &path)
20 {
21         bool found=true;
22         Path result;
23         for(Path::iterator i=path.begin(); i!=path.end(); ++i)
24         {
25                 if(!found || *i=="/")
26                         result/=*i;
27                 else
28                 {
29                         list<string> files;
30                         if(result.size())
31                                 files=list_files(result);
32                         else
33                                 files=list_files(".");
34
35                         found=false;
36                         for(list<string>::iterator j=files.begin(); (j!=files.end() && !found); ++j)
37                                 if(!strcasecmp(*j,*i))
38                                 {
39                                         result/=*j;
40                                         found=true;
41                                 }
42
43                         if(!found)
44                                 result/=*i;
45                 }
46         }
47
48         return result;
49 }
50
51 int mkpath(const Path &path, int mode)
52 {
53         Path p;
54         for(Path::iterator i=path.begin(); i!=path.end(); ++i)
55         {
56                 p/=*i;
57 #ifdef WIN32
58                 if(p.size()==1 && is_windows_drive(*i)) continue;
59 #endif
60                 struct stat st;
61                 int err=stat(p.str().c_str(),&st);
62                 if(err==0)
63                 {
64                         if(!S_ISDIR(st.st_mode))
65                         {
66                                 errno=EEXIST;
67                                 return -1;
68                         }
69                         continue;
70                 }
71                 else if(errno!=ENOENT)
72                         return -1;
73                 else
74                 {
75 #ifdef WIN32
76                         // The win32 version of this function doesn't take the mode argument.  Go figure.
77                         err=mkdir(p.str().c_str());
78 #else
79                         err=mkdir(p.str().c_str(),mode);
80 #endif
81                         if(err==-1) return -1;
82                 }
83         }
84
85         return 0;
86 }
87
88 int rmdir(const Path &path, bool recursive)
89 {
90         if(recursive)
91         {
92                 list<string> files=list_files(path);
93                 for(list<string>::iterator i=files.begin(); i!=files.end(); ++i)
94                 {
95                         Path p=path/ *i;
96                         struct stat st;
97                         stat(p.str().c_str(),&st);
98                         int err=0;
99                         if(S_ISDIR(st.st_mode))
100                                 err=rmdir(p,true);
101                         else
102                                 err=unlink(p.str().c_str());
103                         if(err) return err;
104                 }
105         }
106         return rmdir(path.str().c_str());
107 }
108
109 /**
110 Lists all files in a directory except the implied . and .. entries.
111 */
112 list<string> list_files(const Path &path)
113 {
114         list<string> result;
115         DIR *dir=opendir(path.str().c_str());
116         if(dir)
117         {
118                 while(dirent *de=readdir(dir))
119                 {
120                         const char *fn=de->d_name;
121                         if(fn[0]=='.' && (fn[1]==0 || (fn[1]=='.' && fn[2]==0))) continue;
122                         result.push_back(fn);
123                 }
124                 closedir(dir);
125         }
126         return result;
127 }
128
129 bool exists(const Path &path)
130 {
131         struct stat st;
132         return !stat(path.str().c_str(),&st);
133 }
134
135 Filename splitext(const string &fn)
136 {
137         Filename result;
138         unsigned dot=fn.rfind('.');
139         result.base=fn.substr(0,dot);
140         if(dot!=string::npos)
141                 result.ext=fn.substr(dot);
142         return result;
143 }
144
145 int fnmatch(const string &pat, const Path &fn)
146 {
147         return ::fnmatch(pat.c_str(), fn.str().c_str(), FNM_PATHNAME);
148 }
149
150 } // namespace Path
151 } // namespace Msp