* -------------------------------------------------------------------------
* This file is part of the Vision SDK project.
* Copyright (c) 2025 Huawei Technologies Co.,Ltd.
*
* Vision SDK is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
* Description: Collect information about plug-ins available in the environment.
* Author: MindX SDK
* Create: 2020
* History: NA
*/
#include <gst/gst.h>
#include <ctime>
#include <fstream>
#include <pwd.h>
#include <sys/types.h>
#include <utmp.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <cstring>
#include "dvpp/securec.h"
#include "MxBase/Log/Log.h"
#include "MxBase/Utils/FileUtils.h"
#include "MxBase/Utils/StringUtils.h"
#include "MxTools/PluginInspector/PluginInspector.h"
using namespace MxBase;
namespace {
const std::string LIB_MXBASE = "/../lib/libmxbase.so";
constexpr mode_t DEPLOYMENT_ARCHIVE_MODE = 0440;
constexpr int HOSTNAME_LEN = 256;
constexpr int PATH_MAX_LEN = 1024;
constexpr int BUF_SIZE = 1024;
constexpr int MAX_LOOP = 1024;
std::string GetDeploymentInfo()
{
char hostname[HOSTNAME_LEN] = { 0 };
if (gethostname(hostname, sizeof(hostname)) != 0) {
return {};
}
struct passwd pwd;
struct passwd *info = nullptr;
char buf[BUF_SIZE] = { 0 };
if (getpwuid_r(getuid(), &pwd, buf, BUF_SIZE, &info) != 0 || info == nullptr || info->pw_name == nullptr) {
return {};
}
const int kLenDev = 5;
if (isatty(0) == 0) {
return {};
}
const char *tty = ttyname(0);
if (tty == nullptr) {
return {};
}
if ((strlen(tty) <= kLenDev) || (strlen(tty) > PATH_MAX_LEN)) {
return {};
}
setutent();
struct utmp *ut = nullptr;
for (int i = 0; i < MAX_LOOP; i++) {
ut = getutent();
if (ut == nullptr) {
break;
}
if (strcmp(ut->ut_line, tty + kLenDev) == 0) {
break;
}
}
endutent();
std::string userIP = "";
if (ut != nullptr) {
struct in_addr addr;
if (inet_aton(ut->ut_host, &addr) == 0) {
return {};
}
userIP = ut->ut_host;
} else {
userIP = tty;
}
std::string userNameStr(info->pw_name);
std::string hostNameStr(hostname);
return "[" + userIP + "]" + "[" + userNameStr + "]" + "[" + hostNameStr + "]";
}
bool WriteFile(const std::string& filePath, const std::string& content)
{
if (!FileUtils::ModifyFilePermission(filePath, FILE_MODE)) {
return false;
}
std::ofstream file(filePath, std::ofstream::out | std::ofstream::app);
if (!file.is_open()) {
LogError << "Invalidate file path." << GetErrorInfo(APP_ERR_COMM_INVALID_PATH);
return false;
}
file.write(content.c_str(), content.size());
file.close();
return FileUtils::ModifyFilePermission(filePath, DEPLOYMENT_ARCHIVE_MODE);
}
std::string GetHomePath()
{
struct passwd pd = {};
struct passwd *tmpPwdPtr = nullptr;
char pwdBuffer[PATH_MAX + static_cast<unsigned int>(1)] = {0x00};
int pwdBufferLen = (int)sizeof(pwdBuffer);
if (getpwuid_r(getuid(), &pd, pwdBuffer, pwdBufferLen, &tmpPwdPtr) != 0) {
if (memset_s(pwdBuffer, sizeof(pwdBuffer), 0, sizeof(pwdBuffer)) != EOK) {
LogError << "Call memset_s failed." << GetErrorInfo(APP_ERR_COMM_FAILURE);
}
return "";
}
std::string homePath = pd.pw_dir;
if (memset_s(pwdBuffer, sizeof(pwdBuffer), 0, sizeof(pwdBuffer)) != EOK) {
LogError << "Call memset_s failed." << GetErrorInfo(APP_ERR_COMM_FAILURE);
return "";
}
return homePath;
}
void RecordUsageInfo(const std::string &path, const std::string &result)
{
auto timeInfo = "[" + StringUtils::GetTimeStamp() + "]";
std::string deploymentContent = timeInfo + GetDeploymentInfo() + ":\n";
std::string resultContent = "Invoke InspectAllPlugins " + result + ".\n";
if (!WriteFile(path, deploymentContent + resultContent)) {
LogError << "write file failed." << GetErrorInfo(APP_ERR_COMM_WRITE_FAIL);
}
}
std::string GetLibFilePath(const std::string& curPath)
{
const int maxPathLen = 1000;
if (curPath.size() == 0 || curPath.size() > maxPathLen) {
LogError << "Incorrect file path length." << GetErrorInfo(APP_ERR_COMM_INVALID_PARAM);
return "";
}
std::size_t pos = curPath.rfind('/');
if (pos == std::string::npos) {
LogError << "Cannot find the directory of this file, invalid file path."
<< GetErrorInfo(APP_ERR_COMM_INVALID_PATH);
return "";
}
std::string fullPathString = curPath.substr(0, pos);
std::string libPath = fullPathString + LIB_MXBASE;
return libPath;
}
bool InitLog()
{
if (MxBase::Log::Init() != APP_ERR_OK) {
LogError << "Failed to initialize log.";
return false;
}
return true;
}
}
int main(int argc, char *argv[])
{
if (!InitLog()) {
return APP_ERR_COMM_FAILURE;
}
auto path = GetHomePath() + "/log/mindxsdk/deployment.log";
std::string realPath;
if (!FileUtils::RegularFilePath(path, realPath)) {
LogError << "Invalid filePath. Please check if \"~/log/mindxsdk/deployment.log\" exists. If not, create it."
<< GetErrorInfo(APP_ERR_COMM_INVALID_PATH);
MxBase::Log::UpdateFileMode();
return APP_ERR_COMM_FAILURE;
}
if (!FileUtils::IsFileValid(realPath, false)) {
LogError << "Invalid filePath." << GetErrorInfo(APP_ERR_COMM_INVALID_PATH);
MxBase::Log::UpdateFileMode();
return APP_ERR_COMM_FAILURE;
}
gst_init(&argc, &argv);
if (argc < 1 || argv[0] == nullptr) {
LogError << "Invalid args for this binnary file." << GetErrorInfo(APP_ERR_COMM_INVALID_PARAM);
RecordUsageInfo(realPath, "failed");
MxBase::Log::UpdateFileMode();
return -1;
}
std::string fullPathString = MxBase::FileUtils::GetAbsolutePath(argv[0]);
std::string libPath = GetLibFilePath(fullPathString);
std::string realLibPath;
if (!MxBase::FileUtils::RegularFilePath(libPath, realLibPath) ||
!MxBase::FileUtils::IsFileValid(realLibPath, true)) {
LogError << "Invalid lib file!" << GetErrorInfo(APP_ERR_COMM_FAILURE);
RecordUsageInfo(realPath, "failed");
MxBase::Log::UpdateFileMode();
return APP_ERR_COMM_FAILURE;
}
std::string outputFile = "AllPluginsInfo.json";
if (FileUtils::IsSymlink(outputFile)) {
LogError << "The output file can not be a link." << GetErrorInfo(APP_ERR_COMM_FAILURE);
RecordUsageInfo(realPath, "failed");
MxBase::Log::UpdateFileMode();
return APP_ERR_COMM_FAILURE;
}
RecordUsageInfo(realPath, "successful");
auto inspector = MxTools::PluginInspector();
inspector.ExportAllPluginInfos(outputFile);
MxBase::Log::UpdateFileMode();
return 0;
}