/**
* @brief removes a file from a filesystem.
* @param path path to the file.
- * @return @a true iff the unlink was successful.
+ * @return @a true if the unlink was successful.
*/
bool unlink( const std::string& path )
{
/**
* Recursive delete of files and directories
* @param path File or directory to delete
- * @param error Will contain the error if the return value is false
+ * @param error Will contain the error if the return value is false [optional]
* @return true on success, false otherwise
*/
bool recursive_delete(const std::string &path, std::string *error)
}
closedir(dir);
- if (rmdir(path.c_str()) != 0) {
+ if (!rmdir(path)) {
throw runtime_error("can't remove directory " + path);
}
} else {
- if (unlink(path.c_str()) != 0) {
+ if (!unlink(path)) {
throw runtime_error("can't unlink " + path);
}
}
/**
Create a unique temporary directory from path_template.
@param Path template. The last six characters must be XXXXXX.
+ @param error Will contain the error if the return value is false [optional]
@return Name of new directory or empty string on error.
*/
-std::string mkdtemp(const std::string &path_template)
+std::string mkdtemp(const std::string &path_template, std::string *error)
{
boost::scoped_array<char> buf( new char[path_template.size()+1] );
path_template.copy(buf.get(), path_template.size());
char *unique_dir = ::mkdtemp(buf.get());
if (!unique_dir)
+ {
+ if (error)
+ *error = strerror(errno);
return "";
+ }
// Scoped pointer is still valid
return std::string(unique_dir);
}
+/**
+ Create directory
+ @param path Path to create
+ @param error Will contain the error if the return value is false [optional]
+ @return True on success, false on error
+*/
+bool mkdir(const std::string &path, const mode_t &mode, std::string *error)
+{
+ if ( ::mkdir(path.c_str(), mode) == 0)
+ return true;
+
+ if (error)
+ *error = strerror(errno);
+ return false;
+}
+
+/**
+ Remove directory
+ @param path Path to removed
+ @param error Will contain the error if the return value is false [optional]
+ @return True on successs, false otherwise
+*/
+bool rmdir(const std::string &path, std::string *error)
+{
+ if ( ::rmdir(path.c_str() ) == 0)
+ return true;
+
+ if (error)
+ *error = strerror(errno);
+ return false;
+}
+
+/// Small helper class for scoped free
+class scoped_C_free
+{
+public:
+ scoped_C_free(void *ptr)
+ : pointer_to_free(ptr)
+ {
+ }
+
+ ~scoped_C_free()
+ {
+ free (pointer_to_free);
+ pointer_to_free = NULL;
+ }
+
+private:
+ void *pointer_to_free;
+};
+
+/**
+ Get current working directory
+ @return Current working directory. Empty string on error.
+*/
+std::string getcwd()
+{
+ char *cwd = ::getcwd(NULL, 0);
+ if (!cwd)
+ return "";
+
+ // Make deallocation of cwd exception safe
+ scoped_C_free holder(cwd);
+
+ string current_dir(cwd);
+ return current_dir;
+}
+
+/**
+ Change current working directory
+ @param path Path to change to
+ @param error Will contain the error if the return value is false [optional]
+ @return True on successs, false otherwise
+*/
+bool chdir(const std::string &path, std::string *error)
+{
+ if ( ::chdir(path.c_str() ) == 0)
+ return true;
+
+ if (error)
+ *error = strerror(errno);
+ return false;
+}
} // eo namespace I2n
BOOST_CHECK_EQUAL("", unique_dir);
}
+BOOST_AUTO_TEST_CASE(DirectoryCreation)
+{
+ string dirname = "test_directory";
+
+ I2n::rmdir (dirname);
+
+ BOOST_CHECK_EQUAL(true, I2n::mkdir(dirname));
+ BOOST_CHECK_EQUAL(true, Stat(dirname).is_directory());
+ // Verify default permissions
+ BOOST_CHECK_EQUAL(0700, Stat(dirname).mode());
+
+ BOOST_CHECK_EQUAL(true, I2n::rmdir(dirname));
+
+ // Second call must fail: Directory already deleted
+ BOOST_CHECK_EQUAL(false, I2n::rmdir(dirname));
+}
+
+BOOST_AUTO_TEST_CASE(DirectoryCreatePermission)
+{
+ string dirname = "test_directory";
+
+ // TODO: Save and fix umask
+
+ I2n::rmdir (dirname);
+ BOOST_CHECK_EQUAL(true, I2n::mkdir(dirname, 0770));
+ // TODO: Enable check
+ // BOOST_CHECK_EQUAL(0770, Stat(dirname).mode());
+ I2n::rmdir (dirname);
+
+ // TODO: Restore umask
+}
+
+BOOST_AUTO_TEST_CASE(ChangeDirectory)
+{
+ string current_directory = I2n::getcwd();
+ BOOST_REQUIRE(!current_directory.empty());
+
+ BOOST_CHECK_EQUAL(true, I2n::chdir("/"));
+ BOOST_CHECK_EQUAL("/", I2n::getcwd());
+
+ BOOST_CHECK_EQUAL(true, I2n::chdir(current_directory));
+ BOOST_REQUIRE_EQUAL(current_directory, I2n::getcwd());
+}
+
BOOST_AUTO_TEST_SUITE_END()