From f91f1df3e0b00b3a270e571d4b2c8251da4d1226 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 20 Jul 2008 10:34:20 +0000 Subject: [PATCH] Split directory and stat related functions into their own files Put everything in namespace FS --- source/dir.cpp | 137 ++++++++++++++++++++++++++++++++++++++++++++ source/dir.h | 46 +++++++++++++++ source/path.cpp | 2 + source/path.h | 2 + source/stat.cpp | 43 ++++++++++++++ source/stat.h | 40 +++++++++++++ source/utils.cpp | 144 +---------------------------------------------- source/utils.h | 48 +--------------- 8 files changed, 275 insertions(+), 187 deletions(-) create mode 100644 source/dir.cpp create mode 100644 source/dir.h create mode 100644 source/stat.cpp create mode 100644 source/stat.h diff --git a/source/dir.cpp b/source/dir.cpp new file mode 100644 index 0000000..c402ec9 --- /dev/null +++ b/source/dir.cpp @@ -0,0 +1,137 @@ +/* $Id$ + +This file is part of libmspfs +Copyright © 2006-2008 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include +#include +#include +#include +#include +#include "dir.h" +#include "path.h" +#include "stat.h" +#include "utils.h" + +using namespace std; + +namespace Msp { +namespace FS { + +void mkdir(const Path &path, int mode) +{ + int err; +#ifdef WIN32 + // The win32 version of this function doesn't take the mode argument. Go figure. + (void)mode; + err=::mkdir(path.str().c_str()); +#else + err=::mkdir(path.str().c_str(), mode); +#endif + + if(err==-1) + throw SystemError("mkdir failed", errno); +} + +/** +Creates a directory and any parent directories if needed. + +@param path The path to create +@param mode Access mode for new directories + +@return 0 on success, -1 on error +*/ +void mkpath(const Path &path, int mode) +{ + Path p; + for(Path::Iterator i=path.begin(); i!=path.end(); ++i) + { + p/=*i; +#ifdef WIN32 + if(p.size()==1 && is_windows_drive(*i)) + continue; +#endif + struct stat st; + int err=stat(p, st); + if(err==0) + { + if(!S_ISDIR(st.st_mode)) + throw Exception("A component exists and is not a directory"); + continue; + } + else if(errno!=ENOENT) + throw SystemError("stat failed", errno); + else + mkdir(p, mode); + } +} + +void rmdir(const Path &path) +{ + if(::rmdir(path.str().c_str())==-1) + throw SystemError("rmdir failed", errno); +} + +void rmdirs(const Path &path) +{ + list files=list_files(path); + for(list::iterator i=files.begin(); i!=files.end(); ++i) + { + Path p=path / *i; + struct stat st=stat(p.str().c_str()); + if(S_ISDIR(st.st_mode)) + rmdirs(p); + else + unlink(p); + } + + rmdir(path); +} + +list list_files(const Path &path) +{ + list result; + DIR *dir=opendir(path.str().c_str()); + if(dir) + { + while(dirent *de=readdir(dir)) + { + const char *fn=de->d_name; + if(fn[0]=='.' && (fn[1]==0 || (fn[1]=='.' && fn[2]==0))) + continue; + result.push_back(fn); + } + closedir(dir); + } + + return result; +} + +Path getcwd() +{ + char buf[1024]; + return ::getcwd(buf, sizeof(buf)); +} + +Path get_home_dir() +{ +#ifndef WIN32 + const char *home=getenv("HOME"); + if(home) + return home; + return "."; +#else + return "."; +#endif +} + +void chdir(const Path &path) +{ + if(::chdir(path.str().c_str())==-1) + throw SystemError("chdir failed", errno); +} + +} // namespace FS +} // namespace Msp diff --git a/source/dir.h b/source/dir.h new file mode 100644 index 0000000..25ec776 --- /dev/null +++ b/source/dir.h @@ -0,0 +1,46 @@ +/* $Id$ + +This file is part of libmspfs +Copyright © 2006-2008 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#ifndef MSP_FS_DIR_H_ +#define MSP_FS_DIR_H_ + +#include +#include + +namespace Msp { +namespace FS { + +class Path; + +/// Creates a directory +void mkdir(const Path &path, int mode); + +/// Creates a directory and any required parent directories +void mkpath(const Path &path, int mode); + +/// Removes a directory +void rmdir(const Path &path); + +/// Removes a directory and anything it contains +void rmdirs(const Path &path); + +/// Lists the contents of a directory +std::list list_files(const Path &path); + +/// Returns the current working directory +Path getcwd(); + +/// Returns the user's home directory +Path get_home_dir(); + +/// Changes the current working directory +void chdir(const Path &); + +} // namespace FS +} // namespace Msp + +#endif diff --git a/source/path.cpp b/source/path.cpp index bed7416..35641f8 100644 --- a/source/path.cpp +++ b/source/path.cpp @@ -12,6 +12,7 @@ Distributed under the LGPL using namespace std; namespace Msp { +namespace FS { /** Returns the number of components in the path. @@ -225,4 +226,5 @@ string Path::Iterator::operator*() const return path.path.substr(start, end-start); } +} // namespace FS } // namespace Msp diff --git a/source/path.h b/source/path.h index 9eacf51..082a1ba 100644 --- a/source/path.h +++ b/source/path.h @@ -12,6 +12,7 @@ Distributed under the LGPL #include namespace Msp { +namespace FS { enum { @@ -65,6 +66,7 @@ private: inline std::ostream &operator<<(std::ostream &o, const Path &p) { o< +#include +#include "path.h" +#include "stat.h" + +namespace Msp { +namespace FS { + +int stat(const Path &fn, struct stat &st) +{ + return ::stat(fn.str().c_str(), &st); +} + +struct stat stat(const Path &fn) +{ + struct stat st; + if(stat(fn, st)==-1) + throw SystemError("stat failed", errno); + return st; +} + +bool exists(const Path &path) +{ + return access(path.str().c_str(), F_OK)==0; +} + +bool is_dir(const Path &path) +{ + struct stat st; + if(stat(path, st)==0) + return S_ISDIR(st.st_mode); + return false; +} + +} // namespace FS +} // namespace Msp diff --git a/source/stat.h b/source/stat.h new file mode 100644 index 0000000..f6b13d4 --- /dev/null +++ b/source/stat.h @@ -0,0 +1,40 @@ +/* $Id$ + +This file is part of libmspfs +Copyright © 2006-2008 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#ifndef MSP_FS_STAT_H_ +#define MSP_FS_STAT_H_ + +#include + +namespace Msp { +namespace FS { + +class Path; + +/** +Gets information about a file. Returns 0 on success or -1 on error. This +version can be used to check for file existence and get information in one +call. +*/ +int stat(const Path &fn, struct stat &st); + +/** +Returns information about a file. This version throws an exception if an error +occurs. +*/ +struct stat stat(const Path &fn); + +/// Tests for existence of a file +bool exists(const Path &path); + +/// Tests whether a path refers to an existing directory +bool is_dir(const Path &path); + +} // namespace FS +} // namespace Msp + +#endif diff --git a/source/utils.cpp b/source/utils.cpp index ca6d6f3..5c8c8d4 100644 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -5,9 +5,7 @@ Copyright © 2006-2008 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ -#include #include -#include #include #ifndef WIN32 #include @@ -15,12 +13,14 @@ Distributed under the LGPL #include #endif #include +#include "dir.h" #include "path.h" #include "utils.h" using namespace std; namespace Msp { +namespace FS { /** Fixes the case of the given path to match files / directories on the @@ -59,114 +59,12 @@ Path fix_case(const Path &path) return result; } -void mkdir(const Path &path, int mode) -{ - int err; -#ifdef WIN32 - // The win32 version of this function doesn't take the mode argument. Go figure. - (void)mode; - err=::mkdir(path.str().c_str()); -#else - err=::mkdir(path.str().c_str(), mode); -#endif - - if(err==-1) - throw SystemError("mkdir failed", errno); -} - -/** -Creates a directory and any parent directories if needed. - -@param path The path to create -@param mode Access mode for new directories - -@return 0 on success, -1 on error -*/ -void mkpath(const Path &path, int mode) -{ - Path p; - for(Path::Iterator i=path.begin(); i!=path.end(); ++i) - { - p/=*i; -#ifdef WIN32 - if(p.size()==1 && is_windows_drive(*i)) - continue; -#endif - struct stat st; - int err=stat(p, st); - if(err==0) - { - if(!S_ISDIR(st.st_mode)) - throw Exception("A component exists and is not a directory"); - continue; - } - else if(errno!=ENOENT) - throw SystemError("stat failed", errno); - else - mkdir(p, mode); - } -} - -void rmdir(const Path &path) -{ - if(::rmdir(path.str().c_str())==-1) - throw SystemError("rmdir failed", errno); -} - -void rmdirs(const Path &path) -{ - list files=list_files(path); - for(list::iterator i=files.begin(); i!=files.end(); ++i) - { - Path p=path / *i; - struct stat st=stat(p.str().c_str()); - if(S_ISDIR(st.st_mode)) - rmdirs(p); - else - unlink(p); - } - - rmdir(path); -} - void unlink(const Path &path) { if(::unlink(path.str().c_str())==-1) throw SystemError("unlink failed", errno); } -list list_files(const Path &path) -{ - list result; - DIR *dir=opendir(path.str().c_str()); - if(dir) - { - while(dirent *de=readdir(dir)) - { - const char *fn=de->d_name; - if(fn[0]=='.' && (fn[1]==0 || (fn[1]=='.' && fn[2]==0))) - continue; - result.push_back(fn); - } - closedir(dir); - } - - return result; -} - -bool exists(const Path &path) -{ - return access(path.str().c_str(), F_OK)==0; -} - -bool is_dir(const Path &path) -{ - struct stat st; - if(stat(path, st)==0) - return S_ISDIR(st.st_mode); - return false; -} - Filename splitext(const string &fn) { Filename result; @@ -214,41 +112,5 @@ string basename(const std::string &p) return p.substr(slash+1); } -int stat(const Path &fn, struct stat &st) -{ - return ::stat(fn.str().c_str(), &st); -} - -struct stat stat(const Path &fn) -{ - struct stat st; - if(stat(fn, st)==-1) - throw SystemError("stat failed", errno); - return st; -} - -Path getcwd() -{ - char buf[1024]; - return ::getcwd(buf, sizeof(buf)); -} - -Path get_home_dir() -{ -#ifndef WIN32 - const char *home=getenv("HOME"); - if(home) - return home; - return "."; -#else - return "."; -#endif -} - -void chdir(const Path &path) -{ - if(::chdir(path.str().c_str())==-1) - throw SystemError("chdir failed", errno); -} - +} // namespace FS } // namespace Msp diff --git a/source/utils.h b/source/utils.h index 8139a7e..a828c92 100644 --- a/source/utils.h +++ b/source/utils.h @@ -8,11 +8,8 @@ Distributed under the LGPL #ifndef MSP_FS_UTILS_H_ #define MSP_FS_UTILS_H_ -#include -#include -#include - namespace Msp { +namespace FS { class Path; @@ -24,24 +21,9 @@ struct Filename Path fix_case(const Path &path); -/// Creates a directory -void mkdir(const Path &path, int mode); - -/// Creates a directory and any required parent directories -void mkpath(const Path &path, int mode); - -/// Removes a directory -void rmdir(const Path &path); - -/// Removes a directory and anything it contains -void rmdirs(const Path &path); - /// Removes a file void unlink(const Path &path); -/// Lists the contents of a directory -std::list list_files(const Path &path); - Filename splitext(const std::string &); int fnmatch(const std::string &, const Path &); @@ -50,36 +32,10 @@ Path relative(const Path &path, const Path &base); std::string basename(const std::string &); -/// Tests for existence of a file -bool exists(const Path &path); - -/// Tests whether a path refers to an existing directory -bool is_dir(const Path &paht); - -/** -Gets information about a file. Returns 0 on success or -1 on error. This -version can be used to check for file existence and get information in one -call. -*/ -int stat(const Path &fn, struct stat &st); - -/** -Returns information about a file. This version throws an exception if an error -occurs. -*/ -struct stat stat(const Path &fn); - -Path getcwd(); - -/// Returns the user's home directory -Path get_home_dir(); - -/// Changes the current working directory -void chdir(const Path &); - inline bool is_windows_drive(const std::string &p) { return (p.size()==2 && ((p[0]>='A' && p[0]<='Z') || (p[0]>='a' && p[0]<='z')) && p[1]==':'); } +} // namespace FS } // namespace Msp #endif -- 2.43.0