1cc290419Sopenharmony_ci/*
2cc290419Sopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd.
3cc290419Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4cc290419Sopenharmony_ci * you may not use this file except in compliance with the License.
5cc290419Sopenharmony_ci * You may obtain a copy of the License at
6cc290419Sopenharmony_ci *
7cc290419Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8cc290419Sopenharmony_ci *
9cc290419Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10cc290419Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11cc290419Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12cc290419Sopenharmony_ci * See the License for the specific language governing permissions and
13cc290419Sopenharmony_ci * limitations under the License.
14cc290419Sopenharmony_ci */
15cc290419Sopenharmony_ci#include "file.h"
16cc290419Sopenharmony_ci#include "serial_struct.h"
17cc290419Sopenharmony_ci
18cc290419Sopenharmony_cinamespace Hdc {
19cc290419Sopenharmony_ciHdcFile::HdcFile(HTaskInfo hTaskInfo)
20cc290419Sopenharmony_ci    : HdcTransferBase(hTaskInfo)
21cc290419Sopenharmony_ci{
22cc290419Sopenharmony_ci    commandBegin = CMD_FILE_BEGIN;
23cc290419Sopenharmony_ci    commandData = CMD_FILE_DATA;
24cc290419Sopenharmony_ci    isStableBuf = hTaskInfo->isStableBuf;
25cc290419Sopenharmony_ci}
26cc290419Sopenharmony_ci
27cc290419Sopenharmony_ciHdcFile::~HdcFile()
28cc290419Sopenharmony_ci{
29cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "~HdcFile channelId:%u", taskInfo->channelId);
30cc290419Sopenharmony_ci};
31cc290419Sopenharmony_ci
32cc290419Sopenharmony_civoid HdcFile::StopTask()
33cc290419Sopenharmony_ci{
34cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "StopTask channelId:%u", taskInfo->channelId);
35cc290419Sopenharmony_ci    singalStop = true;
36cc290419Sopenharmony_ci};
37cc290419Sopenharmony_ci
38cc290419Sopenharmony_cibool HdcFile::BeginTransfer(CtxFile *context, const string &command)
39cc290419Sopenharmony_ci{
40cc290419Sopenharmony_ci    int argc = 0;
41cc290419Sopenharmony_ci    bool ret = false;
42cc290419Sopenharmony_ci    StartTraceScope("HdcFile::BeginTransfer");
43cc290419Sopenharmony_ci    char **argv = Base::SplitCommandToArgs(command.c_str(), &argc);
44cc290419Sopenharmony_ci    if (argc < CMD_ARG1_COUNT || argv == nullptr) {
45cc290419Sopenharmony_ci        LogMsg(MSG_FAIL, "Transfer path split failed");
46cc290419Sopenharmony_ci        if (argv) {
47cc290419Sopenharmony_ci            delete[](reinterpret_cast<char *>(argv));
48cc290419Sopenharmony_ci        }
49cc290419Sopenharmony_ci        return false;
50cc290419Sopenharmony_ci    }
51cc290419Sopenharmony_ci    if (!SetMasterParameters(context, command.c_str(), argc, argv)) {
52cc290419Sopenharmony_ci        delete[](reinterpret_cast<char *>(argv));
53cc290419Sopenharmony_ci        return false;
54cc290419Sopenharmony_ci    }
55cc290419Sopenharmony_ci    uv_fs_t *openReq = new uv_fs_t;
56cc290419Sopenharmony_ci    if (openReq == nullptr) {
57cc290419Sopenharmony_ci        delete[](reinterpret_cast<char *>(argv));
58cc290419Sopenharmony_ci        LogMsg(MSG_FAIL, "HdcFile::BeginTransfer new openReq failed");
59cc290419Sopenharmony_ci        return false;
60cc290419Sopenharmony_ci    }
61cc290419Sopenharmony_ci    memset_s(openReq, sizeof(uv_fs_t), 0, sizeof(uv_fs_t));
62cc290419Sopenharmony_ci    openReq->data = context;
63cc290419Sopenharmony_ci    do {
64cc290419Sopenharmony_ci        ++refCount;
65cc290419Sopenharmony_ci        uv_fs_open(loopTask, openReq, context->localPath.c_str(), O_RDONLY, S_IWUSR | S_IRUSR, OnFileOpen);
66cc290419Sopenharmony_ci        context->master = true;
67cc290419Sopenharmony_ci        ret = true;
68cc290419Sopenharmony_ci    } while (false);
69cc290419Sopenharmony_ci    if (!ret) {
70cc290419Sopenharmony_ci        LogMsg(MSG_FAIL, "Transfer path failed, Master:%s Slave:%s", context->localPath.c_str(),
71cc290419Sopenharmony_ci               context->remotePath.c_str());
72cc290419Sopenharmony_ci    }
73cc290419Sopenharmony_ci    delete[](reinterpret_cast<char *>(argv));
74cc290419Sopenharmony_ci    return ret;
75cc290419Sopenharmony_ci}
76cc290419Sopenharmony_ci
77cc290419Sopenharmony_cibool HdcFile::SetMasterParameters(CtxFile *context, const char *command, int argc, char **argv)
78cc290419Sopenharmony_ci{
79cc290419Sopenharmony_ci    int srcArgvIndex = 0;
80cc290419Sopenharmony_ci    string errStr;
81cc290419Sopenharmony_ci    const string cmdOptionTstmp = "-a";
82cc290419Sopenharmony_ci    const string cmdOptionSync = "-sync";
83cc290419Sopenharmony_ci    const string cmdOptionZip = "-z";
84cc290419Sopenharmony_ci    const string cmdOptionModeSync = "-m";
85cc290419Sopenharmony_ci
86cc290419Sopenharmony_ci    for (int i = 0; i < argc; i++) {
87cc290419Sopenharmony_ci        if (argv[i] == cmdOptionZip) {
88cc290419Sopenharmony_ci            context->transferConfig.compressType = COMPRESS_LZ4;
89cc290419Sopenharmony_ci            ++srcArgvIndex;
90cc290419Sopenharmony_ci        } else if (argv[i] == cmdOptionSync) {
91cc290419Sopenharmony_ci            context->transferConfig.updateIfNew = true;
92cc290419Sopenharmony_ci            ++srcArgvIndex;
93cc290419Sopenharmony_ci        } else if (argv[i] == cmdOptionTstmp) {
94cc290419Sopenharmony_ci            // The time zone difference may cause the display time on the PC and the
95cc290419Sopenharmony_ci            // device to differ by several hours
96cc290419Sopenharmony_ci            //
97cc290419Sopenharmony_ci            // ls -al --full-time
98cc290419Sopenharmony_ci            context->transferConfig.holdTimestamp = true;
99cc290419Sopenharmony_ci            ++srcArgvIndex;
100cc290419Sopenharmony_ci        } else if (argv[i] == CMD_OPTION_CLIENTCWD) {
101cc290419Sopenharmony_ci            context->transferConfig.clientCwd = argv[i + 1];
102cc290419Sopenharmony_ci            srcArgvIndex += CMD_ARG1_COUNT;  // skip 2args
103cc290419Sopenharmony_ci        } else if (argv[i] == cmdOptionModeSync) {
104cc290419Sopenharmony_ci            context->fileModeSync = true;
105cc290419Sopenharmony_ci            ++srcArgvIndex;
106cc290419Sopenharmony_ci        } else if (argv[i] == CMDSTR_REMOTE_PARAMETER) {
107cc290419Sopenharmony_ci            ++srcArgvIndex;
108cc290419Sopenharmony_ci        } else if (argv[i][0] == '-') {
109cc290419Sopenharmony_ci            LogMsg(MSG_FAIL, "Unknown file option: %s", argv[i]);
110cc290419Sopenharmony_ci            return false;
111cc290419Sopenharmony_ci        }
112cc290419Sopenharmony_ci    }
113cc290419Sopenharmony_ci    if (argc == srcArgvIndex) {
114cc290419Sopenharmony_ci        LogMsg(MSG_FAIL, "There is no local and remote path");
115cc290419Sopenharmony_ci        return false;
116cc290419Sopenharmony_ci    }
117cc290419Sopenharmony_ci    context->remotePath = argv[argc - 1];
118cc290419Sopenharmony_ci    context->localPath = argv[argc - CMD_FILE_PENULT_PARAM];
119cc290419Sopenharmony_ci    if (taskInfo->serverOrDaemon) {
120cc290419Sopenharmony_ci        // master and server
121cc290419Sopenharmony_ci        if ((srcArgvIndex + 1) == argc) {
122cc290419Sopenharmony_ci            LogMsg(MSG_FAIL, "There is no remote path");
123cc290419Sopenharmony_ci            return false;
124cc290419Sopenharmony_ci        }
125cc290419Sopenharmony_ci        ExtractRelativePath(context->transferConfig.clientCwd, context->localPath);
126cc290419Sopenharmony_ci    } else {
127cc290419Sopenharmony_ci        if ((srcArgvIndex + 1) == argc) {
128cc290419Sopenharmony_ci            context->remotePath = ".";
129cc290419Sopenharmony_ci            context->localPath = argv[argc - 1];
130cc290419Sopenharmony_ci        }
131cc290419Sopenharmony_ci    }
132cc290419Sopenharmony_ci
133cc290419Sopenharmony_ci    context->localName = Base::GetFullFilePath(context->localPath);
134cc290419Sopenharmony_ci
135cc290419Sopenharmony_ci    mode_t mode = mode_t(~S_IFMT);
136cc290419Sopenharmony_ci    if (!Base::CheckDirectoryOrPath(context->localPath.c_str(), true, true, errStr, mode) && (mode & S_IFDIR)) {
137cc290419Sopenharmony_ci        context->isDir = true;
138cc290419Sopenharmony_ci        GetSubFilesRecursively(context->localPath, context->localName, &context->taskQueue);
139cc290419Sopenharmony_ci        if (context->taskQueue.size() == 0) {
140cc290419Sopenharmony_ci            LogMsg(MSG_FAIL, "Operation failed, because the source folder is empty.");
141cc290419Sopenharmony_ci            return false;
142cc290419Sopenharmony_ci        }
143cc290419Sopenharmony_ci        context->fileCnt = 0;
144cc290419Sopenharmony_ci        context->dirSize = 0;
145cc290419Sopenharmony_ci        context->localDirName = Base::GetPathWithoutFilename(context->localPath);
146cc290419Sopenharmony_ci
147cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "localDirName = %s", context->localDirName.c_str());
148cc290419Sopenharmony_ci
149cc290419Sopenharmony_ci        context->localName = context->taskQueue.back();
150cc290419Sopenharmony_ci        context->localPath = context->localDirName + context->localName;
151cc290419Sopenharmony_ci
152cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "localPath = %s", context->localPath.c_str());
153cc290419Sopenharmony_ci        context->taskQueue.pop_back();
154cc290419Sopenharmony_ci    }
155cc290419Sopenharmony_ci    return true;
156cc290419Sopenharmony_ci}
157cc290419Sopenharmony_ci
158cc290419Sopenharmony_civoid HdcFile::CheckMaster(CtxFile *context)
159cc290419Sopenharmony_ci{
160cc290419Sopenharmony_ci    StartTraceScope("HdcFile::CheckMaster");
161cc290419Sopenharmony_ci    if (context->fileModeSync) {
162cc290419Sopenharmony_ci        string s = SerialStruct::SerializeToString(context->fileMode);
163cc290419Sopenharmony_ci        SendToAnother(CMD_FILE_MODE, reinterpret_cast<uint8_t *>(const_cast<char *>(s.c_str())), s.size());
164cc290419Sopenharmony_ci    } else {
165cc290419Sopenharmony_ci        string s = SerialStruct::SerializeToString(context->transferConfig);
166cc290419Sopenharmony_ci        SendToAnother(CMD_FILE_CHECK, reinterpret_cast<uint8_t *>(const_cast<char *>(s.c_str())), s.size());
167cc290419Sopenharmony_ci    }
168cc290419Sopenharmony_ci}
169cc290419Sopenharmony_ci
170cc290419Sopenharmony_civoid HdcFile::WhenTransferFinish(CtxFile *context)
171cc290419Sopenharmony_ci{
172cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "WhenTransferFinish fileCnt:%d", context->fileCnt);
173cc290419Sopenharmony_ci    uint8_t flag = 1;
174cc290419Sopenharmony_ci    context->fileCnt++;
175cc290419Sopenharmony_ci    context->dirSize += context->indexIO;
176cc290419Sopenharmony_ci    SendToAnother(CMD_FILE_FINISH, &flag, 1);
177cc290419Sopenharmony_ci}
178cc290419Sopenharmony_ci
179cc290419Sopenharmony_civoid HdcFile::TransferSummary(CtxFile *context)
180cc290419Sopenharmony_ci{
181cc290419Sopenharmony_ci    uint64_t nMSec = Base::GetRuntimeMSec() -
182cc290419Sopenharmony_ci                     (context->fileCnt > 1 ? context->transferDirBegin : context->transferBegin);
183cc290419Sopenharmony_ci    uint64_t fSize = context->fileCnt > 1 ? context->dirSize : context->indexIO;
184cc290419Sopenharmony_ci    double fRate = static_cast<double>(fSize) / nMSec; // / /1000 * 1000 = 0
185cc290419Sopenharmony_ci    if (context->indexIO >= context->fileSize || context->lastErrno == 0) {
186cc290419Sopenharmony_ci        LogMsg(MSG_OK, "FileTransfer finish, Size:%lld, File count = %d, time:%lldms rate:%.2lfkB/s",
187cc290419Sopenharmony_ci               fSize, context->fileCnt, nMSec, fRate);
188cc290419Sopenharmony_ci    } else {
189cc290419Sopenharmony_ci        constexpr int bufSize = 1024;
190cc290419Sopenharmony_ci        char buf[bufSize] = { 0 };
191cc290419Sopenharmony_ci        uv_strerror_r(static_cast<int>(-context->lastErrno), buf, bufSize);
192cc290419Sopenharmony_ci        LogMsg(MSG_FAIL, "Transfer Stop at:%lld/%lld(Bytes), Reason: %s", context->indexIO, context->fileSize,
193cc290419Sopenharmony_ci               buf);
194cc290419Sopenharmony_ci    }
195cc290419Sopenharmony_ci}
196cc290419Sopenharmony_ci
197cc290419Sopenharmony_cibool HdcFile::FileModeSync(const uint16_t cmd, uint8_t *payload, const int payloadSize)
198cc290419Sopenharmony_ci{
199cc290419Sopenharmony_ci    StartTraceScope("HdcFile::FileModeSync");
200cc290419Sopenharmony_ci    if (ctxNow.master) {
201cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "FileModeSync master ctxNow.fileModeSync = %d size = %zu", ctxNow.fileModeSync,
202cc290419Sopenharmony_ci                  ctxNow.dirMode.size());
203cc290419Sopenharmony_ci        if (ctxNow.dirMode.size() > 0) {
204cc290419Sopenharmony_ci            auto mode = ctxNow.dirMode.back();
205cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "file = %s permissions: %o uId = %u, gId = %u conext = %s",
206cc290419Sopenharmony_ci                mode.fullName.c_str(), mode.perm, mode.uId, mode.gId, mode.context.c_str());
207cc290419Sopenharmony_ci            string s = SerialStruct::SerializeToString(mode);
208cc290419Sopenharmony_ci            ctxNow.dirMode.pop_back();
209cc290419Sopenharmony_ci            SendToAnother(CMD_DIR_MODE, reinterpret_cast<uint8_t *>(const_cast<char *>(s.c_str())), s.size());
210cc290419Sopenharmony_ci        } else {
211cc290419Sopenharmony_ci            string s = SerialStruct::SerializeToString(ctxNow.transferConfig);
212cc290419Sopenharmony_ci            SendToAnother(CMD_FILE_CHECK, reinterpret_cast<uint8_t *>(const_cast<char *>(s.c_str())), s.size());
213cc290419Sopenharmony_ci        }
214cc290419Sopenharmony_ci    } else {
215cc290419Sopenharmony_ci        ctxNow.fileModeSync = true;
216cc290419Sopenharmony_ci        string serialString(reinterpret_cast<char *>(payload), payloadSize);
217cc290419Sopenharmony_ci        if (cmd == CMD_FILE_MODE) {
218cc290419Sopenharmony_ci            SerialStruct::ParseFromString(ctxNow.fileMode, serialString);
219cc290419Sopenharmony_ci        } else {
220cc290419Sopenharmony_ci            FileMode dirMode;
221cc290419Sopenharmony_ci            SerialStruct::ParseFromString(dirMode, serialString);
222cc290419Sopenharmony_ci
223cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "file = %s permissions: %o uId = %u, gId = %u context = %s",
224cc290419Sopenharmony_ci                dirMode.fullName.c_str(), dirMode.perm, dirMode.uId, dirMode.gId, dirMode.context.c_str());
225cc290419Sopenharmony_ci
226cc290419Sopenharmony_ci            vector<string> dirsOfOptName;
227cc290419Sopenharmony_ci            if (dirMode.fullName.find('/') != string::npos) {
228cc290419Sopenharmony_ci                WRITE_LOG(LOG_DEBUG, "dir mode create parent dir from linux system");
229cc290419Sopenharmony_ci                Base::SplitString(dirMode.fullName, "/", dirsOfOptName);
230cc290419Sopenharmony_ci            } else if (dirMode.fullName.find('\\') != string::npos) {
231cc290419Sopenharmony_ci                WRITE_LOG(LOG_DEBUG, "dir mode create parent dir from windows system");
232cc290419Sopenharmony_ci                Base::SplitString(dirMode.fullName, "\\", dirsOfOptName);
233cc290419Sopenharmony_ci            } else {
234cc290419Sopenharmony_ci                dirsOfOptName.emplace_back(dirMode.fullName);
235cc290419Sopenharmony_ci            }
236cc290419Sopenharmony_ci
237cc290419Sopenharmony_ci            dirMode.fullName = "";
238cc290419Sopenharmony_ci            for (auto s : dirsOfOptName) {
239cc290419Sopenharmony_ci                if (dirMode.fullName.empty()) {
240cc290419Sopenharmony_ci                    dirMode.fullName = s;
241cc290419Sopenharmony_ci                } else {
242cc290419Sopenharmony_ci                    dirMode.fullName = dirMode.fullName + Base::GetPathSep() + s;
243cc290419Sopenharmony_ci                }
244cc290419Sopenharmony_ci            }
245cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "dir = %s permissions: %o uId = %u, gId = %u context = %s",
246cc290419Sopenharmony_ci                dirMode.fullName.c_str(), dirMode.perm, dirMode.uId, dirMode.gId, dirMode.context.c_str());
247cc290419Sopenharmony_ci            ctxNow.dirModeMap.insert(std::make_pair(dirMode.fullName, dirMode));
248cc290419Sopenharmony_ci        }
249cc290419Sopenharmony_ci        SendToAnother(CMD_FILE_MODE, nullptr, 0);
250cc290419Sopenharmony_ci    }
251cc290419Sopenharmony_ci    return true;
252cc290419Sopenharmony_ci}
253cc290419Sopenharmony_ci
254cc290419Sopenharmony_cibool HdcFile::SlaveCheck(uint8_t *payload, const int payloadSize)
255cc290419Sopenharmony_ci{
256cc290419Sopenharmony_ci    bool ret = true;
257cc290419Sopenharmony_ci    bool childRet = false;
258cc290419Sopenharmony_ci    string errStr;
259cc290419Sopenharmony_ci    // parse option
260cc290419Sopenharmony_ci    string serialString(reinterpret_cast<char *>(payload), payloadSize);
261cc290419Sopenharmony_ci    TransferConfig &stat = ctxNow.transferConfig;
262cc290419Sopenharmony_ci    SerialStruct::ParseFromString(stat, serialString);
263cc290419Sopenharmony_ci    ctxNow.fileSize = stat.fileSize;
264cc290419Sopenharmony_ci    ctxNow.localPath = stat.path;
265cc290419Sopenharmony_ci    ctxNow.master = false;
266cc290419Sopenharmony_ci#ifdef HDC_DEBUG
267cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "HdcFile fileSize got %" PRIu64 "", ctxNow.fileSize);
268cc290419Sopenharmony_ci#endif
269cc290419Sopenharmony_ci
270cc290419Sopenharmony_ci    if (!CheckLocalPath(ctxNow.localPath, stat.optionalName, errStr)) {
271cc290419Sopenharmony_ci        LogMsg(MSG_FAIL, "%s", errStr.c_str());
272cc290419Sopenharmony_ci        return false;
273cc290419Sopenharmony_ci    }
274cc290419Sopenharmony_ci
275cc290419Sopenharmony_ci    if (!CheckFilename(ctxNow.localPath, stat.optionalName, errStr)) {
276cc290419Sopenharmony_ci        LogMsg(MSG_FAIL, "%s", errStr.c_str());
277cc290419Sopenharmony_ci        return false;
278cc290419Sopenharmony_ci    }
279cc290419Sopenharmony_ci    // check path
280cc290419Sopenharmony_ci    childRet = SmartSlavePath(stat.clientCwd, ctxNow.localPath, stat.optionalName.c_str());
281cc290419Sopenharmony_ci    if (childRet && ctxNow.transferConfig.updateIfNew) {  // file exist and option need update
282cc290419Sopenharmony_ci        // if is newer
283cc290419Sopenharmony_ci        uv_fs_t fs = {};
284cc290419Sopenharmony_ci        uv_fs_stat(nullptr, &fs, ctxNow.localPath.c_str(), nullptr);
285cc290419Sopenharmony_ci        uv_fs_req_cleanup(&fs);
286cc290419Sopenharmony_ci        if ((uint64_t)fs.statbuf.st_mtim.tv_sec >= ctxNow.transferConfig.mtime) {
287cc290419Sopenharmony_ci            LogMsg(MSG_FAIL, "Target file is the same date or newer,path: %s", ctxNow.localPath.c_str());
288cc290419Sopenharmony_ci            return false;
289cc290419Sopenharmony_ci        }
290cc290419Sopenharmony_ci    }
291cc290419Sopenharmony_ci    uv_fs_t *openReq = new uv_fs_t;
292cc290419Sopenharmony_ci    if (openReq == nullptr) {
293cc290419Sopenharmony_ci        LogMsg(MSG_FAIL, "HdcFile::SlaveCheck new openReq failed");
294cc290419Sopenharmony_ci        return false;
295cc290419Sopenharmony_ci    }
296cc290419Sopenharmony_ci    memset_s(openReq, sizeof(uv_fs_t), 0, sizeof(uv_fs_t));
297cc290419Sopenharmony_ci    openReq->data = &ctxNow;
298cc290419Sopenharmony_ci    // begin work
299cc290419Sopenharmony_ci    ++refCount;
300cc290419Sopenharmony_ci    uv_fs_open(loopTask, openReq, ctxNow.localPath.c_str(), UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY,
301cc290419Sopenharmony_ci               S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, OnFileOpen);
302cc290419Sopenharmony_ci    if (ctxNow.transferDirBegin == 0) {
303cc290419Sopenharmony_ci        ctxNow.transferDirBegin = Base::GetRuntimeMSec();
304cc290419Sopenharmony_ci    }
305cc290419Sopenharmony_ci    ctxNow.transferBegin = Base::GetRuntimeMSec();
306cc290419Sopenharmony_ci    return ret;
307cc290419Sopenharmony_ci}
308cc290419Sopenharmony_ci
309cc290419Sopenharmony_civoid HdcFile::TransferNext(CtxFile *context)
310cc290419Sopenharmony_ci{
311cc290419Sopenharmony_ci    context->localName = context->taskQueue.back();
312cc290419Sopenharmony_ci    context->localPath = context->localDirName + context->localName;
313cc290419Sopenharmony_ci    context->taskQueue.pop_back();
314cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "TransferNext localPath = %s queuesize:%d",
315cc290419Sopenharmony_ci              context->localPath.c_str(), ctxNow.taskQueue.size());
316cc290419Sopenharmony_ci    uv_fs_t *openReq = new uv_fs_t;
317cc290419Sopenharmony_ci    if (openReq == nullptr) {
318cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "HdcFile::TransferNext new openReq failed for file %s", context->localPath.c_str());
319cc290419Sopenharmony_ci        OnFileOpenFailed(context);
320cc290419Sopenharmony_ci        return;
321cc290419Sopenharmony_ci    }
322cc290419Sopenharmony_ci    memset_s(openReq, sizeof(uv_fs_t), 0, sizeof(uv_fs_t));
323cc290419Sopenharmony_ci    openReq->data = context;
324cc290419Sopenharmony_ci    do {
325cc290419Sopenharmony_ci        ++refCount;
326cc290419Sopenharmony_ci        uv_fs_open(loopTask, openReq, context->localPath.c_str(), O_RDONLY, S_IWUSR | S_IRUSR, OnFileOpen);
327cc290419Sopenharmony_ci    } while (false);
328cc290419Sopenharmony_ci
329cc290419Sopenharmony_ci    return;
330cc290419Sopenharmony_ci}
331cc290419Sopenharmony_ci
332cc290419Sopenharmony_cibool HdcFile::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize)
333cc290419Sopenharmony_ci{
334cc290419Sopenharmony_ci    HdcTransferBase::CommandDispatch(command, payload, payloadSize);
335cc290419Sopenharmony_ci    bool ret = true;
336cc290419Sopenharmony_ci    StartTraceScope("HdcFile::CommandDispatch");
337cc290419Sopenharmony_ci    switch (command) {
338cc290419Sopenharmony_ci        case CMD_FILE_INIT: {  // initial
339cc290419Sopenharmony_ci            string s = string(reinterpret_cast<char *>(payload), payloadSize);
340cc290419Sopenharmony_ci            ret = BeginTransfer(&ctxNow, s);
341cc290419Sopenharmony_ci            ctxNow.transferBegin = Base::GetRuntimeMSec();
342cc290419Sopenharmony_ci            break;
343cc290419Sopenharmony_ci        }
344cc290419Sopenharmony_ci        case CMD_FILE_CHECK: {
345cc290419Sopenharmony_ci            ret = SlaveCheck(payload, payloadSize);
346cc290419Sopenharmony_ci            break;
347cc290419Sopenharmony_ci        }
348cc290419Sopenharmony_ci        case CMD_FILE_MODE:
349cc290419Sopenharmony_ci        case CMD_DIR_MODE: {
350cc290419Sopenharmony_ci            ret = FileModeSync(command, payload, payloadSize);
351cc290419Sopenharmony_ci            break;
352cc290419Sopenharmony_ci        }
353cc290419Sopenharmony_ci        case CMD_FILE_FINISH: {
354cc290419Sopenharmony_ci            if (*payload) {  // close-step3
355cc290419Sopenharmony_ci                if (ctxNow.isFdOpen) {
356cc290419Sopenharmony_ci                    WRITE_LOG(LOG_DEBUG, "OnFileIO fs_close, localPath:%s result:%d, closeReqSubmitted:%d",
357cc290419Sopenharmony_ci                              ctxNow.localPath.c_str(), ctxNow.openFd, ctxNow.closeReqSubmitted);
358cc290419Sopenharmony_ci                    CloseFd(ctxNow.openFd);
359cc290419Sopenharmony_ci                    // solve the fd leak caused by early exit due to illegal operation on a directory.
360cc290419Sopenharmony_ci                    ctxNow.isFdOpen = false;
361cc290419Sopenharmony_ci                }
362cc290419Sopenharmony_ci                WRITE_LOG(LOG_DEBUG, "Dir = %d taskQueue size = %d", ctxNow.isDir, ctxNow.taskQueue.size());
363cc290419Sopenharmony_ci                if (ctxNow.isDir && (ctxNow.taskQueue.size() > 0)) {
364cc290419Sopenharmony_ci                    TransferNext(&ctxNow);
365cc290419Sopenharmony_ci                } else {
366cc290419Sopenharmony_ci                    ctxNow.ioFinish = true;
367cc290419Sopenharmony_ci                    ctxNow.transferDirBegin = 0;
368cc290419Sopenharmony_ci                    --(*payload);
369cc290419Sopenharmony_ci                    SendToAnother(CMD_FILE_FINISH, payload, 1);
370cc290419Sopenharmony_ci                }
371cc290419Sopenharmony_ci            } else {  // close-step3
372cc290419Sopenharmony_ci                TransferSummary(&ctxNow);
373cc290419Sopenharmony_ci                TaskFinish();
374cc290419Sopenharmony_ci            }
375cc290419Sopenharmony_ci            break;
376cc290419Sopenharmony_ci        }
377cc290419Sopenharmony_ci        default:
378cc290419Sopenharmony_ci            break;
379cc290419Sopenharmony_ci    }
380cc290419Sopenharmony_ci    return ret;
381cc290419Sopenharmony_ci}
382cc290419Sopenharmony_ci}  // namespace Hdc
383