mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-11-04 09:15:29 +01:00 
			
		
		
		
	Better file/directory removal platform code and utilities
This commit is contained in:
		
							
								
								
									
										134
									
								
								src/filesys.cpp
									
									
									
									
									
								
							
							
						
						
									
										134
									
								
								src/filesys.cpp
									
									
									
									
									
								
							@@ -138,32 +138,75 @@ bool PathExists(std::string path)
 | 
			
		||||
	return (GetFileAttributes(path.c_str()) != INVALID_FILE_ATTRIBUTES);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool IsDir(std::string path)
 | 
			
		||||
{
 | 
			
		||||
	DWORD attr = GetFileAttributes(path.c_str());
 | 
			
		||||
	return (attr != INVALID_FILE_ATTRIBUTES &&
 | 
			
		||||
			(attr & FILE_ATTRIBUTE_DIRECTORY));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RecursiveDelete(std::string path)
 | 
			
		||||
{
 | 
			
		||||
	infostream<<"Removing \""<<path<<"\""<<std::endl;
 | 
			
		||||
	infostream<<"Recursively deleting \""<<path<<"\""<<std::endl;
 | 
			
		||||
 | 
			
		||||
	//return false;
 | 
			
		||||
	
 | 
			
		||||
	// This silly function needs a double-null terminated string...
 | 
			
		||||
	// Well, we'll just make sure it has at least two, then.
 | 
			
		||||
	path += "\0\0";
 | 
			
		||||
 | 
			
		||||
	SHFILEOPSTRUCT sfo;
 | 
			
		||||
	sfo.hwnd = NULL;
 | 
			
		||||
	sfo.wFunc = FO_DELETE;
 | 
			
		||||
	sfo.pFrom = path.c_str();
 | 
			
		||||
	sfo.pTo = NULL;
 | 
			
		||||
	sfo.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR;
 | 
			
		||||
	
 | 
			
		||||
	int r = SHFileOperation(&sfo);
 | 
			
		||||
 | 
			
		||||
	if(r != 0)
 | 
			
		||||
		errorstream<<"SHFileOperation returned "<<r<<std::endl;
 | 
			
		||||
 | 
			
		||||
	//return (r == 0);
 | 
			
		||||
	DWORD attr = GetFileAttributes(path.c_str());
 | 
			
		||||
	bool is_directory = (attr != INVALID_FILE_ATTRIBUTES &&
 | 
			
		||||
			(attr & FILE_ATTRIBUTE_DIRECTORY));
 | 
			
		||||
	if(!is_directory)
 | 
			
		||||
	{
 | 
			
		||||
		infostream<<"RecursiveDelete: Deleting file "<<path<<std::endl;
 | 
			
		||||
		//bool did = DeleteFile(path.c_str());
 | 
			
		||||
		bool did = true;
 | 
			
		||||
		if(!did){
 | 
			
		||||
			errorstream<<"RecursiveDelete: Failed to delete file "
 | 
			
		||||
					<<path<<std::endl;
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		infostream<<"RecursiveDelete: Deleting content of directory "
 | 
			
		||||
				<<path<<std::endl;
 | 
			
		||||
		std::vector<DirListNode> content = GetDirListing(path);
 | 
			
		||||
		for(int i=0; i<content.size(); i++){
 | 
			
		||||
			const DirListNode &n = content[i];
 | 
			
		||||
			std::string fullpath = path + DIR_DELIM + n.name;
 | 
			
		||||
			bool did = RecursiveDelete(fullpath);
 | 
			
		||||
			if(!did){
 | 
			
		||||
				errorstream<<"RecursiveDelete: Failed to recurse to "
 | 
			
		||||
						<<fullpath<<std::endl;
 | 
			
		||||
				return false;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		infostream<<"RecursiveDelete: Deleting directory "<<path<<std::endl;
 | 
			
		||||
		//bool did = RemoveDirectory(path.c_str();
 | 
			
		||||
		bool did = true;
 | 
			
		||||
		if(!did){
 | 
			
		||||
			errorstream<<"Failed to recursively delete directory "
 | 
			
		||||
					<<path<<std::endl;
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool DeleteSingleFileOrEmptyDirectory(std::string path)
 | 
			
		||||
{
 | 
			
		||||
	DWORD attr = GetFileAttributes(path.c_str());
 | 
			
		||||
	bool is_directory = (attr != INVALID_FILE_ATTRIBUTES &&
 | 
			
		||||
			(attr & FILE_ATTRIBUTE_DIRECTORY));
 | 
			
		||||
	if(!is_directory)
 | 
			
		||||
	{
 | 
			
		||||
		bool did = DeleteFile(path.c_str());
 | 
			
		||||
		return did;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		bool did = RemoveDirectory(path.c_str());
 | 
			
		||||
		return did;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else // POSIX
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
@@ -249,6 +292,14 @@ bool PathExists(std::string path)
 | 
			
		||||
	return (stat(path.c_str(),&st) == 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool IsDir(std::string path)
 | 
			
		||||
{
 | 
			
		||||
	struct stat statbuf;
 | 
			
		||||
	if(stat(path.c_str(), &statbuf))
 | 
			
		||||
		return false; // Actually error; but certainly not a directory
 | 
			
		||||
	return ((statbuf.st_mode & S_IFDIR) == S_IFDIR);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RecursiveDelete(std::string path)
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
@@ -295,8 +346,51 @@ bool RecursiveDelete(std::string path)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool DeleteSingleFileOrEmptyDirectory(std::string path)
 | 
			
		||||
{
 | 
			
		||||
	if(IsDir(path)){
 | 
			
		||||
		bool did = (rmdir(path.c_str()) == 0);
 | 
			
		||||
		if(!did)
 | 
			
		||||
			errorstream<<"rmdir errno: "<<errno<<": "<<strerror(errno)
 | 
			
		||||
					<<std::endl;
 | 
			
		||||
		return did;
 | 
			
		||||
	} else {
 | 
			
		||||
		bool did = (unlink(path.c_str()) == 0);
 | 
			
		||||
		if(!did)
 | 
			
		||||
			errorstream<<"unlink errno: "<<errno<<": "<<strerror(errno)
 | 
			
		||||
					<<std::endl;
 | 
			
		||||
		return did;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void GetRecursiveSubPaths(std::string path, std::vector<std::string> &dst)
 | 
			
		||||
{
 | 
			
		||||
	std::vector<DirListNode> content = GetDirListing(path);
 | 
			
		||||
	for(unsigned int  i=0; i<content.size(); i++){
 | 
			
		||||
		const DirListNode &n = content[i];
 | 
			
		||||
		std::string fullpath = path + DIR_DELIM + n.name;
 | 
			
		||||
		dst.push_back(fullpath);
 | 
			
		||||
		GetRecursiveSubPaths(fullpath, dst);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool DeletePaths(const std::vector<std::string> &paths)
 | 
			
		||||
{
 | 
			
		||||
	bool success = true;
 | 
			
		||||
	// Go backwards to succesfully delete the output of GetRecursiveSubPaths
 | 
			
		||||
	for(int i=paths.size()-1; i>=0; i--){
 | 
			
		||||
		const std::string &path = paths[i];
 | 
			
		||||
		bool did = DeleteSingleFileOrEmptyDirectory(path);
 | 
			
		||||
		if(!did){
 | 
			
		||||
			errorstream<<"Failed to delete "<<path<<std::endl;
 | 
			
		||||
			success = false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RecursiveDeleteContent(std::string path)
 | 
			
		||||
{
 | 
			
		||||
	infostream<<"Removing content of \""<<path<<"\""<<std::endl;
 | 
			
		||||
 
 | 
			
		||||
@@ -40,24 +40,35 @@ struct DirListNode
 | 
			
		||||
	std::string name;
 | 
			
		||||
	bool dir;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::vector<DirListNode> GetDirListing(std::string path);
 | 
			
		||||
 | 
			
		||||
// Returns true if already exists
 | 
			
		||||
bool CreateDir(std::string path);
 | 
			
		||||
 | 
			
		||||
// Create all directories on the given path that don't already exist.
 | 
			
		||||
bool CreateAllDirs(std::string path);
 | 
			
		||||
 | 
			
		||||
bool PathExists(std::string path);
 | 
			
		||||
 | 
			
		||||
bool IsDir(std::string path);
 | 
			
		||||
 | 
			
		||||
// Only pass full paths to this one. True on success.
 | 
			
		||||
// NOTE: The WIN32 version returns always true.
 | 
			
		||||
bool RecursiveDelete(std::string path);
 | 
			
		||||
 | 
			
		||||
bool DeleteSingleFileOrEmptyDirectory(std::string path);
 | 
			
		||||
 | 
			
		||||
/* Multiplatform */
 | 
			
		||||
 | 
			
		||||
// The path itself not included
 | 
			
		||||
void GetRecursiveSubPaths(std::string path, std::vector<std::string> &dst);
 | 
			
		||||
 | 
			
		||||
// Tries to delete all, returns false if any failed
 | 
			
		||||
bool DeletePaths(const std::vector<std::string> &paths);
 | 
			
		||||
 | 
			
		||||
// Only pass full paths to this one. True on success.
 | 
			
		||||
bool RecursiveDeleteContent(std::string path);
 | 
			
		||||
 | 
			
		||||
// Create all directories on the given path that don't already exist.
 | 
			
		||||
bool CreateAllDirs(std::string path);
 | 
			
		||||
 | 
			
		||||
}//fs
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user