File: pathut.h

package info (click to toggle)
recoll 1.43.9-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 16,892 kB
  • sloc: cpp: 104,589; python: 9,603; xml: 7,272; ansic: 6,447; sh: 1,212; perl: 166; makefile: 72
file content (287 lines) | stat: -rw-r--r-- 10,691 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
/* Copyright (C) 2004-2023 J.F.Dockes
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published by
 *   the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
#ifndef _PATHUT_H_INCLUDED_
#define _PATHUT_H_INCLUDED_

// Miscellaneous pathname-related utility functions, some actually accessing the filesystem, some
// purely textual. Work with Posix or Windows paths. All properly handle UTF-8 encoded non-ASCII
// paths on Windows, which is their reason for existing in many cases.

#include <string>
#include <vector>
#include <set>
#include <cstdint>
#include <fstream>
#include <memory>

#ifndef _WIN32
#include <unistd.h>
#endif

namespace MedocUtils {

// Must be called in main thread before starting other threads
extern void pathut_init_mt();

/// Add a / at the end if none there yet.
extern void path_catslash(std::string& s);
/// Concatenate 2 paths
extern std::string path_cat(const std::string& s1, const std::string& s2);
/// Concatenate 2 or more paths
extern std::string path_cat(const std::string& s1, std::initializer_list<std::string> pathelts);
/// Get the simple file name (get rid of any directory path prefix
extern std::string path_getsimple(const std::string& s);
/// Simple file name + optional suffix stripping
extern std::string path_basename(const std::string& s, const std::string& suff = std::string());
/// Component after last '.'
extern std::string path_suffix(const std::string& s);
/// Get the father directory
extern std::string path_getfather(const std::string& s);
/// Test if path is absolute
extern bool path_isabsolute(const std::string& s);
/// Test if path is root (x:/). root is defined by root/.. == root
extern bool path_isroot(const std::string& p);
/// Test if sub is a subdirectory of top. This is a textual test,
/// links not allowed. Uses path_canon to clean up paths.
extern bool path_isdesc(const std::string& top, const std::string& sub);
/// Check if path looks like a (slashized) Windows UNC path, and extract the //server/volume
extern bool path_isunc(const std::string& p, std::string& volume);

/// Clean up path by removing duplicated / and resolving ../ + make it absolute.
/// Except for possibly obtaining the current directory, the processing
/// is purely textual and does not deal with symbolic link or file existence.
extern std::string path_canon(const std::string& s, const std::string *cwd = nullptr);

/// Check that path refers to same file. Uses dev/ino on Linux,
/// textual comparison on Windows.
bool path_samefile(const std::string& p1, const std::string& p2);

/// Get the current user's home directory
extern std::string path_home();
/// Get the top location for cached data
extern std::string path_cachedir();

/// Expand ~ at the beginning of std::string
extern std::string path_tildexpand(const std::string& s);
/// Use getcwd() to make absolute path if needed. Beware: ***this can fail***
/// we return an empty path in this case.
extern std::string path_absolute(const std::string& s);

/// Stat parameter and check if it's a directory
extern bool path_isdir(const std::string& path, bool follow = false);
/// Stat parameter and check if it's a regular file
extern bool path_isfile(const std::string& path, bool follow = false);

/// Retrieve file size
extern long long path_filesize(const std::string& path);

/// Check that path is traversable and last element exists
/// Returns true if last elt could be checked to exist. False may mean that
/// the file/dir does not exist or that an error occurred.
bool path_exists(const std::string& path);
/// Same but must be readable
bool path_readable(const std::string& path);

#ifdef _WIN32

// Constants for _waccess()
#  ifndef R_OK
#    define R_OK 4
#  endif
#  ifndef W_OK
#    define W_OK 2
#  endif
#  ifndef X_OK
// Not useful/supported on Windows. Define as R_OK
#    define X_OK R_OK
#  endif
#  ifndef F_OK
#    define F_OK 0
#  endif

// Convert between slash and backslash separators.
void path_slashize(std::string& s);
void path_backslashize(std::string& s);

std::string path_shortpath(const std::string& path);
bool path_hasdrive(const std::string& s);
bool path_isdriveabs(const std::string& s);

#else // !_WIN32 ->

#define path_shortpath(path) (path)
#ifndef O_BINARY
#define O_BINARY 0
#endif
#endif /* !_WIN32 */

/// access() or _waccess()
bool path_access(const std::string& path, int mode);

/// Retrieve essential file attributes. This is used rather than a
/// bare stat() to ensure consistent use of the time fields (on
/// windows, we set ctime=mtime as ctime is actually the creation
/// time, for which we have no use).
/// st_btime (birth time) is only really set on Ux/Linux if statx() is available and the file system
/// supports it. Else it is set to st_ctime. On Windows it is set to the creation time.
/// Only st_mtime, st_ctime, st_size, st_mode (file type bits) are set on
/// all systems. st_dev and st_ino are set for special posix usage.
/// The rest is zeroed.
/// @ret 0 for success
struct PathStat {
    enum PstType {PST_REGULAR, PST_SYMLINK, PST_DIR, PST_OTHER, PST_INVALID};
    PstType pst_type{PST_INVALID};
    int64_t pst_size;
    uint64_t pst_mode;
    int64_t pst_mtime;
    int64_t pst_ctime;
    uint64_t pst_ino;
    uint64_t pst_dev;
    uint64_t pst_blocks;
    uint64_t pst_blksize;
    int64_t pst_btime;
};
extern int path_fileprops(const std::string path, struct PathStat *stp, bool follow = true);
extern int path_fileprops(int fd, struct PathStat *stp);

