Skip to content

Latest commit

 

History

History
314 lines (238 loc) · 7.62 KB

unix.c

File metadata and controls

314 lines (238 loc) · 7.62 KB
 
Jul 7, 2001
Jul 7, 2001
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.
*/
May 10, 2002
May 10, 2002
9
10
11
12
#if HAVE_CONFIG_H
# include <config.h>
#endif
May 24, 2002
May 24, 2002
13
14
#if (!defined __BEOS__) /* BeOS uses beos.cpp and posix.c ... */
Jun 29, 2002
Jun 29, 2002
15
16
17
18
#if (defined WIN32) /* cygwin/mingw32? */
#include "win32.c" /* !!! FIXME: holy friggin' hack. */
#else
Mar 5, 2002
Mar 5, 2002
19
20
21
22
23
24
#if ((defined __APPLE__) && (defined __MACH__))
# if (!defined __DARWIN__)
# define __DARWIN__
# endif
#endif
Jul 7, 2001
Jul 7, 2001
25
26
#include <stdio.h>
#include <stdlib.h>
Jul 8, 2001
Jul 8, 2001
27
28
#include <string.h>
#include <ctype.h>
Jul 7, 2001
Jul 7, 2001
29
#include <pthread.h>
Jul 8, 2001
Jul 8, 2001
30
31
32
33
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <sys/stat.h>
Jul 16, 2001
Jul 16, 2001
34
#include <sys/param.h>
Jul 8, 2001
Jul 8, 2001
35
36
37
#include <dirent.h>
#include <time.h>
#include <errno.h>
Mar 5, 2002
Mar 5, 2002
38
Apr 6, 2002
Apr 6, 2002
39
40
41
#if (!defined __DARWIN__)
#include <mntent.h>
#else
Mar 5, 2002
Mar 5, 2002
42
43
#include <sys/ucred.h>
#endif
Jul 7, 2001
Jul 7, 2001
44
Apr 6, 2002
Apr 6, 2002
45
46
47
#include <sys/mount.h>
Jul 7, 2001
Jul 7, 2001
48
49
50
51
52
53
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
const char *__PHYSFS_platformDirSeparator = "/";
Mar 5, 2002
Mar 5, 2002
54
Mar 24, 2002
Mar 24, 2002
55
56
57
58
59
60
61
62
63
64
65
66
67
int __PHYSFS_platformInit(void)
{
return(1); /* always succeed. */
} /* __PHYSFS_platformInit */
int __PHYSFS_platformDeinit(void)
{
return(1); /* always succeed. */
} /* __PHYSFS_platformDeinit */
Mar 5, 2002
Mar 5, 2002
68
69
70
71
72
73
74
75
76
77
#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;
Apr 5, 2002
Apr 5, 2002
78
79
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
Mar 5, 2002
Mar 5, 2002
80
81
82
83
84
85
86
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;
Apr 6, 2002
Apr 6, 2002
87
88
else if ( strcmp( mntbufp[ii].f_fstypename, "cd9660") == 0 )
add_it = 1;
May 21, 2002
May 21, 2002
89
90
/* add other mount types here */
Mar 5, 2002
Mar 5, 2002
91
92
93
if (add_it)
{
Jun 29, 2002
Jun 29, 2002
94
char **tmp = realloc(retval, sizeof (char *) * (cd_count + 1));
Mar 5, 2002
Mar 5, 2002
95
96
97
if (tmp)
{
retval = tmp;
Jun 29, 2002
Jun 29, 2002
98
99
100
retval[cd_count - 1] = (char *)
malloc(strlen(mntbufp[ii].f_mntonname) + 1);
if (retval[cd_count - 1])
Mar 5, 2002
Mar 5, 2002
101
{
Jun 29, 2002
Jun 29, 2002
102
strcpy(retval[cd_count - 1], mntbufp[ii].f_mntonname);
Mar 5, 2002
Mar 5, 2002
103
104
105
106
107
108
109
110
111
112
113
114
115
116
cd_count++;
} /* if */
} /* if */
} /* if */
}
retval[cd_count - 1] = NULL;
return(retval);
} /* __PHYSFS_platformDetectAvailableCDs */
#else /* non-Darwin implementation... */
Jul 7, 2001
Jul 7, 2001
117
118
char **__PHYSFS_platformDetectAvailableCDs(void)
{
Aug 7, 2001
Aug 7, 2001
119
120
121
122
123
char **retval = (char **) malloc(sizeof (char *));
int cd_count = 1; /* We count the NULL entry. */
FILE *mounts = NULL;
struct mntent *ent = NULL;
Apr 5, 2002
Apr 5, 2002
124
125
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
Aug 7, 2001
Aug 7, 2001
126
127
128
129
130
131
132
133
134
*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;
May 21, 2002
May 21, 2002
135
136
/* add other mount types here */
Aug 7, 2001
Aug 7, 2001
137
138
139
if (add_it)
{
Jun 29, 2002
Jun 29, 2002
140
char **tmp = realloc(retval, sizeof (char *) * (cd_count + 1));
Aug 7, 2001
Aug 7, 2001
141
142
143
144
if (tmp)
{
retval = tmp;
retval[cd_count-1] = (char *) malloc(strlen(ent->mnt_dir) + 1);
Jun 29, 2002
Jun 29, 2002
145
if (retval[cd_count - 1])
Aug 7, 2001
Aug 7, 2001
146
{
Jun 29, 2002
Jun 29, 2002
147
strcpy(retval[cd_count - 1], ent->mnt_dir);
Aug 7, 2001
Aug 7, 2001
148
149
150
151
152
153
154
cd_count++;
} /* if */
} /* if */
} /* if */
} /* while */
endmntent(mounts);
Jul 8, 2001
Jul 8, 2001
155
Aug 7, 2001
Aug 7, 2001
156
retval[cd_count - 1] = NULL;
Jul 8, 2001
Jul 8, 2001
157
return(retval);
Mar 5, 2002
Mar 5, 2002
158
159
160
} /* __PHYSFS_platformDetectAvailableCDs */
#endif
Jul 7, 2001
Jul 7, 2001
161
162
May 24, 2002
May 24, 2002
163
164
/* this is in posix.c ... */
extern char *__PHYSFS_platformCopyEnvironmentVariable(const char *varname);
Jul 8, 2001
Jul 8, 2001
165
166
May 21, 2002
May 21, 2002
167
168
169
170
171
172
173
174
175
176
/*
* 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)
Jul 8, 2001
Jul 8, 2001
177
{
May 21, 2002
May 21, 2002
178
179
180
size_t alloc_size = 0;
char *exe = NULL;
char *start = envr;
Jul 8, 2001
Jul 8, 2001
181
182
char *ptr;
May 21, 2002
May 21, 2002
183
184
BAIL_IF_MACRO(bin == NULL, ERR_INVALID_ARGUMENT, NULL);
BAIL_IF_MACRO(envr == NULL, ERR_INVALID_ARGUMENT, NULL);
Jul 8, 2001
Jul 8, 2001
185
186
187
do
{
May 21, 2002
May 21, 2002
188
189
size_t size;
ptr = strchr(start, ':'); /* find next $PATH separator. */
Jul 8, 2001
Jul 8, 2001
190
191
192
if (ptr)
*ptr = '\0';
May 21, 2002
May 21, 2002
193
194
size = strlen(start) + strlen(bin) + 2;
if (size > alloc_size)
Jul 8, 2001
Jul 8, 2001
195
{
May 21, 2002
May 21, 2002
196
197
198
199
200
201
202
203
204
205
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;
Jul 8, 2001
Jul 8, 2001
206
} /* if */
May 21, 2002
May 21, 2002
207
208
/* build full binary path... */
Jul 8, 2001
Jul 8, 2001
209
strcpy(exe, start);
Aug 29, 2001
Aug 29, 2001
210
211
if (exe[strlen(exe) - 1] != '/')
strcat(exe, "/");
May 21, 2002
May 21, 2002
212
213
214
strcat(exe, bin);
if (access(exe, X_OK) == 0) /* Exists as executable? We're done. */
Jul 8, 2001
Jul 8, 2001
215
{
May 21, 2002
May 21, 2002
216
217
218
strcpy(exe, start); /* i'm lazy. piss off. */
return(exe);
} /* if */
Jul 8, 2001
Jul 8, 2001
219
May 21, 2002
May 21, 2002
220
start = ptr + 1; /* start points to beginning of next element. */
Jul 8, 2001
Jul 8, 2001
221
222
} while (ptr != NULL);
May 21, 2002
May 21, 2002
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
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);
May 24, 2002
May 24, 2002
240
envr = __PHYSFS_platformCopyEnvironmentVariable("PATH");
May 21, 2002
May 21, 2002
241
242
BAIL_IF_MACRO(!envr, NULL, NULL);
retval = findBinaryInPath(argv0, envr);
Jul 8, 2001
Jul 8, 2001
243
244
245
246
247
free(envr);
return(retval);
} /* __PHYSFS_platformCalcBaseDir */
Mar 24, 2002
Mar 24, 2002
248
PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
Jul 7, 2001
Jul 7, 2001
249
{
Apr 6, 2002
Apr 6, 2002
250
return((PHYSFS_uint64) ((PHYSFS_uint32) pthread_self()));
Jul 7, 2001
Jul 7, 2001
251
252
253
} /* __PHYSFS_platformGetThreadID */
Jul 8, 2001
Jul 8, 2001
254
255
256
/* Much like my college days, try to sleep for 10 milliseconds at a time... */
void __PHYSFS_platformTimeslice(void)
{
Mar 5, 2002
Mar 5, 2002
257
usleep( 10 * 1000 ); /* don't care if it fails. */
Jul 8, 2001
Jul 8, 2001
258
259
260
} /* __PHYSFS_platformTimeslice */
Jul 16, 2001
Jul 16, 2001
261
262
263
264
265
266
267
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);
May 24, 2002
May 24, 2002
268
retval = (char *) malloc(strlen(resolved_path) + 1);
Jul 16, 2001
Jul 16, 2001
269
270
271
272
273
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
strcpy(retval, resolved_path);
return(retval);
} /* __PHYSFS_platformRealPath */
Aug 23, 2001
Aug 23, 2001
274
Mar 30, 2002
Mar 30, 2002
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
305
306
307
308
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 */
Jun 29, 2002
Jun 29, 2002
309
310
#endif /* win32 check. */
May 24, 2002
May 24, 2002
311
312
#endif /* !defined __BEOS__ */
Jul 7, 2001
Jul 7, 2001
313
/* end of unix.c ... */