all repos — mgba @ 91fb4407b9a3bc64c84d74eaffe9673d89059a10

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