diff options
author | Don Kjer <don@lindenlab.com> | 2007-07-20 20:38:05 +0000 |
---|---|---|
committer | Don Kjer <don@lindenlab.com> | 2007-07-20 20:38:05 +0000 |
commit | d373dcc7cbed5fdea72c6b71a5594e4e85549b43 (patch) | |
tree | 140e20f48db5dc4d7842f05ef2c24ef9e6fc3238 /indra/llvfs | |
parent | c78f99b0b3b4b9ac99a69b63315e821d89a89a3b (diff) |
svn merge -r 64548:64837 svn+ssh://svn/svn/linden/branches/maintenance into release
* WARNING *: maintenance r64837 is not the last rev to use in the next merge. use r65269
Diffstat (limited to 'indra/llvfs')
-rw-r--r-- | indra/llvfs/lldir.cpp | 3 | ||||
-rw-r--r-- | indra/llvfs/lldir_linux.cpp | 17 | ||||
-rw-r--r-- | indra/llvfs/lldir_solaris.cpp | 354 | ||||
-rw-r--r-- | indra/llvfs/lldir_solaris.h | 41 | ||||
-rw-r--r-- | indra/llvfs/llvfs.cpp | 90 |
5 files changed, 482 insertions, 23 deletions
diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index d8d77e6a23..94c1b5de24 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -25,6 +25,9 @@ LLDir_Win32 gDirUtil; #elif LL_DARWIN #include "lldir_mac.h" LLDir_Mac gDirUtil; +#elif LL_SOLARIS +#include "lldir_solaris.h" +LLDir_Solaris gDirUtil; #else #include "lldir_linux.h" LLDir_Linux gDirUtil; diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp index bc8c173492..42e84edf44 100644 --- a/indra/llvfs/lldir_linux.cpp +++ b/indra/llvfs/lldir_linux.cpp @@ -55,7 +55,16 @@ LLDir_Linux::LLDir_Linux() mDirp = NULL; char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ - getcwd(tmp_str, LL_MAX_PATH); + if (getcwd(tmp_str, LL_MAX_PATH) == NULL) + { + strcpy(tmp_str, "/tmp"); + llwarns << "Could not get current directory; changing to " + << tmp_str << llendl; + if (chdir(tmp_str) == -1) + { + llerrs << "Could not change directory to " << tmp_str << llendl; + } + } mExecutableFilename = ""; mExecutablePathAndName = ""; @@ -308,7 +317,11 @@ void LLDir_Linux::getRandomFileInDir(const std::string &dirname, const std::stri std::string LLDir_Linux::getCurPath() { char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ - getcwd(tmp_str, LL_MAX_PATH); + if (getcwd(tmp_str, LL_MAX_PATH) == NULL) + { + llwarns << "Could not get current directory" << llendl; + tmp_str[0] = '\0'; + } return tmp_str; } diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp new file mode 100644 index 0000000000..d9d683741b --- /dev/null +++ b/indra/llvfs/lldir_solaris.cpp @@ -0,0 +1,354 @@ +/** + * @file fmodwrapper.cpp + * @brief dummy source file for building a shared library to wrap libfmod.a + * + * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "linden_common.h" + +#include "lldir_solaris.h" +#include "llerror.h" +#include "llrand.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/param.h> +#include <unistd.h> +#include <glob.h> +#include <pwd.h> +#include <sys/utsname.h> +#define _STRUCTURED_PROC 1 +#include <sys/procfs.h> + +static std::string getCurrentUserHome(char* fallback) +{ + const uid_t uid = getuid(); + struct passwd *pw; + char *result_cstr = fallback; + + pw = getpwuid(uid); + if ((pw != NULL) && (pw->pw_dir != NULL)) + { + result_cstr = (char*) pw->pw_dir; + } + else + { + llinfos << "Couldn't detect home directory from passwd - trying $HOME" << llendl; + const char *const home_env = getenv("HOME"); /* Flawfinder: ignore */ + if (home_env) + { + result_cstr = (char*) home_env; + } + else + { + llwarns << "Couldn't detect home directory! Falling back to " << fallback << llendl; + } + } + + return std::string(result_cstr); +} + + +LLDir_Solaris::LLDir_Solaris() +{ + mDirDelimiter = "/"; + mCurrentDirIndex = -1; + mCurrentDirCount = -1; + mDirp = NULL; + + char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ + getcwd(tmp_str, LL_MAX_PATH); + + mExecutableFilename = ""; + mExecutablePathAndName = ""; + mExecutableDir = strdup(tmp_str); + mWorkingDir = strdup(tmp_str); + mAppRODataDir = strdup(tmp_str); + mOSUserDir = getCurrentUserHome(tmp_str); + mOSUserAppDir = ""; + mLindenUserDir = tmp_str; + + char path [LL_MAX_PATH]; /* Flawfinder: ignore */ + + sprintf(path, "/proc/%d/psinfo", (int)getpid()); + int proc_fd = -1; + if((proc_fd = open(path, O_RDONLY)) == -1){ + llwarns << "unable to open " << path << llendl; + return; + } + psinfo_t proc_psinfo; + if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){ + llwarns << "Unable to read " << path << llendl; + close(proc_fd); + return; + } + + close(proc_fd); + + mExecutableFilename = strdup(proc_psinfo.pr_fname); + llinfos << "mExecutableFilename = [" << mExecutableFilename << "]" << llendl; + + sprintf(path, "/proc/%d/path/a.out", (int)getpid()); + + char execpath[LL_MAX_PATH]; + if(readlink(path, execpath, LL_MAX_PATH) == -1){ + llwarns << "Unable to read link from " << path << llendl; + return; + } + + mExecutablePathAndName = strdup(execpath); + llinfos << "mExecutablePathAndName = [" << mExecutablePathAndName << "]" << llendl; + + // plunk a null at last '/' to get exec dir + char *s = execpath + strlen(execpath) -1; + while(*s != '/' && s != execpath){ + --s; + } + + if(s != execpath){ + *s = (char)NULL; + + mExecutableDir = strdup(execpath); + llinfos << "mExecutableDir = [" << mExecutableDir << "]" << llendl; + } + + // *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something. + mTempDir = "/tmp"; +} + +LLDir_Solaris::~LLDir_Solaris() +{ +} + +// Implementation + + +void LLDir_Solaris::initAppDirs(const std::string &app_name) +{ + mAppName = app_name; + + LLString upper_app_name(app_name); + LLString::toUpper(upper_app_name); + + char* app_home_env = getenv((upper_app_name + "_USER_DIR").c_str()); /* Flawfinder: ignore */ + if (app_home_env) + { + // user has specified own userappdir i.e. $SECONDLIFE_USER_DIR + mOSUserAppDir = app_home_env; + } + else + { + // traditionally on unixoids, MyApp gets ~/.myapp dir for data + mOSUserAppDir = mOSUserDir; + mOSUserAppDir += "/"; + mOSUserAppDir += "."; + LLString lower_app_name(app_name); + LLString::toLower(lower_app_name); + mOSUserAppDir += lower_app_name; + } + + // create any directories we expect to write to. + + int res = LLFile::mkdir(mOSUserAppDir.c_str()); + if (res == -1) + { + if (errno != EEXIST) + { + llwarns << "Couldn't create app user dir " << mOSUserAppDir << llendl; + llwarns << "Default to base dir" << mOSUserDir << llendl; + mOSUserAppDir = mOSUserDir; + } + } + + res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,"").c_str()); + if (res == -1) + { + if (errno != EEXIST) + { + llwarns << "Couldn't create LL_PATH_LOGS dir " << getExpandedFilename(LL_PATH_LOGS,"") << llendl; + } + } + + res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,"").c_str()); + if (res == -1) + { + if (errno != EEXIST) + { + llwarns << "Couldn't create LL_PATH_USER_SETTINGS dir " << getExpandedFilename(LL_PATH_USER_SETTINGS,"") << llendl; + } + } + + res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,"").c_str()); + if (res == -1) + { + if (errno != EEXIST) + { + llwarns << "Couldn't create LL_PATH_CACHE dir " << getExpandedFilename(LL_PATH_CACHE,"") << llendl; + } + } + + res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"").c_str()); + if (res == -1) + { + if (errno != EEXIST) + { + llwarns << "Couldn't create LL_PATH_MOZILLA_PROFILE dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl; + } + } + + mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem"); +} + +U32 LLDir_Solaris::countFilesInDir(const std::string &dirname, const std::string &mask) +{ + U32 file_count = 0; + glob_t g; + + std::string tmp_str; + tmp_str = dirname; + tmp_str += mask; + + if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) + { + file_count = g.gl_pathc; + + globfree(&g); + } + + return (file_count); +} + +// get the next file in the directory +// automatically wrap if we've hit the end +BOOL LLDir_Solaris::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap) +{ + glob_t g; + BOOL result = FALSE; + fname = ""; + + if(!(dirname == mCurrentDir)) + { + // different dir specified, close old search + mCurrentDirIndex = -1; + mCurrentDirCount = -1; + mCurrentDir = dirname; + } + + std::string tmp_str; + tmp_str = dirname; + tmp_str += mask; + + if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) + { + if(g.gl_pathc > 0) + { + if((int)g.gl_pathc != mCurrentDirCount) + { + // Number of matches has changed since the last search, meaning a file has been added or deleted. + // Reset the index. + mCurrentDirIndex = -1; + mCurrentDirCount = g.gl_pathc; + } + + mCurrentDirIndex++; + + if((mCurrentDirIndex >= (int)g.gl_pathc) && wrap) + { + mCurrentDirIndex = 0; + } + + if(mCurrentDirIndex < (int)g.gl_pathc) + { +// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl; + + // The API wants just the filename, not the full path. + //fname = g.gl_pathv[mCurrentDirIndex]; + + char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/'); + + if(s == NULL) + s = g.gl_pathv[mCurrentDirIndex]; + else if(s[0] == '/') + s++; + + fname = s; + + result = TRUE; + } + } + + globfree(&g); + } + + return(result); +} + + +// get a random file in the directory +// automatically wrap if we've hit the end +void LLDir_Solaris::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) +{ + S32 num_files; + S32 which_file; + DIR *dirp; + dirent *entryp = NULL; + + fname = ""; + + num_files = countFilesInDir(dirname,mask); + if (!num_files) + { + return; + } + + which_file = ll_rand(num_files); + +// llinfos << "Random select file #" << which_file << llendl; + + // which_file now indicates the (zero-based) index to which file to play + + if (!((dirp = opendir(dirname.c_str())))) + { + while (which_file--) + { + if (!((entryp = readdir(dirp)))) + { + return; + } + } + + if ((!which_file) && entryp) + { + fname = entryp->d_name; + } + + closedir(dirp); + } +} + +std::string LLDir_Solaris::getCurPath() +{ + char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ + getcwd(tmp_str, LL_MAX_PATH); + return tmp_str; +} + + +BOOL LLDir_Solaris::fileExists(const std::string &filename) +{ + struct stat stat_data; + // Check the age of the file + // Now, we see if the files we've gathered are recent... + int res = stat(filename.c_str(), &stat_data); + if (!res) + { + return TRUE; + } + else + { + return FALSE; + } +} + diff --git a/indra/llvfs/lldir_solaris.h b/indra/llvfs/lldir_solaris.h new file mode 100644 index 0000000000..1ab76230ee --- /dev/null +++ b/indra/llvfs/lldir_solaris.h @@ -0,0 +1,41 @@ +/** + * @file fmodwrapper.cpp + * @brief dummy source file for building a shared library to wrap libfmod.a + * + * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LL_LLDIR_SOLARIS_H +#define LL_LLDIR_SOLARIS_H + +#include "lldir.h" + +#include <stdio.h> +#include <dirent.h> +#include <errno.h> + +class LLDir_Solaris : public LLDir +{ +public: + LLDir_Solaris(); + virtual ~LLDir_Solaris(); + + virtual void initAppDirs(const std::string &app_name); +public: + virtual std::string getCurPath(); + virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); + virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap); + virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname); + /*virtual*/ BOOL fileExists(const std::string &filename); + +private: + DIR *mDirp; + int mCurrentDirIndex; + int mCurrentDirCount; + std::string mCurrentDir; +}; + +#endif // LL_LLDIR_SOLARIS_H + + diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp index 8b31a50bdb..9094bdd24f 100644 --- a/indra/llvfs/llvfs.cpp +++ b/indra/llvfs/llvfs.cpp @@ -15,6 +15,10 @@ #include <map> #if LL_WINDOWS #include <share.h> +#elif LL_SOLARIS +#include <sys/types.h> +#include <unistd.h> +#include <fcntl.h> #else #include <sys/file.h> #endif @@ -359,13 +363,13 @@ LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL r ) { U8 *buffer = new U8[fbuf.st_size]; - fread(buffer, fbuf.st_size, 1, mIndexFP); + size_t nread = fread(buffer, 1, fbuf.st_size, mIndexFP); U8 *tmp_ptr = buffer; std::vector<LLVFSFileBlock*> files_by_loc; - while (tmp_ptr < buffer + fbuf.st_size) + while (tmp_ptr < buffer + nread) { LLVFSFileBlock *block = new LLVFSFileBlock(); @@ -861,12 +865,18 @@ BOOL LLVFS::setMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type // move the file into the new block U8 *buffer = new U8[block->mSize]; fseek(mDataFP, block->mLocation, SEEK_SET); - fread(buffer, block->mSize, 1, mDataFP); - fseek(mDataFP, free_block->mLocation, SEEK_SET); - fwrite(buffer, block->mSize, 1, mDataFP); - // fflush(mDataFP); - - delete[] buffer; + if (fread(buffer, block->mSize, 1, mDataFP) == 1) + { + fseek(mDataFP, free_block->mLocation, SEEK_SET); + if (fwrite(buffer, block->mSize, 1, mDataFP) != 1) + { + llwarns << "Short write" << llendl; + } + + delete[] buffer; + } else { + llwarns << "Short read" << llendl; + } } } @@ -1466,7 +1476,7 @@ void LLVFS::sync(LLVFSFileBlock *block, BOOL remove) } BOOL set_index_to_end = FALSE; - S32 seek_pos = block->mIndexLocation; + long seek_pos = block->mIndexLocation; if (-1 == seek_pos) { @@ -1514,7 +1524,11 @@ void LLVFS::sync(LLVFSFileBlock *block, BOOL remove) fseek(mIndexFP, seek_pos, SEEK_SET); } - fwrite(buffer, LLVFSFileBlock::SERIAL_SIZE, 1, mIndexFP); + if (fwrite(buffer, LLVFSFileBlock::SERIAL_SIZE, 1, mIndexFP) != 1) + { + llwarns << "Short write" << llendl; + } + // fflush(mIndexFP); lockData(); @@ -1643,18 +1657,24 @@ void LLVFS::pokeFiles() // only write data if we actually read 4 bytes // otherwise we're writing garbage and screwing up the file fseek(mDataFP, 0, SEEK_SET); - if (fread(&word, 1, 4, mDataFP) == 4) + if (fread(&word, sizeof(word), 1, mDataFP) == 1) { fseek(mDataFP, 0, SEEK_SET); - fwrite(&word, 1, 4, mDataFP); + if (fwrite(&word, sizeof(word), 1, mDataFP) != 1) + { + llwarns << "Could not write to data file" << llendl; + } fflush(mDataFP); } fseek(mIndexFP, 0, SEEK_SET); - if (fread(&word, 1, 4, mIndexFP) == 4) + if (fread(&word, sizeof(word), 1, mIndexFP) == 1) { fseek(mIndexFP, 0, SEEK_SET); - fwrite(&word, 1, 4, mIndexFP); + if (fwrite(&word, sizeof(word), 1, mIndexFP) != 1) + { + llwarns << "Could not write to index file" << llendl; + } fflush(mIndexFP); } } @@ -1689,21 +1709,26 @@ void LLVFS::audit() fflush(mIndexFP); fseek(mIndexFP, 0, SEEK_END); - S32 index_size = ftell(mIndexFP); + long index_size = ftell(mIndexFP); fseek(mIndexFP, 0, SEEK_SET); + BOOL vfs_corrupt = FALSE; + U8 *buffer = new U8[index_size]; - fread(buffer, index_size, 1, mIndexFP); + + if (fread(buffer, 1, index_size, mIndexFP) != index_size) + { + llwarns << "Index truncated" << llendl; + vfs_corrupt = TRUE; + } U8 *tmp_ptr = buffer; std::map<LLVFSFileSpecifier, LLVFSFileBlock*> found_files; U32 cur_time = (U32)time(NULL); - BOOL vfs_corrupt = FALSE; - std::vector<LLVFSFileBlock*> audit_blocks; - while (tmp_ptr < buffer + index_size) + while (!vfs_corrupt && tmp_ptr < buffer + index_size) { LLVFSFileBlock *block = new LLVFSFileBlock(); audit_blocks.push_back(block); @@ -1783,7 +1808,11 @@ void LLVFS::audit() llwarns << "VFile " << block->mFileID << ":" << block->mFileType << " in memory, not on disk, loc " << block->mIndexLocation<< llendl; fseek(mIndexFP, block->mIndexLocation, SEEK_SET); U8 buf[LLVFSFileBlock::SERIAL_SIZE]; - fread(buf, LLVFSFileBlock::SERIAL_SIZE, 1, mIndexFP); + if (fread(buf, LLVFSFileBlock::SERIAL_SIZE, 1, mIndexFP) != 1) + { + llwarns << "VFile " << block->mFileID + << " gave short read" << llendl; + } LLVFSFileBlock disk_block; disk_block.deserialize(buf, block->mIndexLocation); @@ -2096,6 +2125,12 @@ FILE *LLVFS::openAndLock(const char *filename, const char *mode, BOOL read_lock) int fd; // first test the lock in a non-destructive way +#if LL_SOLARIS + struct flock fl; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 1; +#else // !LL_SOLARIS if (strstr(mode, "w")) { fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */ @@ -2111,13 +2146,19 @@ FILE *LLVFS::openAndLock(const char *filename, const char *mode, BOOL read_lock) fclose(fp); } } +#endif // !LL_SOLARIS // now actually open the file for use fp = LLFile::fopen(filename, mode); /* Flawfinder: ignore */ if (fp) { fd = fileno(fp); +#if LL_SOLARIS + fl.l_type = read_lock ? F_RDLCK : F_WRLCK; + if (fcntl(fd, F_SETLK, &fl) == -1) +#else if (flock(fd, (read_lock ? LOCK_SH : LOCK_EX) | LOCK_NB) == -1) +#endif { fclose(fp); fp = NULL; @@ -2145,7 +2186,14 @@ void LLVFS::unlockAndClose(FILE *fp) flock(fd, LOCK_UN); #endif */ - +#if LL_SOLARIS + struct flock fl; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 1; + fl.l_type = F_UNLCK; + fcntl(fileno(fp), F_SETLK, &fl); +#endif fclose(fp); } } |