diff options
author | Jacek Antonelli | 2008-08-15 23:45:04 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:45:04 -0500 |
commit | 117e22047c5752352342d64e3fb7ce00a4eb8113 (patch) | |
tree | e32de2cfba0dda8705ae528fcd1fbe23ba075685 /linden/indra/llvfs/lldir_solaris.cpp | |
parent | Second Life viewer sources 1.18.0.6 (diff) | |
download | meta-impy-117e22047c5752352342d64e3fb7ce00a4eb8113.zip meta-impy-117e22047c5752352342d64e3fb7ce00a4eb8113.tar.gz meta-impy-117e22047c5752352342d64e3fb7ce00a4eb8113.tar.bz2 meta-impy-117e22047c5752352342d64e3fb7ce00a4eb8113.tar.xz |
Second Life viewer sources 1.18.1.2
Diffstat (limited to 'linden/indra/llvfs/lldir_solaris.cpp')
-rw-r--r-- | linden/indra/llvfs/lldir_solaris.cpp | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/linden/indra/llvfs/lldir_solaris.cpp b/linden/indra/llvfs/lldir_solaris.cpp new file mode 100644 index 0000000..41262aa --- /dev/null +++ b/linden/indra/llvfs/lldir_solaris.cpp | |||
@@ -0,0 +1,374 @@ | |||
1 | /** | ||
2 | * @file fmodwrapper.cpp | ||
3 | * @brief dummy source file for building a shared library to wrap libfmod.a | ||
4 | * | ||
5 | * Copyright (c) 2005-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * Second Life Viewer Source Code | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | #include "linden_common.h" | ||
30 | |||
31 | #include "lldir_solaris.h" | ||
32 | #include "llerror.h" | ||
33 | #include "llrand.h" | ||
34 | #include <sys/types.h> | ||
35 | #include <sys/stat.h> | ||
36 | #include <fcntl.h> | ||
37 | #include <sys/param.h> | ||
38 | #include <unistd.h> | ||
39 | #include <glob.h> | ||
40 | #include <pwd.h> | ||
41 | #include <sys/utsname.h> | ||
42 | #define _STRUCTURED_PROC 1 | ||
43 | #include <sys/procfs.h> | ||
44 | |||
45 | static std::string getCurrentUserHome(char* fallback) | ||
46 | { | ||
47 | const uid_t uid = getuid(); | ||
48 | struct passwd *pw; | ||
49 | char *result_cstr = fallback; | ||
50 | |||
51 | pw = getpwuid(uid); | ||
52 | if ((pw != NULL) && (pw->pw_dir != NULL)) | ||
53 | { | ||
54 | result_cstr = (char*) pw->pw_dir; | ||
55 | } | ||
56 | else | ||
57 | { | ||
58 | llinfos << "Couldn't detect home directory from passwd - trying $HOME" << llendl; | ||
59 | const char *const home_env = getenv("HOME"); /* Flawfinder: ignore */ | ||
60 | if (home_env) | ||
61 | { | ||
62 | result_cstr = (char*) home_env; | ||
63 | } | ||
64 | else | ||
65 | { | ||
66 | llwarns << "Couldn't detect home directory! Falling back to " << fallback << llendl; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | return std::string(result_cstr); | ||
71 | } | ||
72 | |||
73 | |||
74 | LLDir_Solaris::LLDir_Solaris() | ||
75 | { | ||
76 | mDirDelimiter = "/"; | ||
77 | mCurrentDirIndex = -1; | ||
78 | mCurrentDirCount = -1; | ||
79 | mDirp = NULL; | ||
80 | |||
81 | char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ | ||
82 | getcwd(tmp_str, LL_MAX_PATH); | ||
83 | |||
84 | mExecutableFilename = ""; | ||
85 | mExecutablePathAndName = ""; | ||
86 | mExecutableDir = strdup(tmp_str); | ||
87 | mWorkingDir = strdup(tmp_str); | ||
88 | mAppRODataDir = strdup(tmp_str); | ||
89 | mOSUserDir = getCurrentUserHome(tmp_str); | ||
90 | mOSUserAppDir = ""; | ||
91 | mLindenUserDir = tmp_str; | ||
92 | |||
93 | char path [LL_MAX_PATH]; /* Flawfinder: ignore */ | ||
94 | |||
95 | sprintf(path, "/proc/%d/psinfo", (int)getpid()); | ||
96 | int proc_fd = -1; | ||
97 | if((proc_fd = open(path, O_RDONLY)) == -1){ | ||
98 | llwarns << "unable to open " << path << llendl; | ||
99 | return; | ||
100 | } | ||
101 | psinfo_t proc_psinfo; | ||
102 | if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){ | ||
103 | llwarns << "Unable to read " << path << llendl; | ||
104 | close(proc_fd); | ||
105 | return; | ||
106 | } | ||
107 | |||
108 | close(proc_fd); | ||
109 | |||
110 | mExecutableFilename = strdup(proc_psinfo.pr_fname); | ||
111 | llinfos << "mExecutableFilename = [" << mExecutableFilename << "]" << llendl; | ||
112 | |||
113 | sprintf(path, "/proc/%d/path/a.out", (int)getpid()); | ||
114 | |||
115 | char execpath[LL_MAX_PATH]; | ||
116 | if(readlink(path, execpath, LL_MAX_PATH) == -1){ | ||
117 | llwarns << "Unable to read link from " << path << llendl; | ||
118 | return; | ||
119 | } | ||
120 | |||
121 | mExecutablePathAndName = strdup(execpath); | ||
122 | llinfos << "mExecutablePathAndName = [" << mExecutablePathAndName << "]" << llendl; | ||
123 | |||
124 | // plunk a null at last '/' to get exec dir | ||
125 | char *s = execpath + strlen(execpath) -1; | ||
126 | while(*s != '/' && s != execpath){ | ||
127 | --s; | ||
128 | } | ||
129 | |||
130 | if(s != execpath){ | ||
131 | *s = (char)NULL; | ||
132 | |||
133 | mExecutableDir = strdup(execpath); | ||
134 | llinfos << "mExecutableDir = [" << mExecutableDir << "]" << llendl; | ||
135 | } | ||
136 | |||
137 | // *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something. | ||
138 | mTempDir = "/tmp"; | ||
139 | } | ||
140 | |||
141 | LLDir_Solaris::~LLDir_Solaris() | ||
142 | { | ||
143 | } | ||
144 | |||
145 | // Implementation | ||
146 | |||
147 | |||
148 | void LLDir_Solaris::initAppDirs(const std::string &app_name) | ||
149 | { | ||
150 | mAppName = app_name; | ||
151 | |||
152 | LLString upper_app_name(app_name); | ||
153 | LLString::toUpper(upper_app_name); | ||
154 | |||
155 | char* app_home_env = getenv((upper_app_name + "_USER_DIR").c_str()); /* Flawfinder: ignore */ | ||
156 | if (app_home_env) | ||
157 | { | ||
158 | // user has specified own userappdir i.e. $SECONDLIFE_USER_DIR | ||
159 | mOSUserAppDir = app_home_env; | ||
160 | } | ||
161 | else | ||
162 | { | ||
163 | // traditionally on unixoids, MyApp gets ~/.myapp dir for data | ||
164 | mOSUserAppDir = mOSUserDir; | ||
165 | mOSUserAppDir += "/"; | ||
166 | mOSUserAppDir += "."; | ||
167 | LLString lower_app_name(app_name); | ||
168 | LLString::toLower(lower_app_name); | ||
169 | mOSUserAppDir += lower_app_name; | ||
170 | } | ||
171 | |||
172 | // create any directories we expect to write to. | ||
173 | |||
174 | int res = LLFile::mkdir(mOSUserAppDir.c_str()); | ||
175 | if (res == -1) | ||
176 | { | ||
177 | if (errno != EEXIST) | ||
178 | { | ||
179 | llwarns << "Couldn't create app user dir " << mOSUserAppDir << llendl; | ||
180 | llwarns << "Default to base dir" << mOSUserDir << llendl; | ||
181 | mOSUserAppDir = mOSUserDir; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,"").c_str()); | ||
186 | if (res == -1) | ||
187 | { | ||
188 | if (errno != EEXIST) | ||
189 | { | ||
190 | llwarns << "Couldn't create LL_PATH_LOGS dir " << getExpandedFilename(LL_PATH_LOGS,"") << llendl; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,"").c_str()); | ||
195 | if (res == -1) | ||
196 | { | ||
197 | if (errno != EEXIST) | ||
198 | { | ||
199 | llwarns << "Couldn't create LL_PATH_USER_SETTINGS dir " << getExpandedFilename(LL_PATH_USER_SETTINGS,"") << llendl; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,"").c_str()); | ||
204 | if (res == -1) | ||
205 | { | ||
206 | if (errno != EEXIST) | ||
207 | { | ||
208 | llwarns << "Couldn't create LL_PATH_CACHE dir " << getExpandedFilename(LL_PATH_CACHE,"") << llendl; | ||
209 | } | ||
210 | } | ||
211 | |||
212 | res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"").c_str()); | ||
213 | if (res == -1) | ||
214 | { | ||
215 | if (errno != EEXIST) | ||
216 | { | ||
217 | llwarns << "Couldn't create LL_PATH_MOZILLA_PROFILE dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl; | ||
218 | } | ||
219 | } | ||
220 | |||
221 | mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem"); | ||
222 | } | ||
223 | |||
224 | U32 LLDir_Solaris::countFilesInDir(const std::string &dirname, const std::string &mask) | ||
225 | { | ||
226 | U32 file_count = 0; | ||
227 | glob_t g; | ||
228 | |||
229 | std::string tmp_str; | ||
230 | tmp_str = dirname; | ||
231 | tmp_str += mask; | ||
232 | |||
233 | if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) | ||
234 | { | ||
235 | file_count = g.gl_pathc; | ||
236 | |||
237 | globfree(&g); | ||
238 | } | ||
239 | |||
240 | return (file_count); | ||
241 | } | ||
242 | |||
243 | // get the next file in the directory | ||
244 | // automatically wrap if we've hit the end | ||
245 | BOOL LLDir_Solaris::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap) | ||
246 | { | ||
247 | glob_t g; | ||
248 | BOOL result = FALSE; | ||
249 | fname = ""; | ||
250 | |||
251 | if(!(dirname == mCurrentDir)) | ||
252 | { | ||
253 | // different dir specified, close old search | ||
254 | mCurrentDirIndex = -1; | ||
255 | mCurrentDirCount = -1; | ||
256 | mCurrentDir = dirname; | ||
257 | } | ||
258 | |||
259 | std::string tmp_str; | ||
260 | tmp_str = dirname; | ||
261 | tmp_str += mask; | ||
262 | |||
263 | if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) | ||
264 | { | ||
265 | if(g.gl_pathc > 0) | ||
266 | { | ||
267 | if((int)g.gl_pathc != mCurrentDirCount) | ||
268 | { | ||
269 | // Number of matches has changed since the last search, meaning a file has been added or deleted. | ||
270 | // Reset the index. | ||
271 | mCurrentDirIndex = -1; | ||
272 | mCurrentDirCount = g.gl_pathc; | ||
273 | } | ||
274 | |||
275 | mCurrentDirIndex++; | ||
276 | |||
277 | if((mCurrentDirIndex >= (int)g.gl_pathc) && wrap) | ||
278 | { | ||
279 | mCurrentDirIndex = 0; | ||
280 | } | ||
281 | |||
282 | if(mCurrentDirIndex < (int)g.gl_pathc) | ||
283 | { | ||
284 | // llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl; | ||
285 | |||
286 | // The API wants just the filename, not the full path. | ||
287 | //fname = g.gl_pathv[mCurrentDirIndex]; | ||
288 | |||
289 | char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/'); | ||
290 | |||
291 | if(s == NULL) | ||
292 | s = g.gl_pathv[mCurrentDirIndex]; | ||
293 | else if(s[0] == '/') | ||
294 | s++; | ||
295 | |||
296 | fname = s; | ||
297 | |||
298 | result = TRUE; | ||
299 | } | ||
300 | } | ||
301 | |||
302 | globfree(&g); | ||
303 | } | ||
304 | |||
305 | return(result); | ||
306 | } | ||
307 | |||
308 | |||
309 | // get a random file in the directory | ||
310 | // automatically wrap if we've hit the end | ||
311 | void LLDir_Solaris::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) | ||
312 | { | ||
313 | S32 num_files; | ||
314 | S32 which_file; | ||
315 | DIR *dirp; | ||
316 | dirent *entryp = NULL; | ||
317 | |||
318 | fname = ""; | ||
319 | |||
320 | num_files = countFilesInDir(dirname,mask); | ||
321 | if (!num_files) | ||
322 | { | ||
323 | return; | ||
324 | } | ||
325 | |||
326 | which_file = ll_rand(num_files); | ||
327 | |||
328 | // llinfos << "Random select file #" << which_file << llendl; | ||
329 | |||
330 | // which_file now indicates the (zero-based) index to which file to play | ||
331 | |||
332 | if (!((dirp = opendir(dirname.c_str())))) | ||
333 | { | ||
334 | while (which_file--) | ||
335 | { | ||
336 | if (!((entryp = readdir(dirp)))) | ||
337 | { | ||
338 | return; | ||
339 | } | ||
340 | } | ||
341 | |||
342 | if ((!which_file) && entryp) | ||
343 | { | ||
344 | fname = entryp->d_name; | ||
345 | } | ||
346 | |||
347 | closedir(dirp); | ||
348 | } | ||
349 | } | ||
350 | |||
351 | std::string LLDir_Solaris::getCurPath() | ||
352 | { | ||
353 | char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ | ||
354 | getcwd(tmp_str, LL_MAX_PATH); | ||
355 | return tmp_str; | ||
356 | } | ||
357 | |||
358 | |||
359 | BOOL LLDir_Solaris::fileExists(const std::string &filename) | ||
360 | { | ||
361 | struct stat stat_data; | ||
362 | // Check the age of the file | ||
363 | // Now, we see if the files we've gathered are recent... | ||
364 | int res = stat(filename.c_str(), &stat_data); | ||
365 | if (!res) | ||
366 | { | ||
367 | return TRUE; | ||
368 | } | ||
369 | else | ||
370 | { | ||
371 | return FALSE; | ||
372 | } | ||
373 | } | ||
374 | |||