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

4.104.115
Last change on this file since 3fd45d3 was 73eb48a, checked in by Chris Johns <chrisj@…>, on 09/13/14 at 02:20:19

rtk: Fix buffer leak in rld::path::abs_path.

  • 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, 132 * 1024))
117            throw rld::error (::strerror (errno), "get current working directory");
118          path_join (buf, path, apath);
119          delete [] buf;
120        }
121        catch (...)
122        {
123          delete [] buf;
124          throw;
125        }
126      }
127
128      strings ps;
129      strings aps;
130
131      rld::split (ps, apath, RLD_PATH_SEPARATOR);
132
133      for (strings::iterator psi = ps.begin ();
134           psi != ps.end ();
135           ++psi)
136      {
137        const std::string& dir = *psi;
138
139        if (dir.empty () || dir == ".")
140        {
141          /* do nothing */
142        }
143        else if (dir == "..")
144        {
145          aps.pop_back ();
146        }
147        else
148        {
149          aps.push_back (dir);
150        }
151      }
152
153      return RLD_PATH_SEPARATOR + rld::join (aps, RLD_PATH_SEPARATOR_STR);
154    }
155
156    bool
157    check_file (const std::string& path)
158    {
159      struct stat sb;
160      if (::stat (path.c_str (), &sb) == 0)
161        if (S_ISREG (sb.st_mode))
162          return true;
163      return false;
164    }
165
166    bool
167    check_directory (const std::string& path)
168    {
169      struct stat sb;
170      if (::stat (path.c_str (), &sb) == 0)
171        if (S_ISDIR (sb.st_mode))
172          return true;
173      return false;
174    }
175
176    void
177    find_file (std::string& path, const std::string& name, paths& search_paths)
178    {
179      for (paths::iterator pi = search_paths.begin ();
180           pi != search_paths.end ();
181           ++pi)
182      {
183        path_join (*pi, name, path);
184        if (check_file (path))
185          return;
186      }
187      path.clear ();
188    }
189
190    void
191    unlink (const std::string& path, bool not_present_error)
192    {
193      struct stat sb;
194      if (::stat (path.c_str (), &sb) >= 0)
195      {
196        if (!S_ISREG (sb.st_mode))
197            throw rld::error ("Not a regular file", "unlinking: " + path);
198
199        int r;
200#if _WIN32
201        r = ::remove(path.c_str ());
202#else
203        r = ::unlink (path.c_str ());
204#endif
205        if (r < 0)
206          throw rld::error (::strerror (errno), "unlinking: " + path);
207      }
208      else
209      {
210        if (not_present_error)
211          throw rld::error ("Not found", "unlinking: " + path);
212      }
213    }
214  }
215}
Note: See TracBrowser for help on using the repository browser.