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