2020-12-14 13:40:42 +01:00
|
|
|
|
#include "files.h"
|
2020-09-28 23:49:14 +02:00
|
|
|
|
|
2020-10-02 15:54:12 +02:00
|
|
|
|
#include <dirent.h>
|
2021-02-07 21:25:58 +01:00
|
|
|
|
#include <fstream>
|
2020-10-02 15:54:12 +02:00
|
|
|
|
#include <list>
|
|
|
|
|
#include <set>
|
2020-10-08 10:34:12 +02:00
|
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <sys/types.h>
|
2020-11-03 21:02:16 +01:00
|
|
|
|
#include <sys/stat.h>
|
2020-10-08 10:34:12 +02:00
|
|
|
|
|
2020-10-02 15:54:12 +02:00
|
|
|
|
#include "util.h"
|
|
|
|
|
|
2020-12-14 13:40:42 +01:00
|
|
|
|
#ifndef PATH_MAX
|
|
|
|
|
#define PATH_MAX 1024
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-10-07 13:03:07 +02:00
|
|
|
|
void mrbesen::files::parent(const std::string& child, std::string& out) {
|
2020-09-28 23:49:14 +02:00
|
|
|
|
//letzten path trenner finden
|
|
|
|
|
size_t pos = child.rfind('/', child.length() -2); //das erste Zeichen überspringen (könnte ein / sein)
|
|
|
|
|
if(pos == std::string::npos)
|
|
|
|
|
pos = child.rfind('\\');
|
|
|
|
|
if(pos != std::string::npos)
|
|
|
|
|
out = child.substr(0, pos+1);
|
|
|
|
|
else
|
|
|
|
|
out = "";
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-07 13:03:07 +02:00
|
|
|
|
void mrbesen::files::file(const std::string& path, std::string& out) {
|
2020-09-28 23:49:14 +02:00
|
|
|
|
//letzten path trenner finden
|
|
|
|
|
size_t pos = path.rfind('/', path.length() -2); //das erste Zeichen überspringen (könnte ein / sein)
|
|
|
|
|
if(pos == std::string::npos)
|
|
|
|
|
pos = path.rfind('\\');
|
|
|
|
|
if(pos != std::string::npos)
|
|
|
|
|
out = path.substr(pos+1);
|
|
|
|
|
else
|
|
|
|
|
out = path;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-07 13:03:07 +02:00
|
|
|
|
void mrbesen::files::extention(const std::string& path, std::string& ext) {
|
2020-09-29 14:04:19 +02:00
|
|
|
|
std::string filestr;
|
|
|
|
|
file(path, filestr);
|
|
|
|
|
size_t pos = filestr.rfind('.');
|
|
|
|
|
|
|
|
|
|
if(pos == std::string::npos || pos+1 == filestr.size()) {
|
2020-09-28 23:49:14 +02:00
|
|
|
|
ext = "";
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-09-29 14:04:19 +02:00
|
|
|
|
|
|
|
|
|
ext = filestr.substr(pos+1);
|
2020-09-28 23:49:14 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-07 21:25:58 +01:00
|
|
|
|
bool mrbesen::files::iterateFile(const std::string& filename, fileLineCallback clb, bool ignoreBlanks) {
|
|
|
|
|
std::ifstream fs(filename);
|
|
|
|
|
return iterateFile(fs, clb, ignoreBlanks);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool mrbesen::files::iterateFile(std::istream& file, fileLineCallback clb, bool ignoreBlanks) {
|
|
|
|
|
if(!clb) return false;
|
|
|
|
|
if(!file) return false;
|
|
|
|
|
|
|
|
|
|
std::string line;
|
|
|
|
|
while(std::getline(file, line)) {
|
|
|
|
|
mrbesen::util::removeEnd(line, "\r");
|
|
|
|
|
|
|
|
|
|
if(ignoreBlanks && line.empty())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
clb(line);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-02 15:54:12 +02:00
|
|
|
|
template<class Container>
|
2020-10-07 13:03:07 +02:00
|
|
|
|
bool mrbesen::files::scan(const std::string& path, std::insert_iterator<Container> it, bool prefixdir, fileNameFilter fnf) {
|
2021-09-07 02:05:18 +02:00
|
|
|
|
return scan(path, [&](const std::string& p, [[maybe_unused]] FileType t){ it = p; }, prefixdir, fnf);
|
2020-10-02 17:35:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//curently only these are supported, because iterators may break on others upon insertion
|
2020-10-07 13:03:07 +02:00
|
|
|
|
template bool mrbesen::files::scan<std::list<std::string>>(const std::string&, std::insert_iterator<std::list<std::string>>, bool, fileNameFilter);
|
|
|
|
|
template bool mrbesen::files::scan<std::set<std::string>>(const std::string&, std::insert_iterator<std::set<std::string>>, bool, fileNameFilter);
|
|
|
|
|
template bool mrbesen::files::scan<std::multiset<std::string>>(const std::string&, std::insert_iterator<std::multiset<std::string>>, bool, fileNameFilter);
|
2020-10-02 17:35:48 +02:00
|
|
|
|
|
2020-10-07 13:03:07 +02:00
|
|
|
|
bool mrbesen::files::scan(const std::string& path, fileCallback clb, bool prefixdir, fileNameFilter fnf) {
|
2020-12-14 15:18:07 +01:00
|
|
|
|
#if defined(_WIN32) ||defined(_WIN64)
|
|
|
|
|
return false;
|
|
|
|
|
#else
|
2020-10-02 15:54:12 +02:00
|
|
|
|
std::string path_ = path;
|
2020-10-07 13:03:07 +02:00
|
|
|
|
mrbesen::util::insertEnd(path_, "/");
|
2020-10-02 15:54:12 +02:00
|
|
|
|
|
|
|
|
|
::DIR* dir = opendir(path_.c_str());
|
|
|
|
|
if(!dir) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//read dir
|
|
|
|
|
struct ::dirent* entr;
|
|
|
|
|
while((entr = readdir(dir))) {
|
|
|
|
|
std::string fname = entr->d_name;
|
|
|
|
|
FileType type = (FileType) entr->d_type; //DT_BLK DT_CHR DT_DIR DT_FIFO DT_LNK DT_REG DT_SOCK DT_UNKNOWN (dirent.h, man readdir)
|
|
|
|
|
if(fnf) {
|
|
|
|
|
if(!fnf(fname, type)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(prefixdir)
|
|
|
|
|
fname = path_ + fname;
|
2020-10-02 17:35:48 +02:00
|
|
|
|
clb(fname, type);
|
2020-10-02 15:54:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
closedir(dir);
|
|
|
|
|
|
|
|
|
|
return true;
|
2020-12-14 15:18:07 +01:00
|
|
|
|
#endif
|
2020-10-02 15:54:12 +02:00
|
|
|
|
}
|
2020-10-08 10:34:12 +02:00
|
|
|
|
|
|
|
|
|
bool mrbesen::files::readFile(const std::string& name, std::ostream& output, unsigned int maxsize) {
|
|
|
|
|
int fd = open(name.c_str(), O_RDONLY);
|
|
|
|
|
bool ret = readFile(fd, output, maxsize);
|
|
|
|
|
close(fd);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool mrbesen::files::readFile(int fd, std::ostream& output, unsigned int maxsize) {
|
|
|
|
|
if(fd < 0) return false;
|
|
|
|
|
|
|
|
|
|
const int BUFFERSIZE = 1024;
|
|
|
|
|
ssize_t readc;
|
|
|
|
|
uint32_t readbytes = 0;
|
|
|
|
|
do {
|
|
|
|
|
char b[BUFFERSIZE];
|
|
|
|
|
readc = read(fd, b, BUFFERSIZE);
|
|
|
|
|
if(readc == -1) return false; //error
|
|
|
|
|
output << std::string(b, readc);
|
|
|
|
|
readbytes += readc;
|
|
|
|
|
} while(readc == BUFFERSIZE && (readbytes < maxsize || maxsize == 0));
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-03 21:02:16 +01:00
|
|
|
|
bool mrbesen::files::copy(int fd_from, int fd_to) {
|
|
|
|
|
static const uint32_t BUFFERSIZE = 4096;
|
|
|
|
|
char buf[BUFFERSIZE];
|
|
|
|
|
ssize_t rc = -1;
|
|
|
|
|
while(rc) {
|
|
|
|
|
rc = read(fd_from, buf, BUFFERSIZE);
|
|
|
|
|
if(rc < 0) return false; //reading error
|
|
|
|
|
if(rc > 0) {
|
|
|
|
|
ssize_t wc = write(fd_to, buf, rc);
|
|
|
|
|
if(wc != rc) return false; //writing error
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool mrbesen::files::copy(const std::string& from, const std::string& to) {
|
|
|
|
|
int fd1 = open(from.c_str(), O_RDONLY);
|
|
|
|
|
if(fd1 < 0) return false;
|
|
|
|
|
|
|
|
|
|
struct stat sb;
|
|
|
|
|
if(fstat(fd1, &sb)) {
|
|
|
|
|
close(fd1);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
int fd2 = open(to.c_str(), O_WRONLY | O_CREAT, sb.st_mode);
|
|
|
|
|
|
|
|
|
|
bool r = false;
|
|
|
|
|
if(fd2 > -1)
|
|
|
|
|
r = copy(fd1, fd2);
|
|
|
|
|
|
|
|
|
|
close(fd1);
|
|
|
|
|
close(fd2);
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
}
|
2020-12-10 21:09:20 +01:00
|
|
|
|
|
|
|
|
|
std::string mrbesen::files::realPath(const std::string& str) {
|
2020-12-14 13:40:42 +01:00
|
|
|
|
#if defined(_WIN32) ||defined(_WIN64)
|
|
|
|
|
wchar_t bufferin[PATH_MAX];
|
|
|
|
|
for(uint32_t i = 0; i < str.size(); ++i) {
|
|
|
|
|
bufferin[i] = str[i];
|
|
|
|
|
}
|
|
|
|
|
bufferin[str.size()] = 0;
|
|
|
|
|
|
|
|
|
|
wchar_t bufferA[PATH_MAX];
|
|
|
|
|
wchar_t* ret = ::_wfullpath(bufferA, bufferin, PATH_MAX);
|
|
|
|
|
char buffer[PATH_MAX];
|
|
|
|
|
for(uint32_t i = 0; ret[i]; ++i) {
|
|
|
|
|
buffer[i] = ret[i];
|
|
|
|
|
}
|
|
|
|
|
#else
|
2020-12-10 21:09:20 +01:00
|
|
|
|
char buffer[PATH_MAX];
|
|
|
|
|
char* ret = ::realpath(str.c_str(), buffer);
|
2020-12-14 13:40:42 +01:00
|
|
|
|
#endif
|
2020-12-10 21:09:20 +01:00
|
|
|
|
if(ret == nullptr) return "";
|
|
|
|
|
return std::string(buffer);
|
|
|
|
|
}
|