• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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