Core commit. Compile and run on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-core / src / osal / files_win32.c
CommitLineData
451ab91e 1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus-core - osal/files_win32.c *
3 * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
4 * Copyright (C) 2009 Richard Goedeken *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
20 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21
22/* This file contains the definitions for the unix-specific file handling
23 * functions
24 */
25
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <stdlib.h>
29#include <string.h>
30#include <stdio.h>
31#include <direct.h>
32#include <shlobj.h>
33
34#include "files.h"
35#include "api/m64p_types.h"
36#include "api/callbacks.h"
37
38/* definitions for system directories to search when looking for shared data files */
39#if defined(SHAREDIR)
40 #define XSTR(S) STR(S) /* this wacky preprocessor thing is necessary to generate a quote-enclosed */
41 #define STR(S) #S /* copy of the SHAREDIR macro, which is defined by the makefile via gcc -DSHAREDIR="..." */
42 static const int datasearchdirs = 2;
43 static const char *datasearchpath[2] = { XSTR(SHAREDIR), ".\\" };
44 #undef STR
45 #undef XSTR
46#else
47 static const int datasearchdirs = 1;
48 static const char *datasearchpath[1] = { ".\\" };
49#endif
50
51/* local functions */
52static int search_dir_file(char *destpath, const char *path, const char *filename)
53{
54 struct _stat fileinfo;
55
56 /* sanity check to start */
57 if (destpath == NULL || path == NULL || filename == NULL)
58 return 1;
59
60 /* build the full filepath */
61 strcpy(destpath, path);
62 if (destpath[strlen(destpath)-1] != '\\')
63 strcat(destpath, "\\");
64 strcat(destpath, filename);
65
66 /* test for a valid file */
67 if (_stat(destpath, &fileinfo) != 0)
68 return 2;
69 if ((fileinfo.st_mode & _S_IFREG) == 0)
70 return 3;
71
72 /* success - file exists and is a regular file */
73 return 0;
74}
75
76/* global functions */
77
78int osal_mkdirp(const char *dirpath, int mode)
79{
80 char *mypath, *currpath, *lastchar;
81 struct _stat fileinfo;
82
83 // Create a copy of the path, so we can modify it
84 mypath = currpath = _strdup(dirpath);
85 if (mypath == NULL)
86 return 1;
87
88 // if the directory path ends with a separator, remove it
89 lastchar = mypath + strlen(mypath) - 1;
90 if (strchr(OSAL_DIR_SEPARATORS, *lastchar) != NULL)
91 *lastchar = 0;
92
93 // Terminate quickly if the path already exists
94 if (_stat(mypath, &fileinfo) == 0 && (fileinfo.st_mode & _S_IFDIR))
95 goto goodexit;
96
97 while ((currpath = strpbrk(currpath + 1, OSAL_DIR_SEPARATORS)) != NULL)
98 {
99 // if slash is right after colon, then we are looking at drive name prefix (C:\) and should
100 // just skip it, because _stat and _mkdir will both fail for "C:"
101 if (currpath > mypath && currpath[-1] == ':')
102 continue;
103 *currpath = '\0';
104 if (_stat(mypath, &fileinfo) != 0)
105 {
106 if (_mkdir(mypath) != 0)
107 goto errorexit;
108 }
109 else if (!(fileinfo.st_mode & _S_IFDIR))
110 {
111 goto errorexit;
112 }
113 *currpath = OSAL_DIR_SEPARATORS[0];
114 }
115
116 // Create full path
117 if (_mkdir(mypath) != 0)
118 goto errorexit;
119
120goodexit:
121 free(mypath);
122 return 0;
123errorexit:
124 free(mypath);
125 return 1;
126}
127
128const char * osal_get_shared_filepath(const char *filename, const char *firstsearch, const char *secondsearch)
129{
130 static char retpath[_MAX_PATH];
131 int i;
132
133 /* if caller gave us any directories to search, then look there first */
134 if (firstsearch != NULL && search_dir_file(retpath, firstsearch, filename) == 0)
135 return retpath;
136 if (secondsearch != NULL && search_dir_file(retpath, secondsearch, filename) == 0)
137 return retpath;
138
139 /* otherwise check our standard paths */
140 if (search_dir_file(retpath, osal_get_user_configpath(), filename) == 0)
141 return retpath;
142 for (i = 0; i < datasearchdirs; i++)
143 {
144 if (search_dir_file(retpath, datasearchpath[i], filename) == 0)
145 return retpath;
146 }
147
148 /* we couldn't find the file */
149 return NULL;
150}
151
152const char * osal_get_user_configpath(void)
153{
154 static char chHomePath[MAX_PATH];
155 LPITEMIDLIST pidl;
156 LPMALLOC pMalloc;
157 struct _stat fileinfo;
158
159 // Get item ID list for the path of user's personal directory
160 HRESULT hr = SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidl);
161 // get the path in a char string
162 SHGetPathFromIDList(pidl, chHomePath);
163 // do a bunch of crap just to free some memory
164 hr = SHGetMalloc(&pMalloc);
165 pMalloc->lpVtbl->Free(pMalloc, pidl);
166 pMalloc->lpVtbl->Release(pMalloc);
167
168 // tack on 'mupen64plus'
169 if (chHomePath[strlen(chHomePath)-1] != '\\')
170 strcat(chHomePath, "\\");
171 strcat(chHomePath, "Mupen64Plus");
172
173 // if this directory doesn't exist, then make it
174 if (_stat(chHomePath, &fileinfo) == 0)
175 {
176 strcat(chHomePath, "\\");
177 return chHomePath;
178 }
179 else
180 {
181 osal_mkdirp(chHomePath, 0);
182 if (_stat(chHomePath, &fileinfo) == 0)
183 {
184 strcat(chHomePath, "\\");
185 return chHomePath;
186 }
187 }
188
189 /* otherwise we are in trouble */
190 DebugMessage(M64MSG_ERROR, "Failed to open configuration directory '%s'.", chHomePath);
191 return NULL;
192}
193
194const char * osal_get_user_datapath(void)
195{
196 // in windows, these are all the same
197 return osal_get_user_configpath();
198}
199
200const char * osal_get_user_cachepath(void)
201{
202 // in windows, these are all the same
203 return osal_get_user_configpath();
204}
205
206