source: rtems-tools/rtemstoolkit/rld-path.cpp @ efae4ae

4.104.115
Last change on this file since efae4ae was ddbab71, checked in by Chris Johns <chrisj@…>, on 11/03/14 at 22:40:15

Fix buffer leak on error.

  • Property mode set to 100644
File size: 5.1 KB
Line 
1/*
2 * Copyright (c) 2011-2014, Chris Johns <chrisj@rtems.org>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <errno.h>
22#include <string.h>
23#include <sys/stat.h>
24#include <unistd.h>
25
26#include <rld.h>
27
28namespace rld
29{
30  namespace path
31  {
32    const std::string
33    basename (const std::string& name)
34    {
35      size_t b = name.find_last_of (RLD_PATH_SEPARATOR);
36      if (b != std::string::npos)
37        return name.substr (b + 1);
38      return name;
39    }
40
41    const std::string
42    dirname (const std::string& name)
43    {
44      size_t b = name.find_last_of (RLD_PATH_SEPARATOR);
45      if (b != std::string::npos)
46        return name.substr (0, b);
47      return name;
48    }
49
50    const std::string
51    extension (const std::string& name)
52    {
53      size_t b = name.find_last_of ('.');
54      if (b != std::string::npos)
55        return name.substr (b);
56      return name;
57    }
58
59    void
60    path_split (const std::string& path, paths& paths)
61    {
62      strings ps;
63      rld::split (ps, path, RLD_PATHSTR_SEPARATOR);
64      if (ps.size ())
65      {
66        for (strings::iterator psi = ps.begin ();
67             psi != ps.end ();
68             ++psi)
69        {
70          if (check_directory (*psi))
71            paths.push_back (*psi);
72        }
73      }
74    }
75
76    void
77    path_join (const std::string& base, const std::string& part, std::string& joined)
78    {
79      if ((base[base.size () - 1] != RLD_PATH_SEPARATOR) &&
80          (part[0] != RLD_PATH_SEPARATOR))
81        joined = base + RLD_PATH_SEPARATOR + part;
82      else if ((base[base.size () - 1] == RLD_PATH_SEPARATOR) &&
83               (part[0] == RLD_PATH_SEPARATOR))
84        joined = base + &part[1];
85      else
86        joined = base + part;
87    }
88
89    void
90    path_join (const std::string& base, const paths& parts, std::string& joined)
91    {
92      joined = base;
93      for (paths::const_iterator pi = parts.begin ();
94           pi != parts.end ();
95           ++pi)
96      {
97        path_join (joined, *pi, joined);
98      }
99    }
100
101    const std::string
102    path_abs (const std::string& path)
103    {
104      std::string apath;
105
106      if (path[0] == RLD_PATH_SEPARATOR)
107      {
108        apath = path;
109      }
110      else
111      {
112        char* buf = 0;
113        try
114        {
115          buf = new char[32 * 1024];
116          if (!::getcwd (buf, 32 * 1024))
117          {
118            delete [] buf;
119            throw rld::error (::strerror (errno), "get current working directory");
120          }
121          path_join (buf, path, apath);
122          delete [] buf;
123        }
124        catch (...)
125        {
126          delete [] buf;
127          throw;
128        }
129      }
130
131      strings ps;
132      strings aps;
133
134      rld::split (ps, apath, RLD_PATH_SEPARATOR);
135
136      for (strings::iterator psi = ps.begin ();
137           psi != ps.end ();
138           ++psi)
139      {
140        const std::string& dir = *psi;
141
142        if (dir.empty () || dir == ".")
143        {
144          /* do nothing */
145        }
146        else if (dir == "..")
147        {
148          aps.pop_back ();
149        }
150        else
151        {
152          aps.push_back (dir);
153        }
154      }
155
156      return RLD_PATH_SEPARATOR + rld::join (aps, RLD_PATH_SEPARATOR_STR);
157    }
158
159    bool
160    check_file (const std::string& path)
161    {
162      struct stat sb;
163      if (::stat (path.c_str (), &sb) == 0)
164        if (S_ISREG (sb.st_mode))
165          return true;
166      return false;
167    }
168
169    bool
170    check_directory (const std::string& path)
171    {
172      struct stat sb;
173      if (::stat (path.c_str (), &sb) == 0)
174        if (S_ISDIR (sb.st_mode))
175          return true;
176      return false;
177    }
178
179    void
180    find_file (std::string& path, const std::string& name, paths& search_paths)
181    {
182      for (paths::iterator pi = search_paths.begin ();
183           pi != search_paths.end ();
184           ++pi)
185      {
186        path_join (*pi, name, path);
187        if (check_file (path))
188          return;
189      }
190      path.clear ();
191    }
192
193    void
194    unlink (const std::string& path, bool not_present_error)
195    {
196      struct stat sb;
197      if (::stat (path.c_str (), &sb) >= 0)
198      {
199        if (!S_ISREG (sb.st_mode))
200            throw rld::error ("Not a regular file", "unlinking: " + path);
201
202        int r;
203#if _WIN32
204        r = ::remove(path.c_str ());
205#else
206        r = ::unlink (path.c_str ());
207#endif
208        if (r < 0)
209          throw rld::error (::strerror (errno), "unlinking: " + path);
210      }
211      else
212      {
213        if (not_present_error)
214          throw rld::error ("Not found", "unlinking: " + path);
215      }
216    }
217  }
218}
Note: See TracBrowser for help on using the repository browser.