Skip to content

Latest commit

 

History

History
296 lines (232 loc) · 7.57 KB

platform_unix.c

File metadata and controls

296 lines (232 loc) · 7.57 KB
 
Jul 7, 2001
Jul 7, 2001
1
2
3
/*
* Unix support routines for PhysicsFS.
*
Mar 11, 2007
Mar 11, 2007
4
* Please see the file LICENSE.txt in the source's root directory.
Jul 7, 2001
Jul 7, 2001
5
6
7
8
*
* This file written by Ryan C. Gordon.
*/
Mar 11, 2007
Mar 11, 2007
9
10
11
12
#define __PHYSICSFS_INTERNAL__
#include "physfs_platforms.h"
#ifdef PHYSFS_PLATFORM_UNIX
Jun 29, 2002
Jun 29, 2002
13
Jul 8, 2001
Jul 8, 2001
14
15
16
17
18
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <sys/stat.h>
Jul 16, 2001
Jul 16, 2001
19
#include <sys/param.h>
Jul 8, 2001
Jul 8, 2001
20
21
22
#include <dirent.h>
#include <time.h>
#include <errno.h>
Mar 5, 2002
Mar 5, 2002
23
Jul 20, 2002
Jul 20, 2002
24
25
26
27
#ifdef PHYSFS_HAVE_SYS_UCRED_H
# ifdef PHYSFS_HAVE_MNTENT_H
# undef PHYSFS_HAVE_MNTENT_H /* don't do both... */
# endif
May 3, 2009
May 3, 2009
28
# include <sys/mount.h>
Jul 20, 2002
Jul 20, 2002
29
# include <sys/ucred.h>
Mar 5, 2002
Mar 5, 2002
30
#endif
Jul 7, 2001
Jul 7, 2001
31
Jul 20, 2002
Jul 20, 2002
32
33
34
#ifdef PHYSFS_HAVE_MNTENT_H
#include <mntent.h>
#endif
Apr 6, 2002
Apr 6, 2002
35
Apr 13, 2009
Apr 13, 2009
36
37
38
39
#ifdef PHYSFS_HAVE_SYS_MNTTAB_H
#include <sys/mnttab.h>
#endif
Jul 7, 2001
Jul 7, 2001
40
41
#include "physfs_internal.h"
Mar 24, 2002
Mar 24, 2002
42
43
int __PHYSFS_platformInit(void)
{
Jan 28, 2010
Jan 28, 2010
44
return 1; /* always succeed. */
Mar 24, 2002
Mar 24, 2002
45
46
47
48
49
} /* __PHYSFS_platformInit */
int __PHYSFS_platformDeinit(void)
{
Jan 28, 2010
Jan 28, 2010
50
return 1; /* always succeed. */
Mar 24, 2002
Mar 24, 2002
51
52
53
} /* __PHYSFS_platformDeinit */
Jul 25, 2002
Jul 25, 2002
54
/* Stub version for platforms without CD-ROM support. */
Sep 29, 2004
Sep 29, 2004
55
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
Jul 25, 2002
Jul 25, 2002
56
{
Apr 13, 2009
Apr 13, 2009
57
58
#if (defined PHYSFS_NO_CDROM_SUPPORT)
/* no-op. */
Jul 25, 2002
Jul 25, 2002
59
May 24, 2003
May 24, 2003
60
#elif (defined PHYSFS_HAVE_SYS_UCRED_H)
Jul 25, 2002
Jul 25, 2002
61
int i;
Sep 29, 2004
Sep 29, 2004
62
63
struct statfs *mntbufp = NULL;
int mounts = getmntinfo(&mntbufp, MNT_WAIT);
Mar 5, 2002
Mar 5, 2002
64
Jul 25, 2002
Jul 25, 2002
65
66
for (i = 0; i < mounts; i++)
{
Mar 5, 2002
Mar 5, 2002
67
68
int add_it = 0;
Jul 25, 2002
Jul 25, 2002
69
if (strcmp(mntbufp[i].f_fstypename, "iso9660") == 0)
Mar 5, 2002
Mar 5, 2002
70
add_it = 1;
Jul 25, 2002
Jul 25, 2002
71
else if (strcmp( mntbufp[i].f_fstypename, "cd9660") == 0)
Apr 6, 2002
Apr 6, 2002
72
add_it = 1;
May 21, 2002
May 21, 2002
73
74
/* add other mount types here */
Mar 5, 2002
Mar 5, 2002
75
76
if (add_it)
Sep 29, 2004
Sep 29, 2004
77
cb(data, mntbufp[i].f_mntonname);
Jul 25, 2002
Jul 25, 2002
78
} /* for */
Mar 5, 2002
Mar 5, 2002
79
May 24, 2003
May 24, 2003
80
#elif (defined PHYSFS_HAVE_MNTENT_H)
Aug 7, 2001
Aug 7, 2001
81
82
83
84
FILE *mounts = NULL;
struct mntent *ent = NULL;
mounts = setmntent("/etc/mtab", "r");
Mar 13, 2005
Mar 13, 2005
85
BAIL_IF_MACRO(mounts == NULL, ERR_IO_ERROR, /*return void*/);
Aug 7, 2001
Aug 7, 2001
86
87
88
89
90
91
while ( (ent = getmntent(mounts)) != NULL )
{
int add_it = 0;
if (strcmp(ent->mnt_type, "iso9660") == 0)
add_it = 1;
Mar 22, 2010
Mar 22, 2010
92
93
94
95
96
97
98
99
else if (strcmp(ent->mnt_type, "udf") == 0)
add_it = 1;
/* !!! FIXME: these might pick up floppy drives, right? */
else if (strcmp(ent->mnt_type, "auto") == 0)
add_it = 1;
else if (strcmp(ent->mnt_type, "supermount") == 0)
add_it = 1;
May 21, 2002
May 21, 2002
100
Mar 1, 2010
Mar 1, 2010
101
102
/* !!! FIXME: udf? automount? */
May 21, 2002
May 21, 2002
103
/* add other mount types here */
Aug 7, 2001
Aug 7, 2001
104
105
if (add_it)
Sep 29, 2004
Sep 29, 2004
106
cb(data, ent->mnt_dir);
Aug 7, 2001
Aug 7, 2001
107
108
109
} /* while */
endmntent(mounts);
Apr 13, 2009
Apr 13, 2009
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#elif (defined PHYSFS_HAVE_SYS_MNTTAB_H)
FILE *mounts = fopen(MNTTAB, "r");
struct mnttab ent;
BAIL_IF_MACRO(mounts == NULL, ERR_IO_ERROR, /*return void*/);
while (getmntent(mounts, &ent) == 0)
{
int add_it = 0;
if (strcmp(ent.mnt_fstype, "hsfs") == 0)
add_it = 1;
/* add other mount types here */
if (add_it)
cb(data, ent.mnt_mountp);
} /* while */
fclose(mounts);
#else
#error Unknown platform. Should have defined PHYSFS_NO_CDROM_SUPPORT, perhaps.
Mar 5, 2002
Mar 5, 2002
132
#endif
Apr 13, 2009
Apr 13, 2009
133
} /* __PHYSFS_platformDetectAvailableCDs */
Jul 7, 2001
Jul 7, 2001
134
135
May 24, 2002
May 24, 2002
136
137
/* this is in posix.c ... */
extern char *__PHYSFS_platformCopyEnvironmentVariable(const char *varname);
Jul 8, 2001
Jul 8, 2001
138
139
May 21, 2002
May 21, 2002
140
141
142
143
144
145
/*
* 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.
*
Mar 14, 2005
Mar 14, 2005
146
* (envr) will be scribbled over, and you are expected to allocator.Free() the
May 21, 2002
May 21, 2002
147
148
149
* return value when you're done with it.
*/
static char *findBinaryInPath(const char *bin, char *envr)
Jul 8, 2001
Jul 8, 2001
150
{
May 21, 2002
May 21, 2002
151
152
153
size_t alloc_size = 0;
char *exe = NULL;
char *start = envr;
Jul 8, 2001
Jul 8, 2001
154
155
char *ptr;
May 21, 2002
May 21, 2002
156
157
BAIL_IF_MACRO(bin == NULL, ERR_INVALID_ARGUMENT, NULL);
BAIL_IF_MACRO(envr == NULL, ERR_INVALID_ARGUMENT, NULL);
Jul 8, 2001
Jul 8, 2001
158
159
160
do
{
May 21, 2002
May 21, 2002
161
162
size_t size;
ptr = strchr(start, ':'); /* find next $PATH separator. */
Jul 8, 2001
Jul 8, 2001
163
164
165
if (ptr)
*ptr = '\0';
May 21, 2002
May 21, 2002
166
167
size = strlen(start) + strlen(bin) + 2;
if (size > alloc_size)
Jul 8, 2001
Jul 8, 2001
168
{
Mar 14, 2005
Mar 14, 2005
169
char *x = (char *) allocator.Realloc(exe, size);
May 21, 2002
May 21, 2002
170
171
172
if (x == NULL)
{
if (exe != NULL)
Mar 14, 2005
Mar 14, 2005
173
allocator.Free(exe);
May 21, 2002
May 21, 2002
174
175
176
177
178
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
} /* if */
alloc_size = size;
exe = x;
Jul 8, 2001
Jul 8, 2001
179
} /* if */
May 21, 2002
May 21, 2002
180
181
/* build full binary path... */
Jul 8, 2001
Jul 8, 2001
182
strcpy(exe, start);
Nov 30, 2002
Nov 30, 2002
183
if ((exe[0] == '\0') || (exe[strlen(exe) - 1] != '/'))
Aug 29, 2001
Aug 29, 2001
184
strcat(exe, "/");
May 21, 2002
May 21, 2002
185
186
187
strcat(exe, bin);
if (access(exe, X_OK) == 0) /* Exists as executable? We're done. */
Jul 8, 2001
Jul 8, 2001
188
{
May 21, 2002
May 21, 2002
189
strcpy(exe, start); /* i'm lazy. piss off. */
Jan 28, 2010
Jan 28, 2010
190
return exe;
May 21, 2002
May 21, 2002
191
} /* if */
Jul 8, 2001
Jul 8, 2001
192
May 21, 2002
May 21, 2002
193
start = ptr + 1; /* start points to beginning of next element. */
Jul 8, 2001
Jul 8, 2001
194
195
} while (ptr != NULL);
May 21, 2002
May 21, 2002
196
if (exe != NULL)
Mar 14, 2005
Mar 14, 2005
197
allocator.Free(exe);
May 21, 2002
May 21, 2002
198
Jan 28, 2010
Jan 28, 2010
199
return NULL; /* doesn't exist in path. */
May 21, 2002
May 21, 2002
200
201
202
} /* findBinaryInPath */
Jul 8, 2009
Jul 8, 2009
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
static char *readSymLink(const char *path)
{
ssize_t len = 64;
ssize_t rc = -1;
char *retval = NULL;
while (1)
{
char *ptr = (char *) allocator.Realloc(retval, (size_t) len);
if (ptr == NULL)
break; /* out of memory. */
retval = ptr;
rc = readlink(path, retval, len);
if (rc == -1)
break; /* not a symlink, i/o error, etc. */
else if (rc < len)
{
retval[rc] = '\0'; /* readlink doesn't null-terminate. */
return retval; /* we're good to go. */
} /* else if */
len *= 2; /* grow buffer, try again. */
} /* while */
if (retval != NULL)
allocator.Free(retval);
return NULL;
} /* readSymLink */
May 21, 2002
May 21, 2002
235
236
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
{
Mar 19, 2007
Mar 19, 2007
237
238
239
240
241
char *retval = NULL;
char *envr = NULL;
/* fast path: default behaviour can handle this. */
if ( (argv0 != NULL) && (strchr(argv0, '/') != NULL) )
Jan 28, 2010
Jan 28, 2010
242
return NULL; /* higher level will parse out real path from argv0. */
May 21, 2002
May 21, 2002
243
Mar 19, 2007
Mar 19, 2007
244
245
246
247
248
/*
* Try to avoid using argv0 unless forced to. If there's a Linux-like
* /proc filesystem, you can get the full path to the current process from
* the /proc/self/exe symlink.
*/
Jul 8, 2009
Jul 8, 2009
249
retval = readSymLink("/proc/self/exe");
Jul 8, 2009
Jul 8, 2009
250
251
252
253
254
255
256
257
258
259
if (retval == NULL)
{
/* older kernels don't have /proc/self ... try PID version... */
const unsigned long long pid = (unsigned long long) getpid();
char path[64];
const int rc = (int) snprintf(path,sizeof(path),"/proc/%llu/exe",pid);
if ( (rc > 0) && (rc < sizeof(path)) )
retval = readSymLink(path);
} /* if */
Jul 8, 2009
Jul 8, 2009
260
if (retval != NULL) /* chop off filename. */
Mar 19, 2007
Mar 19, 2007
261
{
Jul 8, 2009
Jul 8, 2009
262
263
264
char *ptr = strrchr(retval, '/');
if (ptr != NULL)
*ptr = '\0';
Mar 19, 2007
Mar 19, 2007
265
} /* if */
May 21, 2002
May 21, 2002
266
Mar 19, 2007
Mar 19, 2007
267
268
269
270
271
272
273
274
if ((retval == NULL) && (argv0 != NULL))
{
/* If there's no dirsep on argv0, then look through $PATH for it. */
envr = __PHYSFS_platformCopyEnvironmentVariable("PATH");
BAIL_IF_MACRO(!envr, NULL, NULL);
retval = findBinaryInPath(argv0, envr);
allocator.Free(envr);
} /* if */
May 21, 2002
May 21, 2002
275
Jul 8, 2009
Jul 8, 2009
276
277
278
279
280
281
282
283
if (retval != NULL)
{
/* try to shrink buffer... */
char *ptr = (char *) allocator.Realloc(retval, strlen(retval) + 1);
if (ptr != NULL)
retval = ptr; /* oh well if it failed. */
} /* if */
Jan 28, 2010
Jan 28, 2010
284
return retval;
Jul 8, 2001
Jul 8, 2001
285
286
287
} /* __PHYSFS_platformCalcBaseDir */
Mar 20, 2007
Mar 20, 2007
288
289
int __PHYSFS_platformSetDefaultAllocator(PHYSFS_Allocator *a)
{
Jan 28, 2010
Jan 28, 2010
290
return 0; /* just use malloc() and friends. */
Mar 20, 2007
Mar 20, 2007
291
292
} /* __PHYSFS_platformSetDefaultAllocator */
Mar 11, 2007
Mar 11, 2007
293
#endif /* PHYSFS_PLATFORM_UNIX */
May 24, 2002
May 24, 2002
294
Jul 7, 2001
Jul 7, 2001
295
/* end of unix.c ... */