Add path::leaf method function to the PBD::sys::path class
[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 copy_file(const path & from_path, const path & to_path)
141 {
142         // this implementation could use mucho memory
143         // for big files.
144         std::ifstream in(from_path.to_string().c_str());
145         std::ofstream out(to_path.to_string().c_str());
146         
147         if (!in || !out) {
148                 throw filesystem_error(string_compose(_("Could not open files %1 and %2 for copying"),
149                                         from_path.to_string(), to_path.to_string()));
150         }
151         
152         out << in.rdbuf();
153         
154         if (!in || !out) {
155                 throw filesystem_error(string_compose(_("Could not copy existing file %1 to %2"),
156                                         from_path.to_string(), to_path.to_string()));
157                 remove (to_path);
158         }
159 }
160
161 string
162 basename (const path & p)
163 {
164         string base = Glib::path_get_basename (p.to_string());
165
166         string::size_type n = base.rfind ('.');
167
168         return base.substr (0, n);
169 }
170
171 string
172 extension (const path & p)
173 {
174         string base = Glib::path_get_basename (p.to_string());
175
176         string::size_type n = base.rfind ('.');
177
178         if (n != string::npos)
179         {
180                 return base.substr(n);
181         }
182
183         return string();
184
185 }
186
187 } // namespace sys
188
189 } // namespace PBD