/// Return separator for PATH environment variable
extern const std::string& path_PATHsep();

/// Try to return the directory where this executable resides. On Linux needs main() to have called
/// pathut_setargv0()
extern void pathut_setargv0(const char *argv0);
extern std::string path_thisexecdir();
/// Determine the location for the program constant data (e.g. /usr/share/recoll)
/// @param progname the program name (e.g. "recoll")
/// @param envname  an environment variable name (e.g. RECOLL_DATADIR). This overrides all.
/// @param compiled compiled in value. May be empty.
/// @param alts list of alternate paths. tstpath will be looked for in each. Break when found.
/// @param tstpath subpath to test in the alternate paths (e.g. examples/recoll.conf).
/// @return empty if we fail, else the data location.
extern std::string path_pkgdatadir(
    const std::string& progname, const std::string& envname, const std::string& compiled = "",
    const std::vector<std::string> alts = std::vector<std::string>(),
    const std::string& tstpath = "");

// Note: this is only implemented on Linux, for path_thisexecdir() and only exported for
// testing. Not needed for this on either MacOS or Windows (use ExeCmd::which() where needed
// instead).
#if !defined(_WIN32) && !defined(__APPLE__)
extern std::string path_which(const std::string&);
#endif

/// Directory reading interface. UTF-8 on Windows.
class PathDirContents {
public:
    PathDirContents(const std::string& dirpath);
    ~PathDirContents();
    PathDirContents(const PathDirContents&) = delete;
    PathDirContents& operator=(const PathDirContents&) = delete;

    bool opendir();
    struct Entry {
        std::string d_name;
    };
    const struct Entry* readdir();
    void rewinddir();

private:
    class Internal;
    Internal *m{nullptr};
};

/// Dump directory
extern bool listdir(const std::string& dir, std::string& reason, std::set<std::string>& entries);

/** A small wrapper around statfs et al, to return percentage of disk
    occupation
    @param[output] pc percent occupied
    @param[output] avmbs Mbs available to non-superuser. Mb=1024*1024
*/
bool fsocc(const std::string& path, int *pc, long long *avmbs = nullptr);

/// mkdir -p
extern bool path_makepath(const std::string& path, int mode);

extern bool path_rename(const std::string& oldpath, const std::string& newpath);

///
bool path_chdir(const std::string& path);
std::string path_cwd();
bool path_unlink(const std::string& path);
bool path_rmdir(const std::string& path);

// Setting file times. Windows defines timeval in winsock2.h but it seems safer to use local def
// Also on Windows, we use _wutime and ignore the tv_usec part.
typedef struct path_timeval {
    int64_t tv_sec;
    int64_t tv_usec;
} path_timeval;
bool path_utimes(const std::string& path, struct path_timeval times[2]);

/// Open, path is utf-8 and we do the right thing on Windows.
int path_open(const std::string& path, int flags, int mode = 0);

/* Open file, trying to do the right thing with non-ASCII paths on
 * Windows, where it only works with MSVC at the moment if the path is
 * not ASCII, because it uses fstream(wchar_t*), which is an MSVC
 * extension. On other OSes, just builds the fstream.  We'd need to
 * find a way to make this work with g++. It would be easier in this
 * case to use a FILE (_openw(), then fdopen()), but conftree really
 * depends on std::iostream. 
 *
 * @param path an utf-8 file path.
 * @param mode is an std::fstream mode (ios::in etc.) */
extern bool path_streamopen(const std::string& path, int mode, std::fstream& outstream);


/// Lock/pid file class. This is quite close to the pidfile_xxx
/// utilities in FreeBSD with a bit more encapsulation. I'd have used
/// the freebsd code if it was available elsewhere
class Pidfile {
public:
    Pidfile(const std::string& path)    : m_path(path), m_fd(-1) {}
    ~Pidfile();
    Pidfile(const Pidfile&) = delete;
    Pidfile& operator=(const Pidfile&) = delete;
    
    /// Open/create the pid file.
    /// @return 0 if ok, > 0 for pid of existing process, -1 for other error.
    int open();
    /// Write pid into the pid file
    /// @return 0 ok, -1 error
    int write_pid();
    /// Close the pid file (unlocks)
    int close();
    /// Delete the pid file
    int remove();
    const std::string& getreason() {
        return m_reason;
    }
private:
    std::string m_path;
    int    m_fd;
    std::string m_reason;
    int read_pid();
    int flopen();
};

} // End namespace MedocUtils

using namespace MedocUtils;

#endif /* _PATHUT_H_INCLUDED_ */