-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdrive_reader.cpp
More file actions
99 lines (80 loc) · 2.29 KB
/
drive_reader.cpp
File metadata and controls
99 lines (80 loc) · 2.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include "drive_reader.hpp"
#include <sstream>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <linux/fs.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
namespace sg
{
std::string DriveReader::name()
{
return this->driveName;
}
BlockDeviceReader::BlockDeviceReader(std::string path)
{
this->size = this->readDriveSize(path);
this->driveName = path;
// Yeah, I use linux syscalls to read drive sizes and here
// I use ifstream, I could use just syscalls
// But they're scary and I am too lazy to read how to process errors
// from them. So I'll stick with ifstream, at least for now.
this->devstream = std::ifstream(path, std::ios::binary);
if (!this->devstream.is_open())
{
std::stringstream errMsgStream;
errMsgStream << "Could not open drive "
<< path << " Reason: "
<< strerror(errno);
throw std::runtime_error(errMsgStream.str());
}
}
int BlockDeviceReader::read(void *buf, u32 len, u64 offset)
{
this->devstream.seekg(offset);
this->devstream.read((char*)buf, len);
if (this->devstream.fail())
{
std::stringstream errMsg;
errMsg << "Reading from drive " << this->name() << " has failed. ";
if (this->devstream.eof()) {
errMsg << "Reason: end of file.";
}
else {
errMsg << "Reason: unknown, errno: " << strerror(errno);
}
throw std::runtime_error(errMsg.str());
}
return 0;
}
u64 BlockDeviceReader::driveSize()
{
return this->size;
}
u64 BlockDeviceReader::readDriveSize(std::string path)
{
int fd = open(path.c_str(), O_RDONLY);
if (fd == -1)
{
std::stringstream errMsgStream;
errMsgStream << "Could not read size of drive "
<< path << "; Reason: "
<< strerror(errno);
throw std::runtime_error(errMsgStream.str());
}
size_t driveSize = 0;
int rc = ioctl(fd, BLKGETSIZE64, &driveSize);
close(fd);
if (rc != 0)
{
std::stringstream errMsgStream;
errMsgStream << "Could not read size of drive "
<< path << "; Reason: "
<< strerror(errno);
throw std::runtime_error(errMsgStream.str());
}
return driveSize;
}
} // end namespace sg