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