src/util/vfs/vfs-dirent.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 "util/vfs.h"
7
8#include "util/string.h"
9
10#include <dirent.h>
11#include <sys/stat.h>
12
13static bool _vdClose(struct VDir* vd);
14static void _vdRewind(struct VDir* vd);
15static struct VDirEntry* _vdListNext(struct VDir* vd);
16static struct VFile* _vdOpenFile(struct VDir* vd, const char* path, int mode);
17static struct VDir* _vdOpenDir(struct VDir* vd, const char* path);
18
19static const char* _vdeName(struct VDirEntry* vde);
20static enum VFSType _vdeType(struct VDirEntry* vde);
21
22struct VDirDE;
23struct VDirEntryDE {
24 struct VDirEntry d;
25 struct VDirDE* p;
26 struct dirent* ent;
27};
28
29struct VDirDE {
30 struct VDir d;
31 DIR* de;
32 struct VDirEntryDE vde;
33 char* path;
34};
35
36struct VDir* VDirOpen(const char* path) {
37#ifdef __wii__
38 if (!path || !path[0]) {
39 return VDeviceList();
40 }
41#endif
42 DIR* de = opendir(path);
43 if (!de) {
44 return 0;
45 }
46
47 struct VDirDE* vd = malloc(sizeof(struct VDirDE));
48 if (!vd) {
49 closedir(de);
50 return 0;
51 }
52
53 vd->d.close = _vdClose;
54 vd->d.rewind = _vdRewind;
55 vd->d.listNext = _vdListNext;
56 vd->d.openFile = _vdOpenFile;
57 vd->d.openDir = _vdOpenDir;
58 vd->path = strdup(path);
59 vd->de = de;
60
61 vd->vde.d.name = _vdeName;
62 vd->vde.d.type = _vdeType;
63 vd->vde.p = vd;
64
65 return &vd->d;
66}
67
68bool _vdClose(struct VDir* vd) {
69 struct VDirDE* vdde = (struct VDirDE*) vd;
70 if (closedir(vdde->de) < 0) {
71 return false;
72 }
73 free(vdde->path);
74 free(vdde);
75 return true;
76}
77
78void _vdRewind(struct VDir* vd) {
79 struct VDirDE* vdde = (struct VDirDE*) vd;
80 rewinddir(vdde->de);
81}
82
83struct VDirEntry* _vdListNext(struct VDir* vd) {
84 struct VDirDE* vdde = (struct VDirDE*) vd;
85 vdde->vde.ent = readdir(vdde->de);
86 if (vdde->vde.ent) {
87 return &vdde->vde.d;
88 }
89
90 return 0;
91}
92
93struct VFile* _vdOpenFile(struct VDir* vd, const char* path, int mode) {
94 struct VDirDE* vdde = (struct VDirDE*) vd;
95 if (!path) {
96 return 0;
97 }
98 const char* dir = vdde->path;
99 char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + 2));
100 sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
101
102 struct VFile* file = VFileOpen(combined, mode);
103 free(combined);
104 return file;
105}
106
107struct VDir* _vdOpenDir(struct VDir* vd, const char* path) {
108 struct VDirDE* vdde = (struct VDirDE*) vd;
109 if (!path) {
110 return 0;
111 }
112 const char* dir = vdde->path;
113 char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + 2));
114 sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
115
116 struct VDir* vd2 = VDirOpen(combined);
117 if (!vd2) {
118 vd2 = VDirOpenArchive(combined);
119 }
120 free(combined);
121 return vd2;
122}
123
124const char* _vdeName(struct VDirEntry* vde) {
125 struct VDirEntryDE* vdede = (struct VDirEntryDE*) vde;
126 if (vdede->ent) {
127 return vdede->ent->d_name;
128 }
129 return 0;
130}
131
132static enum VFSType _vdeType(struct VDirEntry* vde) {
133 struct VDirEntryDE* vdede = (struct VDirEntryDE*) vde;
134#ifndef WIN32
135 if (vdede->ent->d_type == DT_DIR) {
136 return VFS_DIRECTORY;
137 }
138 return VFS_FILE;
139#else
140 const char* dir = vdede->p->path;
141 char* combined = malloc(sizeof(char) * (strlen(vdede->ent->d_name) + strlen(dir) + 2));
142 sprintf(combined, "%s%s%s", dir, PATH_SEP, vdede->ent->d_name);
143 struct stat sb;
144 stat(combined, &sb);
145 free(combined);
146
147 if (S_ISDIR(sb.st_mode)) {
148 return VFS_DIRECTORY;
149 }
150 return VFS_FILE;
151#endif
152}