Replace deprecated readdir_r with readdir
[platform/core/security/cert-svc.git] / src / vcore / SignatureFinder.cpp
1 /*
2  * Copyright (c) 2016 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  * @file        SignatureFinder.cpp
18  * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
19  * @version     1.0
20  * @brief       Search for author-signature.xml and signatureN.xml files.
21  */
22 #include <vcore/SignatureFinder.h>
23 #include <dpl/log/log.h>
24
25 #include <dirent.h>
26 #include <errno.h>
27 #include <istream>
28 #include <sstream>
29 #include <memory>
30
31 #include <pcrecpp.h>
32
33
34 namespace ValidationCore {
35
36 namespace {
37
38 const char *SIGNATURE_AUTHOR = "author-signature.xml";
39 const char *REGEXP_DISTRIBUTOR_SIGNATURE = "^(signature)([1-9][0-9]*)(\\.xml)";
40
41 struct dirent *readdir(DIR *dirp) {
42         errno = 0;
43         auto ret = ::readdir(dirp);
44         if (errno != 0)
45                 LogWarning("Error read dir.");
46         return ret;
47 }
48
49 } // anonymous namespace
50
51 class SignatureFinder::Impl {
52 public:
53         Impl(const std::string &dir)
54                 : m_dir(dir)
55                 , m_signatureRegexp(REGEXP_DISTRIBUTOR_SIGNATURE)
56         {}
57
58         virtual ~Impl() {}
59
60         Result find(SignatureFileInfoSet &set);
61
62 private:
63         std::string getFullPath(const std::string &file);
64
65         std::string m_dir;
66         pcrecpp::RE m_signatureRegexp;
67 };
68
69 std::string SignatureFinder::Impl::getFullPath(const std::string &file)
70 {
71         std::string fullPath = m_dir;
72
73         if (fullPath.back() != '/')
74                 fullPath += "/";
75
76         fullPath += file;
77         return fullPath;
78 }
79
80 SignatureFinder::Result SignatureFinder::Impl::find(SignatureFileInfoSet &set)
81 {
82         std::unique_ptr<DIR, std::function<int(DIR *)>> dp(::opendir(m_dir.c_str()),
83                                                                                                            ::closedir);
84         LogDebug("Opendir : " << m_dir);
85         if (dp == nullptr) {
86                 LogError("Error opening directory : " << m_dir);
87                 return ERROR_OPENING_DIR;
88         }
89
90         while (auto dirp = ValidationCore::readdir(dp.get())) {
91                 /* number for author signature is -1 */
92                 if (!strcmp(dirp->d_name, SIGNATURE_AUTHOR)) {
93                         std::string fullPath = getFullPath(std::string(dirp->d_name));
94                         LogDebug("Found author signature file full path : " << fullPath);
95                         set.insert(SignatureFileInfo(fullPath, -1));
96                         continue;
97                 }
98
99                 std::string sig, num, xml;
100                 if (m_signatureRegexp.FullMatch(dirp->d_name, &sig, &num, &xml)) {
101                         std::istringstream stream(num);
102                         int number;
103                         stream >> number;
104                         if (stream.fail())
105                                 return ERROR_ISTREAM;
106
107                         std::string fullPath = getFullPath(std::string(dirp->d_name));
108                         LogDebug("Found signature file full path : " << fullPath);
109                         set.insert(SignatureFileInfo(fullPath, number));
110                 }
111         }
112
113         if (set.size() < 2)
114                 LogWarning("Signature file should exist more than 2.");
115
116         return NO_ERROR;
117 }
118
119 SignatureFinder::SignatureFinder(const std::string &dir)
120         : m_impl(new Impl(dir))
121 {}
122
123 SignatureFinder::~SignatureFinder()
124 {
125         delete m_impl;
126 }
127
128 SignatureFinder::Result SignatureFinder::find(SignatureFileInfoSet &set)
129 {
130         return m_impl->find(set);
131 }
132
133 } // namespace ValidationCore