1 /* Copyright (C) 2004 J.F.Dockes 2 * This program is free software; you can redistribute it and/or modify 3 * it under the terms of the GNU Lesser General Public License as published by 4 * the Free Software Foundation; either version 2.1 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU Lesser General Public License for more details. 11 * 12 * You should have received a copy of the GNU Lesser General Public License 13 * along with this program; if not, write to the 14 * Free Software Foundation, Inc., 15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 */ 17 #ifndef _PATHUT_H_INCLUDED_ 18 #define _PATHUT_H_INCLUDED_ 19 20 #include <string> 21 #include <vector> 22 #include <set> 23 #include <cstdint> 24 #include <fstream> 25 26 // Must be called in main thread before starting other threads 27 extern void pathut_init_mt(); 28 29 /// Add a / at the end if none there yet. 30 extern void path_catslash(std::string& s); 31 /// Concatenate 2 paths 32 extern std::string path_cat(const std::string& s1, const std::string& s2); 33 /// Get the simple file name (get rid of any directory path prefix 34 extern std::string path_getsimple(const std::string& s); 35 /// Simple file name + optional suffix stripping 36 extern std::string path_basename(const std::string& s, 37 const std::string& suff = std::string()); 38 /// Component after last '.' 39 extern std::string path_suffix(const std::string& s); 40 /// Get the father directory 41 extern std::string path_getfather(const std::string& s); 42 /// Test if path is absolute 43 extern bool path_isabsolute(const std::string& s); 44 /// Test if path is root (x:/). root is defined by root/.. == root 45 extern bool path_isroot(const std::string& p); 46 /// Test if sub is a subdirectory of top. This is a textual test, 47 /// links not allowed 48 extern bool path_isdesc(const std::string& top, const std::string& sub); 49 50 /// Clean up path by removing duplicated / and resolving ../ + make it absolute 51 extern std::string path_canon(const std::string& s, const std::string *cwd = 0); 52 53 /// Check that path refers to same file. Uses dev/ino on Linux, 54 /// textual comparison on Windows. 55 bool path_samefile(const std::string& p1, const std::string& p2); 56 57 /// Get the current user's home directory 58 extern std::string path_home(); 59 /// Expand ~ at the beginning of std::string 60 extern std::string path_tildexpand(const std::string& s); 61 /// Use getcwd() to make absolute path if needed. Beware: ***this can fail*** 62 /// we return an empty path in this case. 63 extern std::string path_absolute(const std::string& s); 64 65 /// Stat parameter and check if it's a directory 66 extern bool path_isdir(const std::string& path, bool follow = false); 67 /// Stat parameter and check if it's a regular file 68 extern bool path_isfile(const std::string& path, bool follow = false); 69 70 /// Retrieve file size 71 extern long long path_filesize(const std::string& path); 72 73 /// Check that path is traversable and last element exists 74 /// Returns true if last elt could be checked to exist. False may mean that 75 /// the file/dir does not exist or that an error occurred. 76 bool path_exists(const std::string& path); 77 /// Same but must be readable 78 bool path_readable(const std::string& path); 79 80 #ifdef _WIN32 81 # ifndef R_OK 82 # define R_OK 4 83 # endif 84 # ifndef W_OK 85 # define W_OK 2 86 # endif 87 # ifndef X_OK 88 // Not useful/supported on Windows. Define as R_OK 89 # define X_OK R_OK 90 # endif 91 # ifndef F_OK 92 # define F_OK 0 93 # endif 94 #endif /* _WIN32 */ 95 /// access() or _waccess() 96 bool path_access(const std::string& path, int mode); 97 98 /// Retrieve essential file attributes. This is used rather than a 99 /// bare stat() to ensure consistent use of the time fields (on 100 /// windows, we set ctime=mtime as ctime is actually the creation 101 /// time, for which we have no use). 102 /// Only st_mtime, st_ctime, st_size, st_mode (file type bits) are set on 103 /// all systems. st_dev and st_ino are set for special posix usage. 104 /// The rest is zeroed. 105 /// @ret 0 for success 106 struct PathStat { 107 enum PstType {PST_REGULAR, PST_SYMLINK, PST_DIR, PST_OTHER}; 108 PstType pst_type; 109 int64_t pst_size; 110 uint64_t pst_mode; 111 int64_t pst_mtime; 112 int64_t pst_ctime; 113 uint64_t pst_ino; 114 uint64_t pst_dev; 115 uint64_t pst_blocks; 116 uint64_t pst_blksize; 117 }; 118 extern int path_fileprops(const std::string path, struct PathStat *stp, 119 bool follow = true); 120 121 122 /// Return separator for PATH environment variable 123 extern std::string path_PATHsep(); 124 125 #ifdef _WIN32 126 #include <memory> 127 bool wchartoutf8(const wchar_t *in, std::string& out, size_t len = 0); 128 std::string wchartoutf8(const wchar_t *in, size_t len = 0); 129 bool utf8towchar(const std::string& in, wchar_t *out, size_t obytescap); 130 std::unique_ptr<wchar_t[]> utf8towchar(const std::string& in); 131 #endif 132 133 /// Directory reading interface. UTF-8 on Windows. 134 class PathDirContents { 135 public: 136 PathDirContents(const std::string& dirpath); 137 ~PathDirContents(); 138 139 bool opendir(); 140 struct Entry { 141 std::string d_name; 142 }; 143 const struct Entry* readdir(); 144 void rewinddir(); 145 146 private: 147 class Internal; 148 Internal *m{nullptr}; 149 }; 150 151 /// Dump directory 152 extern bool listdir(const std::string& dir, std::string& reason, 153 std::set<std::string>& entries); 154 155 /** A small wrapper around statfs et al, to return percentage of disk 156 occupation 157 @param[output] pc percent occupied 158 @param[output] avmbs Mbs available to non-superuser. Mb=1024*1024 159 */ 160 bool fsocc(const std::string& path, int *pc, long long *avmbs = 0); 161 162 /// mkdir -p 163 extern bool path_makepath(const std::string& path, int mode); 164 165 /// 166 bool path_chdir(const std::string& path); 167 std::string path_cwd(); 168 bool path_unlink(const std::string& path); 169 bool path_rmdir(const std::string& path); 170 171 /* Open file, trying to do the right thing with non-ASCII paths on 172 * Windows, where it only works with MSVC at the moment if the path is 173 * not ASCII, because it uses fstream(wchar_t*), which is an MSVC 174 * extension. On other OSes, just builds the fstream. We'd need to 175 * find a way to make this work with g++. It would be easier in this 176 * case to use a FILE (_openw(), then fdopen()), but conftree really 177 * depends on std::iostream. 178 * 179 * @param path an utf-8 file path. 180 * @param mode is an std::fstream mode (ios::in etc.) */ 181 extern bool path_streamopen( 182 const std::string& path, int mode, std::fstream& outstream); 183 184 /// Encode according to rfc 1738 185 extern std::string url_encode(const std::string& url, 186 std::string::size_type offs = 0); 187 extern std::string url_decode(const std::string& encoded); 188 //// Convert to file path if url is like file://. This modifies the 189 //// input (and returns a copy for convenience) 190 extern std::string fileurltolocalpath(std::string url); 191 /// Test for file:/// url 192 extern bool urlisfileurl(const std::string& url); 193 /// 194 extern std::string url_parentfolder(const std::string& url); 195 /// Return the host+path part of an url. This is not a general 196 /// routine, it does the right thing only in the recoll context 197 extern std::string url_gpath(const std::string& url); 198 /// Turn absolute path into file:// url 199 extern std::string path_pathtofileurl(const std::string& path); 200 201 /// URI parser, loosely from rfc2396.txt 202 class ParsedUri { 203 public: 204 ParsedUri(std::string uri); 205 bool parsed{false}; 206 std::string scheme; 207 std::string user; 208 std::string pass; 209 std::string host; 210 std::string port; 211 std::string path; 212 std::string query; 213 std::vector<std::pair<std::string,std::string>> parsedquery; 214 std::string fragment; 215 }; 216 217 #ifdef _WIN32 218 /// Convert \ separators to / 219 void path_slashize(std::string& s); 220 void path_backslashize(std::string& s); 221 extern std::string path_shortpath(const std::string& path); 222 #else 223 #define path_shortpath(path) (path) 224 #endif 225 226 /// Lock/pid file class. This is quite close to the pidfile_xxx 227 /// utilities in FreeBSD with a bit more encapsulation. I'd have used 228 /// the freebsd code if it was available elsewhere 229 class Pidfile { 230 public: Pidfile(const std::string & path)231 Pidfile(const std::string& path) : m_path(path), m_fd(-1) {} 232 ~Pidfile(); 233 /// Open/create the pid file. 234 /// @return 0 if ok, > 0 for pid of existing process, -1 for other error. 235 int open(); 236 /// Write pid into the pid file 237 /// @return 0 ok, -1 error 238 int write_pid(); 239 /// Close the pid file (unlocks) 240 int close(); 241 /// Delete the pid file 242 int remove(); getreason()243 const std::string& getreason() { 244 return m_reason; 245 } 246 private: 247 std::string m_path; 248 int m_fd; 249 std::string m_reason; 250 int read_pid(); 251 int flopen(); 252 }; 253 254 #endif /* _PATHUT_H_INCLUDED_ */ 255