src/util/vfs.c (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "vfs.h"
7
8#ifdef PSP2
9#include "platform/psp2/sce-vfs.h"
10#endif
11#ifdef _3DS
12#include "platform/3ds/3ds-vfs.h"
13#endif
14
15struct VFile* VFileOpen(const char* path, int flags) {
16#ifdef USE_VFS_FILE
17 const char* chflags;
18 switch (flags & O_ACCMODE) {
19 case O_WRONLY:
20 if (flags & O_APPEND) {
21 chflags = "ab";
22 } else {
23 chflags = "wb";
24 }
25 break;
26 case O_RDWR:
27 if (flags & O_APPEND) {
28 chflags = "a+b";
29 } else if (flags & O_TRUNC) {
30 chflags = "w+b";
31 } else {
32 chflags = "r+b";
33 }
34 break;
35 case O_RDONLY:
36 chflags = "rb";
37 break;
38 }
39 return VFileFOpen(path, chflags);
40#elif defined(PSP2)
41 int sceFlags = PSP2_O_RDONLY;
42 switch (flags & O_ACCMODE) {
43 case O_WRONLY:
44 sceFlags = PSP2_O_WRONLY;
45 break;
46 case O_RDWR:
47 sceFlags = PSP2_O_RDWR;
48 break;
49 case O_RDONLY:
50 sceFlags = PSP2_O_RDONLY;
51 break;
52 }
53
54 if (flags & O_APPEND) {
55 sceFlags |= PSP2_O_APPEND;
56 }
57 if (flags & O_TRUNC) {
58 sceFlags |= PSP2_O_TRUNC;
59 }
60 if (flags & O_CREAT) {
61 sceFlags |= PSP2_O_CREAT;
62 }
63 return VFileOpenSce(path, sceFlags, 0666);
64#elif defined(USE_VFS_3DS)
65 int ctrFlags = FS_OPEN_READ;
66 switch (flags & O_ACCMODE) {
67 case O_WRONLY:
68 ctrFlags = FS_OPEN_WRITE;
69 break;
70 case O_RDWR:
71 ctrFlags = FS_OPEN_READ | FS_OPEN_WRITE;
72 break;
73 case O_RDONLY:
74 ctrFlags = FS_OPEN_READ;
75 break;
76 }
77
78 if (flags & O_CREAT) {
79 ctrFlags |= FS_OPEN_CREATE;
80 }
81 struct VFile* vf = VFileOpen3DS(&sdmcArchive, path, ctrFlags);
82 if (!vf) {
83 return 0;
84 }
85 if (flags & O_TRUNC) {
86 vf->truncate(vf, 0);
87 }
88 if (flags & O_APPEND) {
89 vf->seek(vf, vf->size(vf), SEEK_SET);
90 }
91 return vf;
92#else
93 return VFileOpenFD(path, flags);
94#endif
95}
96
97ssize_t VFileReadline(struct VFile* vf, char* buffer, size_t size) {
98 size_t bytesRead = 0;
99 while (bytesRead < size - 1) {
100 ssize_t newRead = vf->read(vf, &buffer[bytesRead], 1);
101 if (newRead <= 0) {
102 break;
103 }
104 bytesRead += newRead;
105 if (buffer[bytesRead] == '\n') {
106 break;
107 }
108 }
109 buffer[bytesRead] = '\0';
110 return bytesRead;
111}
112
113ssize_t VFileWrite32LE(struct VFile* vf, int32_t word) {
114 uint32_t leword;
115 STORE_32LE(word, 0, &leword);
116 return vf->write(vf, &leword, 4);
117}
118
119ssize_t VFileWrite16LE(struct VFile* vf, int16_t hword) {
120 uint16_t lehword;
121 STORE_16LE(hword, 0, &lehword);
122 return vf->write(vf, &lehword, 2);
123}
124
125ssize_t VFileRead32LE(struct VFile* vf, void* word) {
126 uint32_t leword;
127 ssize_t r = vf->read(vf, &leword, 4);
128 if (r == 4) {
129 STORE_32LE(leword, 0, word);
130 }
131 return r;
132}
133
134ssize_t VFileRead16LE(struct VFile* vf, void* hword) {
135 uint16_t lehword;
136 ssize_t r = vf->read(vf, &lehword, 2);
137 if (r == 2) {
138 STORE_16LE(lehword, 0, hword);
139 }
140 return r;
141}
142
143struct VFile* VDirOptionalOpenFile(struct VDir* dir, const char* realPath, const char* prefix, const char* suffix, int mode) {
144 char path[PATH_MAX];
145 path[PATH_MAX - 1] = '\0';
146 struct VFile* vf;
147 if (!dir) {
148 if (!realPath) {
149 return 0;
150 }
151 char* dotPoint = strrchr(realPath, '.');
152 if (dotPoint - realPath + 1 >= PATH_MAX - 1) {
153 return 0;
154 }
155 if (dotPoint > strrchr(realPath, '/')) {
156 int len = dotPoint - realPath;
157 strncpy(path, realPath, len);
158 path[len] = 0;
159 strncat(path + len, suffix, PATH_MAX - len - 1);
160 } else {
161 snprintf(path, PATH_MAX - 1, "%s%s", realPath, suffix);
162 }
163 vf = VFileOpen(path, mode);
164 } else {
165 snprintf(path, PATH_MAX - 1, "%s%s", prefix, suffix);
166 vf = dir->openFile(dir, path, mode);
167 }
168 return vf;
169}