/
unix.c
308 lines (234 loc) · 7.48 KB
1
2
3
4
5
6
7
8
/*
* Unix support routines for PhysicsFS.
*
* Please see the file LICENSE in the source's root directory.
*
* This file written by Ryan C. Gordon.
*/
9
10
11
12
#if HAVE_CONFIG_H
# include <config.h>
#endif
13
14
#if (!defined __BEOS__) /* BeOS uses beos.cpp and posix.c ... */
15
16
17
18
19
20
#if ((defined __APPLE__) && (defined __MACH__))
# if (!defined __DARWIN__)
# define __DARWIN__
# endif
#endif
21
22
#include <stdio.h>
#include <stdlib.h>
23
24
#include <string.h>
#include <ctype.h>
25
#include <pthread.h>
26
27
28
29
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <sys/stat.h>
30
#include <sys/param.h>
31
32
33
#include <dirent.h>
#include <time.h>
#include <errno.h>
34
35
36
37
#if (!defined __DARWIN__)
#include <mntent.h>
#else
38
39
#include <sys/ucred.h>
#endif
40
41
42
43
#include <sys/mount.h>
44
45
46
47
48
49
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
const char *__PHYSFS_platformDirSeparator = "/";
50
51
52
53
54
55
56
57
58
59
60
61
62
63
int __PHYSFS_platformInit(void)
{
return(1); /* always succeed. */
} /* __PHYSFS_platformInit */
int __PHYSFS_platformDeinit(void)
{
return(1); /* always succeed. */
} /* __PHYSFS_platformDeinit */
64
65
66
67
68
69
70
71
72
73
#if (defined __DARWIN__)
char **__PHYSFS_platformDetectAvailableCDs(void)
{
char **retval = (char **) malloc(sizeof (char *));
int cd_count = 1; /* We count the NULL entry. */
struct statfs* mntbufp = NULL;
int mounts;
int ii;
74
75
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
76
77
78
79
80
81
82
mounts = getmntinfo( &mntbufp, MNT_WAIT );
for ( ii=0; ii < mounts; ++ii ) {
int add_it = 0;
if ( strcmp( mntbufp[ii].f_fstypename, "iso9660") == 0 )
add_it = 1;
83
84
else if ( strcmp( mntbufp[ii].f_fstypename, "cd9660") == 0 )
add_it = 1;
85
86
/* add other mount types here */
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
if (add_it)
{
char **tmp = realloc(retval, sizeof (char *) * cd_count + 1);
if (tmp)
{
retval = tmp;
retval[cd_count-1] = (char *)
malloc(strlen(mntbufp[ ii ].f_mntonname) + 1);
if (retval[cd_count-1])
{
strcpy(retval[cd_count-1], mntbufp[ ii ].f_mntonname);
cd_count++;
} /* if */
} /* if */
} /* if */
}
retval[cd_count - 1] = NULL;
return(retval);
} /* __PHYSFS_platformDetectAvailableCDs */
#else /* non-Darwin implementation... */
113
114
char **__PHYSFS_platformDetectAvailableCDs(void)
{
115
116
117
118
119
char **retval = (char **) malloc(sizeof (char *));
int cd_count = 1; /* We count the NULL entry. */
FILE *mounts = NULL;
struct mntent *ent = NULL;
120
121
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
122
123
124
125
126
127
128
129
130
*retval = NULL;
mounts = setmntent("/etc/mtab", "r");
BAIL_IF_MACRO(mounts == NULL, ERR_IO_ERROR, retval);
while ( (ent = getmntent(mounts)) != NULL )
{
int add_it = 0;
if (strcmp(ent->mnt_type, "iso9660") == 0)
add_it = 1;
131
132
/* add other mount types here */
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
if (add_it)
{
char **tmp = realloc(retval, sizeof (char *) * cd_count + 1);
if (tmp)
{
retval = tmp;
retval[cd_count-1] = (char *) malloc(strlen(ent->mnt_dir) + 1);
if (retval[cd_count-1])
{
strcpy(retval[cd_count-1], ent->mnt_dir);
cd_count++;
} /* if */
} /* if */
} /* if */
} /* while */
endmntent(mounts);
151
152
retval[cd_count - 1] = NULL;
153
return(retval);
154
155
156
} /* __PHYSFS_platformDetectAvailableCDs */
#endif
157
158
159
160
/* this is in posix.c ... */
extern char *__PHYSFS_platformCopyEnvironmentVariable(const char *varname);
161
162
163
164
165
166
167
168
169
170
171
172
/*
* See where program (bin) resides in the $PATH specified by (envr).
* returns a copy of the first element in envr that contains it, or NULL
* if it doesn't exist or there were other problems. PHYSFS_SetError() is
* called if we have a problem.
*
* (envr) will be scribbled over, and you are expected to free() the
* return value when you're done with it.
*/
static char *findBinaryInPath(const char *bin, char *envr)
173
{
174
175
176
size_t alloc_size = 0;
char *exe = NULL;
char *start = envr;
177
178
char *ptr;
179
180
BAIL_IF_MACRO(bin == NULL, ERR_INVALID_ARGUMENT, NULL);
BAIL_IF_MACRO(envr == NULL, ERR_INVALID_ARGUMENT, NULL);
181
182
183
do
{
184
185
size_t size;
ptr = strchr(start, ':'); /* find next $PATH separator. */
186
187
188
if (ptr)
*ptr = '\0';
189
190
size = strlen(start) + strlen(bin) + 2;
if (size > alloc_size)
191
{
192
193
194
195
196
197
198
199
200
201
char *x = (char *) realloc(exe, size);
if (x == NULL)
{
if (exe != NULL)
free(exe);
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
} /* if */
alloc_size = size;
exe = x;
202
} /* if */
203
204
/* build full binary path... */
205
strcpy(exe, start);
206
207
if (exe[strlen(exe) - 1] != '/')
strcat(exe, "/");
208
209
210
strcat(exe, bin);
if (access(exe, X_OK) == 0) /* Exists as executable? We're done. */
211
{
212
213
214
strcpy(exe, start); /* i'm lazy. piss off. */
return(exe);
} /* if */
215
216
start = ptr + 1; /* start points to beginning of next element. */
217
218
} while (ptr != NULL);
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
if (exe != NULL)
free(exe);
return(NULL); /* doesn't exist in path. */
} /* findBinaryInPath */
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
{
/* If there isn't a path on argv0, then look through the $PATH for it. */
char *retval;
char *envr;
if (strchr(argv0, '/') != NULL) /* default behaviour can handle this. */
return(NULL);
236
envr = __PHYSFS_platformCopyEnvironmentVariable("PATH");
237
238
BAIL_IF_MACRO(!envr, NULL, NULL);
retval = findBinaryInPath(argv0, envr);
239
240
241
242
243
free(envr);
return(retval);
} /* __PHYSFS_platformCalcBaseDir */
244
PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
245
{
246
return((PHYSFS_uint64) ((PHYSFS_uint32) pthread_self()));
247
248
249
} /* __PHYSFS_platformGetThreadID */
250
251
252
/* Much like my college days, try to sleep for 10 milliseconds at a time... */
void __PHYSFS_platformTimeslice(void)
{
253
usleep( 10 * 1000 ); /* don't care if it fails. */
254
255
256
} /* __PHYSFS_platformTimeslice */
257
258
259
260
261
262
263
char *__PHYSFS_platformRealPath(const char *path)
{
char resolved_path[MAXPATHLEN];
char *retval = NULL;
errno = 0;
BAIL_IF_MACRO(!realpath(path, resolved_path), strerror(errno), NULL);
264
retval = (char *) malloc(strlen(resolved_path) + 1);
265
266
267
268
269
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
strcpy(retval, resolved_path);
return(retval);
} /* __PHYSFS_platformRealPath */
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
void *__PHYSFS_platformCreateMutex(void)
{
int rc;
pthread_mutex_t *m = (pthread_mutex_t *) malloc(sizeof (pthread_mutex_t));
BAIL_IF_MACRO(m == NULL, ERR_OUT_OF_MEMORY, NULL);
rc = pthread_mutex_init(m, NULL);
if (rc != 0)
{
free(m);
BAIL_MACRO(strerror(rc), NULL);
} /* if */
return((void *) m);
} /* __PHYSFS_platformCreateMutex */
void __PHYSFS_platformDestroyMutex(void *mutex)
{
pthread_mutex_destroy((pthread_mutex_t *) mutex);
free(mutex);
} /* __PHYSFS_platformDestroyMutex */
int __PHYSFS_platformGrabMutex(void *mutex)
{
return(pthread_mutex_lock((pthread_mutex_t *) mutex) == 0);
} /* __PHYSFS_platformGrabMutex */
void __PHYSFS_platformReleaseMutex(void *mutex)
{
pthread_mutex_unlock((pthread_mutex_t *) mutex);
} /* __PHYSFS_platformReleaseMutex */
305
306
#endif /* !defined __BEOS__ */
307
/* end of unix.c ... */