/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "file_ex.h" #include <fstream> #include <iostream> #include <algorithm> #include <iterator> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <cstdio> #include <securec.h> #include <cstring> #include "directory_ex.h" #include "utils_log.h" using namespace std; const int MAX_FILE_LENGTH = 32 * 1024 * 1024; namespace OHOS { bool LoadStringFromFile(const string& filePath, string& content) { ifstream file(filePath.c_str()); if (!file.is_open()) { UTILS_LOGE("open file failed! filePath:%{public}s", filePath.c_str()); return false; } file.seekg(0, ios::end); const long fileLength = file.tellg(); if (fileLength > MAX_FILE_LENGTH) { UTILS_LOGE("invalid file length(%{public}ld)!", fileLength); return false; } content.clear(); file.seekg(0, ios::beg); copy(istreambuf_iterator<char>(file), istreambuf_iterator<char>(), back_inserter(content)); return true; } string GetFileNameByFd(const int fd) { if (fd <= 0) { return string(); } string fdPath = "/proc/self/fd/" + std::to_string(fd); char fileName[PATH_MAX + 1] = {0}; int ret = readlink(fdPath.c_str(), fileName, PATH_MAX); if (ret < 0 || ret > PATH_MAX) { UTILS_LOGE("Get fileName failed, ret is: %{public}d!", ret); return string(); } fileName[ret] = '\0'; return string(fileName); } bool LoadStringFromFdToFile(int fd, string& content) { string fileName = GetFileNameByFd(fd); if (fileName.empty()) { UTILS_LOGE("LoadStringFromFd get file name by fd failed!"); return false; } if (!LoadStringFromFile(fileName, content)) { UTILS_LOGE("LoadStringFromFd get string from file failed!"); return false; } return true; } bool LoadStringFromFd(int fd, string& content) { if (fd <= 0) { UTILS_LOGE("invalid fd:%{public}d", fd); return false; } const long fileLength = lseek(fd, 0, SEEK_END); if (fileLength > MAX_FILE_LENGTH) { UTILS_LOGE("invalid file length(%{public}ld)!", fileLength); return false; } // lseek is not support the linux file node if (fileLength < 0) { return LoadStringFromFdToFile(fd, content); } if (fileLength == 0) { return true; } content.resize(fileLength); int loc = lseek(fd, 0, SEEK_SET); if (loc == -1) { UTILS_LOGE("lseek file to begin failed!"); return false; } const long len = read(fd, content.data(), fileLength); if (len != fileLength) { UTILS_LOGE("the length read from file is not equal to fileLength!len:%{public}ld,fileLen:%{public}ld", len, fileLength); return false; } return true; } bool SaveStringToFile(const std::string& filePath, const std::string& content, bool truncated /*= true*/) { if (content.empty()) { UTILS_LOGI("content is empty, no need to save!"); return true; } ofstream file; if (truncated) { file.open(filePath.c_str(), ios::out | ios::trunc); } else { file.open(filePath.c_str(), ios::out | ios::app); } if (!file.is_open()) { UTILS_LOGE("open file failed! filePath:%{private}s", filePath.c_str()); return false; } file.write(content.c_str(), content.length()); if (file.fail()) { UTILS_LOGE("write content to file failed!file:%{private}s, content:%{private}s", filePath.c_str(), content.c_str()); return false; } return true; } bool SaveStringToFd(int fd, const std::string& content) { if (fd <= 0) { UTILS_LOGE("invalid fd:%{public}d", fd); return false; } if (content.empty()) { UTILS_LOGI("content is empty, no need to save!"); return true; } const long len = write(fd, content.c_str(), content.length()); if (len < 0) { UTILS_LOGE("write file failed!errno:%{public}d, err:%{public}s", errno, strerror(errno)); return false; } if ((unsigned long)len != content.length()) { UTILS_LOGE("the length write to file is not equal to fileLength!len:%{public}ld, fileLen:%{public}zu", len, content.length()); return false; } return true; } bool LoadBufferFromNodeFile(const string& filePath, vector<char>& content) { string realPath; if (!PathToRealPath(filePath, realPath)) { UTILS_LOGE("filePath to realPath failed! filePath:%{private}s", filePath.c_str()); return false; } FILE *fp = fopen(realPath.c_str(), "r"); if (fp == nullptr) { UTILS_LOGE("open file failed! filePath:%{private}s", realPath.c_str()); return false; } char ch = fgetc(fp); int byteCount = 1; while (!feof(fp)) { if (byteCount > MAX_FILE_LENGTH) { UTILS_LOGE("LoadBufferFromNodeFile invalid file length(%{public}d)!", byteCount); fclose(fp); fp = nullptr; content.clear(); return false; } content.push_back(ch); ch = fgetc(fp); byteCount++; } fclose(fp); fp = nullptr; return true; } /* load file to buffer. If the buffer is not empty,then overwrite */ bool LoadBufferFromFile(const string& filePath, vector<char>& content) { ifstream file; file.open(filePath.c_str(), ios::in | ios::binary); if (!file.is_open()) { UTILS_LOGE("open file failed! filePath:%{private}s", filePath.c_str()); return false; } file.seekg(0, std::ios::end); const long fileLength = file.tellg(); if (fileLength > MAX_FILE_LENGTH) { UTILS_LOGE("invalid file length(%{public}ld)!", fileLength); return false; } // lseek is not support the linux file node if (fileLength < 0) { return LoadBufferFromNodeFile(filePath, content); } if (fileLength == 0) { content.clear(); return true; } file.seekg(0, std::ios::beg); if (file.fail()) { UTILS_LOGE("seekg file to begin failed!filePath:%{private}s", filePath.c_str()); return false; } content.resize(fileLength); file.read(&content[0], fileLength); return true; } bool SaveBufferToFile(const string& filePath, const vector<char>& content, bool truncated /*= true*/) { if (content.empty()) { UTILS_LOGI("content is empty, no need to save!"); return true; } // if the file is not exist,create it first! uint32_t mode = truncated ? (ios::out | ios::binary | ios::trunc) : (ios::out | ios::binary | ios::app); ofstream file; file.open(filePath.c_str(), mode); if (!file.is_open()) { UTILS_LOGE("open file failed! filePath:%{private}s, mode:%{private}d", filePath.c_str(), mode); return false; } file.write(&content[0], content.size()); return true; } bool FileExists(const string& fileName) { return (access(fileName.c_str(), F_OK) == 0); } bool StringExistsInFile(const string& fileName, const string& subStr, bool caseSensitive /*= true*/) { if (subStr.empty()) { UTILS_LOGE("String is empty"); return false; } string str; if (!LoadStringFromFile(fileName, str)) { UTILS_LOGE("File load fail, filePath:%{private}s", fileName.c_str()); return false; } if (caseSensitive) { return (str.find(subStr) != string::npos); } string strlower(str); string sublower(subStr); transform(str.begin(), str.end(), strlower.begin(), ::tolower); transform(subStr.begin(), subStr.end(), sublower.begin(), ::tolower); return (strlower.find(sublower) != string::npos); } int CountStrInStr(const string& str, const string& subStr) { if (subStr.empty()) { UTILS_LOGE("subStr is empty"); return 0; } size_t position = 0; int count = 0; size_t length = subStr.length(); while ((position = str.find(subStr, position)) != string::npos) { position += length; count++; } return count; } int CountStrInFile(const string& fileName, const string& subStr, bool caseSensitive /*= true*/) { if (subStr.empty()) { UTILS_LOGE("String is empty"); return -1; } string str; if (!LoadStringFromFile(fileName, str)) { UTILS_LOGE("File load fail, filePath:%{private}s", fileName.c_str()); return -1; } // If case-insensitive, strings are converted to lowercase. if (caseSensitive) { return CountStrInStr(str, subStr); } string strlower(str); string sublower(subStr); transform(str.begin(), str.end(), strlower.begin(), ::tolower); transform(subStr.begin(), subStr.end(), sublower.begin(), ::tolower); return CountStrInStr(strlower, sublower); } }