00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "global.hpp"
00019
00020
00021
00022
00023
00024 #include <sys/types.h>
00025
00026
00027 #include <sys/stat.h>
00028
00029 #ifdef _WIN32
00030 #include "filesystem_win32.ii"
00031 #else
00032 #include <unistd.h>
00033 #include <dirent.h>
00034 #endif
00035
00036 #ifdef __BEOS__
00037 #include <Directory.h>
00038 #include <FindDirectory.h>
00039 #include <Path.h>
00040 BPath be_path;
00041 #endif
00042
00043
00044 #include <cstdlib>
00045 #include <cerrno>
00046 #include <string>
00047 #include <cstring>
00048 #include <algorithm>
00049 #include <fstream>
00050 #include <iostream>
00051 #include <iomanip>
00052 #include <sstream>
00053 #include <set>
00054
00055 #include "wesconfig.h"
00056 #include "config.hpp"
00057 #include "filesystem.hpp"
00058 #include "game_config.hpp"
00059 #include "log.hpp"
00060 #include "scoped_resource.hpp"
00061 #include "util.hpp"
00062 #include "loadscreen.hpp"
00063
00064 #define DBG_FS LOG_STREAM(debug, filesystem)
00065 #define LOG_FS LOG_STREAM(info, filesystem)
00066 #define ERR_FS LOG_STREAM(err, filesystem)
00067
00068 namespace {
00069 const mode_t AccessMode = 00770;
00070 }
00071
00072 #ifdef __APPLE__
00073 #include <CoreFoundation/CoreFoundation.h>
00074 #include <CoreFoundation/CFString.h>
00075 #include <CoreFoundation/CFBase.h>
00076 #endif
00077
00078 bool ends_with(const std::string& str, const std::string& suffix)
00079 {
00080 return str.size() >= suffix.size() && std::equal(suffix.begin(),suffix.end(),str.end()-suffix.size());
00081 }
00082
00083
00084 #define MAINCFG "_main.cfg"
00085 #define FINALCFG "_final.cfg"
00086
00087
00088
00089 void get_files_in_dir(const std::string directory,
00090 std::vector<std::string>* files,
00091 std::vector<std::string>* dirs,
00092 FILE_NAME_MODE mode,
00093 FILE_FILTER filter,
00094 FILE_REORDER_OPTION reorder)
00095 {
00096
00097
00098
00099 #ifndef __AMIGAOS4__
00100 if(!directory.empty() && directory[0] != '/' && !game_config::path.empty()){
00101 const std::string& dir = game_config::path + "/" + directory;
00102 if(is_directory(dir)) {
00103 get_files_in_dir(dir,files,dirs,mode,filter,reorder);
00104 return;
00105 }
00106 }
00107 #endif
00108
00109 struct stat st;
00110
00111 if (reorder == DO_REORDER) {
00112 LOG_FS << "searching _main.cfg in directory " << directory << '\n';
00113 std::string maincfg;
00114 if (directory.empty() || directory[directory.size()-1] == '/'
00115 #ifdef __AMIGAOS4__
00116 || (directory[directory.size()-1]==':')
00117 #endif
00118 )
00119 maincfg = directory + MAINCFG;
00120 else
00121 maincfg = (directory + "/") + MAINCFG;
00122
00123 if (::stat(maincfg.c_str(), &st) != -1) {
00124 LOG_FS << "_main.cfg found : " << maincfg << '\n';
00125 if (files != NULL) {
00126 if (mode == ENTIRE_FILE_PATH)
00127 files->push_back(maincfg);
00128 else
00129 files->push_back(MAINCFG);
00130 }
00131 return;
00132 }
00133 }
00134
00135 DIR* dir = opendir(directory.c_str());
00136
00137 if(dir == NULL) {
00138 return;
00139 }
00140
00141 struct dirent* entry;
00142 while((entry = readdir(dir)) != NULL) {
00143 if(entry->d_name[0] == '.')
00144 continue;
00145 #ifdef __APPLE__
00146
00147
00148 char macname[MAXNAMLEN+1];
00149 CFStringRef cstr = CFStringCreateWithCString(NULL,
00150 entry->d_name,
00151 kCFStringEncodingUTF8);
00152 CFMutableStringRef mut_str = CFStringCreateMutableCopy(NULL,
00153 0, cstr);
00154 CFStringNormalize(mut_str, kCFStringNormalizationFormC);
00155 CFStringGetCString(mut_str,
00156 macname,sizeof(macname)-1,
00157 kCFStringEncodingUTF8);
00158 CFRelease(cstr);
00159 CFRelease(mut_str);
00160 const std::string basename = macname;
00161 #else
00162
00163 const std::string basename = entry->d_name;
00164 #endif
00165
00166 std::string fullname;
00167 if (directory.empty() || directory[directory.size()-1] == '/'
00168 #ifdef __AMIGAOS4__
00169 || (directory[directory.size()-1]==':')
00170 #endif
00171 )
00172 fullname = directory + basename;
00173 else
00174 fullname = directory + "/" + basename;
00175
00176 if (::stat(fullname.c_str(), &st) != -1) {
00177 if (S_ISREG(st.st_mode)) {
00178 if (files != NULL) {
00179 if (mode == ENTIRE_FILE_PATH)
00180 files->push_back(fullname);
00181 else
00182 files->push_back(basename);
00183 }
00184 } else if (S_ISDIR(st.st_mode)) {
00185 if (filter == SKIP_MEDIA_DIR
00186 && (basename == "images"|| basename == "sounds"))
00187 continue;
00188
00189 if (reorder == DO_REORDER &&
00190 ::stat((fullname+"/"+MAINCFG).c_str(), &st)!=-1 &&
00191 S_ISREG(st.st_mode)) {
00192 LOG_FS << "_main.cfg found : ";
00193 if (files != NULL) {
00194 if (mode == ENTIRE_FILE_PATH) {
00195 files->push_back(fullname + "/" + MAINCFG);
00196 LOG_FS << fullname << "/" << MAINCFG << '\n';
00197 } else {
00198 files->push_back(basename + "/" + MAINCFG);
00199 LOG_FS << basename << "/" << MAINCFG << '\n';
00200 }
00201 } else {
00202
00203 LOG_FS << fullname << "/" << MAINCFG << " not used now but skip the directory \n";
00204 }
00205 } else if (dirs != NULL) {
00206 if (mode == ENTIRE_FILE_PATH)
00207 dirs->push_back(fullname);
00208 else
00209 dirs->push_back(basename);
00210 }
00211 }
00212 }
00213 }
00214
00215 closedir(dir);
00216
00217 if(files != NULL)
00218 std::sort(files->begin(),files->end());
00219
00220 if (dirs != NULL)
00221 std::sort(dirs->begin(),dirs->end());
00222
00223 if (files != NULL && reorder == DO_REORDER) {
00224 for (unsigned int i = 0; i < files->size(); i++)
00225 if (ends_with((*files)[i], FINALCFG)) {
00226 files->push_back((*files)[i]);
00227 files->erase(files->begin()+i);
00228 break;
00229 }
00230 }
00231 }
00232
00233 std::string get_prefs_file()
00234 {
00235 return get_user_data_dir() + "/preferences";
00236 }
00237
00238 std::string get_save_index_file()
00239 {
00240 return get_user_data_dir() + "/save_index";
00241 }
00242
00243 std::string get_saves_dir()
00244 {
00245 const std::string dir_path = get_user_data_dir() + "/saves";
00246 return get_dir(dir_path);
00247 }
00248
00249 std::string get_cache_dir()
00250 {
00251 const std::string dir_path = get_user_data_dir() + "/cache";
00252 return get_dir(dir_path);
00253 }
00254
00255 std::string get_intl_dir()
00256 {
00257 #ifdef _WIN32
00258 return get_cwd() + "/po";
00259 #endif
00260
00261 #ifdef USE_INTERNAL_DATA
00262 return get_cwd() + "/" LOCALEDIR;
00263 #endif
00264
00265 #if HAS_RELATIVE_LOCALEDIR
00266 std::string res = game_config::path + "/" LOCALEDIR;
00267 #else
00268 std::string res = LOCALEDIR;
00269 #endif
00270
00271 return res;
00272 }
00273
00274 std::string get_screenshot_dir()
00275 {
00276 const std::string dir_path = get_user_data_dir() + "/screenshots";
00277 return get_dir(dir_path);
00278 }
00279
00280 std::string get_next_filename(const std::string& name, const std::string& extension)
00281 {
00282 std::string next_filename;
00283 int counter = 0;
00284
00285 do {
00286 std::stringstream filename;
00287
00288 filename << name;
00289 filename.width(3);
00290 filename.fill('0');
00291 filename.setf(std::ios_base::right);
00292 filename << counter << extension;
00293 counter++;
00294 next_filename = filename.str();
00295 } while(file_exists(next_filename) && counter < 1000);
00296 return next_filename;
00297 }
00298
00299
00300 std::string get_upload_dir()
00301 {
00302 const std::string dir_path = get_user_data_dir() + "/upload";
00303 return get_dir(dir_path);
00304 }
00305
00306 std::string get_dir(const std::string& dir_path)
00307 {
00308 DIR* dir = opendir(dir_path.c_str());
00309 if(dir == NULL) {
00310 const int res = mkdir(dir_path.c_str(),AccessMode);
00311 if(res == 0) {
00312 dir = opendir(dir_path.c_str());
00313 } else {
00314 ERR_FS << "could not open or create directory: " << dir_path << '\n';
00315 }
00316 }
00317
00318 if(dir == NULL)
00319 return "";
00320
00321 closedir(dir);
00322
00323 return dir_path;
00324 }
00325
00326 bool make_directory(const std::string& path)
00327 {
00328 return (mkdir(path.c_str(),AccessMode) == 0);
00329 }
00330
00331
00332
00333 bool delete_directory(const std::string& path)
00334 {
00335 bool ret = true;
00336 std::vector<std::string> files;
00337 std::vector<std::string> dirs;
00338
00339 get_files_in_dir(path, &files, &dirs, ENTIRE_FILE_PATH);
00340
00341 if(!files.empty()) {
00342 for(std::vector<std::string>::const_iterator i = files.begin(); i != files.end(); ++i) {
00343 errno = 0;
00344 if(remove((*i).c_str()) != 0) {
00345 LOG_FS << "remove(" << (*i) << "): " << strerror(errno) << "\n";
00346 ret = false;
00347 }
00348 }
00349 }
00350
00351 if(!dirs.empty()) {
00352 for(std::vector<std::string>::const_iterator j = dirs.begin(); j != dirs.end(); ++j) {
00353 if(!delete_directory(*j))
00354 ret = false;
00355 }
00356 }
00357
00358 errno = 0;
00359 if(remove(path.c_str()) != 0) {
00360 LOG_FS << "remove(" << path << "): " << strerror(errno) << "\n";
00361 ret = false;
00362 }
00363 return ret;
00364 }
00365
00366 std::string get_cwd()
00367 {
00368 char buf[1024];
00369 const char* const res = getcwd(buf,sizeof(buf));
00370 if(res != NULL) {
00371 std::string str(res);
00372
00373 #ifdef _WIN32
00374 std::replace(str.begin(),str.end(),'\\','/');
00375 #endif
00376
00377 return str;
00378 } else {
00379 return "";
00380 }
00381 }
00382
00383 std::string get_user_data_dir()
00384 {
00385 #ifdef _WIN32
00386
00387 static bool inited_dirs = false;
00388
00389 if(!inited_dirs) {
00390 _mkdir("userdata");
00391 _mkdir("userdata/editor");
00392 _mkdir("userdata/editor/maps");
00393 _mkdir("userdata/data");
00394 _mkdir("userdata/data/ais");
00395 _mkdir("userdata/data/scenarios");
00396 _mkdir("userdata/data/scenarios/multiplayer");
00397 _mkdir("userdata/data/maps");
00398 _mkdir("userdata/data/maps/multiplayer");
00399 _mkdir("userdata/saves");
00400 inited_dirs = true;
00401 }
00402
00403 char buf[256];
00404 const char* const res = getcwd(buf,sizeof(buf));
00405
00406 if(res != NULL) {
00407 std::string cur_path(res);
00408 std::replace(cur_path.begin(),cur_path.end(),'\\','/');
00409 return cur_path + "/userdata";
00410 } else {
00411 return "userdata";
00412 }
00413 #elif defined(__BEOS__)
00414 if (be_path.InitCheck() != B_OK) {
00415 BPath tpath;
00416 if (find_directory(B_USER_SETTINGS_DIRECTORY, &be_path, true) == B_OK) {
00417 be_path.Append("wesnoth");
00418 } else {
00419 be_path.SetTo("/boot/home/config/settings/wesnoth");
00420 }
00421 tpath = be_path;
00422 tpath.Append("editor/maps");
00423 create_directory(tpath.Path(), 0775);
00424 }
00425 return be_path.Path();
00426 #else
00427
00428 #ifndef __AMIGAOS4__
00429 static const char* const current_dir = ".";
00430 const char* home_str = getenv("HOME");
00431 #else
00432 static const char* const current_dir = " ";
00433 const char* home_str = "PROGDIR:";
00434 #endif
00435 if(home_str == NULL)
00436 home_str = current_dir;
00437
00438 const std::string home(home_str);
00439
00440 #ifndef PREFERENCES_DIR
00441 #define PREFERENCES_DIR ".wesnoth"
00442 #endif
00443
00444 #ifndef __AMIGAOS4__
00445 const std::string dir_path = home + std::string("/") + PREFERENCES_DIR;
00446 #else
00447 const std::string dir_path = home + PREFERENCES_DIR;
00448 #endif
00449 DIR* dir = opendir(dir_path.c_str());
00450 if(dir == NULL) {
00451 const int res = mkdir(dir_path.c_str(),AccessMode);
00452
00453
00454 mkdir((dir_path + "/editor").c_str(),AccessMode);
00455 mkdir((dir_path + "/editor/maps").c_str(),AccessMode);
00456 mkdir((dir_path + "/data").c_str(),AccessMode);
00457 mkdir((dir_path + "/data/ais").c_str(),AccessMode);
00458 mkdir((dir_path + "/data/scenarios").c_str(),AccessMode);
00459 mkdir((dir_path + "/data/scenarios/multiplayer").c_str(),AccessMode);
00460 mkdir((dir_path + "/data/maps").c_str(),AccessMode);
00461 mkdir((dir_path + "/data/maps/multiplayer").c_str(),AccessMode);
00462 mkdir((dir_path + "/saves").c_str(),AccessMode);
00463 if(res == 0) {
00464 dir = opendir(dir_path.c_str());
00465 } else {
00466 ERR_FS << "could not open or create directory: " << dir_path << '\n';
00467 }
00468 }
00469
00470 if(dir == NULL)
00471 return "";
00472
00473 closedir(dir);
00474
00475 return dir_path;
00476 #endif
00477 }
00478
00479 static std::string read_stream(std::istream& s)
00480 {
00481 std::stringstream ss;
00482 ss << s.rdbuf();
00483 return ss.str();
00484 }
00485
00486 std::istream *istream_file(std::string const &fname)
00487 {
00488 LOG_FS << "streaming " << fname << " for reading.\n";
00489 if (!fname.empty() && fname[0] != '/' && !game_config::path.empty()) {
00490 std::ifstream *s = new std::ifstream((game_config::path + "/" + fname).c_str(),std::ios_base::binary);
00491 if (s->is_open())
00492 return s;
00493 LOG_FS << "could not open " << fname << " for reading.\n";
00494 delete s;
00495 }
00496
00497
00498
00499
00500 std::istream *s = new std::ifstream(fname.c_str(), std::ios_base::binary);
00501 if (s->fail()) {
00502 LOG_FS << "streaming " << fname << " failed.\n";
00503 }
00504 return s;
00505 }
00506
00507 std::string read_file(std::string const &fname)
00508 {
00509 scoped_istream s = istream_file(fname);
00510 return read_stream(*s);
00511 }
00512
00513 std::ostream *ostream_file(std::string const &fname)
00514 {
00515 LOG_FS << "streaming " << fname << " for writing.\n";
00516 return new std::ofstream(fname.c_str(), std::ios_base::binary);
00517 }
00518
00519
00520 void write_file(const std::string& fname, const std::string& data)
00521 {
00522
00523 const util::scoped_FILE file(fopen(fname.c_str(),"wb"));
00524 if(file.get() == NULL) {
00525 throw io_exception("Could not open file for writing: '" + fname + "'");
00526 }
00527
00528 const size_t block_size = 4096;
00529 char buf[block_size];
00530
00531 for(size_t i = 0; i < data.size(); i += block_size) {
00532 const size_t bytes = minimum<size_t>(block_size,data.size() - i);
00533 std::copy(data.begin() + i, data.begin() + i + bytes,buf);
00534 const size_t res = fwrite(buf,1,bytes,file.get());
00535 if(res != bytes) {
00536 throw io_exception("Error writing to file: '" + fname + "'");
00537 }
00538 }
00539 }
00540
00541
00542 std::string read_map(const std::string& name)
00543 {
00544 std::string res = read_file("data/maps/" + name);
00545 if(res == "") {
00546 res = read_file(get_user_data_dir() + "/data/maps/" + name);
00547 }
00548
00549 if(res == "") {
00550 res = read_file(get_user_data_dir() + "/editor/maps/" + name);
00551 }
00552
00553 return res;
00554 }
00555
00556 static bool is_directory_internal(const std::string& fname)
00557 {
00558 #ifdef _WIN32
00559 _finddata_t info;
00560 const long handle = _findfirst((fname + "/*").c_str(),&info);
00561 if(handle >= 0) {
00562 _findclose(handle);
00563 return true;
00564 } else {
00565 return false;
00566 }
00567
00568 #else
00569 struct stat dir_stat;
00570 if(::stat(fname.c_str(), &dir_stat) == -1) {
00571 return false;
00572 }
00573
00574 return S_ISDIR(dir_stat.st_mode);
00575 #endif
00576 }
00577
00578 bool is_directory(const std::string& fname)
00579 {
00580 if(fname.empty()) {
00581 return false;
00582 }
00583 if(fname[0] != '/' && !game_config::path.empty()) {
00584 if(is_directory_internal(game_config::path + "/" + fname))
00585 return true;
00586 }
00587
00588 return is_directory_internal(fname);
00589 }
00590
00591 bool file_exists(const std::string& name)
00592 {
00593 std::ifstream file(name.c_str(),std::ios_base::binary);
00594 if (file.rdstate() != 0) {
00595 return false;
00596 }
00597 file.close();
00598 return true;
00599 }
00600
00601 time_t file_create_time(const std::string& fname)
00602 {
00603 struct stat buf;
00604 if(::stat(fname.c_str(),&buf) == -1)
00605 return 0;
00606
00607 return buf.st_mtime;
00608 }
00609
00610
00611 std::string next_filename(const std::string &dirname, unsigned int max)
00612 {
00613 std::vector<std::string> files;
00614 std::stringstream fname;
00615 unsigned int num = 1;
00616
00617
00618 get_files_in_dir(dirname, &files);
00619
00620
00621 std::vector<std::string>::reverse_iterator i;
00622 for (i = files.rbegin(); i != files.rend(); ++i) {
00623 if (i->length() == 8) {
00624 try {
00625 num = lexical_cast<int>(*i)+1;
00626 break;
00627 } catch (bad_lexical_cast &) {
00628 }
00629 }
00630 }
00631
00632
00633 if (max) {
00634 for (unsigned int j = 0; j + max < files.size(); j++) {
00635 delete_directory(dirname + "/" + files[j]);
00636 }
00637 }
00638
00639 fname << std::setw(8) << std::setfill('0') << num;
00640 return dirname + "/" + fname.str();
00641 }
00642
00643
00644
00645
00646 bool is_gzip_file(const std::string& filename)
00647 {
00648 return (filename.length() > 3
00649 && filename.substr(filename.length() - 3) == ".gz");
00650 }
00651
00652 file_tree_checksum::file_tree_checksum()
00653 : nfiles(0), sum_size(0), modified(0)
00654 {}
00655
00656 file_tree_checksum::file_tree_checksum(const config& cfg) :
00657 nfiles (lexical_cast_default<size_t>(cfg["nfiles"])),
00658 sum_size(lexical_cast_default<size_t>(cfg["size"])),
00659 modified(lexical_cast_default<time_t>(cfg["modified"]))
00660 {
00661 }
00662
00663 void file_tree_checksum::write(config& cfg) const
00664 {
00665 cfg["nfiles"] = lexical_cast<std::string>(nfiles);
00666 cfg["size"] = lexical_cast<std::string>(sum_size);
00667 cfg["modified"] = lexical_cast<std::string>(modified);
00668 }
00669
00670 bool operator==(const file_tree_checksum& lhs, const file_tree_checksum& rhs)
00671 {
00672 return lhs.nfiles == rhs.nfiles && lhs.sum_size == rhs.sum_size &&
00673 lhs.modified == rhs.modified;
00674 }
00675
00676 bool operator!=(const file_tree_checksum& lhs, const file_tree_checksum& rhs)
00677 {
00678 return !operator==(lhs,rhs);
00679 }
00680
00681 static void get_file_tree_checksum_internal(const std::string& path, file_tree_checksum& res)
00682 {
00683 std::vector<std::string> files, dirs;
00684 get_files_in_dir(path,&files,&dirs, ENTIRE_FILE_PATH, SKIP_MEDIA_DIR);
00685 increment_filesystem_progress();
00686 for(std::vector<std::string>::const_iterator i = files.begin(); i != files.end(); ++i) {
00687 ++res.nfiles;
00688
00689 struct stat buf;
00690 if(::stat(i->c_str(),&buf) != -1) {
00691 if(buf.st_mtime > res.modified) {
00692 res.modified = buf.st_mtime;
00693 }
00694
00695 res.sum_size += buf.st_size;
00696 }
00697 }
00698
00699 for(std::vector<std::string>::const_iterator j = dirs.begin(); j != dirs.end(); ++j) {
00700 get_file_tree_checksum_internal(*j,res);
00701 }
00702 }
00703
00704 const file_tree_checksum& data_tree_checksum(bool reset)
00705 {
00706 static file_tree_checksum checksum;
00707 if (reset)
00708 checksum.reset();
00709 if(checksum.nfiles == 0) {
00710 get_file_tree_checksum_internal("data/",checksum);
00711 get_file_tree_checksum_internal(get_user_data_dir() + "/data/",checksum);
00712 LOG_FS << "calculated data tree checksum: "
00713 << checksum.nfiles << " files; "
00714 << checksum.sum_size << " bytes\n";
00715 }
00716
00717 return checksum;
00718 }
00719
00720 int file_size(const std::string& fname)
00721 {
00722 struct stat buf;
00723 if(::stat(fname.c_str(),&buf) == -1)
00724 return -1;
00725
00726 return buf.st_size;
00727 }
00728
00729 std::string file_name(const std::string& file)
00730
00731 {
00732 #ifdef _WIN32
00733 static const std::string dir_separators = "\\/:";
00734 #else
00735 static const std::string dir_separators = "/";
00736 #endif
00737
00738 std::string::size_type pos = file.find_last_of(dir_separators);
00739
00740 if(pos == std::string::npos)
00741 return file;
00742 if(pos >= file.size()-1)
00743 return "";
00744
00745 return file.substr(pos+1);
00746 }
00747
00748 std::string directory_name(const std::string& file)
00749
00750 {
00751 #ifdef _WIN32
00752 static const std::string dir_separators = "\\/:";
00753 #else
00754 static const std::string dir_separators = "/";
00755 #endif
00756
00757 std::string::size_type pos = file.find_last_of(dir_separators);
00758
00759 if(pos == std::string::npos)
00760 return "";
00761
00762 return file.substr(0,pos+1);
00763 }
00764
00765 namespace {
00766
00767 std::set<std::string> binary_paths;
00768
00769 typedef std::map<std::string,std::vector<std::string> > paths_map;
00770 paths_map binary_paths_cache;
00771
00772 }
00773
00774 static void init_binary_paths()
00775 {
00776 if(binary_paths.empty()) {
00777 binary_paths.insert("");
00778 }
00779 }
00780
00781 binary_paths_manager::binary_paths_manager() : paths_()
00782 {}
00783
00784 binary_paths_manager::binary_paths_manager(const config& cfg) : paths_()
00785 {
00786 set_paths(cfg);
00787 }
00788
00789 binary_paths_manager::~binary_paths_manager()
00790 {
00791 cleanup();
00792 }
00793
00794 void binary_paths_manager::set_paths(const config& cfg)
00795 {
00796 cleanup();
00797 init_binary_paths();
00798
00799 const config::child_list& items = cfg.get_children("binary_path");
00800 for(config::child_list::const_iterator i = items.begin(); i != items.end(); ++i) {
00801 std::string path = (**i)["path"].str();
00802 if (!path.empty() && path[path.size()-1] != '/') path += "/";
00803 if(binary_paths.count(path) == 0) {
00804 binary_paths.insert(path);
00805 paths_.push_back(path);
00806 }
00807 }
00808 }
00809
00810 void binary_paths_manager::cleanup()
00811 {
00812 binary_paths_cache.clear();
00813
00814 for(std::vector<std::string>::const_iterator i = paths_.begin(); i != paths_.end(); ++i) {
00815 binary_paths.erase(*i);
00816 }
00817 }
00818
00819 void clear_binary_paths_cache()
00820 {
00821 binary_paths_cache.clear();
00822 }
00823
00824 const std::vector<std::string>& get_binary_paths(const std::string& type)
00825 {
00826 const paths_map::const_iterator itor = binary_paths_cache.find(type);
00827 if(itor != binary_paths_cache.end()) {
00828 return itor->second;
00829 }
00830
00831 std::vector<std::string>& res = binary_paths_cache[type];
00832
00833 init_binary_paths();
00834
00835 for(std::set<std::string>::const_iterator i = binary_paths.begin(); i != binary_paths.end(); ++i) {
00836 res.push_back(get_user_data_dir() + "/" + *i + type + "/");
00837
00838 if(!game_config::path.empty()) {
00839 res.push_back(game_config::path + "/" + *i + type + "/");
00840 }
00841
00842 res.push_back(*i + type + "/");
00843 }
00844
00845 return res;
00846 }
00847
00848 std::string get_binary_file_location(const std::string& type, const std::string& filename)
00849 {
00850 const std::vector<std::string>& paths = get_binary_paths(type);
00851 if(!filename.empty()) {
00852 DBG_FS << "Looking for " << filename << " in '.'\n";
00853 if(file_exists(filename) || is_directory(filename)) {
00854 DBG_FS << " Found at " << filename << "\n";
00855 return filename;
00856 }
00857 }
00858
00859 for(std::vector<std::string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
00860 const std::string file = *i + filename;
00861 DBG_FS << " Checking " << *i << "\n";
00862 if(file_exists(file) || is_directory(file)) {
00863 DBG_FS << " Found at " << file << "\n";
00864 return file;
00865 }
00866 }
00867
00868 DBG_FS << " " << filename << " not found.\n";
00869 return "";
00870 }
00871
00872 scoped_istream& scoped_istream::operator=(std::istream *s)
00873 {
00874 delete stream;
00875 stream = s;
00876 return *this;
00877 }
00878
00879 scoped_istream::~scoped_istream()
00880 {
00881 delete stream;
00882 }
00883
00884 scoped_ostream& scoped_ostream::operator=(std::ostream *s)
00885 {
00886 delete stream;
00887 stream = s;
00888 return *this;
00889 }
00890
00891 scoped_ostream::~scoped_ostream()
00892 {
00893 delete stream;
00894 }