2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
21 #include <klay/filesystem.h>
22 #include <klay/process.h>
23 #include <klay/exception.h>
24 #include <klay/audit/logger.h>
26 #include "ext4-tool.h"
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)
36 static unsigned int divCeilSafely(unsigned int a, unsigned int b)
41 return ((a - 1) / b) + 1;
44 Ext4Tool::Ext4Tool(const std::string &src) :
45 source(src), blockSize(0), totalBlockCount(0)
47 unsigned int firstDataBlock = 0;
48 unsigned int blocksPerGroup = 0;
49 unsigned int clustersPerGroup = 0;
50 runtime::File device(source);
52 if (device.exists() == false)
53 throw runtime::Exception("Source doesn't exist");
55 device.open(O_RDONLY);
57 // read totalBlockCount
58 device.lseek(ODE_SUPERBLOCK_OFFSET + 4, SEEK_SET);
59 device.read(&totalBlockCount, 4);
61 // read firstDataBlock
62 device.lseek(ODE_SUPERBLOCK_OFFSET + 20, SEEK_SET);
63 device.read(&firstDataBlock, 4);
66 device.lseek(ODE_SUPERBLOCK_OFFSET + 24, SEEK_SET);
67 device.read(&blockSize, 4);
68 blockSize = (ODE_EXT2_MIN_BLOCK_SIZE << blockSize);
70 // read blocksPerGroup
71 device.lseek(ODE_SUPERBLOCK_OFFSET + 32, SEEK_SET);
72 device.read(&blocksPerGroup, 4);
74 // read clustersPerGroup
75 device.lseek(ODE_SUPERBLOCK_OFFSET + 36, SEEK_SET);
76 device.read(&clustersPerGroup, 4);
78 unsigned int groupDescCount = divCeilSafely(totalBlockCount - firstDataBlock, blocksPerGroup);
79 int blockNbytes = clustersPerGroup / 8;
82 unsigned int descPerBlock = blockSize / ODE_EXT2_MIN_DESC_SIZE;
83 unsigned int descBlockCount = divCeilSafely(groupDescCount, descPerBlock);
85 // read first meta block
86 data group_desc(descBlockCount * blockSize);
87 device.lseek((firstDataBlock + 1) * blockSize, SEEK_SET);
88 device.read(group_desc.data(), (descBlockCount * blockSize));
91 unsigned int blkItr = firstDataBlock;
93 // this structure just is used for easy type-casting.
94 struct odeExtGroupDesc {
95 unsigned int blockBitmap; /* Blocks bitmap block */
96 /* skip other member */
101 unsigned int start = firstDataBlock;
102 unsigned int real_end = blocksPerGroup * groupDescCount - 1 + start;
103 size_t size = (size_t) (((real_end - start) / 8) + 1);
104 size = (size + 7) & ~3;
108 for (unsigned int i = 0; i < groupDescCount; i++) {
109 data block_bitmap(blockSize);
111 unsigned int blk = (((struct odeExtGroupDesc *)(((unsigned char *)(group_desc.data())) + i * ODE_EXT2_MIN_DESC_SIZE))->blockBitmap);
112 device.lseek(blk * blockSize, SEEK_SET);
113 device.read(block_bitmap.data(), blockSize);
115 cnt = blockNbytes << 3;
116 memcpy(bitmap.data() + (blkItr >> 3), block_bitmap.data(), (cnt + 7) >> 3);
117 blkItr += blockNbytes << 3;
123 Ext4Tool::~Ext4Tool()
127 unsigned int Ext4Tool::getBlockSize()
132 unsigned int Ext4Tool::getTotalBlockCount()
134 return totalBlockCount;
137 bool Ext4Tool::isUsedBlock(unsigned int blockIndex)
139 unsigned char *addr = (bitmap.data() + (blockIndex >> 3));
140 int mask = 1 << (blockIndex & 0x07);
148 void Ext4Tool::forceCleanUp()
150 std::vector<std::string> args = {
156 runtime::Process proc("/sbin/e2fsck", args);
158 proc.waitForFinished();