diff options
Diffstat (limited to 'contrib/atf/atf-run/fs.cpp')
-rw-r--r-- | contrib/atf/atf-run/fs.cpp | 264 |
1 files changed, 0 insertions, 264 deletions
diff --git a/contrib/atf/atf-run/fs.cpp b/contrib/atf/atf-run/fs.cpp deleted file mode 100644 index b8931e5..0000000 --- a/contrib/atf/atf-run/fs.cpp +++ /dev/null @@ -1,264 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if defined(HAVE_CONFIG_H) -#include "bconfig.h" -#endif - -extern "C" { -#include <sys/types.h> -#include <sys/param.h> -#include <sys/mount.h> -#include <sys/stat.h> - -#include <unistd.h> -} - -#include <cerrno> -#include <cstdlib> -#include <cstring> - -#include "atf-c++/detail/process.hpp" -#include "atf-c++/detail/sanity.hpp" - -#include "fs.hpp" -#include "user.hpp" - -namespace impl = atf::atf_run; -#define IMPL_NAME "atf::atf_run" - -// ------------------------------------------------------------------------ -// Auxiliary functions. -// ------------------------------------------------------------------------ - -static void cleanup_aux(const atf::fs::path&, dev_t, bool); -static void cleanup_aux_dir(const atf::fs::path&, const atf::fs::file_info&, - bool); -static void do_unmount(const atf::fs::path&); - -// The cleanup routines below are tricky: they are executed immediately after -// a test case's death, and after we have forcibly killed any stale processes. -// However, even if the processes are dead, this does not mean that the file -// system we are scanning is stable. In particular, if the test case has -// mounted file systems through fuse/puffs, the fact that the processes died -// does not mean that the file system is truly unmounted. -// -// The code below attempts to cope with this by catching errors and either -// ignoring them or retrying the actions on the same file/directory a few times -// before giving up. -static const int max_retries = 5; -static const int retry_delay_in_seconds = 1; - -// The erase parameter in this routine is to control nested mount points. -// We want to descend into a mount point to unmount anything that is -// mounted under it, but we do not want to delete any files while doing -// this traversal. In other words, we erase files until we cross the -// first mount point, and after that point we only scan and unmount. -static -void -cleanup_aux(const atf::fs::path& p, dev_t parent_device, bool erase) -{ - try { - atf::fs::file_info fi(p); - - if (fi.get_type() == atf::fs::file_info::dir_type) - cleanup_aux_dir(p, fi, fi.get_device() == parent_device); - - if (fi.get_device() != parent_device) - do_unmount(p); - - if (erase) { - if (fi.get_type() == atf::fs::file_info::dir_type) - atf::fs::rmdir(p); - else - atf::fs::remove(p); - } - } catch (const atf::system_error& e) { - if (e.code() != ENOENT && e.code() != ENOTDIR) - throw e; - } -} - -static -void -cleanup_aux_dir(const atf::fs::path& p, const atf::fs::file_info& fi, - bool erase) -{ - if (erase && ((fi.get_mode() & S_IRWXU) != S_IRWXU)) { - int retries = max_retries; -retry_chmod: - if (chmod(p.c_str(), fi.get_mode() | S_IRWXU) == -1) { - if (retries > 0) { - retries--; - ::sleep(retry_delay_in_seconds); - goto retry_chmod; - } else { - throw atf::system_error(IMPL_NAME "::cleanup(" + - p.str() + ")", "chmod(2) failed", - errno); - } - } - } - - std::set< std::string > subdirs; - { - bool ok = false; - int retries = max_retries; - while (!ok) { - INV(retries > 0); - try { - const atf::fs::directory d(p); - subdirs = d.names(); - ok = true; - } catch (const atf::system_error& e) { - retries--; - if (retries == 0) - throw e; - ::sleep(retry_delay_in_seconds); - } - } - INV(ok); - } - - for (std::set< std::string >::const_iterator iter = subdirs.begin(); - iter != subdirs.end(); iter++) { - const std::string& name = *iter; - if (name != "." && name != "..") - cleanup_aux(p / name, fi.get_device(), erase); - } -} - -static -void -do_unmount(const atf::fs::path& in_path) -{ - // At least, FreeBSD's unmount(2) requires the path to be absolute. - // Let's make it absolute in all cases just to be safe that this does - // not affect other systems. - const atf::fs::path& abs_path = in_path.is_absolute() ? - in_path : in_path.to_absolute(); - -#if defined(HAVE_UNMOUNT) - int retries = max_retries; -retry_unmount: - if (unmount(abs_path.c_str(), 0) == -1) { - if (errno == EBUSY && retries > 0) { - retries--; - ::sleep(retry_delay_in_seconds); - goto retry_unmount; - } else { - throw atf::system_error(IMPL_NAME "::cleanup(" + in_path.str() + - ")", "unmount(2) failed", errno); - } - } -#else - // We could use umount(2) instead if it was available... but - // trying to do so under, e.g. Linux, is a nightmare because we - // also have to update /etc/mtab to match what we did. It is - // satf::fser to just leave the system-specific umount(8) tool deal - // with it, at least for now. - - const atf::fs::path prog("umount"); - atf::process::argv_array argv("umount", abs_path.c_str(), NULL); - - atf::process::status s = atf::process::exec(prog, argv, - atf::process::stream_inherit(), atf::process::stream_inherit()); - if (!s.exited() || s.exitstatus() != EXIT_SUCCESS) - throw std::runtime_error("Call to unmount failed"); -#endif -} - -// ------------------------------------------------------------------------ -// The "temp_dir" class. -// ------------------------------------------------------------------------ - -impl::temp_dir::temp_dir(const atf::fs::path& p) -{ - atf::utils::auto_array< char > buf(new char[p.str().length() + 1]); - std::strcpy(buf.get(), p.c_str()); - if (::mkdtemp(buf.get()) == NULL) - throw system_error(IMPL_NAME "::temp_dir::temp_dir(" + - p.str() + ")", "mkdtemp(3) failed", - errno); - - m_path.reset(new atf::fs::path(buf.get())); -} - -impl::temp_dir::~temp_dir(void) -{ - cleanup(*m_path); -} - -const atf::fs::path& -impl::temp_dir::get_path(void) - const -{ - return *m_path; -} - -// ------------------------------------------------------------------------ -// Free functions. -// ------------------------------------------------------------------------ - -atf::fs::path -impl::change_directory(const atf::fs::path& dir) -{ - atf::fs::path olddir = get_current_dir(); - - if (olddir != dir) { - if (::chdir(dir.c_str()) == -1) - throw system_error(IMPL_NAME "::chdir(" + dir.str() + ")", - "chdir(2) failed", errno); - } - - return olddir; -} - -void -impl::cleanup(const atf::fs::path& p) -{ - atf::fs::file_info fi(p); - cleanup_aux(p, fi.get_device(), true); -} - -atf::fs::path -impl::get_current_dir(void) -{ - std::auto_ptr< char > cwd; -#if defined(HAVE_GETCWD_DYN) - cwd.reset(getcwd(NULL, 0)); -#else - cwd.reset(getcwd(NULL, MAXPATHLEN)); -#endif - if (cwd.get() == NULL) - throw atf::system_error(IMPL_NAME "::get_current_dir()", - "getcwd() failed", errno); - - return atf::fs::path(cwd.get()); -} |