• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 "b_filesystem/b_file.h"
17 
18 #include <cstring>
19 #include <fcntl.h>
20 #include <libgen.h>
21 #include <sys/sendfile.h>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <system_error>
25 #include <unistd.h>
26 
27 #include "b_error/b_error.h"
28 #include "filemgmt_libhilog.h"
29 
30 namespace OHOS::FileManagement::Backup {
31 using namespace std;
32 
ReadFile(const UniqueFd & fd)33 unique_ptr<char[]> BFile::ReadFile(const UniqueFd &fd)
34 {
35     if (lseek(fd, 0, SEEK_SET) == -1) {
36         throw BError(errno);
37     }
38 
39     struct stat stat = {};
40     if (fstat(fd, &stat) == -1) {
41         throw BError(errno);
42     }
43     off_t fileSize = stat.st_size;
44     if (fileSize == 0) {
45         HILOGI("Deserialized an empty file");
46         return make_unique<char[]>(1);
47     }
48 
49     auto buf = make_unique<char[]>(fileSize + 1);
50     if (read(fd, buf.get(), fileSize) == -1) {
51         throw BError(errno);
52     }
53     return buf;
54 }
55 
SendFile(int outFd,int inFd)56 void BFile::SendFile(int outFd, int inFd)
57 {
58     off_t offset = 0;
59     long ret = 0;
60     if (lseek(outFd, 0, SEEK_SET) == -1) {
61         throw BError(errno);
62     }
63     if (lseek(inFd, 0, SEEK_SET) == -1) {
64         throw BError(errno);
65     }
66     struct stat stat = {};
67     if (fstat(inFd, &stat) == -1) {
68         throw BError(errno);
69     }
70     while ((ret = sendfile(outFd, inFd, &offset, stat.st_size)) > 0) {
71     };
72 
73     if (ret == -1) {
74         throw BError(errno);
75     }
76     ret = ftruncate(outFd, offset);
77     if (ret == -1) {
78         throw BError(errno);
79     }
80 }
81 
Write(const UniqueFd & fd,const string & str)82 void BFile::Write(const UniqueFd &fd, const string &str)
83 {
84     int ret = pwrite(fd, str.c_str(), str.length(), 0);
85     if (ret == -1) {
86         throw BError(errno);
87     }
88     if (ftruncate(fd, ret) == -1) {
89         throw BError(errno);
90     }
91 }
92 
CopyFile(const string & from,const string & to)93 bool BFile::CopyFile(const string &from, const string &to)
94 {
95     if (from == to) {
96         return true;
97     }
98 
99     try {
100         auto resolvedPath = make_unique<char[]>(PATH_MAX);
101         if (!realpath(from.data(), resolvedPath.get())) {
102             HILOGI("failed to real path for the file %{public}s", from.c_str());
103             return false;
104         }
105         string oldPath(resolvedPath.get());
106         UniqueFd fdFrom(open(oldPath.data(), O_RDONLY));
107         if (fdFrom == -1) {
108             HILOGE("failed to open the file %{public}s", from.c_str());
109             throw BError(errno);
110         }
111 
112         unique_ptr<char, function<void(void *p)>> dir {strdup(to.data()), free};
113         if (!dir) {
114             throw BError(errno);
115         }
116         if (!realpath(dirname(dir.get()), resolvedPath.get())) {
117             HILOGI("failed to real path for %{public}s", to.c_str());
118             return false;
119         }
120         string newPath(resolvedPath.get());
121         unique_ptr<char, function<void(void *p)>> name {strdup(to.data()), free};
122         if (!name) {
123             throw BError(errno);
124         }
125         newPath.append("/").append(basename(name.get()));
126         UniqueFd fdTo(open(newPath.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR));
127         if (fdTo == -1) {
128             HILOGE("failed to open the file %{public}s", to.c_str());
129             throw BError(errno);
130         }
131 
132         SendFile(fdTo, fdFrom);
133         return true;
134     } catch (const BError &e) {
135         HILOGE("%{public}s", e.what());
136     } catch (const exception &e) {
137         HILOGE("%{public}s", e.what());
138     } catch (...) {
139         HILOGE("");
140     }
141     return false;
142 }
143 } // namespace OHOS::FileManagement::Backup