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}