106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License.
506f6ba60Sopenharmony_ci * You may obtain a copy of the License at
606f6ba60Sopenharmony_ci *
706f6ba60Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
806f6ba60Sopenharmony_ci *
906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and
1306f6ba60Sopenharmony_ci * limitations under the License.
1406f6ba60Sopenharmony_ci */
1506f6ba60Sopenharmony_ci
1606f6ba60Sopenharmony_ci#include <cstdio>
1706f6ba60Sopenharmony_ci#include <ctime>
1806f6ba60Sopenharmony_ci#include <sstream>
1906f6ba60Sopenharmony_ci
2006f6ba60Sopenharmony_ci#include <sys/time.h>
2106f6ba60Sopenharmony_ci
2206f6ba60Sopenharmony_ci
2306f6ba60Sopenharmony_ci#include "libbpf_logger.h"
2406f6ba60Sopenharmony_ci#include "hhlog.h"
2506f6ba60Sopenharmony_ci
2606f6ba60Sopenharmony_cistatic constexpr int FILE_MODE = 0644;
2706f6ba60Sopenharmony_ci
2806f6ba60Sopenharmony_cistd::unique_ptr<LIBBPFLogger> LIBBPFLogger::MakeUnique(const std::string& logFile, int logLevel)
2906f6ba60Sopenharmony_ci{
3006f6ba60Sopenharmony_ci    std::unique_ptr<LIBBPFLogger> logger {new(std::nothrow) LIBBPFLogger {logLevel}};
3106f6ba60Sopenharmony_ci    if (logger == nullptr) {
3206f6ba60Sopenharmony_ci        return nullptr;
3306f6ba60Sopenharmony_ci    }
3406f6ba60Sopenharmony_ci#if defined(BPF_LOGGER_DEBUG) || defined(BPF_LOGGER_INFO) || defined(BPF_LOGGER_WARN) ||   \
3506f6ba60Sopenharmony_ci    defined(BPF_LOGGER_ERROR) || defined(BPF_LOGGER_FATAL)
3606f6ba60Sopenharmony_ci    if (logger->OpenLogFile(logFile) != 0) {
3706f6ba60Sopenharmony_ci        return nullptr;
3806f6ba60Sopenharmony_ci    }
3906f6ba60Sopenharmony_ci#endif
4006f6ba60Sopenharmony_ci    return logger;
4106f6ba60Sopenharmony_ci}
4206f6ba60Sopenharmony_ci
4306f6ba60Sopenharmony_ciint LIBBPFLogger::Printf(int logLevel, const char* format, va_list args)
4406f6ba60Sopenharmony_ci{
4506f6ba60Sopenharmony_ci    HHLOGI(true, "current libbpf log level = %d, target level = %d", logLevel, logLevel_);
4606f6ba60Sopenharmony_ci    if (logLevel > logLevel_) {
4706f6ba60Sopenharmony_ci        return 0;
4806f6ba60Sopenharmony_ci    }
4906f6ba60Sopenharmony_ci#if defined(BPF_LOGGER_DEBUG) || defined(BPF_LOGGER_INFO) || defined(BPF_LOGGER_WARN) ||   \
5006f6ba60Sopenharmony_ci    defined(BPF_LOGGER_ERROR) || defined(BPF_LOGGER_FATAL)
5106f6ba60Sopenharmony_ci    return vdprintf(fd_, format, args);
5206f6ba60Sopenharmony_ci#else
5306f6ba60Sopenharmony_ci    return 0;
5406f6ba60Sopenharmony_ci#endif
5506f6ba60Sopenharmony_ci}
5606f6ba60Sopenharmony_ci
5706f6ba60Sopenharmony_ciint LIBBPFLogger::OpenLogFile(const std::string& logFile)
5806f6ba60Sopenharmony_ci{
5906f6ba60Sopenharmony_ci    if (logFile.compare("stdout") == 0) {
6006f6ba60Sopenharmony_ci        if (fcntl(STDOUT_FILENO, F_GETFL)) {
6106f6ba60Sopenharmony_ci            fd_ = open("/dev/stdout", O_WRONLY);
6206f6ba60Sopenharmony_ci        } else {
6306f6ba60Sopenharmony_ci            fd_ = STDOUT_FILENO;
6406f6ba60Sopenharmony_ci        }
6506f6ba60Sopenharmony_ci        if (fd_ < 0) {
6606f6ba60Sopenharmony_ci            return -1;
6706f6ba60Sopenharmony_ci        }
6806f6ba60Sopenharmony_ci        return 0;
6906f6ba60Sopenharmony_ci    }
7006f6ba60Sopenharmony_ci    auto fileName = GetLogFileName();
7106f6ba60Sopenharmony_ci    if (fileName.length() == 0) {
7206f6ba60Sopenharmony_ci        return -1;
7306f6ba60Sopenharmony_ci    }
7406f6ba60Sopenharmony_ci    fileName = "/data/local/tmp/" + fileName;
7506f6ba60Sopenharmony_ci    fd_ = open(fileName.c_str(), O_WRONLY | O_CREAT, FILE_MODE);
7606f6ba60Sopenharmony_ci    if (fd_ < 0) {
7706f6ba60Sopenharmony_ci        return -1;
7806f6ba60Sopenharmony_ci    }
7906f6ba60Sopenharmony_ci    unlink(logFile.c_str());
8006f6ba60Sopenharmony_ci    if (link(fileName.c_str(), logFile.c_str()) != 0) {
8106f6ba60Sopenharmony_ci        return -1;
8206f6ba60Sopenharmony_ci    }
8306f6ba60Sopenharmony_ci
8406f6ba60Sopenharmony_ci    return 0;
8506f6ba60Sopenharmony_ci}
8606f6ba60Sopenharmony_ci
8706f6ba60Sopenharmony_cistd::string LIBBPFLogger::GetLogFileName() const
8806f6ba60Sopenharmony_ci{
8906f6ba60Sopenharmony_ci    struct timeval timer;
9006f6ba60Sopenharmony_ci    gettimeofday(&timer, nullptr);
9106f6ba60Sopenharmony_ci    time_t now = (time_t) timer.tv_sec;
9206f6ba60Sopenharmony_ci    struct tm* tmPtr {nullptr};
9306f6ba60Sopenharmony_ci    tmPtr = localtime(&now);
9406f6ba60Sopenharmony_ci    CHECK_NOTNULL(tmPtr, "", "GetLogFileName fail");
9506f6ba60Sopenharmony_ci    std::stringstream ss;
9606f6ba60Sopenharmony_ci    constexpr int yearStart {1900};
9706f6ba60Sopenharmony_ci    constexpr int monthStart {1};
9806f6ba60Sopenharmony_ci    ss << std::to_string(tmPtr->tm_year + yearStart) << ".";
9906f6ba60Sopenharmony_ci    ss << std::to_string(tmPtr->tm_mon + monthStart) << ".";
10006f6ba60Sopenharmony_ci    ss << std::to_string(tmPtr->tm_mday) << "_";
10106f6ba60Sopenharmony_ci    ss << std::to_string(tmPtr->tm_hour) << ".";
10206f6ba60Sopenharmony_ci    ss << std::to_string(tmPtr->tm_min) << ".";
10306f6ba60Sopenharmony_ci    ss << std::to_string(tmPtr->tm_sec) << ".libbpf.log";
10406f6ba60Sopenharmony_ci    return ss.str();
10506f6ba60Sopenharmony_ci}