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