dedup/src/fileindexer.cpp

96 lines
2.2 KiB
C++

#include "fileindexer.h"
#include <sys/stat.h>
#include <unistd.h>
#include <Log.h>
std::multimap<uint64_t, std::shared_ptr<File>> FileIndexer::index(const SearchFolder& firstfolder) {
std::list<SearchFolder> folders;
folders.emplace_back(firstfolder);
map_t out;
while(!folders.empty()) {
SearchFolder sf = folders.front();
folders.pop_front();
DIR* dirptr = ::opendir(sf.path.c_str());
if(!dirptr) {
Log::error << "Could not open directory: " << sf.path;
continue;
}
errno = 0;
while(dirent* dircont = ::readdir(dirptr)) {
handleFolderContent(dircont, sf, folders, out);
}
if(errno != 0) {
Log::error << "failed to read directory: " << sf.path << ' ' << strerror(errno) << " (" << errno << ')';
}
::closedir(dirptr);
}
return out;
}
void FileIndexer::setIgnoreDotFiles(bool b) {
ignoredotfiles = b;
}
void FileIndexer::setIgnoreInodeIDs(bool b) {
ignoreInodeID = b;
}
void FileIndexer::handleFolderContent(dirent* dircont, const SearchFolder& sf, std::list<SearchFolder>& newfolders, map_t& newfiles) {
std::string name(dircont->d_name);
std::string filepath = sf.path + "/" + name;
// handle dotfiles
if(name == "." || name == ".." || (ignoredotfiles && name.at(0) == '.')) {
return;
}
// handle subfolders
if(dircont->d_type == DT_DIR) {
if(sf.recurse) {
newfolders.emplace_back(filepath, true);
Log::note << "found new subdir to index: " << filepath;
return;
}
}
// regular file
if(dircont->d_type == DT_REG) {
handleNewFile(dircont->d_ino, filepath, newfiles);
}
}
void FileIndexer::handleNewFile(ino_t inode, const std::string& path, map_t& newfiles) {
// check for already scanned inodes
if(!ignoreInodeID) {
auto it = knownInodes.find(inode);
if(it != knownInodes.end()) {
Log::note << "found already detected file: " << inode << ' ' << path;
return;
}
}
struct stat statbuf;
int res = stat(path.c_str(), &statbuf);
if(res == -1) {
Log::error << "stat failed: " << path << " error: " << strerror(errno) << " (" << errno << ')';
return;
}
loff_t fileSize = statbuf.st_size;
nlink_t linkCount = statbuf.st_nlink;
if(!ignoreInodeID) {
knownInodes.insert(inode);
}
newfiles.insert({fileSize, std::make_shared<File>(fileSize, inode, linkCount, path)});
}