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