4d82ed2fe6152796d1423bb84de12034102179ab
[ardour.git] / libs / pbd / filesystem.cc
1 /*
2         Copyright (C) 2007 Tim Mayberry 
3
4         This program is free software; you can redistribute it and/or modify
5         it under the terms of the GNU General Public License as published by
6         the Free Software Foundation; either version 2 of the License, or
7         (at your option) any later version.
8
9         This program is distributed in the hope that it will be useful,
10         but WITHOUT ANY WARRANTY; without even the implied warranty of
11         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12         GNU General Public License for more details.
13
14         You should have received a copy of the GNU General Public License
15         along with this program; if not, write to the Free Software
16         Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <sys/stat.h>
20
21 #include <glib.h>
22 #include <glib/gstdio.h>
23
24 #include <cerrno>
25 #include <fstream>
26
27 #include <glibmm/fileutils.h>
28 #include <glibmm/miscutils.h>
29
30 #include "pbd/filesystem.h"
31 #include "pbd/error.h"
32 #include "pbd/compose.h"
33
34 #include "i18n.h"
35
36 namespace PBD {
37
38 namespace sys {
39         
40 path&
41 path::operator/=(const path& rhs)
42 {
43         m_path = Glib::build_filename(m_path, rhs.m_path);
44         return *this;
45 }
46
47 path&
48 path::operator/=(const string& rhs)
49 {
50         m_path = Glib::build_filename(m_path, rhs);
51         return *this;
52 }
53
54 path&
55 path::operator/=(const char* rhs)
56 {
57         m_path = Glib::build_filename(m_path, rhs);
58         return *this;
59 }
60
61 string
62 path::leaf () const
63 {
64         return Glib::path_get_basename(m_path);
65 }
66
67 path
68 path::branch_path () const
69 {
70         string dir = Glib::path_get_dirname (m_path);
71
72         /*
73          * glib returns "." to signify that the path
74          * has no directory components(branch path)
75          * whereas boost::filesystem returns an empty
76          * string
77          */
78         if(dir == ".")
79         {
80                 return "";
81         }
82         return dir;
83 }
84
85 bool
86 exists (const path & p)
87 {
88         return Glib::file_test (p.to_string(), Glib::FILE_TEST_EXISTS);
89 }
90
91 bool
92 is_directory (const path & p)
93 {
94         return Glib::file_test (p.to_string(), Glib::FILE_TEST_IS_DIR);
95 }
96
97 bool
98 create_directory(const path & p)
99 {
100         if(is_directory(p)) return false;
101
102         int error = g_mkdir (p.to_string().c_str(), S_IRWXU|S_IRWXG|S_IRWXO);
103
104         if(error == -1)
105         {
106                 throw filesystem_error(g_strerror(errno), errno);
107         }
108         return true;
109 }
110
111 bool
112 create_directories(const path & p)
113 {
114         if(is_directory(p)) return false;
115
116         int error = g_mkdir_with_parents (p.to_string().c_str(), S_IRWXU|S_IRWXG|S_IRWXO);
117
118         if(error == -1)
119         {
120                 throw filesystem_error(g_strerror(errno), errno);
121         }
122         return true;
123 }
124
125 bool
126 remove(const path & p)
127 {
128         if(!exists(p)) return false;
129
130         int error = g_unlink (p.to_string().c_str());
131
132         if(error == -1)
133         {
134                 throw filesystem_error(g_strerror(errno), errno);
135         }
136         return true;
137 }
138
139 void
140 rename (const path & from_path, const path & to_path)
141 {
142         // g_rename is a macro that evaluates to ::rename on
143         // POSIX systems, without the global namespace qualifier
144         // it would evaluate to a recursive call(if it compiled)
145         if ( ::g_rename( from_path.to_string().c_str(),
146                                 to_path.to_string().c_str() ) == -1 )
147         {
148                 throw filesystem_error(g_strerror(errno), errno);
149         }
150 }
151
152 // XXX character encoding.
153 void
154 copy_file(const path & from_path, const path & to_path)
155 {
156         std::ifstream in(from_path.to_string().c_str());
157         std::ofstream out(to_path.to_string().c_str());
158         
159         if (!in || !out) {
160                 throw filesystem_error(string_compose(_("Could not open files %1 and %2 for copying"),
161                                         from_path.to_string(), to_path.to_string()));
162         }
163         
164         out << in.rdbuf();
165         
166         if (!in || !out) {
167                 remove (to_path);
168                 throw filesystem_error(string_compose(_("Could not copy existing file %1 to %2"),
169                                         from_path.to_string(), to_path.to_string()));
170         }
171 }
172
173 string
174 basename (const path & p)
175 {
176         string base(p.leaf());
177
178         string::size_type n = base.rfind ('.');
179
180         return base.substr (0, n);
181 }
182
183 string
184 extension (const path & p)
185 {
186         string base(p.leaf());
187
188         string::size_type n = base.rfind ('.');
189
190         if (n != string::npos)
191         {
192                 return base.substr(n);
193         }
194
195         return string();
196
197 }
198
199 } // namespace sys
200
201 } // namespace PBD