diff --git a/README_zh.md b/README_zh.md
index 97f4b55dab28059c2e6c00d18ee459a5a22c6e71..bbdeb389957f23affc027ab6496ffa3f3a923c00 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -1,15 +1,21 @@
-# hdc组件
+# HDC-鸿蒙设备连接器
- [简介](#section662115419449)
- [架构](#section15908143623714)
- [目录](#section161941989596)
+ - [下载说明](#section129654513263)
+ - [1.通过git clone方式下载(建议)](#section161941989591)
+ - [2.通过网页形式下载](#section161941989592)
+ - [3.支持环境](#section161941989593)
+ - [4.BUG上报](#section161941989594)
- [使用说明](#section129654513264)
- [相关仓](#section1371113476307)
+- [FAQ](#section1371113476308)
## 简介
-hdc(Harmony Device Connector) 是OpenHarmony为开发人员提供的用于调试的命令行工具,开发机器上使用设备连接器hdc client/server命令行工具,该工具需支持部署在Windows/Linux/Mac等系统上与鸿蒙设备(或模拟器)进行连接调试通信。PC端hdc工具需要针对以上开发机操作系统平台分别发布相应的版本,设备端hdc daemon需跟随设备镜像发布包括对模拟器进行支持。下文将介绍hdc的常用命令及使用举例。
+HDC(Harmony Device Connector) 是OpenHarmony为开发人员提供的用于调试的命令行工具,开发机器上使用设备连接器hdc client/server命令行工具,该工具需支持部署在Windows/Linux/Mac等系统上与鸿蒙设备(或模拟器)进行连接调试通信。PC端hdc工具需要针对以上开发机操作系统平台分别发布相应的版本,设备端hdc daemon需跟随设备镜像发布包括对模拟器进行支持。下文将介绍hdc的常用命令及使用举例。
## 架构
@@ -34,11 +40,37 @@ hdc主要有三部分组成:
│ └── prebuilt # 预编译目录,存放预编译的二进制文件
```
+### 下载说明
+
+
+[1.通过git clone方式下载(建议)](#section161941989591)
+```
+外仓命令为:
+git clone git@gitee.com:openharmony/developtools_hdc_standard.git
+合作仓命令为:
+git clone git@gitee.com:OHOS_STD/developtools_hdc_standard.git
+```
+
+[2.通过网页形式下载](#section161941989592)
+通过网页形式下载prebuilt,请使用类似如下URL打开网页:
+``` https://gitee.com/openharmony/developtools_hdc_standard/blob/master/prebuilt/windows/hdc-std.exe```
+点击中间下载方式进行下载,windows版本文件大小在**5M左右**,linux版本在**2M左右**,不要使用右击另存为方式进行保存下载,这样下载不对,下载后检查文件大小(**说三遍**)。
+
+[3.支持环境](#section161941989593)
+支持运行环境 linux版本建议ubuntu20 CentOS8 64位,其他版本相近也应该可以,libc++.so引用错误请使用ldd/readelf等命令检查库引用 windows版本建议windows10 64位,windows8也应该可以,Windows7等EOF版本尚未测试,如果低版本windows winusb库缺失,请使用zadig更新库。
+
+[4.BUG上报](#section161941989594)
+近期hdc刚开发完成,适配和调整变动较多,如果遇到异常情况,建议按照如下步骤进行排查:
+1)首先核对server与daemon版本是否匹配,hdc-std -v, hdcd -v。
+2)更新工程最新的线上代码和预编译文件,是否在后续版本中已解决问题。
+3)规范的和详细的提出issue,我们将尽快跟进。
+
+
### 使用说明
-hdc当前支持如下命令:
+hdc当前常用命令如下,未尽命令使用hdc -h或者hdc --help查看:
-**表 1** hdc命令列表
+**表 1** hdc常用命令列表
Option
@@ -198,4 +230,6 @@ hdc当前支持如下命令:
研发工具链子系统
-**developtools\_hdc\_standard**
\ No newline at end of file
+**developtools\_hdc\_standard**
+
+## FAQ
\ No newline at end of file
diff --git a/prebuilt/linux/hdc_std b/prebuilt/linux/hdc_std
index 2c31bd319eeaec08c8cf5aeef63d0c3c8aa95bbf..3f170d86adebd72324b404682ed3dad89b34cea4 100755
Binary files a/prebuilt/linux/hdc_std and b/prebuilt/linux/hdc_std differ
diff --git a/prebuilt/windows/hdc_std.exe b/prebuilt/windows/hdc_std.exe
index 18f49eba614fe6613d39526d5033f59c11cae992..4174db891ebcf5cb7f805be1a945631b18caecd6 100644
--- a/prebuilt/windows/hdc_std.exe
+++ b/prebuilt/windows/hdc_std.exe
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8f969acb481533102a41fc2262a18d99d2cd9f58bb7d7860519f44b225cf7918
-size 3301376
+oid sha256:7d95e291cc173be53b2542f593f65cbeb726c8d6d6f5bf2edc5cfdfc2c4db607
+size 3301888
diff --git a/src/common/define.h b/src/common/define.h
index ee2f6ad44d75c45e29d54dc539a158087b707cfe..c41a651d7e051a7ed0350185734de3be41d62cda 100644
--- a/src/common/define.h
+++ b/src/common/define.h
@@ -48,14 +48,16 @@ constexpr uint16_t MAX_IP_PORT = 65535;
constexpr uint8_t STREAM_MAIN = 0; // work at main thread
constexpr uint8_t STREAM_WORK = 1; // work at work thread
constexpr uint16_t MAX_CONNECTKEY_SIZE = 32; // usb sn/tcp ipport
-constexpr uint8_t MAX_IO_OVERLAP = 255; //
+constexpr uint8_t MAX_IO_OVERLAP = 32; // test on windows 32 is OK
constexpr auto TIME_BASE = 1000; // time unit conversion base value
constexpr uint16_t AID_SHELL = 2000;
+// double-word(hex)=[0]major[1][2]monor[3][4]version[5]fix(a-p)[6][7]reserve
+constexpr uint32_t HDC_VERSION_NUMBER = 0x10100f00;
// general one argument command argc
constexpr int CMD_ARG1_COUNT = 2;
// The first child versions must match, otherwise server and daemon must be upgraded
-const string VERSION_NUMBER = "1.1.0p"; // same with openssl version, 1.1.2==VERNUMBER 0x10102000
+const string VERSION_NUMBER = "1.1.0q"; // same with openssl version, 1.1.2==VERNUMBER 0x10102000
const string HANDSHAKE_MESSAGE = "OHOS HDC"; // sep not char '-', not more than 11 bytes
const string PACKET_FLAG = "HW"; // must 2bytes
const string EMPTY_ECHO = "[Empty]";
@@ -90,6 +92,6 @@ const string CMDSTR_FORWARD_RPORT = "rport";
const string CMDSTR_APP_INSTALL = "install";
const string CMDSTR_APP_UNINSTALL = "uninstall";
const string CMDSTR_APP_SIDELOAD = "sideload";
-const string CMDSTR_LIST_JDWP = "list jpid";
+const string CMDSTR_LIST_JDWP = "jpid";
} // namespace Hdc
#endif // HDC_DEFINE_H
diff --git a/src/common/define_plus.h b/src/common/define_plus.h
index c3de4a5b10044a4c675c1cc2738dd968776831eb..ba34687dfd1ab8d4cffc97e8f397eb5113d396e0 100644
--- a/src/common/define_plus.h
+++ b/src/common/define_plus.h
@@ -122,6 +122,7 @@ enum HdcCommand {
CMD_UNITY_JPID,
// Shell commands types
CMD_SHELL_INIT = 2000,
+ CMD_SHELL_DATA,
// Forward commands types
CMD_FORWARD_INIT = 2500,
CMD_FORWARD_CHECK,
diff --git a/src/common/file.cpp b/src/common/file.cpp
index 834024b46031b541cc8f711b91e2c1995b579528..ab105434a4302832d91314773b9dc2a5002aaf71 100644
--- a/src/common/file.cpp
+++ b/src/common/file.cpp
@@ -37,57 +37,65 @@ void HdcFile::StopTask()
// Send supported below styles
// send|recv path/filename path/filename
// send|recv filename path
-bool HdcFile::BeginTransfer(CtxFile *context, const char *command)
+bool HdcFile::BeginTransfer(CtxFile *context, const string &command)
{
int argc = 0;
- int srcOffset = 0;
bool ret = false;
+ char **argv = Base::SplitCommandToArgs(command.c_str(), &argc);
+ if (argc < CMD_ARG1_COUNT || argv == nullptr) {
+ LogMsg(MSG_FAIL, "Transfer path split failed");
+ if (argv) {
+ delete[]((char *)argv);
+ }
+ return false;
+ }
+ if (!GetLocalRemotePath(context, command.c_str(), argc, argv)) {
+ delete[]((char *)argv);
+ return false;
+ }
+ do {
+ ++refCount;
+ uv_fs_open(loopTask, &context->fsOpenReq, context->localPath.c_str(), O_RDONLY, S_IWUSR | S_IRUSR, OnFileOpen);
+ context->master = true;
+ ret = true;
+ } while (false);
+ if (!ret) {
+ LogMsg(MSG_FAIL, "Transfer path failed, Master:%s Slave:%s", context->localPath.c_str(),
+ context->remotePath.c_str());
+ }
+ delete[]((char *)argv);
+ return ret;
+}
+
+bool HdcFile::GetLocalRemotePath(CtxFile *context, const char *command, int argc, char **argv)
+{
+ int srcArgvIndex = 0;
const string CMD_OPTION_TSTMP = "-a";
const string CMD_OPTION_SYNC = "-sync";
const string CMD_OPTION_ZIP = "-z";
-
- char **argv = Base::SplitCommandToArgs(command, &argc);
- if (argc < CMD_ARG1_COUNT) {
- goto Finish;
- }
- context->localPath = argv[argc - 2];
for (int i = 0; i < argc - CMD_ARG1_COUNT; i++) {
if (argv[i] == CMD_OPTION_ZIP) {
context->transferConfig.compressType = COMPRESS_LZ4;
- srcOffset += strlen(argv[i]) + 1;
+ ++srcArgvIndex;
} else if (argv[i] == CMD_OPTION_SYNC) {
context->transferConfig.updateIfNew = true;
- srcOffset += strlen(argv[i]) + 1;
+ ++srcArgvIndex;
} else if (argv[i] == CMD_OPTION_TSTMP) {
context->transferConfig.holdTimestamp = true;
- srcOffset += strlen(argv[i]) + 1;
+ ++srcArgvIndex;
+ } else if (argv[i][0] == '-') {
+ LogMsg(MSG_FAIL, "Unknow file option: %s", argv[i]);
+ return false;
}
}
context->remotePath = argv[argc - 1];
- if (argc > CMD_ARG1_COUNT) {
- context->localPath
- = std::string(command + srcOffset, strlen(command) - srcOffset - context->remotePath.size() - 1);
- } else {
- context->localPath = argv[0];
- }
-
+ context->localPath = argv[argc - 2];
if (!Base::CheckDirectoryOrPath(context->localPath.c_str(), true, true)) {
- goto Finish;
+ LogMsg(MSG_FAIL, "Src not exist, path: %s", context->localPath.c_str());
+ return false;
}
context->localName = Base::GetFullFilePath(context->localPath);
- ++refCount;
- uv_fs_open(loopTask, &context->fsOpenReq, context->localPath.c_str(), O_RDONLY, S_IWUSR | S_IRUSR, OnFileOpen);
- context->master = true;
- ret = true;
-
-Finish:
- if (!ret) {
- LogMsg(MSG_FAIL, "Transfer master path failed");
- }
- if (argv) {
- delete[]((char *)argv);
- }
- return ret;
+ return true;
}
void HdcFile::CheckMaster(CtxFile *context)
@@ -107,7 +115,7 @@ void HdcFile::TransferSummary(CtxFile *context)
{
uint64_t nMSec = Base::GetRuntimeMSec() - context->transferBegin;
double fRate = static_cast(context->indexIO) / nMSec; // / /1000 * 1000 = 0
- LogMsg(MSG_OK, "FileTransfer finish, Size:%lld time:%lldms rate:%lfkB/s", context->indexIO, nMSec, fRate);
+ LogMsg(MSG_OK, "FileTransfer finish, Size:%lld time:%lldms rate:%.2lfkB/s", context->indexIO, nMSec, fRate);
}
bool HdcFile::SlaveCheck(uint8_t *payload, const int payloadSize)
@@ -149,7 +157,8 @@ bool HdcFile::CommandDispatch(const uint16_t command, uint8_t *payload, const in
bool ret = true;
switch (command) {
case CMD_FILE_INIT: { // initial
- ret = BeginTransfer(&ctxNow, (char *)payload);
+ string s = string((char *)payload, payloadSize);
+ ret = BeginTransfer(&ctxNow, s);
ctxNow.transferBegin = Base::GetRuntimeMSec();
break;
}
diff --git a/src/common/file.h b/src/common/file.h
index 854336f3ce6dc86faba968dce00d1b77be2eab59..a36e4239471f571d9c0b301e8e334e85f092635d 100644
--- a/src/common/file.h
+++ b/src/common/file.h
@@ -30,9 +30,10 @@ private:
bool SlaveCheck(uint8_t *payload, const int payloadSize);
void CheckMaster(CtxFile *context);
void WhenTransferFinish(CtxFile *context);
- bool BeginTransfer(CtxFile *context, const char *command);
+ bool BeginTransfer(CtxFile *context, const string &command);
void TransferSummary(CtxFile *context);
+ bool GetLocalRemotePath(CtxFile *context, const char *command, int argc, char **argv);
};
-} // namespace Hdc
+} // namespace Hdc
#endif
\ No newline at end of file
diff --git a/src/common/transfer.cpp b/src/common/transfer.cpp
index 9bb86d7637f079b178a9378b0b1107dacea65244..b1d1d96d4faf738fa731c99e5df6f33c43a5906b 100644
--- a/src/common/transfer.cpp
+++ b/src/common/transfer.cpp
@@ -60,7 +60,7 @@ int HdcTransferBase::SimpleFileIO(CtxFile *context, uint64_t index, uint8_t *sen
CtxFileIO *ioContext = new CtxFileIO();
bool ret = false;
while (true) {
- if (!buf || !ioContext || !bytes) {
+ if (!buf || !ioContext || bytes < 0) {
break;
}
uv_fs_t *req = &ioContext->fs;
@@ -74,10 +74,7 @@ int HdcTransferBase::SimpleFileIO(CtxFile *context, uint64_t index, uint8_t *sen
} else {
// The US_FS_WRITE here must be brought into the actual file offset, which cannot be incorporated with local
// accumulated index because UV_FS_WRITE will be executed multiple times and then trigger a callback.
- if (!sendBuf || !bytes) {
- break;
- }
- if (memcpy_s(ioContext->bufIO, bytes, sendBuf, bytes) != EOK) {
+ if (bytes > 0 && memcpy_s(ioContext->bufIO, bytes, sendBuf, bytes) != EOK) {
break;
}
uv_buf_t iov = uv_buf_init(reinterpret_cast(ioContext->bufIO), bytes);
@@ -143,23 +140,24 @@ bool HdcTransferBase::SendIOPayload(CtxFile *context, int index, uint8_t *data,
payloadHead.compressType = context->transferConfig.compressType;
payloadHead.uncompressSize = dataSize;
payloadHead.index = index;
- switch (payloadHead.compressType) {
+ if (dataSize > 0) {
+ switch (payloadHead.compressType) {
#ifdef HARMONY_PROJECT
- case COMPRESS_LZ4: {
- // clang-format off
- compressSize = LZ4_compress_default((const char *)data, (char *)sendBuf + payloadPrefixReserve,
- dataSize, dataSize);
- // clang-format on
- break;
- }
+ case COMPRESS_LZ4: {
+ compressSize = LZ4_compress_default((const char *)data, (char *)sendBuf + payloadPrefixReserve,
+ dataSize, dataSize);
+ break;
+ }
#endif
- default: { // COMPRESS_NONE
- if (memcpy_s(sendBuf + payloadPrefixReserve, sendBufSize - payloadPrefixReserve, data, dataSize) != EOK) {
- delete[] sendBuf;
- return false;
+ default: { // COMPRESS_NONE
+ if (memcpy_s(sendBuf + payloadPrefixReserve, sendBufSize - payloadPrefixReserve, data, dataSize)
+ != EOK) {
+ delete[] sendBuf;
+ return false;
+ }
+ compressSize = dataSize;
+ break;
}
- compressSize = dataSize;
- break;
}
}
payloadHead.compressSize = compressSize;
@@ -188,12 +186,10 @@ void HdcTransferBase::OnFileIO(uv_fs_t *req)
uv_fs_req_cleanup(req);
--thisClass->refCount;
while (true) {
- if (req->result <= 0) { // Read error or master read completion
+ if (req->result < 0) {
+ WRITE_LOG(LOG_DEBUG, "OnFileIO error: %s", uv_strerror((int)req->result));
+ context->closeNotify = true;
tryFinishIO = true;
- if (req->result < 0) {
- WRITE_LOG(LOG_DEBUG, "OnFileIO error: %s", uv_strerror((int)req->result));
- context->closeNotify = true;
- }
break;
}
context->indexIO += req->result;
@@ -202,9 +198,11 @@ void HdcTransferBase::OnFileIO(uv_fs_t *req)
tryFinishIO = true;
break;
}
- // read continue until result >0, let single file packet +packet header less than GetMaxBufSize()
- constexpr auto maxBufFactor = 0.8;
- thisClass->SimpleFileIO(context, context->indexIO, nullptr, Base::GetMaxBufSize() * maxBufFactor);
+ if (context->indexIO < context->fileSize) {
+ // read continue until result >0, let single file packet +packet header less than GetMaxBufSize()
+ constexpr auto maxBufFactor = 0.8;
+ thisClass->SimpleFileIO(context, context->indexIO, nullptr, Base::GetMaxBufSize() * maxBufFactor);
+ }
} else if (req->fs_type == UV_FS_WRITE) { // write
if (context->indexIO >= context->fileSize) {
// The active end must first read it first, but you can't make Finish first, because Slave may not
@@ -246,15 +244,16 @@ void HdcTransferBase::OnFileOpen(uv_fs_t *req)
uv_fs_t fs;
Base::ZeroStruct(fs.statbuf);
uv_fs_fstat(nullptr, &fs, context->fsOpenReq.result, nullptr);
- uv_fs_req_cleanup(&fs);
-
TransferConfig &st = context->transferConfig;
st.fileSize = fs.statbuf.st_size;
st.optionalName = context->localName;
st.atime = fs.statbuf.st_atim.tv_sec;
st.mtime = fs.statbuf.st_mtim.tv_sec;
st.path = context->remotePath;
+ // update ctxNow=context child value
+ context->fileSize = st.fileSize;
+ uv_fs_req_cleanup(&fs);
thisClass->CheckMaster(context);
} else { // write
thisClass->SendToAnother(thisClass->commandBegin, nullptr, 0);
@@ -340,21 +339,23 @@ bool HdcTransferBase::RecvIOPayload(CtxFile *context, uint8_t *data, int dataSiz
return false;
}
int clearSize = 0;
- switch (pld.compressType) {
+ if (pld.compressSize > 0) {
+ switch (pld.compressType) {
#ifdef HARMONY_PROJECT
- case COMPRESS_LZ4: {
- clearSize = LZ4_decompress_safe((const char *)data + payloadPrefixReserve, (char *)clearBuf,
- pld.compressSize, pld.uncompressSize);
- break;
- }
+ case COMPRESS_LZ4: {
+ clearSize = LZ4_decompress_safe((const char *)data + payloadPrefixReserve, (char *)clearBuf,
+ pld.compressSize, pld.uncompressSize);
+ break;
+ }
#endif
- default: { // COMPRESS_NONE
- if (memcpy_s(clearBuf, pld.uncompressSize, data + payloadPrefixReserve, pld.compressSize) != EOK) {
- delete[] clearBuf;
- return false;
+ default: { // COMPRESS_NONE
+ if (memcpy_s(clearBuf, pld.uncompressSize, data + payloadPrefixReserve, pld.compressSize) != EOK) {
+ delete[] clearBuf;
+ return false;
+ }
+ clearSize = pld.compressSize;
+ break;
}
- clearSize = pld.compressSize;
- break;
}
}
while (true) {
diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp
index cba5cb7676325febadcd572ec45a0e9bbf5f8529..c96e738709e12e679479f6e013beb5bfdf678fa9 100644
--- a/src/daemon/daemon.cpp
+++ b/src/daemon/daemon.cpp
@@ -111,7 +111,7 @@ bool HdcDaemon::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uin
ret = TaskCommandDispatch(hTaskInfo, TYPE_UNITY, command, payload, payloadSize);
break;
case CMD_SHELL_INIT:
- case CMD_KERNEL_ECHO_RAW:
+ case CMD_SHELL_DATA:
ret = TaskCommandDispatch(hTaskInfo, TYPE_SHELL, command, payload, payloadSize);
break;
case CMD_FILE_CHECK:
diff --git a/src/daemon/daemon_unity.cpp b/src/daemon/daemon_unity.cpp
index 34b578d1d281abd3afe0a8f29f8d40c73535abe6..9b4ba1e7f228b1f781e2060153dd2a19fd455643 100644
--- a/src/daemon/daemon_unity.cpp
+++ b/src/daemon/daemon_unity.cpp
@@ -166,14 +166,14 @@ bool HdcDaemonUnity::RemountDevice()
return true;
}
-bool HdcDaemonUnity::RebootDevice(const uint8_t *cmd, const int cmdSize)
+bool HdcDaemonUnity::RebootDevice(const string &cmd)
{
sync();
string propertyVal;
- if (!cmdSize) {
+ if (!cmd.size()) {
propertyVal = "reboot";
} else {
- propertyVal = Base::StringFormat("reboot,%s", cmd);
+ propertyVal = Base::StringFormat("reboot,%s", cmd.c_str());
}
return Base::SetHdcProperty(rebootProperty.c_str(), propertyVal.c_str());
}
@@ -228,9 +228,10 @@ bool HdcDaemonUnity::CommandDispatch(const uint16_t command, uint8_t *payload, c
bool ret = true;
HdcDaemon *daemon = (HdcDaemon *)taskInfo->ownerSessionClass;
// Both are not executed, do not need to be detected 'childReady'
+ string strPayload = string((char *)payload, payloadSize);
switch (command) {
case CMD_UNITY_EXECUTE: {
- ExecuteShell((char *)payload);
+ ExecuteShell((char *)strPayload.c_str());
break;
}
case CMD_UNITY_REMOUNT: {
@@ -240,21 +241,21 @@ bool HdcDaemonUnity::CommandDispatch(const uint16_t command, uint8_t *payload, c
}
case CMD_UNITY_REBOOT: {
ret = false;
- RebootDevice(payload, payloadSize);
+ RebootDevice(strPayload);
break;
}
case CMD_UNITY_RUNMODE: {
ret = false;
- SetDeviceRunMode(daemon, (const char *)payload);
+ SetDeviceRunMode(daemon, strPayload.c_str());
break;
}
case CMD_UNITY_HILOG: {
- GetHiLog((const char *)payload);
+ GetHiLog(strPayload.c_str());
break;
}
case CMD_UNITY_ROOTRUN: {
ret = false;
- if (payloadSize != 0 && !strcmp((char *)payload, "r")) {
+ if (payloadSize != 0 && !strcmp((char *)strPayload.c_str(), "r")) {
Base::SetHdcProperty("persist.hdc.root", "0");
} else {
Base::SetHdcProperty("persist.hdc.root", "1");
@@ -263,7 +264,7 @@ bool HdcDaemonUnity::CommandDispatch(const uint16_t command, uint8_t *payload, c
break;
}
case CMD_UNITY_TERMINATE: {
- daemon->PostStopInstanceMessage(!strcmp((char *)payload, "1"));
+ daemon->PostStopInstanceMessage(!strcmp((char *)strPayload.c_str(), "1"));
break;
}
case CMD_UNITY_BUGREPORT_INIT: {
diff --git a/src/daemon/daemon_unity.h b/src/daemon/daemon_unity.h
index d95ed18313ea21920b8beea55a7c85fca8be203e..6b82378118ac6032a497be2401b18242edc18bc0 100644
--- a/src/daemon/daemon_unity.h
+++ b/src/daemon/daemon_unity.h
@@ -31,7 +31,7 @@ private:
bool FindMountDeviceByPath(const char *toQuery, char *dev);
bool RemountPartition(const char *dir);
bool RemountDevice();
- bool RebootDevice(const uint8_t *cmd, const int cmdSize);
+ bool RebootDevice(const string &cmd);
bool SetDeviceRunMode(void *daemonIn, const char *cmd);
bool GetHiLog(const char *cmd);
bool ListJdwpProcess(void *daemonIn);
diff --git a/src/daemon/shell.cpp b/src/daemon/shell.cpp
index f19aa480410fc624f24ed87271dafc719a20f542..5e77e6f404118097fe0b00b29e476a065c160670 100644
--- a/src/daemon/shell.cpp
+++ b/src/daemon/shell.cpp
@@ -57,6 +57,23 @@ void HdcShell::StopTask()
runningProtect = false;
};
+bool HdcShell::SpecialSignal(uint8_t ch)
+{
+ const uint8_t TXT_SIGNAL_ETX = 0x3;
+ bool ret = true;
+ switch (ch) {
+ case TXT_SIGNAL_ETX: { // Ctrl+C
+ pid_t tpgid = tcgetpgrp(fdPTY);
+ kill(tpgid, SIGINT);
+ break;
+ }
+ default:
+ ret = false;
+ break;
+ }
+ return ret;
+}
+
bool HdcShell::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize)
{
switch (command) {
@@ -67,13 +84,15 @@ bool HdcShell::CommandDispatch(const uint16_t command, uint8_t *payload, const i
}
break;
}
- case CMD_KERNEL_ECHO_RAW:
+ case CMD_SHELL_DATA:
if (!childReady) {
WRITE_LOG(LOG_DEBUG, "Shell not running");
return false;
}
- // payloadSize tail with \0
- childShell->Write(payload, payloadSize - 1);
+ if (payloadSize == 1 && SpecialSignal(payload[0])) {
+ } else {
+ childShell->Write(payload, payloadSize);
+ }
break;
default:
break;
@@ -120,7 +139,7 @@ int HdcShell::CreateSubProcessPTY(const char *cmd, const char *arg0, const char
close(ptm);
return -2;
}
-
+ fcntl(ptm, F_SETFD, FD_CLOEXEC);
if (ptsname_r(ptm, devname, sizeof(devname)) != 0) {
WRITE_LOG(LOG_DEBUG, "Trouble with ptmx, error:%s", strerror(errno));
close(ptm);
@@ -151,10 +170,6 @@ bool HdcShell::FinishShellProc(const void *context, const bool result, const str
bool HdcShell::ChildReadCallback(const void *context, uint8_t *buf, const int size)
{
HdcShell *thisClass = (HdcShell *)context;
- if (size == CMD_ARG1_COUNT && *buf == 0x5e && *(buf + 1) == 0x43) {
- WRITE_LOG(LOG_WARN, "sh.ChildReadCallback fstop");
- thisClass->TaskFinish();
- }
if (!thisClass->SendToAnother(CMD_KERNEL_ECHO_RAW, (uint8_t *)buf, size)) {
thisClass->TaskFinish();
}
diff --git a/src/daemon/shell.h b/src/daemon/shell.h
index 0f25378cf8570719e7106a31f19390af1790dd98..51a80379a9b96fd37177f1d770f2dd5c9b5ef8e5 100644
--- a/src/daemon/shell.h
+++ b/src/daemon/shell.h
@@ -32,6 +32,7 @@ private:
static bool FinishShellProc(const void *context, const bool result, const string exitMsg);
static bool ChildReadCallback(const void *context, uint8_t *buf, const int size);
int ChildForkDo(const char *devname, int ptm, const char *cmd, const char *arg0, const char *arg1);
+ bool SpecialSignal(uint8_t ch);
pid_t pidShell = 0;
int fdPTY;
diff --git a/src/host/client.cpp b/src/host/client.cpp
index 5648286f0642de414d565188e13c67b15bd06f52..80327634f0246ffc99ff1dd7762c6a1bf4d9367a 100644
--- a/src/host/client.cpp
+++ b/src/host/client.cpp
@@ -220,12 +220,11 @@ void HdcClient::ReadStd(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
{
HChannel hChannel = (HChannel)stream->data;
HdcClient *thisClass = (HdcClient *)hChannel->clsChannel;
- char *pCmd = hChannel->bufStd;
+ char *command = hChannel->bufStd;
if (nread <= 0) {
return; // error
}
- thisClass->Send(hChannel->channelId, (uint8_t *)pCmd, strlen(pCmd) + 1);
- WRITE_LOG(LOG_DEBUG, "send:%s", pCmd);
+ thisClass->Send(hChannel->channelId, (uint8_t *)command, strlen(command));
Base::ZeroArray(hChannel->bufStd);
}
diff --git a/src/host/client.h b/src/host/client.h
index ea112ba8f7d8e83a721137f4183ad3828a2c4909..6d315d549b4d9582e57f4bce39f9100ed56157d6 100644
--- a/src/host/client.h
+++ b/src/host/client.h
@@ -29,31 +29,30 @@ protected:
private:
static void DoCtrlServiceWork(uv_check_t *handle);
static void Connect(uv_connect_t *connection, int status);
- int ConnectServerForClient(const char *stringIP, uint16_t port);
- void BindLocalStd();
- int ReadChannel(HChannel hChannel, uint8_t *buf, const int bytesIO);
- void BindLocalStd(HChannel hChannel);
static void AllocStdbuf(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf);
static void ReadStd(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf);
static void CommandWorker(uv_timer_t *handle);
+ int ConnectServerForClient(const char *stringIP, uint16_t port);
+ int ReadChannel(HChannel hChannel, uint8_t *buf, const int bytesIO);
+ int PreHandshake(HChannel hChannel, const uint8_t *buf);
string AutoConnectKey(string &doCommand, const string &preConnectKey) const;
uint32_t GetLastPID();
bool StartKillServer(const char *cmd, bool startOrKill);
+ void BindLocalStd();
+ void BindLocalStd(HChannel hChannel);
void ModifyTty(bool setOrRestore, uv_tty_t *tty);
- int PreHandshake(HChannel hChannel, const uint8_t *buf);
void NotifyInstanceChannelFree(HChannel hChannel);
#ifndef _WIN32
termios terminalState;
#endif
-
- HChannel channel;
string connectKey;
+ string command;
uint16_t debugRetryCount;
+ bool bShellInteractive = false;
uv_timer_t waitTimeDoCmd;
uv_check_t ctrlServerWork;
- string command;
- bool bShellInteractive = false;
+ HChannel channel;
};
} // namespace Hdc
#endif
\ No newline at end of file
diff --git a/src/host/main.cpp b/src/host/main.cpp
index 3720718120df8337d88dfa54d6bf3d2f54c03e36..729ad3814916ba90e9d1a4492df54d8cd2eb9573 100644
--- a/src/host/main.cpp
+++ b/src/host/main.cpp
@@ -83,6 +83,7 @@ int SplitOptionAndCommand(int argc, const char **argv, string &outOption, string
{
bool foundCommand = false;
int resultChild = 0;
+ // we want to start from 1, ignore argv[0], but it has issue
for (int i = 0; i < argc; ++i) {
if (!foundCommand) {
resultChild = IsRegisterCommand(outCommand, argv[i], (i == argc - 1) ? nullptr : argv[i + 1]);
@@ -96,7 +97,9 @@ int SplitOptionAndCommand(int argc, const char **argv, string &outOption, string
}
if (foundCommand) {
outCommand += outCommand.size() ? " " : "";
- outCommand += argv[i];
+ string rawCmd = argv[i];
+ string packageCmd = Base::StringFormat("\"%s\"", argv[i]);
+ outCommand += rawCmd.find(" ") == string::npos ? rawCmd : packageCmd;
} else {
outOption += outOption.size() ? " " : "";
outOption += argv[i];
@@ -141,7 +144,7 @@ int RunClientMode(string &commands, string &serverListenString, string &connectK
uv_loop_init(&loopMain);
HdcClient client(false, DEFAULT_SERVER_ADDR, &loopMain);
if (!commands.size()) {
- Base::PrintMessage("Nothing to do...");
+ Base::PrintMessage("Unknow operation command...");
TranslateCommand::Usage();
return 0;
}
diff --git a/src/host/server_for_client.cpp b/src/host/server_for_client.cpp
index a5185af29e63f6ac2f0eef5ffd3791dabde28b71..cee7dd3f784e23a1eff53a404fc1b527a02b49be 100644
--- a/src/host/server_for_client.cpp
+++ b/src/host/server_for_client.cpp
@@ -398,7 +398,7 @@ bool HdcServerForClient::TaskCommand(HChannel hChannel, void *formatCommandInput
{
TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
HdcServer *ptrServer = (HdcServer *)clsServer;
- int sizeSend = formatCommand->paraments.size() == 0 ? 0 : (formatCommand->paraments.size() + 1);
+ int sizeSend = formatCommand->paraments.size();
string cmdFlag;
uint8_t sizeCmdFlag = 0;
if (CMD_FILE_INIT == formatCommand->cmdFlag) {
@@ -438,12 +438,12 @@ bool HdcServerForClient::DoCommandRemote(HChannel hChannel, void *formatCommandI
{
TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
bool ret = false;
- int sizeSend = formatCommand->paraments.size() == 0 ? 0 : (formatCommand->paraments.size() + 1);
+ int sizeSend = formatCommand->paraments.size();
string cmdFlag;
switch (formatCommand->cmdFlag) {
// Some simple commands only need to forward the instruction, no need to start Task
case CMD_SHELL_INIT:
- case CMD_KERNEL_ECHO_RAW:
+ case CMD_SHELL_DATA:
case CMD_UNITY_EXECUTE:
case CMD_UNITY_TERMINATE:
case CMD_UNITY_REMOUNT:
@@ -452,7 +452,6 @@ bool HdcServerForClient::DoCommandRemote(HChannel hChannel, void *formatCommandI
case CMD_UNITY_HILOG:
case CMD_UNITY_ROOTRUN:
case CMD_UNITY_JPID: {
- // strlen+1 Prevent DAEMON memory sticks from causing Strlen errors
if (!SendToDaemon(hChannel, formatCommand->cmdFlag, (uint8_t *)formatCommand->paraments.c_str(),
sizeSend)) {
break;
@@ -604,8 +603,7 @@ int HdcServerForClient::ReadChannel(HChannel hChannel, uint8_t *bufPtr, const in
if (!hChannel->handshakeOK) {
return ChannelHandShake(hChannel, bufPtr, bytesIO);
}
- TranslateCommand::FormatCommand formatCommand;
- Base::ZeroStruct(formatCommand);
+ struct TranslateCommand::FormatCommand formatCommand = { 0 };
if (!hChannel->interactiveShellMode) {
string retEcho = String2FormatCommand((char *)bufPtr, bytesIO, &formatCommand);
if (retEcho.length()) {
@@ -621,8 +619,8 @@ int HdcServerForClient::ReadChannel(HChannel hChannel, uint8_t *bufPtr, const in
return ret;
}
} else {
- formatCommand.paraments = (char *)bufPtr;
- formatCommand.cmdFlag = CMD_KERNEL_ECHO_RAW;
+ formatCommand.paraments = string((char *)bufPtr, bytesIO);
+ formatCommand.cmdFlag = CMD_SHELL_DATA;
}
if (!DoCommand(hChannel, &formatCommand)) {
return -3; // error or want close
diff --git a/src/host/translate.cpp b/src/host/translate.cpp
index 195cafc7ed67089abab5a9ad42fba3431fd8e529..c6126719a7f03c6630abf7943843273d532f644b 100644
--- a/src/host/translate.cpp
+++ b/src/host/translate.cpp
@@ -40,7 +40,7 @@ namespace TranslateCommand {
"\n"
"service commands(on daemon):\n"
" target mount - Set /system /vendor partition read-write\n"
- " target boot [bootloader|recovery] - Reboot the device or boot into bootloader\\recovery.\n"
+ " target boot [-bootloader|-recovery] - Reboot the device or boot into bootloader\\recovery.\n"
" smode [-r] - Restart daemon with root permissions, '-r' to cancel root\n"
" permissions\n"
" tmode usb - Reboot the device, listening on USB\n"
diff --git a/src/test/ut_command.cpp b/src/test/ut_command.cpp
index 24b6b0ed5ba816b7459c81fc2e2bb21dad30858d..95b4c0bd83639db8b13f3f95022d27c5eb732478 100644
--- a/src/test/ut_command.cpp
+++ b/src/test/ut_command.cpp
@@ -106,7 +106,7 @@ int TestTaskCommand(int method, const string &debugServerPort, const string &deb
TestRunClient(debugServerPort, debugConnectKey, bufString);
break;
case UT_TEST_TMP:
- TestRunClient(debugServerPort, debugConnectKey, "shell pwd");
+ TestRunClient(debugServerPort, debugConnectKey, "shell");
#ifdef DEF_NULL
while (true) {
uv_sleep(50);
@@ -126,6 +126,8 @@ int TestTaskCommand(int method, const string &debugServerPort, const string &deb
TestRunClient(debugServerPort, debugConnectKey, "file send /mnt/hgfs/vtmp/f.txt /tmp/f2.txt");
TestRunClient(debugServerPort, debugConnectKey, "file recv /tmp/f2.txt /mnt/hgfs/vtmp/f2.txt");
TestRunClient(debugServerPort, debugConnectKey, "shell find /proc");
+ TestRunClient(debugServerPort, debugConnectKey, "file send \"/d/a b/1.txt\" \"/d/a b/2.txt\"");
+ TestRunClient(debugServerPort, debugConnectKey, "file recv \"/d/a b/1.txt\" \"/d/a b/2.txt\"");
#endif
break;
default:
|
|---|