X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fpbd%2Ffile_utils.cc;h=1101ba650458d42889ffea8fc63114fd7ac21f43;hb=cb3a60493620e5965de72d34fe0c0d2cce7ec037;hp=44254989c1bfbd227930aa9da8e206f1143ab6aa;hpb=2a7ed69c28c5c4606ff13b3605b9bc9c3eba607d;p=ardour.git diff --git a/libs/pbd/file_utils.cc b/libs/pbd/file_utils.cc index 44254989c1..1101ba6504 100644 --- a/libs/pbd/file_utils.cc +++ b/libs/pbd/file_utils.cc @@ -1,5 +1,6 @@ /* - Copyright (C) 2007 Tim Mayberry + Copyright (C) 2007-2014 Tim Mayberry + Copyright (C) 1998-2014 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,19 +26,35 @@ #ifdef COMPILER_MINGW #include // For W_OK +#define strtok_r strtok_s #endif #include #include #include -#include +#include +#include /* strerror */ + +/* open() */ +#include +#include +#include + +/* close(), read(), write() */ +#ifdef COMPILER_MSVC +#include // Microsoft's nearest equivalent to +#include +#else +#include +#include +#endif #include "pbd/compose.h" #include "pbd/file_utils.h" #include "pbd/debug.h" #include "pbd/error.h" -#include "pbd/pathscanner.h" +#include "pbd/pathexpand.h" #include "pbd/stl_delete.h" #include "i18n.h" @@ -47,14 +64,38 @@ using namespace std; namespace PBD { void -get_files_in_directory (const std::string& directory_path, vector& result) +get_directory_contents (const std::string& directory_path, + vector& result, + bool files_only, + bool recurse) { + // perhaps we don't need this check assuming an exception is thrown + // as it would save checking that the path is a directory twice when + // recursing if (!Glib::file_test (directory_path, Glib::FILE_TEST_IS_DIR)) return; try { Glib::Dir dir(directory_path); - std::copy(dir.begin(), dir.end(), std::back_inserter(result)); + Glib::DirIterator i = dir.begin(); + + while (i != dir.end()) { + + string fullpath = Glib::build_filename (directory_path, *i); + + bool is_dir = Glib::file_test (fullpath, Glib::FILE_TEST_IS_DIR); + + if (is_dir && recurse) { + get_directory_contents (fullpath, result, files_only, recurse); + } + + i++; + + if (is_dir && files_only) { + continue; + } + result.push_back (fullpath); + } } catch (Glib::FileError& err) { @@ -63,63 +104,56 @@ get_files_in_directory (const std::string& directory_path, vector& resul } void -find_matching_files_in_directory (const std::string& directory, - const Glib::PatternSpec& pattern, - vector& result) +get_files_in_directory (const std::string& directory_path, vector& result) +{ + return get_directory_contents (directory_path, result, true, false); +} + +void +find_files_matching_pattern (vector& result, + const Searchpath& paths, + const Glib::PatternSpec& pattern) { vector tmp_files; - get_files_in_directory (directory, tmp_files); - result.reserve(tmp_files.size()); + for (vector::const_iterator i = paths.begin(); i != paths.end(); ++i) { + get_files_in_directory (*i, tmp_files); + } for (vector::iterator file_iter = tmp_files.begin(); file_iter != tmp_files.end(); ++file_iter) { - if (!pattern.match(*file_iter)) continue; - - std::string full_path(directory); - full_path = Glib::build_filename (full_path, *file_iter); + string filename = Glib::path_get_basename (*file_iter); + if (!pattern.match(filename)) continue; DEBUG_TRACE ( DEBUG::FileUtils, - string_compose("Found file %1\n", full_path) + string_compose("Found file %1\n", *file_iter) ); - result.push_back(full_path); + result.push_back(*file_iter); } -} -void -find_matching_files_in_directories (const vector& paths, - const Glib::PatternSpec& pattern, - vector& result) -{ - for (vector::const_iterator path_iter = paths.begin(); - path_iter != paths.end(); - ++path_iter) - { - find_matching_files_in_directory (*path_iter, pattern, result); - } } void -find_matching_files_in_search_path (const Searchpath& search_path, - const Glib::PatternSpec& pattern, - vector& result) +find_files_matching_pattern (vector& result, + const Searchpath& paths, + const string& pattern) { - find_matching_files_in_directories (search_path, pattern, result); + Glib::PatternSpec tmp(pattern); + find_files_matching_pattern (result, paths, tmp); } bool -find_file_in_search_path(const Searchpath& search_path, - const string& filename, - std::string& result) +find_file (const Searchpath& search_path, + const string& filename, + std::string& result) { vector tmp; - Glib::PatternSpec tmp_pattern(filename); - find_matching_files_in_search_path (search_path, tmp_pattern, tmp); + find_files_matching_pattern (tmp, search_path, filename); if (tmp.size() == 0) { @@ -148,26 +182,142 @@ find_file_in_search_path(const Searchpath& search_path, return true; } +static +bool +regexp_filter (const string& str, void *arg) +{ + regex_t* pattern = (regex_t*)arg; + return regexec (pattern, str.c_str(), 0, 0, 0) == 0; +} + +void +find_files_matching_regex (vector& result, + const Searchpath& paths, + const std::string& regexp) +{ + int err; + char msg[256]; + regex_t compiled_pattern; + + if ((err = regcomp (&compiled_pattern, regexp.c_str(), + REG_EXTENDED|REG_NOSUB))) { + + regerror (err, &compiled_pattern, + msg, sizeof (msg)); + + error << "Cannot compile soundfile regexp for use (" + << msg + << ")" + << endmsg; + + return; + } + + find_files_matching_filter (result, paths, + regexp_filter, &compiled_pattern, + true, true, false); + + regfree (&compiled_pattern); +} + +void +find_files_matching_filter (vector& result, + const Searchpath& paths, + bool (*filter)(const string &, void *), + void *arg, + bool match_fullpath, bool return_fullpath, + bool recurse) +{ + vector all_files; + + for (vector::const_iterator i = paths.begin(); i != paths.end(); ++i) { + string expanded_path = path_expand (*i); + get_directory_contents (expanded_path, all_files, true, recurse); + } + + for (vector::iterator i = all_files.begin(); i != all_files.end(); ++i) { + + string fullpath = *i; + string filename = Glib::path_get_basename (*i); + string search_str; + + if (match_fullpath) { + search_str = *i; + } else { + search_str = filename; + } + + if (!filter(search_str, arg)) { + continue; + } + + DEBUG_TRACE (DEBUG::FileUtils, + string_compose("Found file %1 matching filter\n", search_str)); + + if (return_fullpath) { + result.push_back(fullpath); + } else { + result.push_back(filename); + } + } +} + bool copy_file(const std::string & from_path, const std::string & to_path) { if (!Glib::file_test (from_path, Glib::FILE_TEST_EXISTS)) return false; - Glib::RefPtr from_file = Gio::File::create_for_path(from_path); - Glib::RefPtr to_file = Gio::File::create_for_path(to_path); + int fd_from = -1; + int fd_to = -1; + char buf[4096]; // BUFSIZ ?? + ssize_t nread; - try - { - from_file->copy (to_file, Gio::FILE_COPY_OVERWRITE); + fd_from = ::open(from_path.c_str(), O_RDONLY); + if (fd_from < 0) { + goto copy_error; } - catch(const Glib::Exception& ex) - { - error << string_compose (_("Unable to Copy file %1 to %2 (%3)"), - from_path, to_path, ex.what()) - << endmsg; - return false; + + fd_to = ::open(to_path.c_str(), O_WRONLY | O_CREAT, 0666); + if (fd_to < 0) { + goto copy_error; } - return true; + + while (nread = ::read(fd_from, buf, sizeof(buf)), nread > 0) { + char *out_ptr = buf; + do { + ssize_t nwritten = ::write(fd_to, out_ptr, nread); + if (nwritten >= 0) { + nread -= nwritten; + out_ptr += nwritten; + } else if (errno != EINTR) { + goto copy_error; + } + } while (nread > 0); + } + + if (nread == 0) { + if (::close(fd_to)) { + fd_to = -1; + goto copy_error; + } + ::close(fd_from); + return true; + } + +copy_error: + int saved_errno = errno; + + if (fd_from >= 0) { + ::close(fd_from); + } + if (fd_to >= 0) { + ::close(fd_to); + } + + error << string_compose (_("Unable to Copy file %1 to %2 (%3)"), + from_path, to_path, strerror(saved_errno)) + << endmsg; + return false; } static @@ -179,24 +329,21 @@ bool accept_all_files (string const &, void *) void copy_files(const std::string & from_path, const std::string & to_dir) { - PathScanner scanner; - vector* files = scanner (from_path, accept_all_files, 0, true, false); - - if (files) { - for (vector::iterator i = files->begin(); i != files->end(); ++i) { - std::string from = Glib::build_filename (from_path, **i); - std::string to = Glib::build_filename (to_dir, **i); - copy_file (from, to); - } - vector_delete (files); + vector files; + find_files_matching_filter (files, from_path, accept_all_files, 0, true, false); + + for (vector::iterator i = files.begin(); i != files.end(); ++i) { + std::string from = Glib::build_filename (from_path, *i); + std::string to = Glib::build_filename (to_dir, *i); + copy_file (from, to); } } std::string get_absolute_path (const std::string & p) { - Glib::RefPtr f = Gio::File::create_for_path (p); - return f->get_path (); + if (Glib::path_is_absolute(p)) return p; + return Glib::build_filename (Glib::get_current_dir(), p); } bool @@ -257,4 +404,53 @@ exists_and_writable (const std::string & p) return true; } +int +remove_directory_internal (const string& dir, size_t* size, vector* paths, + bool just_remove_files) +{ + vector tmp_paths; + struct stat statbuf; + int ret = 0; + + get_directory_contents (dir, tmp_paths, just_remove_files, true); + + for (vector::const_iterator i = tmp_paths.begin(); + i != tmp_paths.end(); ++i) { + + if (g_stat (i->c_str(), &statbuf)) { + continue; + } + + if (::g_remove (i->c_str())) { + error << string_compose (_("cannot remove path %1 (%2)"), *i, strerror (errno)) + << endmsg; + ret = 1; + } + + if (paths) { + paths->push_back (Glib::path_get_basename(*i)); + } + + if (size) { + *size += statbuf.st_size; + } + + } + + return ret; +} + +int +clear_directory (const string& dir, size_t* size, vector* paths) +{ + return remove_directory_internal (dir, size, paths, true); +} + +// rm -rf -- used to remove saved plugin state +void +remove_directory (const std::string& dir) +{ + remove_directory_internal (dir, 0, 0, false); +} + } // namespace PBD