1 /* Copyright (C) 2010-2016 The RetroArch team
2 *
3 * ---------------------------------------------------------------------------------------
4 * The following license statement only applies to this file (retro_dirent.c).
5 * ---------------------------------------------------------------------------------------
6 *
7 * Permission is hereby granted, free of charge,
8 * to any person obtaining a copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation the rights to
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 #include <stdlib.h>
24 #include <stdio.h>
25
26 #include <retro_common.h>
27
28 #include <boolean.h>
29 #include <retro_stat.h>
30 #include <retro_dirent.h>
31
retro_opendir(const char * name)32 struct RDIR *retro_opendir(const char *name)
33 {
34 #if defined(_WIN32)
35 char path_buf[1024];
36 #endif
37 struct RDIR *rdir = (struct RDIR*)calloc(1, sizeof(*rdir));
38
39 if (!rdir)
40 return NULL;
41
42 #if defined(_WIN32)
43 snprintf(path_buf, sizeof(path_buf), "%s\\*", name);
44 rdir->directory = FindFirstFile(path_buf, &rdir->entry);
45 #elif defined(VITA) || defined(PSP)
46 rdir->directory = sceIoDopen(name);
47 #elif defined(_3DS)
48 rdir->directory = (name && *name)? opendir(name) : NULL;
49 rdir->entry = NULL;
50 #else
51 rdir->directory = opendir(name);
52 rdir->entry = NULL;
53 #endif
54
55 return rdir;
56 }
57
retro_dirent_error(struct RDIR * rdir)58 bool retro_dirent_error(struct RDIR *rdir)
59 {
60 #if defined(_WIN32)
61 return (rdir->directory == INVALID_HANDLE_VALUE);
62 #elif defined(VITA) || defined(PSP)
63 return (rdir->directory < 0);
64 #else
65 return !(rdir->directory);
66 #endif
67 }
68
retro_readdir(struct RDIR * rdir)69 int retro_readdir(struct RDIR *rdir)
70 {
71 #if defined(_WIN32)
72 if(rdir->next)
73 return (FindNextFile(rdir->directory, &rdir->entry) != 0);
74 else {
75 rdir->next = true;
76 return (rdir->directory != INVALID_HANDLE_VALUE);
77 }
78 #elif defined(VITA) || defined(PSP)
79 return (sceIoDread(rdir->directory, &rdir->entry) > 0);
80 #else
81 return ((rdir->entry = readdir(rdir->directory)) != NULL);
82 #endif
83 }
84
retro_dirent_get_name(struct RDIR * rdir)85 const char *retro_dirent_get_name(struct RDIR *rdir)
86 {
87 #if defined(_WIN32)
88 return rdir->entry.cFileName;
89 #elif defined(VITA) || defined(PSP)
90 return rdir->entry.d_name;
91 #else
92 return rdir->entry->d_name;
93 #endif
94 }
95
96 /**
97 *
98 * retro_dirent_is_dir:
99 * @rdir : pointer to the directory entry.
100 * @path : path to the directory entry.
101 *
102 * Is the directory listing entry a directory?
103 *
104 * Returns: true if directory listing entry is
105 * a directory, false if not.
106 */
retro_dirent_is_dir(struct RDIR * rdir,const char * path)107 bool retro_dirent_is_dir(struct RDIR *rdir, const char *path)
108 {
109 #if defined(_WIN32)
110 const WIN32_FIND_DATA *entry = (const WIN32_FIND_DATA*)&rdir->entry;
111 return entry->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
112 #elif defined(PSP) || defined(VITA)
113 const SceIoDirent *entry = (const SceIoDirent*)&rdir->entry;
114 #if defined(PSP)
115 return (entry->d_stat.st_attr & FIO_SO_IFDIR) == FIO_SO_IFDIR;
116 #elif defined(VITA)
117 return SCE_S_ISDIR(entry->d_stat.st_mode);
118 #endif
119 #elif defined(DT_DIR)
120 const struct dirent *entry = (const struct dirent*)rdir->entry;
121 if (entry->d_type == DT_DIR)
122 return true;
123 /* This can happen on certain file systems. */
124 if (entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK)
125 return path_is_directory(path);
126 return false;
127 #else
128 /* dirent struct doesn't have d_type, do it the slow way ... */
129 return path_is_directory(path);
130 #endif
131 }
132
retro_closedir(struct RDIR * rdir)133 void retro_closedir(struct RDIR *rdir)
134 {
135 if (!rdir)
136 return;
137
138 #if defined(_WIN32)
139 if (rdir->directory != INVALID_HANDLE_VALUE)
140 FindClose(rdir->directory);
141 #elif defined(VITA) || defined(PSP)
142 sceIoDclose(rdir->directory);
143 #else
144 if (rdir->directory)
145 closedir(rdir->directory);
146 #endif
147
148 free(rdir);
149 }
150