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 _3DS
9#include "platform/3ds/3ds-vfs.h"
10#endif
11
12struct VFile* VFileOpen(const char* path, int flags) {
13#ifdef USE_VFS_FILE
14 const char* chflags;
15 switch (flags & O_ACCMODE) {
16 case O_WRONLY:
17 if (flags & O_APPEND) {
18 chflags = "ab";
19 } else {
20 chflags = "wb";
21 }
22 break;
23 case O_RDWR:
24 if (flags & O_APPEND) {
25 chflags = "a+b";
26 } else if (flags & O_TRUNC) {
27 chflags = "w+b";
28 } else {
29 chflags = "r+b";
30 }
31 break;
32 case O_RDONLY:
33 chflags = "rb";
34 break;
35 }
36 return VFileFOpen(path, chflags);
37#elif defined(_3DS)
38 int ctrFlags = FS_OPEN_READ;
39 switch (flags & O_ACCMODE) {
40 case O_WRONLY:
41 ctrFlags = FS_OPEN_WRITE;
42 break;
43 case O_RDWR:
44 ctrFlags = FS_OPEN_READ | FS_OPEN_WRITE;
45 break;
46 case O_RDONLY:
47 ctrFlags = FS_OPEN_READ;
48 break;
49 }
50
51 if (flags & O_CREAT) {
52 ctrFlags |= FS_OPEN_CREATE;
53 }
54 struct VFile* vf = VFileOpen3DS(&sdmcArchive, path, ctrFlags);
55 if (!vf) {
56 return 0;
57 }
58 if (flags & O_TRUNC) {
59 vf->truncate(vf, 0);
60 }
61 if (flags & O_APPEND) {
62 vf->seek(vf, vf->size(vf), SEEK_SET);
63 }
64 return vf;
65#else
66 return VFileOpenFD(path, flags);
67#endif
68}
69
70ssize_t VFileReadline(struct VFile* vf, char* buffer, size_t size) {
71 size_t bytesRead = 0;
72 while (bytesRead < size - 1) {
73 ssize_t newRead = vf->read(vf, &buffer[bytesRead], 1);
74 if (newRead <= 0) {
75 break;
76 }
77 bytesRead += newRead;
78 if (buffer[bytesRead] == '\n') {
79 break;
80 }
81 }
82 buffer[bytesRead] = '\0';
83 return bytesRead;
84}
85
86ssize_t VFileWrite32LE(struct VFile* vf, int32_t word) {
87 uint32_t leword;
88 STORE_32LE(word, 0, &leword);
89 return vf->write(vf, &leword, 4);
90}
91
92ssize_t VFileWrite16LE(struct VFile* vf, int16_t hword) {
93 uint16_t lehword;
94 STORE_16LE(hword, 0, &lehword);
95 return vf->write(vf, &lehword, 2);
96}
97
98ssize_t VFileRead32LE(struct VFile* vf, void* word) {
99 uint32_t leword;
100 ssize_t r = vf->read(vf, &leword, 4);
101 if (r == 4) {
102 STORE_32LE(leword, 0, word);
103 }
104 return r;
105}
106
107ssize_t VFileRead16LE(struct VFile* vf, void* hword) {
108 uint16_t lehword;
109 ssize_t r = vf->read(vf, &lehword, 2);
110 if (r == 2) {
111 STORE_16LE(lehword, 0, hword);
112 }
113 return r;
114}
115
116struct VFile* VDirOptionalOpenFile(struct VDir* dir, const char* realPath, const char* prefix, const char* suffix, int mode) {
117 char path[PATH_MAX];
118 path[PATH_MAX - 1] = '\0';
119 struct VFile* vf;
120 if (!dir) {
121 if (!realPath) {
122 return 0;
123 }
124 char* dotPoint = strrchr(realPath, '.');
125 if (dotPoint - realPath + 1 >= PATH_MAX - 1) {
126 return 0;
127 }
128 if (dotPoint > strrchr(realPath, '/')) {
129 int len = dotPoint - realPath;
130 strncpy(path, realPath, len);
131 path[len] = 0;
132 strncat(path + len, suffix, PATH_MAX - len - 1);
133 } else {
134 snprintf(path, PATH_MAX - 1, "%s%s", realPath, suffix);
135 }
136 vf = VFileOpen(path, mode);
137 } else {
138 snprintf(path, PATH_MAX - 1, "%s%s", prefix, suffix);
139 vf = dir->openFile(dir, path, mode);
140 }
141 return vf;
142}