diff --git a/src/testmains/trpathut.cpp b/src/testmains/trpathut.cpp index 9dba4898..5b723b42 100644 --- a/src/testmains/trpathut.cpp +++ b/src/testmains/trpathut.cpp @@ -2,48 +2,88 @@ #include #include +#include #include +#include using namespace std; -static const char *thisprog; -static int op_flags; -#define OPT_MOINS 0x1 -#define OPT_r 0x2 -#define OPT_s 0x4 -static char usage [] = - "pathut\n" - ; -static void -Usage(void) +static std::map options { + {"path_home", 0}, + {"path_tildexpand", 0}, + {"listdir", 0}, + }; + +static const char *thisprog; +static void Usage(void) { - fprintf(stderr, "%s: usage:\n%s", thisprog, usage); + string sopts; + for (const auto& opt: options) { + sopts += "--" + opt.first + "\n"; + } + fprintf(stderr, "%s: usage: %s\n%s", thisprog, thisprog, sopts.c_str()); exit(1); } -int main(int argc, const char **argv) +int main(int argc, char **argv) { - thisprog = argv[0]; - argc--; argv++; + thisprog = *argv; + std::vector long_options; - while (argc > 0 && **argv == '-') { - (*argv)++; - if (!(**argv)) - /* Cas du "adb - core" */ - Usage(); - while (**argv) - switch (*(*argv)++) { - default: Usage(); break; - } - b1: argc--; argv++; + for (auto& entry : options) { + struct option opt; + opt.name = entry.first.c_str(); + opt.has_arg = 0; + opt.flag = &entry.second; + opt.val = 1; + long_options.push_back(opt); } + long_options.push_back({0, 0, 0, 0}); - if (argc != 0) + while (getopt_long(argc, argv, "", &long_options[0], nullptr) != -1) { + } + if (options["path_home"]) { + if (optind != argc) { + cerr << "Usage: trsmallut --path_home\n"; + return 1; + } + cout << "path_home() -> [" << path_home() << "]\n"; + } else if (options["path_tildexpand"]) { + if (optind >= argc) { + cerr << "Usage: trsmallut --path_tildexpand \n"; + return 1; + } + string s = argv[optind]; + argc--; + if (optind != argc) { + return 1; + } + cout << "path_tildexpand(" << s << ") -> [" << path_tildexpand(s) << + "]\n"; + } else if (options["listdir"]) { + if (optind >= argc) { + cerr << "Usage: trsmallut --listdir \n"; + return 1; + } + std::string path = argv[optind]; + argc--; + if (optind != argc) { + cerr << "Usage: trsmallut --listdir \n"; + return 1; + } + std::string reason; + std::set entries; + if (!listdir(path, reason, entries)) { + std::cerr<< "listdir(" << path << ") failed : " << reason << "\n"; + return 1; + } + for (const auto& entry : entries) { + cout << entry << "\n"; + } + } else { Usage(); - - cout << "path_home() -> [" << path_home() << "]\n"; - cout << "path_tildexpand(~) -> [" << path_tildexpand("~") << "]\n"; + } return 0; } diff --git a/src/utils/fstreewalk.cpp b/src/utils/fstreewalk.cpp index b9a4f1be..9e468ff4 100644 --- a/src/utils/fstreewalk.cpp +++ b/src/utils/fstreewalk.cpp @@ -19,17 +19,10 @@ #include -#ifdef _MSC_VER -#include "msvc_dirent.h" -#else // !_MSC_VER -#include -#endif // _MSC_VER - #include #include #include #include - #include #include #include @@ -39,7 +32,6 @@ #include "log.h" #include "pathut.h" #include "fstreewalk.h" -#include "transcode.h" using namespace std; @@ -329,20 +321,6 @@ FsTreeWalker::Status FsTreeWalker::walk(const string& _top, FsTreeWalkerCB& cb) return FtwOk; } -#ifdef _WIN32 -#define DIRENT _wdirent -#define DIRHDL _WDIR -#define OPENDIR _wopendir -#define CLOSEDIR _wclosedir -#define READDIR _wreaddir -#else -#define DIRENT dirent -#define DIRHDL DIR -#define OPENDIR opendir -#define CLOSEDIR closedir -#define READDIR readdir -#endif - // Note that the 'norecurse' flag is handled as part of the directory read. // This means that we always go into the top 'walk()' parameter if it is a // directory, even if norecurse is set. Bug or Feature ? @@ -391,20 +369,9 @@ FsTreeWalker::Status FsTreeWalker::iwalk(const string &top, } #endif - SYSPATH(top, systop); - DIRHDL *d = OPENDIR(systop); - if (nullptr == d) { + PathDirContents dc(top); + if (!dc.opendir()) { data->logsyserr("opendir", top); -#ifdef _WIN32 - int rc = GetLastError(); - LOGERR("opendir failed: LastError " << rc << endl); - if (rc == ERROR_NETNAME_DELETED) { - // 64: share disconnected. - // Not too sure of the errno in this case. - // Make sure it's not one of the permissible ones - errno = ENODEV; - } -#endif switch (errno) { case EPERM: case EACCES: @@ -421,25 +388,20 @@ FsTreeWalker::Status FsTreeWalker::iwalk(const string &top, } } - struct DIRENT *ent; - while (errno = 0, ((ent = READDIR(d)) != 0)) { + const struct PathDirContents::Entry *ent; + while (errno = 0, ((ent = dc.readdir()) != nullptr)) { string fn; struct PathStat st; -#ifdef _WIN32 - string sdname; - if (!wchartoutf8(ent->d_name, sdname)) { - LOGERR("wchartoutf8 failed in " << top << endl); + const string& dname{ent->d_name}; + if (dname.empty()) { + // ??? continue; } - const char *dname = sdname.c_str(); -#else - const char *dname = ent->d_name; -#endif // Maybe skip dotfiles if ((data->options & FtwSkipDotFiles) && dname[0] == '.') continue; // Skip . and .. - if (!strcmp(dname, ".") || !strcmp(dname, "..")) + if (dname == "." || dname == "..") continue; // Skipped file names match ? @@ -530,8 +492,6 @@ FsTreeWalker::Status FsTreeWalker::iwalk(const string &top, } out: - if (d) - CLOSEDIR(d); return status; } diff --git a/src/utils/pathut.cpp b/src/utils/pathut.cpp index 8484181c..71d59bce 100644 --- a/src/utils/pathut.cpp +++ b/src/utils/pathut.cpp @@ -68,9 +68,15 @@ #include #include -#ifndef PRETEND_USE -#define PRETEND_USE(expr) ((void)(expr)) -#endif +// Listing directories: we include the normal dirent.h on Unix-derived +// systems, and on MinGW, where it comes with a supplemental wide char +// interface. When building with MSVC, we use our bundled msvc_dirent.h, +// which is equivalent to the one in MinGW +#ifdef _MSC_VER +#include "msvc_dirent.h" +#else // !_MSC_VER +#include +#endif // _MSC_VER #ifdef _WIN32 @@ -115,14 +121,17 @@ #define LSTAT _wstati64 #define STATBUF _stati64 #define ACCESS _waccess -#define OPENDIR _wopendir +#define OPENDIR ::_wopendir +#define DIRHDL _WDIR #define CLOSEDIR _wclosedir -#define READDIR _wreaddir +#define READDIR ::_wreaddir +#define REWINDDIR ::_wrewinddir #define DIRENT _wdirent #define DIRHDL _WDIR #define MKDIR(a,b) _wmkdir(a) #define OPEN ::_wopen #define UNLINK _wunlink +#define RMDIR _wrmdir #define CHDIR _wchdir #define ftruncate _chsize_s @@ -149,25 +158,22 @@ #define LSTAT lstat #define STATBUF stat #define ACCESS access -#define OPENDIR opendir +#define OPENDIR ::opendir +#define DIRHDL DIR #define CLOSEDIR closedir -#define READDIR readdir +#define READDIR ::readdir +#define REWINDDIR ::rewinddir #define DIRENT dirent #define DIRHDL DIR #define MKDIR(a,b) mkdir(a,b) #define O_BINARY 0 #define OPEN ::open #define UNLINK ::unlink +#define RMDIR ::rmdir #define CHDIR ::chdir #endif /* !_WIN32 */ -#ifdef _MSC_VER -#include -#else // !_MSC_VER -#include -#endif // _MSC_VER - using namespace std; #ifndef PATHUT_SSIZE_T @@ -645,28 +651,6 @@ string path_home() #endif } -// The default place to store the default config and other stuff (e.g webqueue) -string path_homedata() -{ -#ifdef _WIN32 - wchar_t *cp; - SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &cp); - string dir; - if (cp != 0) { - wchartoutf8(cp, dir); - } - if (!dir.empty()) { - dir = path_canon(dir); - } else { - dir = path_cat(path_home(), "AppData/Local/"); - } - return dir; -#else - // We should use an xdg-conforming location, but, history... - return path_home(); -#endif -} - string path_tildexpand(const string& s) { if (s.empty() || s[0] != '~') { @@ -889,6 +873,12 @@ bool path_unlink(const std::string& path) return UNLINK(syspath) == 0; } +bool path_rmdir(const std::string& path) +{ + SYSPATH(path, syspath); + return RMDIR(syspath) == 0; +} + #if !defined(__GNUC__) || __GNUC__ > 4 || defined(__clang__) // Not sure what g++ version supports fstream assignment but 4.9 // (jessie) certainly does not @@ -1032,6 +1022,11 @@ bool path_readable(const string& path) SYSPATH(path, syspath); return ACCESS(syspath, R_OK) == 0; } +bool path_access(const std::string& path, int mode) +{ + SYSPATH(path, syspath); + return ACCESS(syspath, mode) == 0; +} /* There is a lot of vagueness about what should be percent-encoded or * not in a file:// url. The constraint that we have is that we may use @@ -1296,56 +1291,105 @@ ParsedUri::ParsedUri(std::string uri) } } +/// Directory reading interface. UTF-8 on Windows. +class PathDirContents::Internal { +public: + ~Internal() { + if (dirhdl) { + CLOSEDIR(dirhdl); + } + } + + DIRHDL *dirhdl{nullptr}; + PathDirContents::Entry entry; + std::string dirpath; +}; + +PathDirContents::PathDirContents(const std::string& dirpath) +{ + m = new Internal; + m->dirpath = dirpath; +} + +PathDirContents::~PathDirContents() +{ + delete m; +} + +bool PathDirContents::opendir() +{ + if (m->dirhdl) { + CLOSEDIR(m->dirhdl); + m->dirhdl = nullptr; + } + SYSPATH(m->dirpath, sysdir); + m->dirhdl = OPENDIR(sysdir); +#ifdef _WIN32 + int rc = GetLastError(); + LOGERR("opendir failed: LastError " << rc << endl); + if (rc == ERROR_NETNAME_DELETED) { + // 64: share disconnected. + // Not too sure of the errno in this case. + // Make sure it's not one of the permissible ones + errno = ENODEV; + } +#endif + return ! (nullptr == m->dirhdl); +} + +void PathDirContents::rewinddir() +{ + REWINDDIR(m->dirhdl); +} + +const struct PathDirContents::Entry* PathDirContents::readdir() +{ + struct DIRENT *ent = READDIR(m->dirhdl); + if (nullptr == ent) { + return nullptr; + } +#ifdef _WIN32 + string sdname; + if (!wchartoutf8(ent->d_name, sdname)) { + LOGERR("wchartoutf8 failed for " << ent->d_name << endl); + return nullptr; + } + const char *dname = sdname.c_str(); +#else + const char *dname = ent->d_name; +#endif + m->entry.d_name = dname; + return &m->entry; +} + + bool listdir(const string& dir, string& reason, set& entries) { - struct STATBUF st; - int statret; ostringstream msg; - DIRHDL *d = 0; - - SYSPATH(dir, sysdir); - - statret = LSTAT(sysdir, &st); - if (statret == -1) { - msg << "listdir: cant stat " << dir << " errno " << errno; - goto out; - } - if (!S_ISDIR(st.st_mode)) { + PathDirContents dc(dir); + + if (!path_isdir(dir)) { msg << "listdir: " << dir << " not a directory"; goto out; } - if (ACCESS(sysdir, R_OK) < 0) { + if (!path_access(dir, R_OK)) { msg << "listdir: no read access to " << dir; goto out; } - d = OPENDIR(sysdir); - if (d == 0) { + if (!dc.opendir()) { msg << "listdir: cant opendir " << dir << ", errno " << errno; goto out; } - - struct DIRENT *ent; - while ((ent = READDIR(d)) != 0) { -#ifdef _WIN32 - string sdname; - if (!wchartoutf8(ent->d_name, sdname)) { + const struct PathDirContents::Entry *ent; + while ((ent = dc.readdir()) != 0) { + if (ent->d_name == "." || ent->d_name == "..") { continue; } - const char *dname = sdname.c_str(); -#else - const char *dname = ent->d_name; -#endif - if (!strcmp(dname, ".") || !strcmp(dname, "..")) { - continue; - } - entries.insert(dname); + entries.insert(ent->d_name); } out: - if (d) { - CLOSEDIR(d); - } reason = msg.str(); if (reason.empty()) { return true; diff --git a/src/utils/pathut.h b/src/utils/pathut.h index be1b4206..79528ee3 100644 --- a/src/utils/pathut.h +++ b/src/utils/pathut.h @@ -39,6 +39,21 @@ extern std::string path_basename(const std::string& s, 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 +extern bool path_isdesc(const std::string& top, const std::string& sub); + +/// Clean up path by removing duplicated / and resolving ../ + make it absolute +extern std::string path_canon(const std::string& s, const std::string *cwd = 0); + +/// 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(); /// Expand ~ at the beginning of std::string @@ -46,26 +61,6 @@ 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); -/// Clean up path by removing duplicated / and resolving ../ + make it absolute -extern std::string path_canon(const std::string& s, const std::string *cwd = 0); -/// Use glob(3) to return the file names matching pattern inside dir -extern std::vector path_dirglob(const std::string& dir, - const std::string pattern); -/// Encode according to rfc 1738 -extern std::string url_encode(const std::string& url, - std::string::size_type offs = 0); -extern std::string url_decode(const std::string& encoded); -//// Convert to file path if url is like file://. This modifies the -//// input (and returns a copy for convenience) -extern std::string fileurltolocalpath(std::string url); -/// Test for file:/// url -extern bool urlisfileurl(const std::string& url); -/// -extern std::string url_parentfolder(const std::string& url); - -/// Return the host+path part of an url. This is not a general -/// routine, it does the right thing only in the recoll context -extern std::string url_gpath(const std::string& url); /// Stat parameter and check if it's a directory extern bool path_isdir(const std::string& path, bool follow = false); @@ -75,7 +70,30 @@ extern bool path_isfile(const std::string& path, bool follow = false); /// Retrieve file size extern long long path_filesize(const std::string& path); -bool path_samefile(const std::string& p1, const std::string& p2); +/// 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 +# 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 +#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 @@ -100,12 +118,6 @@ struct PathStat { extern int path_fileprops(const std::string path, struct PathStat *stp, bool follow = true); -/// 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. -extern bool path_exists(const std::string& path); -/// Same but must be readable -extern bool path_readable(const std::string& path); /// Return separator for PATH environment variable extern std::string path_PATHsep(); @@ -121,6 +133,24 @@ extern bool utf8towchar(const std::string& in, wchar_t *out, size_t obytescap); #define SYSPATH(PATH, SPATH) const char *SPATH = PATH.c_str() #endif +/// Directory reading interface. UTF-8 on Windows. +class PathDirContents { +public: + PathDirContents(const std::string& dirpath); + ~PathDirContents(); + + 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& entries); @@ -136,10 +166,11 @@ bool fsocc(const std::string& path, int *pc, long long *avmbs = 0); extern bool path_makepath(const std::string& path, int mode); /// -extern bool path_chdir(const std::string& path); -extern std::string path_cwd(); -extern bool path_unlink(const std::string& path); - +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); + /* 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 @@ -151,20 +182,23 @@ extern bool path_unlink(const std::string& path); * @param path an utf-8 file path. * @param mode is an std::fstream mode (ios::in etc.) */ extern std::fstream path_open(const std::string& path, int mode); -extern bool path_open(const std::string& path, int mode, std::fstream& outstream); - -/// Where we create the user data subdirs -extern std::string path_homedata(); -/// 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 -extern bool path_isdesc(const std::string& top, const std::string& sub); +extern bool path_open( + const std::string& path, int mode, std::fstream& outstream); +/// Encode according to rfc 1738 +extern std::string url_encode(const std::string& url, + std::string::size_type offs = 0); +extern std::string url_decode(const std::string& encoded); +//// Convert to file path if url is like file://. This modifies the +//// input (and returns a copy for convenience) +extern std::string fileurltolocalpath(std::string url); +/// Test for file:/// url +extern bool urlisfileurl(const std::string& url); +/// +extern std::string url_parentfolder(const std::string& url); +/// Return the host+path part of an url. This is not a general +/// routine, it does the right thing only in the recoll context +extern std::string url_gpath(const std::string& url); /// Turn absolute path into file:// url extern std::string path_pathtofileurl(const std::string& path); diff --git a/src/utils/rclutil.cpp b/src/utils/rclutil.cpp index 9ee1b3bd..1312b1fb 100644 --- a/src/utils/rclutil.cpp +++ b/src/utils/rclutil.cpp @@ -194,6 +194,28 @@ static bool path_gettempfilename(string& filename, string& reason) } #endif // posix +// The default place to store the default config and other stuff (e.g webqueue) +string path_homedata() +{ +#ifdef _WIN32 + wchar_t *cp; + SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &cp); + string dir; + if (cp != 0) { + wchartoutf8(cp, dir); + } + if (!dir.empty()) { + dir = path_canon(dir); + } else { + dir = path_cat(path_home(), "AppData/Local/"); + } + return dir; +#else + // We should use an xdg-conforming location, but, history... + return path_home(); +#endif +} + // Check if path is either non-existing or an empty directory. bool path_empty(const string& path) { diff --git a/src/utils/rclutil.h b/src/utils/rclutil.h index a8236daa..de6abd3a 100644 --- a/src/utils/rclutil.h +++ b/src/utils/rclutil.h @@ -33,6 +33,9 @@ extern std::string path_defaultrecollconfsubdir(); // Check if path is either non-existing or an empty directory. extern bool path_empty(const std::string& path); +/// Where we create the user data subdirs +extern std::string path_homedata(); + /// e.g. /usr/share/recoll. Depends on OS and config extern const std::string& path_pkgdatadir(); diff --git a/src/utils/smallut.h b/src/utils/smallut.h index 2c5fc492..a2a0218b 100644 --- a/src/utils/smallut.h +++ b/src/utils/smallut.h @@ -41,6 +41,9 @@ void smallut_init_mt(); #ifndef deleteZ #define deleteZ(X) {delete X;X = 0;} #endif +#ifndef PRETEND_USE +#define PRETEND_USE(var) ((void)(var)) +#endif #endif /* SMALLUT_DISABLE_MACROS */ // Case-insensitive compare. ASCII ONLY ! diff --git a/src/utils/wipedir.cpp b/src/utils/wipedir.cpp index f0d09063..847b04a1 100644 --- a/src/utils/wipedir.cpp +++ b/src/utils/wipedir.cpp @@ -19,140 +19,72 @@ #include "wipedir.h" -#include -#include - -#include #include #include "log.h" #include "pathut.h" -#ifdef _MSC_VER -#include "msvc_dirent.h" -#else // !_MSC_VER -#include -#endif // _MSC_VER - #ifdef _WIN32 -#include "safefcntl.h" -#include "safeunistd.h" -#include "safewindows.h" -#include "safesysstat.h" -#include "transcode.h" - -#define STAT _wstati64 -#define LSTAT _wstati64 -#define STATBUF _stati64 -#define ACCESS _waccess -#define OPENDIR _wopendir -#define CLOSEDIR _wclosedir -#define READDIR _wreaddir -#define DIRENT _wdirent -#define DIRHDL _WDIR -#define UNLINK _wunlink -#define RMDIR _wrmdir - +# include "safeunistd.h" #else // Not windows -> - -#include -#include -#include - -#define STAT stat -#define LSTAT lstat -#define STATBUF stat -#define ACCESS access -#define OPENDIR opendir -#define CLOSEDIR closedir -#define READDIR readdir -#define DIRENT dirent -#define DIRHDL DIR -#define UNLINK unlink -#define RMDIR rmdir +# include #endif -using namespace std; -int wipedir(const string& dir, bool selfalso, bool recurse) +int wipedir(const std::string& dir, bool selfalso, bool recurse) { - struct STATBUF st; - int statret; int ret = -1; - SYSPATH(dir, sysdir); - statret = LSTAT(sysdir, &st); - if (statret == -1) { - LOGSYSERR("wipedir", "stat", dir); - return -1; - } - if (!S_ISDIR(st.st_mode)) { - LOGERR("wipedir: " << dir << " not a directory\n"); - return -1; + if (!path_isdir(dir)) { + LOGERR("wipedir: " << dir << " not a directory\n"); + return -1; } - if (ACCESS(sysdir, R_OK|W_OK|X_OK) < 0) { - LOGSYSERR("wipedir", "access", dir); - return -1; + if (!path_access(dir, R_OK|W_OK|X_OK)) { + LOGSYSERR("wipedir", "access", dir); + return -1; } - DIRHDL *d = OPENDIR(sysdir); - if (d == 0) { - LOGSYSERR("wipedir", "opendir", dir); - return -1; + PathDirContents dc(dir); + if (!dc.opendir()) { + LOGSYSERR("wipedir", "opendir", dir); + return -1; } int remaining = 0; - struct DIRENT *ent; - while ((ent = READDIR(d)) != 0) { -#ifdef _WIN32 - string sdname; - if (!wchartoutf8(ent->d_name, sdname)) { + const struct PathDirContents::Entry *ent; + while ((ent = dc.readdir()) != 0) { + const std::string& dname{ent->d_name}; + if (dname == "." || dname == "..") continue; - } - const char *dname = sdname.c_str(); -#else - const char *dname = ent->d_name; -#endif - if (!strcmp(dname, ".") || !strcmp(dname, "..")) - continue; - string fn = path_cat(dir, dname); + std::string fn = path_cat(dir, dname); - SYSPATH(fn, sysfn); - struct STATBUF st; - int statret = LSTAT(sysfn, &st); - if (statret == -1) { - LOGSYSERR("wipedir", "stat", fn); - goto out; - } - if (S_ISDIR(st.st_mode)) { - if (recurse) { - int rr = wipedir(fn, true, true); - if (rr == -1) - goto out; - else - remaining += rr; + if (path_isdir(fn)) { + if (recurse) { + int rr = wipedir(fn, true, true); + if (rr == -1) + goto out; + else + remaining += rr; + } else { + remaining++; + } } else { - remaining++; + if (!path_unlink(fn)) { + LOGSYSERR("wipedir", "unlink", fn); + goto out; + } } - } else { - if (UNLINK(sysfn) < 0) { - LOGSYSERR("wipedir", "unlink", fn); - goto out; - } - } } ret = remaining; if (selfalso && ret == 0) { - if (RMDIR(sysdir) < 0) { - LOGSYSERR("wipedir", "rmdir", dir); - ret = -1; - } + if (!path_rmdir(dir)) { + LOGSYSERR("wipedir", "rmdir", dir); + ret = -1; + } } out: - if (d) - CLOSEDIR(d); return ret; }