xref: /aosp_15_r20/external/gptfdisk/diskio-heap.cc (revision 57696d54d05c64fd1b1787f8371dbcf104911cfb)
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