blob: 5e77cb50d03514b792492796daedbef9ee6777d4 [file] [log] [blame]
William A. Kennington III226bc422021-05-05 17:08:36 -07001#include <systemd/sd-bus.h>
2
3#include <sdbusplus/message/native_types.hpp>
4#include <sdbusplus/utility/memory.hpp>
5
6#include <array>
7
8namespace sdbusplus
9{
10namespace message
11{
12namespace details
13{
14
15std::string string_path_wrapper::filename() const
16{
17 size_t firstIndex = str.rfind('/');
18
19 // Dbus paths must start with /, if we don't find one, it's an error
20 if (firstIndex == std::string::npos)
21 {
22 return "";
23 }
24 firstIndex++;
25 // If we don't see that this was encoded by sdbusplus, return the naive
26 // version of the filename path.
27 const char* filename = str.c_str() + firstIndex;
28 if (*filename != '_')
29 {
30 return std::string(filename);
31 }
32
33 _cleanup_free_ char* out = nullptr;
34 int r = sd_bus_path_decode_many(filename, "%", &out);
35 if (r <= 0)
36 {
37 return "";
38 }
39 return std::string(out);
40}
41
42string_path_wrapper string_path_wrapper::parent_path() const
43{
44 auto index = str.rfind('/');
45 if (index == std::string::npos)
46 {
47 return string_path_wrapper("/");
48 }
49 if (index <= 1)
50 {
51 return string_path_wrapper("/");
52 }
53
54 return str.substr(0, index);
55}
56
57string_path_wrapper string_path_wrapper::operator/(const char* extId) const
58{
59 string_path_wrapper out;
60 _cleanup_free_ char* encOut = nullptr;
61 int ret = sd_bus_path_encode(str.c_str(), extId, &encOut);
62 if (ret < 0)
63 {
64 return out;
65 }
66 out.str = encOut;
67
68 size_t firstIndex = str.size();
69 if (str != "/")
70 {
71 firstIndex++;
72 }
73
74 // Attempt to encode the first character of the path. This allows the
75 // filename() method to "detect" that this is a path that's been encoded
76 // and to decode it properly. This was needed to support a number of
77 // paths that currently dont' have any encoding, and utilize underscores
78 // Ideally this, and the equivalent code in filename() would go away
79 // when all paths are being encoded per systemds methods.
80 if (out.str[firstIndex] == '_')
81 {
82 return out;
83 }
84
85 constexpr std::array<char, 16> hex{'0', '1', '2', '3', '4', '5', '6', '7',
86 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
87 uint8_t firstChar = static_cast<uint8_t>(*extId);
88 out.str[firstIndex] = '_';
89 std::array<char, 2> encoded{hex[(firstChar >> 4) & 0xF],
90 hex[firstChar & 0xF]};
91 out.str.insert(out.str.begin() + firstIndex + 1, encoded.begin(),
92 encoded.end());
93
94 return out;
95}
96
97string_path_wrapper& string_path_wrapper::operator/=(const char* extId)
98{
99 string_path_wrapper out = this->operator/(extId);
100 this->str = std::move(out.str);
101 return *this;
102}
103
104} // namespace details
105} // namespace message
106} // namespace sdbusplus