Fix logger usage according to KLAY API changed
[platform/core/security/ode.git] / server / ext4-tool.cpp
1 /*
2  *  Copyright (c) 2015 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 #include <fcntl.h>
17
18 #include <string>
19 #include <vector>
20
21 #include <klay/filesystem.h>
22 #include <klay/process.h>
23 #include <klay/exception.h>
24
25 #include "logger.h"
26 #include "ext4-tool.h"
27
28 namespace ode {
29
30 #define ODE_SUPERBLOCK_OFFSET           1024
31 #define ODE_SUPERBLOCK_SIZE                     1024
32 #define ODE_EXT2_MIN_DESC_SIZE          32
33 #define ODE_EXT2_MIN_BLOCK_LOG_SIZE     10      /* 1024 */
34 #define ODE_EXT2_MIN_BLOCK_SIZE         (1 << ODE_EXT2_MIN_BLOCK_LOG_SIZE)
35
36 #define ODE_EXT2_MAGIC                          0xEF53
37
38 namespace {
39
40 unsigned int divCeilSafely(unsigned int a, unsigned int b)
41 {
42         if (!a)
43                 return 0;
44
45         return ((a - 1) / b) + 1;
46 }
47
48 void execAndWait(const std::string &path, std::vector<std::string> &args)
49 {
50         runtime::Process proc(path, args);
51
52         int ret = proc.execute();
53         if (ret < 0)
54                 throw runtime::Exception(path + " failed for " + args.back());
55
56         ret = proc.waitForFinished();
57         if (ret < 0 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0)
58                 throw runtime::Exception(path + " failed for " + args.back());
59 }
60
61 } // namespace
62
63 Ext4Tool::Ext4Tool(const std::string &src) :
64         source(src), blockSize(0), totalBlockCount(0)
65 {
66         if (!isExt(src))
67                 throw runtime::Exception(source + " is not an ext2/3/4 filesystem");
68
69         readInfo();
70 }
71
72 Ext4Tool::~Ext4Tool()
73 {
74 }
75
76 bool Ext4Tool::isExt(const std::string &src)
77 {
78         unsigned short magic;
79         runtime::File device(src);
80         bool ret;
81
82         if (!device.exists())
83                 throw runtime::Exception(src + " doesn't exist");
84
85         device.open(O_RDONLY);
86
87         device.lseek(ODE_SUPERBLOCK_OFFSET + 56, SEEK_SET);
88         device.read(&magic, 2);
89
90         if (magic == ODE_EXT2_MAGIC)
91                 ret = true;
92         else
93                 ret = false;
94
95         device.close();
96
97         return ret;
98 }
99
100 void Ext4Tool::readInfo()
101 {
102         unsigned int firstDataBlock = 0;
103         unsigned int blocksPerGroup = 0;
104         unsigned int clustersPerGroup = 0;
105         runtime::File device(source);
106
107         if (!device.exists())
108                 throw runtime::Exception(source + " doesn't exist");
109
110         device.open(O_RDONLY);
111
112         // read totalBlockCount
113         device.lseek(ODE_SUPERBLOCK_OFFSET +  4, SEEK_SET);
114         device.read(&totalBlockCount, 4);
115
116         // read firstDataBlock
117         device.lseek(ODE_SUPERBLOCK_OFFSET + 20, SEEK_SET);
118         device.read(&firstDataBlock, 4);
119
120         // read blockSize
121         device.lseek(ODE_SUPERBLOCK_OFFSET + 24, SEEK_SET);
122         device.read(&blockSize, 4);
123         blockSize = (ODE_EXT2_MIN_BLOCK_SIZE << blockSize);
124
125         // read blocksPerGroup
126         device.lseek(ODE_SUPERBLOCK_OFFSET + 32, SEEK_SET);
127         device.read(&blocksPerGroup, 4);
128
129         // read clustersPerGroup
130         device.lseek(ODE_SUPERBLOCK_OFFSET + 36, SEEK_SET);
131         device.read(&clustersPerGroup, 4);
132
133         unsigned int groupDescCount = divCeilSafely(totalBlockCount - firstDataBlock, blocksPerGroup);
134         int blockNbytes = clustersPerGroup / 8;
135
136         // read group_desc
137         unsigned int descPerBlock = blockSize / ODE_EXT2_MIN_DESC_SIZE;
138         unsigned int descBlockCount = divCeilSafely(groupDescCount, descPerBlock);
139
140         // read first meta block
141         data group_desc(descBlockCount * blockSize);
142         device.lseek((firstDataBlock + 1) * blockSize, SEEK_SET);
143         device.read(group_desc.data(), (descBlockCount * blockSize));
144
145         unsigned int cnt = blockNbytes << 3;
146         unsigned int blkItr = firstDataBlock;
147
148         // this structure just is used for easy type-casting.
149         struct odeExtGroupDesc {
150                 unsigned int    blockBitmap;    /* Blocks bitmap block */
151                 /* skip other member */
152         };
153
154         // read bitmap
155         {
156                 unsigned int start = firstDataBlock;
157                 unsigned int real_end = blocksPerGroup * groupDescCount - 1 + start;
158                 size_t size = (size_t) (((real_end - start) / 8) + 1);
159                 size = (size + 7) & ~3;
160                 bitmap.resize(size);
161         }
162
163         for (unsigned int i = 0; i < groupDescCount; i++) {
164                 unsigned int blk = (((struct odeExtGroupDesc *)(((unsigned char *)(group_desc.data())) + i * ODE_EXT2_MIN_DESC_SIZE))->blockBitmap);
165
166                 try {
167                         data block_bitmap(blockSize);
168                         device.lseek(blk * blockSize, SEEK_SET);
169                         device.read(block_bitmap.data(), blockSize);
170
171                         memcpy(bitmap.data() + (blkItr >> 3), block_bitmap.data(), (cnt + 7) >> 3);
172                 } catch (runtime::Exception &e) {
173                         WARN(SINK, "Block " + std::to_string(blk) + " is missing");
174                         memset(bitmap.data() + (blkItr >> 3), 0, (cnt + 7) >> 3);
175                 }
176                 blkItr += cnt;
177         }
178
179         device.close();
180 }
181
182 unsigned int Ext4Tool::getBlockSize()
183 {
184         return blockSize;
185 }
186
187 unsigned int Ext4Tool::getTotalBlockCount()
188 {
189         return totalBlockCount;
190 }
191
192 bool Ext4Tool::isUsedBlock(unsigned int blockIndex)
193 {
194         unsigned char *addr = (bitmap.data() + (blockIndex >> 3));
195         int mask = 1 << (blockIndex & 0x07);
196
197         if (mask & *addr)
198                 return true;
199
200         return false;
201 }
202
203 void Ext4Tool::mkfs(const std::string &src)
204 {
205         static const char *mkfsPath = "/sbin/mkfs.ext4";
206         std::vector<std::string> args = {
207                 mkfsPath,
208                 "-F",
209                 "-q",
210                 src
211         };
212
213         execAndWait(mkfsPath, args);
214 }
215
216 void Ext4Tool::forceCleanUp()
217 {
218         static const char *fsckPath = "/sbin/fsck.ext4";
219         std::vector<std::string> args = {
220                 fsckPath,
221                 "-f",
222                 "-y",
223                 source
224         };
225
226         execAndWait(fsckPath, args);
227 }
228
229 } // namespace ode