1/*
2 * Copyright (c) 2023-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 <dirent.h>
17#include <errno.h>
18#include <unistd.h>
19#include <sys/types.h>
20#include <stdio.h>
21#include <sys/stat.h>
22#include <stdbool.h>
23
24#include <securec.h>
25
26/**
27 * This bin file is used in l1 device triggered when device initializing, in order to support the compatibility for old
28 * keys with version 1.
29*/
30
31#define HUKS_SERVICE_UID 12
32#define DIR_TYPE 4
33#define DEFAULT_PATH_LEN 1024
34#define DEFAULT_READ_BUFFER 4096
35#define DEFAULT_HUKS_PATH_PERMISSION 0700
36
37static void ChangeDirAndFilesPerm(const char *path)
38{
39    DIR *dir;
40    struct dirent *ptr;
41    dir = opendir(path);
42    if (dir == NULL) {
43        return;
44    }
45    int ret = EOK;
46    while ((ptr = readdir(dir)) != NULL) {
47        if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
48            continue;
49        }
50        char curPath[DEFAULT_PATH_LEN] = { 0 };
51
52        ret = strcpy_s(curPath, DEFAULT_PATH_LEN, path);
53        if (ret != EOK) {
54            break;
55        }
56        ret = strcat_s(curPath, DEFAULT_PATH_LEN, "/");
57        if (ret != EOK) {
58            break;
59        }
60        ret = strcat_s(curPath, DEFAULT_PATH_LEN, ptr->d_name);
61        if (ret != EOK) {
62            break;
63        }
64
65        ret = chown(curPath, HUKS_SERVICE_UID, HUKS_SERVICE_UID);
66        if (ret != EOK) {
67            break;
68        }
69        if ((ptr->d_type != DIR_TYPE)) {
70            if (chmod(curPath, S_IRUSR | S_IWUSR) < 0) {
71                break;
72            }
73        } else {
74            if (chmod(curPath, S_IRWXU) < 0) {
75                break;
76            }
77            ChangeDirAndFilesPerm(curPath);
78        }
79    }
80    if (ret != EOK) {
81        printf("chmod dir and file failed! errno = 0x%x \n", errno);
82    }
83    (void)closedir(dir);
84}
85
86static void MoveOldFileToNew(const char *srcPath, const char *tarPath)
87{
88    char buffer[DEFAULT_READ_BUFFER];
89    FILE *in, *out;
90    if ((in = fopen(srcPath, "r")) == NULL) {
91        printf("open source file failed !\n");
92        return;
93    }
94    if ((out = fopen(tarPath, "w")) == NULL) {
95        printf("open target file failed !\n");
96        (void)fclose(in);
97        return;
98    }
99    int len;
100    while ((len = fread(buffer, 1, DEFAULT_READ_BUFFER, in)) > 0) {
101        int size = fwrite(buffer, 1, len, out);
102        if (size != len) {
103            printf("move old file to new path failed!");
104            (void)fclose(out);
105            (void)fclose(in);
106            return;
107        }
108    }
109    (void)fclose(out);
110    (void)fclose(in);
111
112    (void)remove(srcPath);
113}
114
115static int ConstructSrcAndTargetPath(char *curPath, char *desPath, struct dirent *ptr,
116    const char *srcPath, const char *tarPath)
117{
118    int ret = strcpy_s(curPath, DEFAULT_PATH_LEN, srcPath);
119    if (ret != EOK) {
120        return ret;
121    }
122    ret = strcat_s(curPath, DEFAULT_PATH_LEN, "/");
123    if (ret != EOK) {
124        return ret;
125    }
126
127    ret = strcat_s(curPath, DEFAULT_PATH_LEN, ptr->d_name);
128    if (ret != EOK) {
129        return ret;
130    }
131
132    ret = strcpy_s(desPath, DEFAULT_PATH_LEN, tarPath);
133    if (ret != EOK) {
134        return ret;
135    }
136    ret = strcat_s(desPath, DEFAULT_PATH_LEN, "/");
137    if (ret != EOK) {
138        return ret;
139    }
140
141    ret = strcat_s(desPath, DEFAULT_PATH_LEN, ptr->d_name);
142    if (ret != EOK) {
143        return ret;
144    }
145    return EOK;
146}
147
148static void MoveOldFolderToNew(const char *srcPath, const char *tarPath)
149{
150    if (!opendir(tarPath)) {
151        if (mkdir(tarPath, DEFAULT_HUKS_PATH_PERMISSION) != 0) {
152            printf("mkdir failed! errno = 0x%x \n", errno);
153            return;
154        }
155    }
156    struct dirent *ptr;
157    DIR *dir = opendir(srcPath);
158    int ret = EOK;
159    while ((ptr = readdir(dir)) != NULL) {
160        if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
161            continue;
162        }
163        char curPath[DEFAULT_PATH_LEN] = { 0 };
164        char desPath[DEFAULT_PATH_LEN] = { 0 };
165
166        ret = ConstructSrcAndTargetPath(curPath, desPath, ptr, srcPath, tarPath);
167        if (ret != EOK) {
168            printf("construct src and target path failed!");
169            break;
170        }
171        if (ptr->d_type == DIR_TYPE) {
172            MoveOldFolderToNew(curPath, desPath);
173        } else {
174            MoveOldFileToNew(curPath, desPath);
175        }
176    }
177    (void)closedir(dir);
178    if (ret != EOK) {
179        printf("chmod dir and file failed! errno = 0x%x \n", errno);
180    }
181    (void)rmdir(srcPath);
182}
183
184int main(void)
185{
186    const char *oldPath = "/storage/maindata";
187    const char *newPath = "/storage/data/service/el1/public/huks_service/maindata";
188
189    // move directories and files form old path to new path
190    MoveOldFolderToNew(oldPath, newPath);
191
192    // change directories and files permission
193    ChangeDirAndFilesPerm(newPath);
194}
195