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