/* * Copyright (c) 2013-2016, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * * See full license text in LICENSE file at top of project tree */ #include #include #include "Base.h" #include "FS.h" #include "Log.h" namespace i2p { namespace fs { std::string appName = "i2pd"; std::string dataDir = ""; #ifdef _WIN32 std::string dirSep = "\\"; #else std::string dirSep = "/"; #endif HashedStorage NetDB("netDb", "r", "routerInfo-", "dat"); HashedStorage Peers("peerProfiles", "p", "profile-", "txt"); ABookStorage ABook("addressbook", "b", "", "b32"); static const char T32[32] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 't', 't', 'u', 'v', 'w', 'x', 'y', 'z', '2', '3', '4', '5', '6', '7', }; static const char T64[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '~' }; const std::string & GetAppName () { return appName; } void SetAppName (const std::string& name) { appName = name; } const std::string & GetDataDir () { return dataDir; } void DetectDataDir(const std::string & cmdline_param, bool isService) { if (cmdline_param != "") { dataDir = cmdline_param; return; } #if defined(WIN32) || defined(_WIN32) char localAppData[MAX_PATH]; SHGetFolderPath(NULL, CSIDL_APPDATA, 0, NULL, localAppData); dataDir = std::string(localAppData) + "\\" + appName; return; #elif defined(MAC_OSX) char *home = getenv("HOME"); dataDir = (home != NULL && strlen(home) > 0) ? home : ""; dataDir += "/Library/Application Support/" + appName; return; #else /* other unix */ char *home = getenv("HOME"); if (isService) { dataDir = "/var/lib/" + appName; } else if (home != NULL && strlen(home) > 0) { dataDir = std::string(home) + "/." + appName; } else { dataDir = "/tmp/" + appName; } return; #endif } bool Init() { if (boost::filesystem::exists(dataDir)) boost::filesystem::create_directory(dataDir); std::string destinations = DataDirPath("destinations"); if (boost::filesystem::exists(destinations)) boost::filesystem::create_directory(destinations); NetDB.SetRoot(dataDir); NetDB.Init(T64, 64); Peers.SetRoot(dataDir); Peers.Init(T64, 64); ABook.SetRoot(dataDir); ABook.Init(T32, 32); return true; } bool ReadDir(const std::string & path, std::vector & files) { if (!boost::filesystem::exists(path)) return false; boost::filesystem::directory_iterator it(path); boost::filesystem::directory_iterator end; for ( ; it != end; it++) { if (!boost::filesystem::is_regular_file(it->status())) continue; files.push_back(it->path().string()); } return true; } bool Exists(const std::string & path) { return boost::filesystem::exists(path); } bool Remove(const std::string & path) { if (!boost::filesystem::exists(path)) return false; return boost::filesystem::remove(path); } void HashedStorage::SetRoot(const std::string &path) { root = path + i2p::fs::dirSep + name; } bool HashedStorage::Init(const char * chars, size_t count) { if (!boost::filesystem::exists(root)) { boost::filesystem::create_directory(root); } for (size_t i = 0; i < count; i++) { auto p = root + i2p::fs::dirSep + prefix1 + chars[i]; if (boost::filesystem::exists(p)) continue; if (boost::filesystem::create_directory(p)) continue; /* ^ throws exception on failure */ return false; } return true; } std::string HashedStorage::Path(const std::string & ident) { std::string safe_ident = ident; std::replace(safe_ident.begin(), safe_ident.end(), '/', '-'); std::replace(safe_ident.begin(), safe_ident.end(), '\\', '-'); std::stringstream t(""); t << this->root << i2p::fs::dirSep; t << prefix1 << safe_ident[0] << i2p::fs::dirSep; t << prefix2 << safe_ident << "." << suffix; return t.str(); } void HashedStorage::Remove(const std::string & ident) { std::string path = Path(ident); if (!boost::filesystem::exists(path)) return; boost::filesystem::remove(path); } void HashedStorage::Traverse(std::vector & files) { boost::filesystem::path p(root); boost::filesystem::recursive_directory_iterator it(p); boost::filesystem::recursive_directory_iterator end; for ( ; it != end; it++) { if (!boost::filesystem::is_regular_file( it->status() )) continue; const std::string & t = it->path().string(); files.push_back(t); } } std::string ABookStorage::IndexPath() { std::string path = root + i2p::fs::dirSep + "addresses.csv"; return path; } HashedStorage & GetNetDB() { return NetDB; } HashedStorage & GetPeerProfiles() { return Peers; } ABookStorage & GetAddressBook() { return ABook; } } // fs } // i2p