1*57696d54SAkhilesh Sanikop /*
2*57696d54SAkhilesh Sanikop * Copyright (C) 2020 The Android Open Source Project
3*57696d54SAkhilesh Sanikop *
4*57696d54SAkhilesh Sanikop * This software is licensed under the terms of the GNU General Public
5*57696d54SAkhilesh Sanikop * License version 2, as published by the Free Software Foundation, and
6*57696d54SAkhilesh Sanikop * may be copied, distributed, and modified under those terms.
7*57696d54SAkhilesh Sanikop *
8*57696d54SAkhilesh Sanikop * This program is distributed in the hope that it will be useful,
9*57696d54SAkhilesh Sanikop * but WITHOUT ANY WARRANTY; without even the implied warranty of
10*57696d54SAkhilesh Sanikop * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11*57696d54SAkhilesh Sanikop * GNU General Public License for more details.
12*57696d54SAkhilesh Sanikop */
13*57696d54SAkhilesh Sanikop
14*57696d54SAkhilesh Sanikop #include <fcntl.h>
15*57696d54SAkhilesh Sanikop #include <sys/stat.h>
16*57696d54SAkhilesh Sanikop #include <unistd.h>
17*57696d54SAkhilesh Sanikop
18*57696d54SAkhilesh Sanikop #include "diskio.h"
19*57696d54SAkhilesh Sanikop
20*57696d54SAkhilesh Sanikop using namespace std;
21*57696d54SAkhilesh Sanikop
OpenForRead(const unsigned char * data,size_t size)22*57696d54SAkhilesh Sanikop int DiskIO::OpenForRead(const unsigned char* data, size_t size) {
23*57696d54SAkhilesh Sanikop this->data = data;
24*57696d54SAkhilesh Sanikop this->size = size;
25*57696d54SAkhilesh Sanikop this->off = 0;
26*57696d54SAkhilesh Sanikop this->isOpen = 1;
27*57696d54SAkhilesh Sanikop this->openForWrite = 0;
28*57696d54SAkhilesh Sanikop return 1;
29*57696d54SAkhilesh Sanikop }
30*57696d54SAkhilesh Sanikop
MakeRealName(void)31*57696d54SAkhilesh Sanikop void DiskIO::MakeRealName(void) { this->realFilename = this->userFilename; }
32*57696d54SAkhilesh Sanikop
OpenForRead(void)33*57696d54SAkhilesh Sanikop int DiskIO::OpenForRead(void) {
34*57696d54SAkhilesh Sanikop struct stat64 st;
35*57696d54SAkhilesh Sanikop
36*57696d54SAkhilesh Sanikop if (this->isOpen) {
37*57696d54SAkhilesh Sanikop if (this->openForWrite) {
38*57696d54SAkhilesh Sanikop Close();
39*57696d54SAkhilesh Sanikop } else {
40*57696d54SAkhilesh Sanikop return 1;
41*57696d54SAkhilesh Sanikop }
42*57696d54SAkhilesh Sanikop }
43*57696d54SAkhilesh Sanikop
44*57696d54SAkhilesh Sanikop this->fd = open(realFilename.c_str(), O_RDONLY | O_CREAT, S_IRUSR | S_IRGRP | S_IROTH);
45*57696d54SAkhilesh Sanikop if (this->fd == -1) {
46*57696d54SAkhilesh Sanikop this->realFilename = this->userFilename = "";
47*57696d54SAkhilesh Sanikop } else {
48*57696d54SAkhilesh Sanikop if (fstat64(fd, &st) == 0) {
49*57696d54SAkhilesh Sanikop if (!(S_ISDIR(st.st_mode) || S_ISFIFO(st.st_mode) ||
50*57696d54SAkhilesh Sanikop S_ISSOCK(st.st_mode))) {
51*57696d54SAkhilesh Sanikop this->isOpen = 1;
52*57696d54SAkhilesh Sanikop }
53*57696d54SAkhilesh Sanikop }
54*57696d54SAkhilesh Sanikop }
55*57696d54SAkhilesh Sanikop return this->isOpen;
56*57696d54SAkhilesh Sanikop }
57*57696d54SAkhilesh Sanikop
OpenForWrite(void)58*57696d54SAkhilesh Sanikop int DiskIO::OpenForWrite(void) {
59*57696d54SAkhilesh Sanikop if ((this->isOpen) && (this->openForWrite)) {
60*57696d54SAkhilesh Sanikop return 1;
61*57696d54SAkhilesh Sanikop }
62*57696d54SAkhilesh Sanikop
63*57696d54SAkhilesh Sanikop Close();
64*57696d54SAkhilesh Sanikop this->fd = open(realFilename.c_str(), O_WRONLY | O_CREAT,
65*57696d54SAkhilesh Sanikop S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
66*57696d54SAkhilesh Sanikop if (fd >= 0) {
67*57696d54SAkhilesh Sanikop this->isOpen = 1;
68*57696d54SAkhilesh Sanikop this->openForWrite = 1;
69*57696d54SAkhilesh Sanikop }
70*57696d54SAkhilesh Sanikop return this->isOpen;
71*57696d54SAkhilesh Sanikop }
72*57696d54SAkhilesh Sanikop
Close(void)73*57696d54SAkhilesh Sanikop void DiskIO::Close(void) {
74*57696d54SAkhilesh Sanikop if (this->isOpen) {
75*57696d54SAkhilesh Sanikop close(this->fd);
76*57696d54SAkhilesh Sanikop }
77*57696d54SAkhilesh Sanikop this->isOpen = 0;
78*57696d54SAkhilesh Sanikop this->openForWrite = 0;
79*57696d54SAkhilesh Sanikop }
80*57696d54SAkhilesh Sanikop
GetBlockSize(void)81*57696d54SAkhilesh Sanikop int DiskIO::GetBlockSize(void) {
82*57696d54SAkhilesh Sanikop return 512;
83*57696d54SAkhilesh Sanikop }
84*57696d54SAkhilesh Sanikop
GetPhysBlockSize(void)85*57696d54SAkhilesh Sanikop int DiskIO::GetPhysBlockSize(void) {
86*57696d54SAkhilesh Sanikop return 512;
87*57696d54SAkhilesh Sanikop }
88*57696d54SAkhilesh Sanikop
GetNumHeads(void)89*57696d54SAkhilesh Sanikop uint32_t DiskIO::GetNumHeads(void) {
90*57696d54SAkhilesh Sanikop return 255;
91*57696d54SAkhilesh Sanikop }
92*57696d54SAkhilesh Sanikop
GetNumSecsPerTrack(void)93*57696d54SAkhilesh Sanikop uint32_t DiskIO::GetNumSecsPerTrack(void) {
94*57696d54SAkhilesh Sanikop return 63;
95*57696d54SAkhilesh Sanikop }
96*57696d54SAkhilesh Sanikop
DiskSync(void)97*57696d54SAkhilesh Sanikop int DiskIO::DiskSync(void) {
98*57696d54SAkhilesh Sanikop return 1;
99*57696d54SAkhilesh Sanikop }
100*57696d54SAkhilesh Sanikop
Seek(uint64_t sector)101*57696d54SAkhilesh Sanikop int DiskIO::Seek(uint64_t sector) {
102*57696d54SAkhilesh Sanikop int retval = 1;
103*57696d54SAkhilesh Sanikop off_t seekTo = sector * static_cast<uint64_t>(GetBlockSize());
104*57696d54SAkhilesh Sanikop
105*57696d54SAkhilesh Sanikop if (!isOpen) {
106*57696d54SAkhilesh Sanikop if (OpenForRead() != 1) {
107*57696d54SAkhilesh Sanikop retval = 0;
108*57696d54SAkhilesh Sanikop }
109*57696d54SAkhilesh Sanikop }
110*57696d54SAkhilesh Sanikop
111*57696d54SAkhilesh Sanikop if (isOpen && seekTo < this->size) {
112*57696d54SAkhilesh Sanikop off_t sought = lseek64(fd, seekTo, SEEK_SET);
113*57696d54SAkhilesh Sanikop if (sought != seekTo) {
114*57696d54SAkhilesh Sanikop retval = 0;
115*57696d54SAkhilesh Sanikop }
116*57696d54SAkhilesh Sanikop }
117*57696d54SAkhilesh Sanikop
118*57696d54SAkhilesh Sanikop if (retval) {
119*57696d54SAkhilesh Sanikop this->off = seekTo;
120*57696d54SAkhilesh Sanikop }
121*57696d54SAkhilesh Sanikop
122*57696d54SAkhilesh Sanikop return retval;
123*57696d54SAkhilesh Sanikop }
124*57696d54SAkhilesh Sanikop
Read(void * buffer,int numBytes)125*57696d54SAkhilesh Sanikop int DiskIO::Read(void* buffer, int numBytes) {
126*57696d54SAkhilesh Sanikop int actualBytes = 0;
127*57696d54SAkhilesh Sanikop if (this->size > this->off) {
128*57696d54SAkhilesh Sanikop actualBytes = std::min(static_cast<int>(this->size - this->off), numBytes);
129*57696d54SAkhilesh Sanikop memcpy(buffer, this->data + this->off, actualBytes);
130*57696d54SAkhilesh Sanikop }
131*57696d54SAkhilesh Sanikop return actualBytes;
132*57696d54SAkhilesh Sanikop }
133*57696d54SAkhilesh Sanikop
Write(void * buffer,int numBytes)134*57696d54SAkhilesh Sanikop int DiskIO::Write(void *buffer, int numBytes) {
135*57696d54SAkhilesh Sanikop int blockSize, i, numBlocks, retval = 0;
136*57696d54SAkhilesh Sanikop char *tempSpace;
137*57696d54SAkhilesh Sanikop
138*57696d54SAkhilesh Sanikop if ((!this->isOpen) || (!this->openForWrite)) {
139*57696d54SAkhilesh Sanikop OpenForWrite();
140*57696d54SAkhilesh Sanikop }
141*57696d54SAkhilesh Sanikop
142*57696d54SAkhilesh Sanikop if (this->isOpen) {
143*57696d54SAkhilesh Sanikop blockSize = GetBlockSize();
144*57696d54SAkhilesh Sanikop if (numBytes <= blockSize) {
145*57696d54SAkhilesh Sanikop numBlocks = 1;
146*57696d54SAkhilesh Sanikop tempSpace = new char[blockSize];
147*57696d54SAkhilesh Sanikop } else {
148*57696d54SAkhilesh Sanikop numBlocks = numBytes / blockSize;
149*57696d54SAkhilesh Sanikop if ((numBytes % blockSize) != 0)
150*57696d54SAkhilesh Sanikop numBlocks++;
151*57696d54SAkhilesh Sanikop tempSpace = new char[numBlocks * blockSize];
152*57696d54SAkhilesh Sanikop }
153*57696d54SAkhilesh Sanikop if (tempSpace == NULL) {
154*57696d54SAkhilesh Sanikop return 0;
155*57696d54SAkhilesh Sanikop }
156*57696d54SAkhilesh Sanikop
157*57696d54SAkhilesh Sanikop memcpy(tempSpace, buffer, numBytes);
158*57696d54SAkhilesh Sanikop for (i = numBytes; i < numBlocks * blockSize; i++) {
159*57696d54SAkhilesh Sanikop tempSpace[i] = 0;
160*57696d54SAkhilesh Sanikop }
161*57696d54SAkhilesh Sanikop retval = write(fd, tempSpace, numBlocks * blockSize);
162*57696d54SAkhilesh Sanikop
163*57696d54SAkhilesh Sanikop if (((numBlocks * blockSize) != numBytes) && (retval > 0))
164*57696d54SAkhilesh Sanikop retval = numBytes;
165*57696d54SAkhilesh Sanikop
166*57696d54SAkhilesh Sanikop delete[] tempSpace;
167*57696d54SAkhilesh Sanikop }
168*57696d54SAkhilesh Sanikop return retval;
169*57696d54SAkhilesh Sanikop }
170*57696d54SAkhilesh Sanikop
DiskSize(int *)171*57696d54SAkhilesh Sanikop uint64_t DiskIO::DiskSize(int *) {
172*57696d54SAkhilesh Sanikop return this->size / GetBlockSize();
173*57696d54SAkhilesh Sanikop }
174