• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <ctime>
17 #include <sstream>
18 #include <sys/time.h>
19 #include <fcntl.h>
20 #include <poll.h>
21 #include <unistd.h>
22 
23 #include "bpf_log_reader.h"
24 
25 static constexpr int FILE_MODE = 0644;
26 
~BPFLogReader()27 BPFLogReader::~BPFLogReader()
28 {
29     Stop();
30     if (worker_.joinable()) {
31         worker_.join();
32     }
33     if (ifd_ >= 0) {
34         close(ifd_);
35         ifd_ = -1;
36     }
37     if (ofd_ >= 0) {
38         close(ofd_);
39         ofd_ = -1;
40     }
41 }
42 
MakeUnique(const std::string & logFile)43 std::unique_ptr<BPFLogReader> BPFLogReader::MakeUnique(const std::string& logFile)
44 {
45     std::unique_ptr<BPFLogReader> logReader {new(std::nothrow) BPFLogReader {}};
46     if (logReader == nullptr) {
47         return nullptr;
48     }
49     if (logReader->EnableTracePipe() != 0) {
50         return nullptr;
51     }
52     if (logReader->OpenTracePipe() != 0) {
53         return nullptr;
54     }
55     if (logReader->OpenLogFile(logFile) != 0) {
56         return nullptr;
57     }
58     return logReader;
59 }
60 
GetLogFileName() const61 std::string BPFLogReader::GetLogFileName() const
62 {
63     struct timeval timer;
64     gettimeofday(&timer, nullptr);
65     time_t now = (time_t) timer.tv_sec;
66     struct tm* tmPtr {nullptr};
67     tmPtr = localtime(&now);
68     if (tmPtr == nullptr) {
69         return "";
70     }
71     std::stringstream ss;
72     constexpr int yearStart {1900};
73     constexpr int monthStart {1};
74     ss << "/data/local/tmp/";
75     ss << std::to_string(tmPtr->tm_year + yearStart) << ".";
76     ss << std::to_string(tmPtr->tm_mon + monthStart) << ".";
77     ss << std::to_string(tmPtr->tm_mday) << "_";
78     ss << std::to_string(tmPtr->tm_hour) << ".";
79     ss << std::to_string(tmPtr->tm_min) << ".";
80     ss << std::to_string(tmPtr->tm_sec) << ".bpf.log";
81     return ss.str();
82 }
83 
OpenLogFile(const std::string & logFile)84 int BPFLogReader::OpenLogFile(const std::string& logFile)
85 {
86     if (logFile.compare("stdout") == 0) {
87         if (fcntl(STDOUT_FILENO, F_GETFL)) {
88             ofd_ = open("/dev/stdout", O_WRONLY);
89         } else {
90             ofd_ = STDOUT_FILENO;
91         }
92         if (ofd_ < 0) {
93             return -1;
94         }
95         return 0;
96     }
97     auto fileName = GetLogFileName();
98     if (fileName.length() == 0) {
99         return -1;
100     }
101     ofd_ = open(fileName.c_str(), O_WRONLY | O_CREAT, FILE_MODE);
102     if (ofd_ < 0) {
103         return -1;
104     }
105     unlink(logFile.c_str());
106     if (link(fileName.c_str(), logFile.c_str()) != 0) {
107         return -1;
108     }
109 
110     return 0;
111 }
112 
EnableTracePipe() const113 int BPFLogReader::EnableTracePipe() const
114 {
115     int fd = open(confPath_.c_str(), O_WRONLY);
116     if (fd < 0) {
117         return -1;
118     }
119     if (ftruncate(fd, 0) != 0) {
120     }
121     char c {'1'};
122     int ret = write(fd, &c, sizeof(c));
123     if (ret != sizeof(c)) {
124         return -1;
125     }
126     close(fd);
127 
128     return 0;
129 }
130 
OpenTracePipe()131 int BPFLogReader::OpenTracePipe()
132 {
133     ifd_ = open(pipePath_.c_str(), O_RDONLY | O_NONBLOCK);
134     if (ifd_ < 0) {
135         return -1;
136     }
137     return 0;
138 }
139 
MoveBPFLog()140 int BPFLogReader::MoveBPFLog()
141 {
142     constexpr size_t bufSize {1024};
143     char buffer[bufSize];
144     while (true) {
145         struct pollfd fds;
146         fds.fd = ifd_;
147         fds.events = POLLIN;
148         constexpr int timeout {10};
149         constexpr nfds_t nfds {1};
150         int ret = poll(&fds, nfds, timeout);
151         if (stop_ or ret == -1) {
152             break;
153         }
154         if (ret == nfds) {
155             ret = read(ifd_, buffer, sizeof(buffer));
156             if (ret <= 0) {
157                 break;
158             }
159             ret = write(ofd_, buffer, ret);
160             if (ret <= 0) {
161                 break;
162             }
163         }
164     }
165     return 0;
166 }