Skip to content

Latest commit

 

History

History
301 lines (236 loc) · 7.69 KB

platform_unix.c

File metadata and controls

301 lines (236 loc) · 7.69 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 15, 2010
Mar 15, 2010
42
43
44
45
/* !!! FIXME: we should probably remove MAXPATHLEN entirely, if we can. */
#ifndef MAXPATHLEN
#define MAXPATHLEN 1024
#endif
Mar 5, 2002
Mar 5, 2002
46
Mar 24, 2002
Mar 24, 2002
47
48
int __PHYSFS_platformInit(void)
{
Jan 28, 2010
Jan 28, 2010
49
return 1; /* always succeed. */
Mar 24, 2002
Mar 24, 2002
50
51
52
53
54
} /* __PHYSFS_platformInit */
int __PHYSFS_platformDeinit(void)
{
Jan 28, 2010
Jan 28, 2010
55
return 1; /* always succeed. */
Mar 24, 2002
Mar 24, 2002
56
57
58
} /* __PHYSFS_platformDeinit */
Jul 25, 2002
Jul 25, 2002
59
/* Stub version for platforms without CD-ROM support. */
Sep 29, 2004
Sep 29, 2004
60
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
Jul 25, 2002
Jul 25, 2002
61
{
Apr 13, 2009
Apr 13, 2009
62
63
#if (defined PHYSFS_NO_CDROM_SUPPORT)
/* no-op. */
Jul 25, 2002
Jul 25, 2002
64
May 24, 2003
May 24, 2003
65
#elif (defined PHYSFS_HAVE_SYS_UCRED_H)
Jul 25, 2002
Jul 25, 2002
66
int i;
Sep 29, 2004
Sep 29, 2004
67
68
struct statfs *mntbufp = NULL;
int mounts = getmntinfo(&mntbufp, MNT_WAIT);
Mar 5, 2002
Mar 5, 2002
69
Jul 25, 2002
Jul 25, 2002
70
71
for (i = 0; i < mounts; i++)
{
Mar 5, 2002
Mar 5, 2002
72
73
int add_it = 0;
Jul 25, 2002
Jul 25, 2002
74
if (strcmp(mntbufp[i].f_fstypename, "iso9660") == 0)
Mar 5, 2002
Mar 5, 2002
75
add_it = 1;
Jul 25, 2002
Jul 25, 2002
76
else if (strcmp( mntbufp[i].f_fstypename, "cd9660") == 0)
Apr 6, 2002
Apr 6, 2002
77
add_it = 1;
May 21, 2002
May 21, 2002
78
79
/* add other mount types here */
Mar 5, 2002
Mar 5, 2002
80
81
if (add_it)
Sep 29, 2004
Sep 29, 2004
82
cb(data, mntbufp[i].f_mntonname);
Jul 25, 2002
Jul 25, 2002
83
} /* for */
Mar 5, 2002
Mar 5, 2002
84
May 24, 2003
May 24, 2003
85
#elif (defined PHYSFS_HAVE_MNTENT_H)
Aug 7, 2001
Aug 7, 2001
86
87
88
89
FILE *mounts = NULL;
struct mntent *ent = NULL;
mounts = setmntent("/etc/mtab", "r");
Mar 13, 2005
Mar 13, 2005
90
BAIL_IF_MACRO(mounts == NULL, ERR_IO_ERROR, /*return void*/);
Aug 7, 2001
Aug 7, 2001
91
92
93
94
95
96
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
97
98
99
100
101
102
103
104
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
105
Mar 1, 2010
Mar 1, 2010
106
107
/* !!! FIXME: udf? automount? */
May 21, 2002
May 21, 2002
108
/* add other mount types here */
Aug 7, 2001
Aug 7, 2001
109
110
if (add_it)
Sep 29, 2004
Sep 29, 2004
111
cb(data, ent->mnt_dir);
Aug 7, 2001
Aug 7, 2001
112
113
114
} /* while */
endmntent(mounts);
Apr 13, 2009
Apr 13, 2009
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#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
137
#endif
Apr 13, 2009
Apr 13, 2009
138
} /* __PHYSFS_platformDetectAvailableCDs */
Jul 7, 2001
Jul 7, 2001
139
140
May 24, 2002
May 24, 2002
141
142
/* this is in posix.c ... */
extern char *__PHYSFS_platformCopyEnvironmentVariable(const char *varname);
Jul 8, 2001
Jul 8, 2001
143
144
May 21, 2002
May 21, 2002
145
146
147
148
149
150
/*
* 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
151
* (envr) will be scribbled over, and you are expected to allocator.Free() the
May 21, 2002
May 21, 2002
152
153
154
* return value when you're done with it.
*/
static char *findBinaryInPath(const char *bin, char *envr)
Jul 8, 2001
Jul 8, 2001
155
{
May 21, 2002
May 21, 2002
156
157
158
size_t alloc_size = 0;
char *exe = NULL;
char *start = envr;
Jul 8, 2001
Jul 8, 2001
159
160
char *ptr;
May 21, 2002
May 21, 2002
161
162
BAIL_IF_MACRO(bin == NULL, ERR_INVALID_ARGUMENT, NULL);
BAIL_IF_MACRO(envr == NULL, ERR_INVALID_ARGUMENT, NULL);
Jul 8, 2001
Jul 8, 2001
163
164
165
do
{
May 21, 2002
May 21, 2002
166
167
size_t size;
ptr = strchr(start, ':'); /* find next $PATH separator. */
Jul 8, 2001
Jul 8, 2001
168
169
170
if (ptr)
*ptr = '\0';
May 21, 2002
May 21, 2002
171
172
size = strlen(start) + strlen(bin) + 2;
if (size > alloc_size)
Jul 8, 2001
Jul 8, 2001
173
{
Mar 14, 2005
Mar 14, 2005
174
char *x = (char *) allocator.Realloc(exe, size);
May 21, 2002
May 21, 2002
175
176
177
if (x == NULL)
{
if (exe != NULL)
Mar 14, 2005
Mar 14, 2005
178
allocator.Free(exe);
May 21, 2002
May 21, 2002
179
180
181
182
183
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
} /* if */
alloc_size = size;
exe = x;
Jul 8, 2001
Jul 8, 2001
184
} /* if */
May 21, 2002
May 21, 2002
185
186
/* build full binary path... */
Jul 8, 2001
Jul 8, 2001
187
strcpy(exe, start);
Nov 30, 2002
Nov 30, 2002
188
if ((exe[0] == '\0') || (exe[strlen(exe) - 1] != '/'))
Aug 29, 2001
Aug 29, 2001
189
strcat(exe, "/");
May 21, 2002
May 21, 2002
190
191
192
strcat(exe, bin);
if (access(exe, X_OK) == 0) /* Exists as executable? We're done. */
Jul 8, 2001
Jul 8, 2001
193
{
May 21, 2002
May 21, 2002
194
strcpy(exe, start); /* i'm lazy. piss off. */
Jan 28, 2010
Jan 28, 2010
195
return exe;
May 21, 2002
May 21, 2002
196
} /* if */
Jul 8, 2001
Jul 8, 2001
197
May 21, 2002
May 21, 2002
198
start = ptr + 1; /* start points to beginning of next element. */
Jul 8, 2001
Jul 8, 2001
199
200
} while (ptr != NULL);
May 21, 2002
May 21, 2002
201
if (exe != NULL)
Mar 14, 2005
Mar 14, 2005
202
allocator.Free(exe);
May 21, 2002
May 21, 2002
203
Jan 28, 2010
Jan 28, 2010
204
return NULL; /* doesn't exist in path. */
May 21, 2002
May 21, 2002
205
206
207
} /* findBinaryInPath */
Jul 8, 2009
Jul 8, 2009
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
235
236
237
238
239
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
240
241
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
{
Mar 19, 2007
Mar 19, 2007
242
243
244
245
246
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
247
return NULL; /* higher level will parse out real path from argv0. */
May 21, 2002
May 21, 2002
248
Mar 19, 2007
Mar 19, 2007
249
250
251
252
253
/*
* 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
254
retval = readSymLink("/proc/self/exe");
Jul 8, 2009
Jul 8, 2009
255
256
257
258
259
260
261
262
263
264
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
265
if (retval != NULL) /* chop off filename. */
Mar 19, 2007
Mar 19, 2007
266
{
Jul 8, 2009
Jul 8, 2009
267
268
269
char *ptr = strrchr(retval, '/');
if (ptr != NULL)
*ptr = '\0';
Mar 19, 2007
Mar 19, 2007
270
} /* if */
May 21, 2002
May 21, 2002
271
Mar 19, 2007
Mar 19, 2007
272
273
274
275
276
277
278
279
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
280
Jul 8, 2009
Jul 8, 2009
281
282
283
284
285
286
287
288
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
289
return retval;
Jul 8, 2001
Jul 8, 2001
290
291
292
} /* __PHYSFS_platformCalcBaseDir */
Mar 20, 2007
Mar 20, 2007
293
294
int __PHYSFS_platformSetDefaultAllocator(PHYSFS_Allocator *a)
{
Jan 28, 2010
Jan 28, 2010
295
return 0; /* just use malloc() and friends. */
Mar 20, 2007
Mar 20, 2007
296
297
} /* __PHYSFS_platformSetDefaultAllocator */
Mar 11, 2007
Mar 11, 2007
298
#endif /* PHYSFS_PLATFORM_UNIX */
May 24, 2002
May 24, 2002
299
Jul 7, 2001
Jul 7, 2001
300
/* end of unix.c ... */