all repos — mgba @ 6cf4179a974d6745953d0d354ea8266512d84b83

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