libzypp 17.31.23
Pathname.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12#include <iostream>
13#include <climits>
14
15#include <zypp-core/base/String.h>
16#include <zypp-core/Pathname.h>
17#include <zypp-core/Url.h>
18
19using std::string;
20
22namespace zypp
23{
25 namespace filesystem
26 {
27
29 //
30 // METHOD NAME : Pathname::_assign
31 // METHOD TYPE : void
32 //
33 void Pathname::_assign( const string & name_r )
34 {
35 _name.clear();
36 if ( name_r.empty() )
37 return;
38 _name.reserve( name_r.size() );
39
40 // Collect up to "/.."
41 enum Pending {
42 P_none = 0, // ""
43 P_slash = 1, // "/"
44 P_dot1 = 2, // "/."
45 P_dot2 = 3 // "/.."
46 } pending = P_none;
47
48 // Assert relative path starting with "./"
49 // We rely on this below!
50 if ( name_r[0] != '/' )
51 {
52 _name += '.';
53 pending = P_slash;
54 }
55
56 // Lambda handling the "/.." case:
57 // [] + "/.." ==> []
58 // [.] + "/.." ==> [./..]
59 // [foo] is always [./foo] due to init above
60 // [*/..] + "/.." ==> [*/../..]
61 // [*/foo] + "/.." ==> [*]
62 auto goParent_f = [&](){
63 if ( _name.empty() )
64 /*NOOP*/;
65 else if ( _name.size() == 1 ) // content is '.'
66 _name += "/..";
67 else
68 {
69 std::string::size_type pos = _name.rfind( "/" );
70 if ( pos == _name.size() - 3 && _name[pos+1] == '.' && _name[pos+2] == '.' )
71 _name += "/..";
72 else
73 _name.erase( pos );
74 }
75 };
76
77 for ( char ch : name_r )
78 {
79 switch ( ch )
80 {
81 case '/':
82 switch ( pending )
83 {
84 case P_none: pending = P_slash; break;
85 case P_slash: break;
86 case P_dot1: pending = P_slash; break;
87 case P_dot2: goParent_f(); pending = P_slash; break;
88 }
89 break;
90
91 case '.':
92 switch ( pending )
93 {
94 case P_none: _name += '.'; break;
95 case P_slash: pending = P_dot1; break;
96 case P_dot1: pending = P_dot2; break;
97 case P_dot2: _name += "/..."; pending = P_none; break;
98 }
99 break;
100
101 default:
102 switch ( pending )
103 {
104 case P_none: break;
105 case P_slash: _name += '/'; pending = P_none; break;
106 case P_dot1: _name += "/."; pending = P_none; break;
107 case P_dot2: _name += "/.."; pending = P_none; break;
108 }
109 _name += ch;
110 break;
111 }
112 }
113
114 switch ( pending )
115 {
116 case P_none: break;
117 case P_slash: if ( _name.empty() ) _name = "/"; break;
118 case P_dot1: if ( _name.empty() ) _name = "/"; break;
119 case P_dot2: goParent_f(); if ( _name.empty() ) _name = "/"; break;
120 }
121 return;
122 }
123
125 //
126 // METHOD NAME : Pathname::dirname
127 // METHOD TYPE : Pathname
128 //
130 {
131 if ( name_r.empty() )
132 return Pathname();
133
134 Pathname ret_t( name_r );
135 std::string::size_type idx = ret_t._name.find_last_of( '/' );
136
137 if ( idx == std::string::npos ) {
138 ret_t._name = ".";
139 } else if ( idx == 0 ) {
140 ret_t._name = "/";
141 } else {
142 ret_t._name.erase( idx );
143 }
144
145 return ret_t;
146 }
147
149 //
150 // METHOD NAME : Pathname::basename
151 // METHOD TYPE : string
152 //
153 string Pathname::basename( const Pathname & name_r )
154 {
155 if ( name_r.empty() )
156 return string();
157
158 string ret_t( name_r.asString() );
159 std::string::size_type idx = ret_t.find_last_of( '/' );
160 if ( idx != std::string::npos && ( idx != 0 || ret_t.size() != 1 ) ) {
161 ret_t.erase( 0, idx+1 );
162 }
163
164 return ret_t;
165 }
166
168 //
169 // METHOD NAME : Pathname::asUrl
170 // METHOD TYPE : Url
171 //
172 Url Pathname::asUrl( const std::string & scheme_r ) const
173 {
174 Url ret;
175 ret.setPathName( asString() );
176 ret.setScheme( scheme_r );
177 return ret;
178 }
179
181 { return asUrl( "dir" ); }
182
184 { return asUrl( "dir" ); }
185
187 { return asUrl( "file" ); }
188
189
190 std::string Pathname::showRoot( const Pathname & root_r, const Pathname & path_r )
191 {
192 return str::Str() << "(" << root_r << ")" << path_r;
193 }
194
195 std::string Pathname::showRootIf( const Pathname & root_r, const Pathname & path_r )
196 {
197 if ( root_r.empty() || root_r == "/" )
198 return path_r.asString();
199 return showRoot( root_r, path_r );
200 }
201
203 //
204 // METHOD NAME : Pathname::extension
205 // METHOD TYPE : string
206 //
207 string Pathname::extension( const Pathname & name_r )
208 {
209 if ( name_r.empty() )
210 return string();
211
212 string base( basename( name_r ) );
213 std::string::size_type pos = base.rfind( '.' );
214 switch ( pos )
215 {
216 case 0:
217 if ( base.size() == 1 ) // .
218 return string();
219 break;
220 case 1:
221 if ( base.size() == 2 && base[0] == '.' ) // ..
222 return string();
223 break;
224 case std::string::npos:
225 return string();
226 break;
227 }
228 return base.substr( pos );
229 }
230
232 {
233 std::string real;
234 if( !empty())
235 {
236 #if __GNUC__ > 2
238 char *ptr = ::realpath(_name.c_str(), NULL);
239 if( ptr != NULL)
240 {
241 real = ptr;
242 free( ptr);
243 }
244 else
246 if( EINVAL == errno)
247 {
248 char buff[PATH_MAX + 2];
249 memset(buff, '\0', sizeof(buff));
250 if( ::realpath(_name.c_str(), buff) != NULL)
251 {
252 real = buff;
253 }
254 }
255 #else
256 char buff[PATH_MAX + 2];
257 memset(buff, '\0', sizeof(buff));
258 if( ::realpath(_name.c_str(), buff) != NULL)
259 {
260 real = buff;
261 }
262 #endif
263 }
264 return zypp::Pathname(real);
265 }
266
268 //
269 // METHOD NAME : Pathname::assertprefix
270 // METHOD TYPE : Pathname
271 //
272 Pathname Pathname::assertprefix( const Pathname & root_r, const Pathname & path_r )
273 {
274 if ( root_r.empty()
275 || path_r == root_r
276 || str::hasPrefix( path_r.asString(), root_r.asString() ) )
277 return path_r;
278 return root_r / path_r;
279 }
280
281 Pathname Pathname::stripprefix( const Pathname & root_r, const Pathname & path_r )
282 {
283 if ( root_r.emptyOrRoot() )
284 return path_r;
285 if ( root_r == path_r )
286 return "/";
287 std::string rest( str::stripPrefix( path_r.asString(), root_r.asString() ) );
288 if ( rest[0] == '/' ) // needs to be a dir prefix!
289 return rest;
290 return path_r;
291 }
292
294 //
295 // METHOD NAME : Pathname::cat
296 // METHOD TYPE : Pathname
297 //
298 Pathname Pathname::cat( const Pathname & name_r, const Pathname & add_tv )
299 {
300 if ( add_tv.empty() )
301 return name_r;
302 if ( name_r.empty() )
303 return add_tv;
304
305 string ret_ti( name_r._name );
306 if( add_tv._name[0] != '/' )
307 ret_ti += '/';
308 return ret_ti + add_tv._name;
309 }
310
312 //
313 // METHOD NAME : Pathname::Extend
314 // METHOD TYPE : Pathname
315 //
316 Pathname Pathname::extend( const Pathname & l, const string & r )
317 {
318 return l.asString() + r;
319 }
320
322 } // namespace filesystem
325} // namespace zypp
Url manipulation class.
Definition: Url.h:92
void setPathName(const std::string &path, EEncoding eflag=zypp::url::E_DECODED)
Set the path name.
Definition: Url.cc:764
void setScheme(const std::string &scheme)
Set the scheme name in the URL.
Definition: Url.cc:668
static std::string showRoot(const Pathname &root_r, const Pathname &path_r)
String representation as "(root)/path".
Definition: Pathname.cc:190
Pathname extend(const std::string &r) const
Append string r to the last component of the path.
Definition: Pathname.h:173
static Pathname stripprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r with any root_r dir prefix striped.
Definition: Pathname.cc:281
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:124
bool emptyOrRoot() const
Test for "" or "/".
Definition: Pathname.h:121
Pathname cat(const Pathname &r) const
Concatenation of pathnames.
Definition: Pathname.h:165
Pathname()
Default ctor: an empty path.
Definition: Pathname.h:48
const std::string & asString() const
String representation.
Definition: Pathname.h:91
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:128
bool empty() const
Test for an empty path.
Definition: Pathname.h:114
static Pathname assertprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r prefixed with root_r, unless it is already prefixed.
Definition: Pathname.cc:272
void _assign(const std::string &name_r)
Definition: Pathname.cc:33
Pathname realpath() const
Returns this path as the absolute canonical pathname.
Definition: Pathname.cc:231
static std::string showRootIf(const Pathname &root_r, const Pathname &path_r)
String representation as "(root)/path", unless root is "/" or empty.
Definition: Pathname.cc:195
std::string extension() const
Return all of the characters in name after and including the last dot in the last element of name.
Definition: Pathname.h:135
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition: String.h:1027
std::string stripPrefix(const C_Str &str_r, const C_Str &prefix_r)
Strip a prefix_r from str_r and return the resulting string.
Definition: String.h:1034
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition: String.h:212