1 #include "elog_entry.hpp"
2 
3 #include "elog_serialize.hpp"
4 #include "extensions.hpp"
5 #include "log_manager.hpp"
6 #include "paths.hpp"
7 
8 #include <fcntl.h>
9 #include <unistd.h>
10 
11 #include <phosphor-logging/lg2.hpp>
12 #include <xyz/openbmc_project/Common/File/error.hpp>
13 
14 namespace phosphor
15 {
16 namespace logging
17 {
18 
19 // TODO Add interfaces to handle the error log id numbering
20 
21 void Entry::delete_()
22 {
23     parent.erase(id());
24 }
25 
26 bool Entry::resolved(bool value)
27 {
28     auto current =
29         sdbusplus::server::xyz::openbmc_project::logging::Entry::resolved();
30     if (value != current)
31     {
32         // Resolve operation will be prohibited if delete operation is
33         // prohibited.
34         for (auto& func : Extensions::getDeleteProhibitedFunctions())
35         {
36             try
37             {
38                 bool prohibited = false;
39                 func(id(), prohibited);
40 
41                 if (prohibited)
42                 {
43                     throw sdbusplus::xyz::openbmc_project::Common::Error::
44                         Unavailable();
45                 }
46             }
47             catch (const sdbusplus::xyz::openbmc_project::Common::Error::
48                        Unavailable& e)
49             {
50                 throw;
51             }
52             catch (const std::exception& e)
53             {
54                 lg2::error("An extension's deleteProhibited function threw an "
55                            "exception: {ERROR}",
56                            "ERROR", e);
57             }
58         }
59         value ? associations({}) : associations(assocs);
60         current =
61             sdbusplus::server::xyz::openbmc_project::logging::Entry::resolved(
62                 value);
63 
64         uint64_t ms = std::chrono::duration_cast<std::chrono::milliseconds>(
65                           std::chrono::system_clock::now().time_since_epoch())
66                           .count();
67         updateTimestamp(ms);
68 
69         serialize(*this);
70     }
71 
72     return current;
73 }
74 
75 std::string Entry::eventId(std::string value)
76 {
77     auto current =
78         sdbusplus::server::xyz::openbmc_project::logging::Entry::eventId();
79     if (value != current)
80     {
81         current =
82             sdbusplus::server::xyz::openbmc_project::logging::Entry::eventId(
83                 value);
84         serialize(*this);
85     }
86 
87     return current;
88 }
89 
90 std::string Entry::resolution(std::string value)
91 {
92     auto current =
93         sdbusplus::server::xyz::openbmc_project::logging::Entry::resolution();
94     if (value != current)
95     {
96         current =
97             sdbusplus::server::xyz::openbmc_project::logging::Entry::resolution(
98                 value);
99         serialize(*this);
100     }
101 
102     return current;
103 }
104 
105 sdbusplus::message::unix_fd Entry::getEntry()
106 {
107     int fd = open(path().c_str(), O_RDONLY | O_NONBLOCK);
108     if (fd == -1)
109     {
110         auto e = errno;
111         lg2::error("Failed to open Entry File ERRNO={ERRNO}, PATH={PATH}",
112                    "ERRNO", e, "PATH", path());
113         throw sdbusplus::xyz::openbmc_project::Common::File::Error::Open();
114     }
115 
116     // Schedule the fd to be closed by sdbusplus when it sends it back over
117     // D-Bus.
118     sdeventplus::Event event = sdeventplus::Event::get_default();
119     fdCloseEventSource = std::make_unique<sdeventplus::source::Defer>(
120         event, std::bind(std::mem_fn(&Entry::closeFD), this, fd,
121                          std::placeholders::_1));
122 
123     return fd;
124 }
125 
126 void Entry::closeFD(int fd, sdeventplus::source::EventBase& /*source*/)
127 {
128     close(fd);
129     fdCloseEventSource.reset();
130 }
131 
132 } // namespace logging
133 } // namespace phosphor
134