all repos — mgba @ 17d343656f2bd4e0ae212d3abdc10e6e5108049a

mGBA Game Boy Advance Emulator

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}