Spring cleaning
[platform/core/test/security-tests.git] / src / cynara-tests / common / cynara_test_file_operations.cpp
1 /*
2  * Copyright (c) 2015-2020 Samsung Electronics Co., Ltd. All rights reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16
17 #include <cstdlib>
18 #include <dirent.h>
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <ftw.h>
22 #include <pwd.h>
23 #include <sys/sendfile.h>
24 #include <sys/smack.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28
29 #include <cynara_test_commons.h>
30 #include <dpl/test/test_runner.h>
31 #include <memory.h>
32
33 #include <cynara_test_file_operations.h>
34
35 namespace FileOperations
36 {
37
38 namespace {
39
40 int removeFile(const char *fpath, const struct stat * /*sb*/,
41                           int tflag, struct FTW * /*ftwbuf*/)
42 {
43     if (tflag == FTW_F)
44         RUNNER_ASSERT_ERRNO_MSG(!unlink(fpath), "Unable to unlink " << fpath << " file");
45     else
46         RUNNER_ASSERT_MSG(tflag == FTW_DP, "Visited file should not exist. Path: " << fpath);
47     return 0;
48 }
49
50 void syncElem(const std::string &filename, int flags, mode_t mode)
51 {
52     int fileFd = TEMP_FAILURE_RETRY(open(filename.c_str(), flags, mode));
53     RUNNER_ASSERT_ERRNO_MSG(fileFd != -1, "open failed name=" << filename);
54     FdUniquePtr fdPtr(&fileFd);
55
56     int ret = fsync(fileFd);
57     RUNNER_ASSERT_ERRNO_MSG(ret != -1, "fsync failed name=" << filename);
58 }
59
60 void syncDir(const std::string &dirname, mode_t mode = S_IRUSR | S_IWUSR) {
61     syncElem(dirname, O_DIRECTORY, mode);
62 }
63
64 void copyCynaraFile(const std::string &src, const std::string &dst)
65 {
66     using PwBufPtr = CStringPtr;
67     int inFd = TEMP_FAILURE_RETRY(open(src.c_str(), O_RDONLY));
68     RUNNER_ASSERT_ERRNO_MSG(inFd > 0, "Opening " << src << " file failed");
69     FdUniquePtr inFdPtr(&inFd);
70
71     int outFd = TEMP_FAILURE_RETRY(creat(dst.c_str(), 0700));
72     RUNNER_ASSERT_ERRNO_MSG(outFd > 0, "Creating " << dst << " file failed");
73     FdUniquePtr outFdPtr(&outFd);
74
75     long int len = sysconf(_SC_GETPW_R_SIZE_MAX);
76     RUNNER_ASSERT_MSG(len != -1, "No suggested buflen");
77     size_t buflen = len;
78     char *buf = static_cast<char*>(malloc(buflen));
79
80     PwBufPtr pwBufPtr(buf);
81
82     struct passwd pwbuf, *pwbufp = nullptr;
83     int ret = TEMP_FAILURE_RETRY(getpwnam_r(CynaraTestConsts::USER.c_str(),
84                                             &pwbuf, buf, buflen, &pwbufp));
85     RUNNER_ASSERT_ERRNO_MSG(ret == 0, "getpwnam_r failed on " << CynaraTestConsts::USER << " user");
86     RUNNER_ASSERT_MSG(pwbufp, "User " << CynaraTestConsts::USER << " does not exist");
87
88     ret = fchown(outFd, pwbufp->pw_uid, pwbufp->pw_gid);
89     RUNNER_ASSERT_ERRNO_MSG(ret != -1, "fchown failed");
90
91     ret = smack_fsetlabel(outFd, CynaraTestConsts::LABEL.c_str(), SMACK_LABEL_ACCESS);
92     RUNNER_ASSERT_MSG(ret == 0, "Setting smack label failed");
93
94     struct stat statSrc;
95     ret = fstat(inFd, &statSrc);
96     RUNNER_ASSERT_ERRNO_MSG(ret != -1, "fstat failed");
97
98     ret = sendfile(outFd, inFd, 0, statSrc.st_size);
99     RUNNER_ASSERT_ERRNO_MSG(ret != -1, "sendfile failed");
100
101     ret = fsync(outFd);
102     RUNNER_ASSERT_ERRNO_MSG(ret != -1, "fsync failed");
103 }
104
105 } // namespace
106
107 bool dirExists(const std::string &directory)
108 {
109     struct stat st;
110     int ret = stat(directory.c_str(), &st);
111     if (ret == -1 && errno == ENOENT) {
112         return false;
113     } else if (ret == -1) {
114         RUNNER_ASSERT_ERRNO_MSG(false, "Cannot stat " << directory
115                                           << " not due to its nonexistence");
116     }
117     RUNNER_ASSERT_MSG(st.st_mode & S_IFDIR, directory << " is not a directory");
118     return true;
119 }
120
121 void copyCynaraFiles(const std::string &source, const std::string &destination)
122 {
123     DIR *dirPtr = nullptr;
124     struct dirent *direntPtr;
125
126     RUNNER_ASSERT_ERRNO_MSG(dirPtr = opendir(source.c_str()),
127                                "opening " << source << " dir failed");
128     DirPtr dirScopedPtr(dirPtr);
129
130     while((direntPtr = readdir(dirPtr)) != nullptr) {
131         if (!strcmp(direntPtr->d_name, ".")
132          || !strcmp(direntPtr->d_name, ".."))
133             continue;
134         std::string tempDest = destination + "/" + direntPtr->d_name;
135         std::string tempSrc = source + "/" + direntPtr->d_name;
136         copyCynaraFile(tempSrc, tempDest);
137     }
138
139     syncDir(destination);
140 }
141
142 void makeDir(const std::string &directory)
143 {
144     RUNNER_ASSERT_ERRNO_MSG(!mkdir(directory.c_str(), S_IRWXU | S_IRWXG | S_IRWXO),
145                                "Unable to make " << directory << " test directory");
146
147     syncDir(directory);
148 }
149
150 void removeDirFiles(const std::string &dir)
151 {
152     int ret = nftw(dir.c_str(), removeFile, 2, FTW_DEPTH | FTW_PHYS);
153     if (ret == -1)
154         RUNNER_ASSERT_ERRNO_MSG(errno == ENOENT, "nftw failed");
155     else
156         syncDir(dir);
157 }
158
159 void removeDirIfExists(const std::string &dir)
160 {
161     RUNNER_ASSERT_ERRNO_MSG(!rmdir(dir.c_str()) || errno == ENOENT,
162                                "Removing " << dir << " dir failed");
163 }
164
165 } // namespace FileOperations