File indexing completed on 2024-05-19 16:50:18
0001 /***************************************************************************** 0002 * Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify * 0005 * it under the terms of the GNU Lesser General Public License as * 0006 * published by the Free Software Foundation; either version 2.1 of the * 0007 * License, or (at your option) version 3, or any later version accepted * 0008 * by the membership of KDE e.V. (or its successor approved by the * 0009 * membership of KDE e.V.), which shall act as a proxy defined in * 0010 * Section 6 of version 3 of the license. * 0011 * * 0012 * This program is distributed in the hope that it will be useful, * 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 0015 * Lesser General Public License for more details. * 0016 * * 0017 * You should have received a copy of the GNU Lesser General Public * 0018 * License along with this library. If not, * 0019 * see <http://www.gnu.org/licenses/>. * 0020 *****************************************************************************/ 0021 0022 #include "dirs.h" 0023 #include "log.h" 0024 #include "strs.h" 0025 0026 #include <config.h> 0027 0028 #include <forward_list> 0029 0030 #include <sys/types.h> 0031 #include <pwd.h> 0032 #include <sys/types.h> 0033 #include <dirent.h> 0034 #include <libgen.h> 0035 0036 namespace QtCurve { 0037 0038 QTC_EXPORT void 0039 makePath(const char *path, int mode) 0040 { 0041 if (isDir(path)) { 0042 return; 0043 } 0044 Str::Buff<1024> opath(path); 0045 size_t len = opath.size() - 1; 0046 while (opath[len - 1] == '/') { 0047 opath[len - 1] = '\0'; 0048 len--; 0049 } 0050 char *p = opath.get() + strspn(opath, "/"); 0051 if (!*p) { 0052 return; 0053 } 0054 p += 1; 0055 for (;*p;p++) { 0056 if (*p == '/') { 0057 *p = '\0'; 0058 if (access(opath, F_OK)) { 0059 mkdir(opath, mode | 0300); 0060 } 0061 *p = '/'; 0062 } 0063 } 0064 if (access(opath, F_OK)) { 0065 mkdir(opath, mode); 0066 } 0067 } 0068 0069 // Home 0070 QTC_EXPORT const char* 0071 getHome() 0072 { 0073 static uniqueStr dir = [] { 0074 const char *env_home = getenv("HOME"); 0075 if (qtcLikely(env_home && *env_home == '/')) { 0076 return Str::cat(env_home, "/"); 0077 } else { 0078 struct passwd *pw = getpwuid(getuid()); 0079 if (qtcLikely(pw && pw->pw_dir && *pw->pw_dir == '/')) { 0080 return Str::cat(pw->pw_dir, "/"); 0081 } 0082 } 0083 return strdup("/tmp/"); 0084 }; 0085 return dir.get(); 0086 } 0087 0088 // XDG dirs 0089 QTC_EXPORT const char* 0090 getXDGConfigHome() 0091 { 0092 static uniqueStr dir = [] { 0093 const char *env_home = getenv("XDG_CONFIG_HOME"); 0094 if (env_home && *env_home == '/') { 0095 return Str::cat(env_home, "/"); 0096 } else { 0097 return Str::cat(getHome(), ".config/"); 0098 } 0099 }; 0100 return dir.get(); 0101 } 0102 0103 QTC_EXPORT const char* 0104 getXDGDataHome() 0105 { 0106 static uniqueStr dir = [] { 0107 const char *env_home = getenv("XDG_DATA_HOME"); 0108 if (env_home && *env_home == '/') { 0109 return Str::cat(env_home, "/"); 0110 } else { 0111 return Str::cat(getHome(), ".local/share/"); 0112 } 0113 }; 0114 return dir.get(); 0115 } 0116 0117 // TODO 0118 const std::forward_list<uniqueStr>& 0119 getKDE4Home() 0120 { 0121 static const std::forward_list<uniqueStr> homes = [] { 0122 std::forward_list<uniqueStr> res; 0123 auto add_dir = [&] (char *dir) { 0124 if (isDir(dir)) { 0125 res.emplace_front(dir); 0126 } else { 0127 free(dir); 0128 } 0129 }; 0130 add_dir(Str::cat(getHome(), ".kde/")); 0131 add_dir(Str::cat(getHome(), ".kde4/")); 0132 char *env = getenv(getuid() ? "KDEHOME" : "KDEROOTHOME"); 0133 if (env && env[0] == '/') { 0134 add_dir(Str::cat(env, "/")); 0135 } else { 0136 #ifndef QTC_KDE4_DEFAULT_HOME_DEFAULT 0137 add_dir(Str::cat(getHome(), QTC_KDE4_DEFAULT_HOME "/")); 0138 #endif 0139 } 0140 return res; 0141 }(); 0142 return homes; 0143 } 0144 0145 QTC_EXPORT const char* 0146 getConfDir() 0147 { 0148 static uniqueStr dir = [] { 0149 const char *env_home = getenv("QTCURVE_CONFIG_DIR"); 0150 char *res = ((env_home && *env_home == '/') ? Str::cat(env_home, "/") : 0151 Str::cat(getXDGConfigHome(), "qtcurve/")); 0152 makePath(res, 0700); 0153 return res; 0154 }; 0155 return dir.get(); 0156 } 0157 0158 QTC_EXPORT char* 0159 getConfFile(const char *file, char *buff) 0160 { 0161 if (file[0] == '/') 0162 return Str::fill(buff, file); 0163 return Str::fill(buff, getConfDir(), file); 0164 } 0165 0166 static const std::forward_list<std::string>& 0167 getPresetDirs() 0168 { 0169 static const std::forward_list<std::string> dirs = [] { 0170 std::forward_list<std::string> res; 0171 auto add_dir = [&] (const char *dir, bool needfree=true) { 0172 if (isDir(dir)) { 0173 res.emplace_front(dir); 0174 } 0175 if (needfree) { 0176 free(const_cast<char*>(dir)); 0177 } 0178 }; 0179 for (auto &kde_home: getKDE4Home()) { 0180 add_dir(Str::cat(kde_home.get(), "share/apps/QtCurve/")); 0181 } 0182 if (auto xdg_data_dirs = getenv("XDG_DATA_DIRS")) { 0183 while (true) { 0184 auto delim = strchr(xdg_data_dirs, ':'); 0185 if (delim) { 0186 auto origin = xdg_data_dirs; 0187 xdg_data_dirs = delim + 1; 0188 if (origin[0] != '/') 0189 continue; 0190 std::string dir(origin, delim - origin); 0191 dir += "/QtCurve/"; 0192 if (isDir(dir.c_str())) { 0193 res.push_front(std::move(dir)); 0194 } 0195 } else if (xdg_data_dirs[0] == '/') { 0196 std::string dir(xdg_data_dirs); 0197 dir += "/QtCurve/"; 0198 if (isDir(dir.c_str())) 0199 res.push_front(std::move(dir)); 0200 break; 0201 } else { 0202 break; 0203 } 0204 } 0205 } else { 0206 add_dir("/usr/local/share/QtCurve/", false); 0207 add_dir("/usr/share/QtCurve/", false); 0208 } 0209 auto xdg_home = Str::cat(getXDGDataHome(), "QtCurve/"); 0210 makePath(xdg_home, 0700); 0211 add_dir(xdg_home); 0212 return res; 0213 }(); 0214 return dirs; 0215 } 0216 0217 QTC_EXPORT std::map<std::string, std::string> 0218 getPresets() 0219 { 0220 std::map<std::string, std::string> presets; 0221 0222 for (auto &dir_name: getPresetDirs()) { 0223 DIR *dir = opendir(dir_name.c_str()); 0224 if (!dir) 0225 continue; 0226 while (auto ent = readdir(dir)) { 0227 auto fname = ent->d_name; 0228 // Non preset files 0229 if (!Str::endsWith(fname, ".qtcurve")) 0230 continue; 0231 size_t name_len = strlen(fname) - strlen(".qtcurve"); 0232 std::string name(fname, name_len); 0233 // preset already loaded 0234 if (presets.find(name) != presets.end()) 0235 continue; 0236 presets[name] = dir_name + fname; 0237 } 0238 closedir(dir); 0239 } 0240 0241 return presets; 0242 } 0243 0244 }