1/*
2 * Copyright (c) 2022-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#define HST_LOG_TAG "FileSystem"
16
17#include "osal/filesystem/file_system.h"
18#ifdef _WIN32
19#include <direct.h>
20#include <fcntl.h>
21#include <windows.h>
22#else
23#include <unistd.h>
24#endif
25
26#include <cerrno>
27#include <cstdio>
28#include <cstdlib>
29#include <cstring>
30#include <dirent.h>
31#include "common/log.h"
32
33namespace {
34constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_FOUNDATION, "FileSystem" };
35}
36
37#ifndef _WIN32
38mode_t umask(mode_t mask);
39#endif
40
41namespace OHOS {
42namespace Media {
43bool FileSystem::IsRegularFile(const std::string& path)
44{
45    struct stat s {};
46    return (stat(path.c_str(), &s) == 0) && S_ISREG(s.st_mode);
47}
48
49bool FileSystem::IsFdValid(int32_t fd, struct stat& s)
50{
51    return fstat(fd, &s) == 0;
52}
53
54bool FileSystem::IsRegularFile(int32_t fd)
55{
56    struct stat s {};
57    return IsFdValid(fd, s) && S_ISREG(s.st_mode);
58}
59
60bool FileSystem::IsSocketFile(int32_t fd)
61{
62    struct stat s {};
63    return IsFdValid(fd, s) && S_ISSOCK(s.st_mode);
64}
65
66bool FileSystem::IsSeekable(int32_t fd)
67{
68    return IsRegularFile(fd) && lseek(fd, 0, SEEK_CUR) != -1;
69}
70
71bool FileSystem::IsDirectory(const std::string& path)
72{
73    struct stat s {};
74    return (stat(path.c_str(), &s) == 0) && S_ISDIR(s.st_mode);
75}
76
77// judge regular file, directory, symbolic link file path exists
78bool FileSystem::IsExists(const std::string& path)
79{
80    return access(path.c_str(), 0) != -1;
81}
82
83bool FileSystem::MakeDir(const std::string& path)
84{
85#ifdef _WIN32
86    if (mkdir(path.c_str()) == -1) {
87        MEDIA_LOG_E("Fail to create dir " PUBLIC_LOG_S " due to " PUBLIC_LOG_S, path.c_str(), std::strerror(errno));
88        return false;
89    }
90#else
91#ifndef OHOS_LITE
92    auto oldMask = umask(0);
93#endif
94    if (mkdir(path.c_str(), 755) == -1) { // 755 directory access permissions
95        MEDIA_LOG_E("Fail to create dir " PUBLIC_LOG_S " due to " PUBLIC_LOG_S, path.c_str(), std::strerror(errno));
96#ifndef OHOS_LITE
97        umask(oldMask);
98#endif
99        return false;
100    }
101#ifndef OHOS_LITE
102    umask(oldMask);
103#endif
104#endif
105    return true;
106}
107
108bool FileSystem::MakeMultipleDir(const std::string& path)
109{
110    FALSE_RETURN_V(!IsExists(path), true);
111
112    // pos is 1, not 0  example: D:/a/b, /local/tmp/
113    // Avoid Linux root path before is empty string, which makes it impossible to judge whether the path exists
114    auto index = path.find('/', 1);
115    while (index != std::string::npos) {
116        std::string tPath = path.substr(0, index);
117        FALSE_RETURN_V(IsExists(tPath) || MakeDir(tPath), false);
118        index = path.find('/', index + 1);
119    }
120    return path[path.size() - 1] == '/' || MakeDir(path);
121}
122
123void FileSystem::ClearFileContent(const std::string& fullPath)
124{
125    MEDIA_LOG_I("Clear file content path : " PUBLIC_LOG_S, fullPath.c_str());
126    auto filePtr = fopen(fullPath.c_str(), "w+");
127    if (!filePtr) {
128        MEDIA_LOG_E("Clear file content fail.");
129        return;
130    }
131    fclose(filePtr);
132}
133
134void FileSystem::RemoveFilesInDir(const std::string& path)
135{
136    DIR *directory;
137    if ((directory = opendir(path.c_str())) != nullptr) {
138        struct dirent *info;
139        while ((info = readdir(directory)) != nullptr) {
140            if (strcmp(info->d_name, ".") == 0 || strcmp(info->d_name, "..") == 0) {
141                continue;
142            }
143            std::string fullPath = path + "/" + info->d_name;
144            MEDIA_LOG_D("Remove file : " PUBLIC_LOG_S, fullPath.c_str());
145            NZERO_LOG(remove(fullPath.c_str()));
146        }
147        closedir(directory);
148    }
149}
150} // namespace Media
151} // namespace OHOS