* reverted some changes from rev500, finally crazyc was correct (when he skipped...
[open-ps2-loader.git] / src / util.c
blobec1776ce7a1bc03ab0c8b86d9e84585c1d70eb48
1 /*
2 Copyright 2009, Ifcaro & volca
3 Licenced under Academic Free License version 3.0
4 Review OpenUsbLd README & LICENSE files for further details.
5 */
7 #include "include/util.h"
8 #include "include/ioman.h"
9 #include <io_common.h>
10 #include <string.h>
11 #include "malloc.h"
12 #include "fileio.h"
14 extern void *icon_sys;
15 extern int size_icon_sys;
16 extern void *icon_icn;
17 extern int size_icon_icn;
19 static int mcID = -1;
21 int getFileSize(int fd) {
22 int size = fioLseek(fd, 0, SEEK_END);
23 fioLseek(fd, 0, SEEK_SET);
24 return size;
27 static void writeMCIcon() {
28 void** buffer = &icon_icn;
29 file_buffer_t* fileBuffer = openFileBuffer("mc?:OPL/opl.icn", O_WRONLY | O_CREAT | O_TRUNC, 0, 0);
30 if (fileBuffer) {
31 writeFileBuffer(fileBuffer, (char *)buffer, size_icon_icn);
32 closeFileBuffer(fileBuffer);
35 buffer = &icon_sys;
36 fileBuffer = openFileBuffer("mc?:OPL/icon.sys", O_WRONLY | O_CREAT | O_TRUNC, 0, 0);
37 if (fileBuffer) {
38 writeFileBuffer(fileBuffer, (char *)buffer, size_icon_sys);
39 closeFileBuffer(fileBuffer);
43 static int checkMC() {
44 if (mcID == -1) {
45 int fd = fioDopen("mc0:OPL");
46 if(fd < 0) {
47 fd = fioDopen("mc1:OPL");
48 if(fd < 0) {
49 // No base dir found on any MC, will create the folder
50 if (fioMkdir("mc0:OPL") >= 0) {
51 mcID = 0x30;
52 writeMCIcon();
54 else if (fioMkdir("mc1:OPL") >= 0) {
55 mcID = 0x31;
56 writeMCIcon();
59 else {
60 fioDclose(fd);
61 mcID = 0x31;
64 else {
65 fioDclose(fd);
66 mcID = 0x30;
69 return mcID;
72 static int checkFile(char* path, int mode) {
73 // check if it is mc
74 if (strncmp(path, "mc", 2) == 0) {
76 // if user didn't explicitly asked for a MC (using '?' char)
77 if (path[2] == 0x3F) {
79 // Use default detected card
80 if (checkMC() >= 0)
81 path[2] = mcID;
82 else
83 return 0;
86 // in create mode, we check that the directory exist, or create it
87 if (mode & O_CREAT) {
88 char dirPath[255];
89 char* pos = strrchr(path, '/');
90 if (pos) {
91 memcpy(dirPath, path, pos - path);
92 dirPath[pos - path] = '\0';
93 int fd = fioDopen(dirPath);
94 if (fd < 0) {
95 if (fioMkdir(dirPath) < 0)
96 return 0;
98 else
99 fioDclose(fd);
103 return 1;
106 int openFile(char* path, int mode) {
107 if (checkFile(path, mode))
108 return fioOpen(path, mode);
109 else
110 return -1;
113 void* readFile(char* path, int align, int* size) {
114 void *buffer = NULL;
116 int fd = openFile(path, O_RDONLY);
117 if (fd >= 0) {
118 unsigned int realSize = getFileSize(fd);
120 if ((*size > 0) && (*size != realSize)) {
121 LOG("Invalid filesize, expected: %d, got: %d\n", *size, realSize);
122 fioClose(fd);
123 return NULL;
126 if (align > 0)
127 buffer = memalign(128, realSize); // The allocation is aligned to aid the DMA transfers
128 else
129 buffer = malloc(realSize);
131 if (!buffer) {
132 LOG("readFile: Failed allocation of %d bytes", realSize);
133 *size = 0;
134 } else {
135 fioRead(fd, buffer, realSize);
136 fioClose(fd);
137 *size = realSize;
140 return buffer;
143 void checkCreateDir(char* dirPath) {
144 int fd = fioDopen(dirPath);
145 if (fd < 0)
146 fioMkdir(dirPath);
147 else
148 fioDclose(fd);
151 int listDir(char* path, char* separator, int maxElem,
152 int (*readEntry)(int index, char *path, char* separator, char* name, unsigned int mode)) {
153 int fdDir, index = 0;
154 if (checkFile(path, O_RDONLY)) {
155 fio_dirent_t record;
157 fdDir = fioDopen(path);
158 if (fdDir > 0) {
159 while (index < maxElem && fioDread(fdDir, &record) > 0)
160 index = readEntry(index, path, separator, record.name, record.stat.mode);
162 fioDclose(fdDir);
165 return index;
168 /* size will be the maximum line size possible */
169 file_buffer_t* openFileBuffer(char* fpath, int mode, short allocResult, unsigned int size) {
170 file_buffer_t* fileBuffer = NULL;
172 int fd = openFile(fpath, mode);
173 if (fd >= 0) {
174 fileBuffer = (file_buffer_t*) malloc(sizeof(file_buffer_t));
175 fileBuffer->size = size;
176 fileBuffer->available = 0;
177 fileBuffer->buffer = (char*) malloc(size * sizeof(char));
178 if (mode == O_RDONLY)
179 fileBuffer->lastPtr = NULL;
180 else
181 fileBuffer->lastPtr = fileBuffer->buffer;
182 fileBuffer->allocResult = allocResult;
183 fileBuffer->fd = fd;
184 fileBuffer->mode = mode;
187 return fileBuffer;
190 int readFileBuffer(file_buffer_t* fileBuffer, char** outBuf) {
191 int lineSize = 0, read, length;
192 char* posLF = NULL;
194 while (1) {
195 // if lastPtr is set, then we continue the read from this point as reference
196 if (fileBuffer->lastPtr) {
197 // Calculate the remaining chars to the right of lastPtr
198 lineSize = fileBuffer->available - (fileBuffer->lastPtr - fileBuffer->buffer);
199 /*LOG("##### Continue read, position: %X (total: %d) line size (\\0 not inc.): %d end: %x\n",
200 fileBuffer->lastPtr - fileBuffer->buffer, fileBuffer->available, lineSize, fileBuffer->lastPtr[lineSize]);*/
201 posLF = strchr(fileBuffer->lastPtr, 0x0A);
204 if (!posLF) { // We can come here either when the buffer is empty, or if the remaining chars don't have a LF
206 // if available, we shift the remaining chars to the left ...
207 if (lineSize) {
208 //LOG("##### LF not found, Shift %d characters from end to beginning\n", lineSize);
209 memmove(fileBuffer->buffer, fileBuffer->lastPtr, lineSize);
212 // ... and complete the buffer if we're not at EOF
213 if (fileBuffer->fd >= 0) {
215 // Load as many characters necessary to fill the buffer
216 length = fileBuffer->size - lineSize - 1;
217 //LOG("##### Asking for %d characters to complete buffer\n", length);
218 read = fioRead(fileBuffer->fd, fileBuffer->buffer + lineSize, length);
219 fileBuffer->buffer[lineSize + read] = '\0';
221 // Search again (from the lastly added chars only), the result will be "analyzed" in next if
222 posLF = strchr(fileBuffer->buffer + lineSize, 0x0A);
224 // Now update read context info
225 lineSize = lineSize + read;
226 //LOG("##### %d characters really read, line size now (\\0 not inc.): %d\n", read, lineSize);
228 // If buffer not full it means we are at EOF
229 if (fileBuffer->size != lineSize + 1) {
230 //LOG("##### Reached EOF\n");
231 fioClose(fileBuffer->fd);
232 fileBuffer->fd = -1;
236 fileBuffer->lastPtr = fileBuffer->buffer;
237 fileBuffer->available = lineSize;
240 if(posLF)
241 lineSize = posLF - fileBuffer->lastPtr;
243 // Check the previous char (on Windows there are CR/LF instead of single linux LF)
244 if (lineSize)
245 if (*(fileBuffer->lastPtr + lineSize - 1) == 0x0D)
246 lineSize--;
248 fileBuffer->lastPtr[lineSize] = '\0';
249 *outBuf = fileBuffer->lastPtr;
251 //LOG("##### Result line is \"%s\" size: %d avail: %d pos: %d\n", fileBuffer->lastPtr, lineSize, fileBuffer->available, fileBuffer->lastPtr - fileBuffer->buffer);
253 // If we are at EOF and no more chars available to scan, then we are finished
254 if (!lineSize && !fileBuffer->available && fileBuffer->fd == -1)
255 return 0;
257 if (fileBuffer->lastPtr[0] == 0x23) {// '#' for comment lines
258 if (posLF)
259 fileBuffer->lastPtr = posLF + 1;
260 else
261 fileBuffer->lastPtr = NULL;
262 continue;
265 if (lineSize && fileBuffer->allocResult) {
266 *outBuf = (char*) malloc((lineSize + 1) * sizeof(char));
267 memcpy(*outBuf, fileBuffer->lastPtr, lineSize + 1);
270 // Either move the pointer to next chars, or set it to null to force a whole buffer read (if possible)
271 if (posLF)
272 fileBuffer->lastPtr = posLF + 1;
273 else {
274 fileBuffer->lastPtr = NULL;
277 return 1;
281 void writeFileBuffer(file_buffer_t* fileBuffer, char* inBuf, int size) {
282 //LOG("writeFileBuffer avail: %d size: %d\n", fileBuffer->available, size);
283 if (fileBuffer->available && fileBuffer->available + size > fileBuffer->size) {
284 //LOG("writeFileBuffer flushing: %d\n", fileBuffer->available);
285 fioWrite(fileBuffer->fd, fileBuffer->buffer, fileBuffer->available);
286 fileBuffer->lastPtr = fileBuffer->buffer;
287 fileBuffer->available = 0;
290 if (size > fileBuffer->size) {
291 //LOG("writeFileBuffer direct write: %d\n", size);
292 fioWrite(fileBuffer->fd, inBuf, size);
294 else {
295 memcpy(fileBuffer->lastPtr, inBuf, size);
296 fileBuffer->lastPtr += size;
297 fileBuffer->available += size;
299 //LOG("writeFileBuffer lastPrt: %d\n", (fileBuffer->lastPtr - fileBuffer->buffer));
303 void closeFileBuffer(file_buffer_t* fileBuffer) {
304 if (fileBuffer->fd >= 0) {
305 if (fileBuffer->mode != O_RDONLY && fileBuffer->available) {
306 //LOG("writeFileBuffer final write: %d\n", fileBuffer->available);
307 fioWrite(fileBuffer->fd, fileBuffer->buffer, fileBuffer->available);
309 fioClose(fileBuffer->fd);
311 free(fileBuffer->buffer);
312 free(fileBuffer);
313 fileBuffer = NULL;
316 // a simple maximum of two inline
317 inline int max(int a, int b) {
318 return a > b ? a : b;
321 // a simple minimum of two inline
322 inline int min(int a, int b) {
323 return a < b ? a : b;
326 // single digit from hex decode
327 int fromHex(char digit) {
328 if ((digit >= '0') && (digit <= '9')) {
329 return (digit - '0');
330 } else if ( (digit >= 'A') && (digit <= 'F') ) {
331 return (digit - 'A' + 10);
332 } else if ( (digit >= 'a') && (digit <= 'f') ) {
333 return (digit - 'a' + 10);
334 } else
335 return -1;
338 static const char htab[16] = "0123456789ABCDEF";
339 char toHex(int digit) {
340 return htab[digit & 0x0F];