libzypp  17.31.31
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 
19 using std::string;
20 
22 namespace zypp
23 {
24  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
237 
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
Pathname realpath() const
Returns this path as the absolute canonical pathname.
Definition: Pathname.cc:231
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
Pathname extend(const std::string &r) const
Append string r to the last component of the path.
Definition: Pathname.h:173
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 basename() const
Return the last component of this path.
Definition: Pathname.h:128
bool emptyOrRoot() const
Test for "" or "/".
Definition: Pathname.h:121
bool empty() const
Test for an empty path.
Definition: Pathname.h:114
void setPathName(const std::string &path, EEncoding eflag=zypp::url::E_DECODED)
Set the path name.
Definition: Url.cc:764
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition: String.h:211
void setScheme(const std::string &scheme)
Set the scheme name in the URL.
Definition: Url.cc:668
const std::string & asString() const
String representation.
Definition: Pathname.h:91
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:124
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
Pathname()
Default ctor: an empty path.
Definition: Pathname.h:48
static std::string showRoot(const Pathname &root_r, const Pathname &path_r)
String representation as "(root)/path".
Definition: Pathname.cc:190
SolvableIdType size_type
Definition: PoolMember.h:126
void _assign(const std::string &name_r)
Definition: Pathname.cc:33
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition: String.h:1027
Pathname cat(const Pathname &r) const
Concatenation of pathnames.
Definition: Pathname.h:165
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
Url manipulation class.
Definition: Url.h:91
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