1 /*
2 * Copyright (c) 2024 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 <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <sys/stat.h>
20 #include <sys/resource.h>
21 #include <unistd.h>
22 #include <errno.h>
23
24 #include "hnp_base.h"
25
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29
HnpProcessRunCheck(const char * runPath)30 int HnpProcessRunCheck(const char *runPath)
31 {
32 char cmdBuffer[BUFFER_SIZE];
33 FILE *cmdOutput;
34
35 HNP_LOGI("runPath[%{public}s] running check", runPath);
36
37 /* 判断进程是否运行 */
38 cmdOutput = popen("lsof", "rb");
39 if (cmdOutput == NULL) {
40 HNP_LOGE("hnp uninstall lsof command unsuccess");
41 return HNP_ERRNO_BASE_FILE_OPEN_FAILED;
42 }
43
44 while (fgets(cmdBuffer, sizeof(cmdBuffer), cmdOutput) != NULL) {
45 if (strstr(cmdBuffer, runPath) != NULL) {
46 HNP_LOGE("hnp install path is running now, path[%{public}s]", cmdBuffer);
47 pclose(cmdOutput);
48 return HNP_ERRNO_PROCESS_RUNNING;
49 }
50 }
51
52 pclose(cmdOutput);
53 return 0;
54 }
55
CheckSymlink(HnpCfgInfo * hnpCfg,const char * linkPath)56 static int CheckSymlink(HnpCfgInfo *hnpCfg, const char *linkPath)
57 {
58 HNP_ERROR_CHECK(linkPath != NULL && hnpCfg != NULL && hnpCfg->name != NULL,
59 return HNP_ERRNO_SYMLINK_CHECK_FAILED, "invalid param");
60
61 // 软链不存在 允许覆盖
62 struct stat statBuf;
63 HNP_INFO_CHECK(lstat(linkPath, &statBuf) == 0, return 0,
64 "softLink not exist, ignore check");
65
66 // 获取软链信息
67 char targetPath[MAX_FILE_PATH_LEN] = {0};
68 ssize_t bytes = readlink(linkPath, targetPath, MAX_FILE_PATH_LEN);
69 HNP_ERROR_CHECK(bytes > 0 && bytes < MAX_FILE_PATH_LEN, return HNP_ERRNO_SYMLINK_CHECK_FAILED,
70 "readlink failed %{public}d %{public}zd %{public}s", errno, bytes, linkPath);
71
72 // 获取软连接所在目录
73 char linkCopy[MAX_FILE_PATH_LEN] = {0};
74 int ret = snprintf_s(linkCopy, MAX_FILE_PATH_LEN, MAX_FILE_PATH_LEN - 1,
75 "%s", linkPath);
76 HNP_ERROR_CHECK(ret > 0, return HNP_ERRNO_SYMLINK_CHECK_FAILED,
77 "copy link path failed %{public}d", errno);
78 const char *pos = strrchr(linkCopy, DIR_SPLIT_SYMBOL);
79 HNP_ERROR_CHECK(pos != NULL && pos - linkCopy < MAX_FILE_PATH_LEN - 1,
80 return HNP_ERRNO_SYMLINK_CHECK_FAILED, "invalid link");
81 linkCopy[pos - linkCopy + 1] = '\0';
82
83 // 拼接源文件路径
84 char sourcePath[MAX_FILE_PATH_LEN] = {0} ;
85 ret = snprintf_s(sourcePath, MAX_FILE_PATH_LEN, MAX_FILE_PATH_LEN - 1,
86 "%s/%s", linkCopy, targetPath);
87 HNP_ERROR_CHECK(ret > 0, return HNP_ERRNO_SYMLINK_CHECK_FAILED,
88 "Get Source file path failed");
89 // 源文件不存在 允许覆盖
90 HNP_ONLY_EXPER(access(sourcePath, F_OK) != 0, return 0);
91
92 // 判断源文件所属hnp
93 char *target = targetPath;
94 while (strncmp(target, "../", strlen("../")) == 0) {
95 target += strlen("../");
96 }
97 char *split = strstr(target, ".org/");
98 HNP_ERROR_CHECK(split != NULL, return HNP_ERRNO_SYMLINK_CHECK_FAILED,
99 "invalid source file %{public}s", targetPath);
100 *split = '\0';
101
102 HNP_LOGI("CheckSymlink with oldHnp %{public}s now %{public}s", target, hnpCfg->name);
103 return strcmp(hnpCfg->name, target);
104 }
105
HnpRelPath(const char * fromPath,const char * toPath,char * relPath)106 APPSPAWN_STATIC void HnpRelPath(const char *fromPath, const char *toPath, char *relPath)
107 {
108 char *from = strdup(fromPath);
109 if (from == NULL) {
110 return;
111 }
112 char *to = strdup(toPath);
113 if (to == NULL) {
114 free(from);
115 return;
116 }
117 int numDirs = 0;
118 int ret;
119
120 char *fromHead = from;
121 char *toHead = to;
122
123 while ((*from != '\0') && (*to != '\0') && (*from == *to)) {
124 from++;
125 to++;
126 }
127
128 while (from > fromHead && *(from - 1) != DIR_SPLIT_SYMBOL) {
129 from--;
130 to--;
131 }
132
133 char *p = from;
134 while (*p) {
135 if (*p == DIR_SPLIT_SYMBOL) {
136 numDirs++;
137 }
138 p++;
139 }
140
141 for (int i = 0; i < numDirs; i++) {
142 ret = strcat_s(relPath, MAX_FILE_PATH_LEN, "../");
143 if (ret != 0) {
144 HNP_LOGE("Failed to strcat rel path");
145 free(fromHead);
146 free(toHead);
147 return;
148 }
149 }
150 ret = strcat_s(relPath, MAX_FILE_PATH_LEN, to);
151 if (ret != 0) {
152 HNP_LOGE("Failed to strcat rel path");
153 free(fromHead);
154 free(toHead);
155 return;
156 }
157
158 free(fromHead);
159 free(toHead);
160
161 return;
162 }
163
HnpSymlink(const char * srcFile,const char * dstFile,HnpCfgInfo * hnpCfg,bool canRecovery,bool isPublic)164 int HnpSymlink(const char *srcFile, const char *dstFile, HnpCfgInfo *hnpCfg, bool canRecovery, bool isPublic)
165 {
166 int ret;
167 char relpath[MAX_FILE_PATH_LEN];
168
169 if (isPublic) {
170 HNP_ERROR_CHECK(canRecovery, return HNP_ERRNO_SYMLINK_CHECK_FAILED,
171 "can't recovery this hnp: %{public}s softlink", dstFile);
172 HNP_ERROR_CHECK(CheckSymlink(hnpCfg, dstFile) == 0, return HNP_ERRNO_SYMLINK_CHECK_FAILED,
173 "checkSymlink failed");
174 }
175 (void)unlink(dstFile);
176
177 HnpRelPath(dstFile, srcFile, relpath);
178 ret = symlink(relpath, dstFile);
179 if (ret < 0) {
180 HNP_LOGE("hnp install generate soft link unsuccess, src:%{public}s, dst:%{public}s, errno:%{public}d", srcFile,
181 dstFile, errno);
182 return HNP_ERRNO_GENERATE_SOFT_LINK_FAILED;
183 }
184
185 return 0;
186 }
187
188 #ifdef __cplusplus
189 }
190 #endif
191