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}