• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "rmdirent.h"
17 
18 #include <cstring>
19 #include <dirent.h>
20 #include <filesystem>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <tuple>
24 #include <unistd.h>
25 
26 #include "filemgmt_libhilog.h"
27 
28 namespace OHOS {
29 namespace FileManagement {
30 namespace ModuleFileIO {
31 using namespace std;
32 using namespace OHOS::FileManagement::LibN;
33 
34 #ifdef __MUSL__
RmDirent(const string & fpath)35 static NError RmDirent(const string &fpath)
36 {
37     std::filesystem::path strToPath(fpath);
38     std::uintmax_t num = std::filesystem::remove_all(strToPath);
39     if (!num || std::filesystem::exists(strToPath)) {
40         HILOGE("Failed to remove file or directory by path");
41         return NError(errno);
42     }
43 
44     return NError(ERRNO_NOERR);
45 }
46 
47 #else
RmDirent(const string & fpath)48 static NError RmDirent(const string &fpath)
49 {
50     if (rmdir(fpath.c_str()) == 0) {
51         return NError(ERRNO_NOERR);
52     }
53     auto dir = opendir(fpath.c_str());
54     if (!dir) {
55         return NError(errno);
56     }
57     struct dirent* entry = readdir(dir);
58     while (entry) {
59         if (strncmp(entry->d_name, ".", strlen(".")) == 0 ||
60             strncmp(entry->d_name, "..", strlen("..")) == 0) {
61             entry = readdir(dir);
62             continue;
63         }
64         struct stat fileInformation;
65         string filePath = fpath + '/';
66         filePath.insert(filePath.length(), entry->d_name);
67         if (stat(filePath.c_str(), &fileInformation) != 0) {
68             closedir(dir);
69             HILOGE("Failed to close directory");
70             return NError(errno);
71         }
72         if ((fileInformation.st_mode & S_IFMT) == S_IFDIR) {
73             auto err = RmDirent(filePath);
74             if (err) {
75                 closedir(dir);
76                 return err;
77             }
78         } else {
79             if (unlink(filePath.c_str()) != 0) {
80                 closedir(dir);
81                 return NError(errno);
82             }
83         }
84         entry = readdir(dir);
85     }
86     closedir(dir);
87     if (rmdir(fpath.c_str()) != 0) {
88         return NError(errno);
89     }
90     return NError(ERRNO_NOERR);
91 }
92 #endif
93 
Sync(napi_env env,napi_callback_info info)94 napi_value Rmdirent::Sync(napi_env env, napi_callback_info info)
95 {
96     NFuncArg funcArg(env, info);
97     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
98         HILOGE("Number of arguments unmatched");
99         NError(EINVAL).ThrowErr(env);
100         return nullptr;
101     }
102 
103     auto [succ, path, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
104     if (!succ) {
105         HILOGE("Invalid path from JS first argument");
106         NError(EINVAL).ThrowErr(env);
107         return nullptr;
108     }
109 
110     auto err = RmDirent(string(path.get()));
111     if (err) {
112         err.ThrowErr(env);
113         return nullptr;
114     }
115 
116     return NVal::CreateUndefined(env).val_;
117 }
118 
Async(napi_env env,napi_callback_info info)119 napi_value Rmdirent::Async(napi_env env, napi_callback_info info)
120 {
121     NFuncArg funcArg(env, info);
122     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
123         HILOGE("Number of arguments unmatched");
124         NError(EINVAL).ThrowErr(env);
125         return nullptr;
126     }
127 
128     auto [succ, path, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
129     if (!succ) {
130         HILOGE("Invalid path from JS first argument");
131         NError(EINVAL).ThrowErr(env);
132         return nullptr;
133     }
134 
135     auto cbExec = [tmpPath = string(path.get())]() -> NError {
136         return RmDirent(tmpPath);
137     };
138     auto cbCompl = [](napi_env env, NError err) -> NVal {
139         if (err) {
140             return { env, err.GetNapiErr(env) };
141         } else {
142             return NVal::CreateUndefined(env);
143         }
144     };
145 
146     NVal thisVar(env, funcArg.GetThisVar());
147     size_t argc = funcArg.GetArgc();
148     if (argc == NARG_CNT::ONE) {
149         return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_RMDIRENT_NAME, cbExec, cbCompl).val_;
150     } else {
151         NVal cb(env, funcArg[NARG_POS::SECOND]);
152         return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_RMDIRENT_NAME, cbExec, cbCompl).val_;
153     }
154 }
155 } // namespace ModuleFileIO
156 } // namespace FileManagement
157 } // namespace OHOS