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