# # # patch "cmd_netsync.cc" # from [fe74ba809d95febb94f85a2d2ed9f761c93e25bd] # to [ba4c038a24ffe3ba8951da91b859c426c5876571] # # patch "file_io.cc" # from [7423effadb4f6f69b74ae1a775a8d54aebf8da85] # to [c1938a3a23c60dfeceaafcc39e17bbfd72c9a029] # # patch "key_store.cc" # from [8aa35766f11519f5bc75d3787c5a261419fa13f9] # to [c15c1c54b12ba2e79540d132da465c88d48ada34] # # patch "paths.cc" # from [3ef5b269b34464ce341cc7acdb56f8e166690da5] # to [2de577ffde502496c4d1dcb088575fe00151ab6e] # # patch "paths.hh" # from [4d95cee5f8bb191423762ac0a7c8c6967b3f44a1] # to [0966af72ddd577e28330fe2f1615e29760f869e1] # # patch "platform.hh" # from [4591a65680cb8f6cbbf3b4087c306906914ef246] # to [bd5be744c791a66527b0184fa5dbc5d8ec94e223] # # patch "unix/fs.cc" # from [7ea18b19c14fd6ce9e70657b03785e1da1c45b64] # to [acfcf6c10807375e73504586d0f844f5264cb11a] # # patch "win32/fs.cc" # from [f7e4c47be8ae99b191aa36ecd70d423992bc7aba] # to [918ede5caf8f3f46fb54f462d29610713adf2339] # # patch "work.cc" # from [a3065afa293f68402807da156ea7d2243c27ec6d] # to [d602424dc046f080220d23b5dc663b93b573284a] # ============================================================ --- cmd_netsync.cc fe74ba809d95febb94f85a2d2ed9f761c93e25bd +++ cmd_netsync.cc ba4c038a24ffe3ba8951da91b859c426c5876571 @@ -29,7 +29,7 @@ static const var_key default_exclude_pat static const var_key default_exclude_pattern_key(var_domain("database"), var_name("default-exclude-pattern")); -static string const ws_internal_db_file_name("mtn.db"); +static char const ws_internal_db_file_name[] = "mtn.db"; static void extract_address(args_vector const & args, ============================================================ --- file_io.cc 7423effadb4f6f69b74ae1a775a8d54aebf8da85 +++ file_io.cc c1938a3a23c60dfeceaafcc39e17bbfd72c9a029 @@ -10,10 +10,6 @@ #include "base.hh" #include #include -#include -#include -#include -#include #include "botan/botan.h" @@ -24,21 +20,6 @@ #include "platform-wrapped.hh" #include "numeric_vocab.hh" -namespace fs = boost::filesystem; - -// Parts of boost::filesystem change in 1.34 . One particular -// difference is that some exceptions are different now. - -#include - -#if BOOST_VERSION < 103400 -# define FS_ERROR fs::filesystem_error -# define FS_ERROR_SYSTEM native_error -#else -# define FS_ERROR fs::filesystem_path_error -# define FS_ERROR_SYSTEM system_error -#endif - // this file deals with talking to the filesystem, loading and // saving files. @@ -46,7 +27,7 @@ using std::ofstream; using std::ifstream; using std::ios_base; using std::ofstream; -using std::runtime_error; +using std::logic_error; using std::string; using std::vector; @@ -193,45 +174,25 @@ bool guess_binary(string const & s) return false; } -static fs::path -mkdir(any_path const & p) -{ - return fs::path(p.as_external(), fs::native); -} - void mkdir_p(any_path const & p) { - try + switch (get_path_status(p)) { - fs::create_directories(mkdir(p)); + case path::directory: + return; + case path::file: + E(false, F("could not create directory '%s': it is a file") % p); + case path::nonexistent: + mkdir_p(p.dirname()); + do_mkdir(p.as_external()); } - catch (FS_ERROR & err) - { - // check for this case first, because in this case, the next line will - // print "could not create directory: Success". Which is unhelpful. - E(get_path_status(p) != path::file, - F("could not create directory '%s'\nit is a file") % p); - E(false, - F("could not create directory '%s'\n%s") - % err.path1().native_directory_string() % os_strerror(err.FS_ERROR_SYSTEM())); - } - require_path_is_directory(p, - F("could not create directory '%s'") % p, - F("could not create directory '%s'\nit is a file") % p); } void make_dir_for(any_path const & p) { - fs::path tmp(p.as_external(), fs::native); - if (tmp.has_branch_path()) - { - fs::path dir = tmp.branch_path(); - fs::create_directories(dir); - N(fs::exists(dir) && fs::is_directory(dir), - F("failed to create directory '%s' for '%s'") % dir.string() % p); - } + mkdir_p(p.dirname()); } void @@ -259,13 +220,62 @@ delete_file_or_dir_shallow(any_path cons do_remove(p.as_external()); } +namespace +{ + struct fill_pc_vec : public dirent_consumer + { + fill_pc_vec(vector & v) : v(v) { v.clear(); } + + // FIXME BUG: this treats 's' as being already utf8, but it is actually + // in the external character set. Also, will I() out on invalid + // pathnames, when it should N() or perhaps W() and skip. + virtual void consume(char const * s) + { v.push_back(path_component(s)); } + + private: + vector & v; + }; + + struct file_deleter : public dirent_consumer + { + file_deleter(any_path const & p) : parent(p) {} + virtual void consume(char const * f) + { + // FIXME: same bug as above. + do_remove((parent / path_component(f)).as_external()); + } + private: + any_path const & parent; + }; +} + +static void +do_remove_recursive(any_path const & p) +{ + // for the reasons described in walk_tree_recursive, we read the entire + // directory before recursing into any subdirs. however, it is safe to + // delete files as we encounter them, and we do so. + vector subdirs; + fill_pc_vec subdir_fill(subdirs); + file_deleter delete_files(p); + + do_read_directory(p.as_external(), delete_files, subdir_fill); + for (vector::const_iterator i = subdirs.begin(); + i != subdirs.end(); i++) + do_remove_recursive(p / *i); + + do_remove(p.as_external()); +} + + void delete_dir_recursive(any_path const & p) { require_path_is_directory(p, F("directory to delete, '%s', does not exist") % p, F("directory to delete, '%s', is a file") % p); - fs::remove_all(mkdir(p)); + + do_remove_recursive(p); } void @@ -326,25 +336,12 @@ read_data(any_path const & p, data & dat dat = data(pipe.read_all_as_string()); } -namespace -{ - struct fill_pc_vec : public dirent_consumer - { - fill_pc_vec(vector & v) : v(v) { v.clear(); } - virtual void consume(char const * s) - { v.push_back(path_component(s)); } - - private: - vector & v; - }; -} - void read_directory(any_path const & path, vector & files, vector & dirs) { fill_pc_vec ff(files), df(dirs); - do_read_directory(system_path(path).as_external(), ff, df); + do_read_directory(path.as_external(), ff, df); } // This function can only be called once per run. @@ -422,103 +419,92 @@ write_data_userprivate(system_path const write_data_impl(path, data, tmpdir, true); } +// recursive directory walking + tree_walker::~tree_walker() {} -static inline bool -try_file_pathize(fs::path const & p, file_path & fp) +bool +tree_walker::visit_dir(file_path const & path) { + return true; +} + +// subroutine of walk_tree_recursive: if the path composition of PATH and PC +// is a valid file_path, write it to ENTRY and return true. otherwise, +// generate an appropriate diagnostic and return false. in this context, an +// invalid path is *not* an invariant failure, because it came from a +// directory scan. ??? arguably belongs as a file_path method. +static bool +safe_compose(file_path const & path, path_component const & pc, bool isdir, + file_path & entry) +{ try { - // FIXME BUG: This has broken charset handling - fp = file_path_internal(p.string()); + entry = path / pc; return true; } - catch (runtime_error const & c) + catch (logic_error) { - // This arguably has broken charset handling too... - W(F("caught runtime error %s constructing file path for %s") - % c.what() % p.string()); + // do what the above operator/ did, by hand, and then figure out what + // sort of diagnostic to issue. + utf8 badpth; + if (path.empty()) + badpth = utf8(pc()); + else + badpth = utf8(path.as_internal() + "/" + pc()); + + if (!isdir) + W(F("skipping file '%s' with unsupported name") % badpth); + else if (bookkeeping_path::internal_string_is_bookkeeping_path(badpth)) + L(FL("ignoring bookkeeping directory '%s'") % badpth); + else + W(F("skipping directory '%s' with unsupported name") % badpth); return false; } } static void -walk_tree_recursive(fs::path const & absolute, - fs::path const & relative, +walk_tree_recursive(file_path const & path, tree_walker & walker) { - system_path root(absolute.string()); - vector files, dirs; - - read_directory(root, files, dirs); - - // At this point, the directory iterator has gone out of scope, and its - // memory released. This is important, because it can allocate rather a + // Read the directory up front, so that the directory handle is released + // before we recurse. This is important, because it can allocate rather a // bit of memory (especially on ReiserFS, see [1]; opendir uses the // filesystem's blocksize as a clue how much memory to allocate). We used - // to recurse into subdirectories directly in the loop below; this left - // the memory describing _this_ directory pinned on the heap. Then our - // recursive call itself made another recursive call, etc., causing a huge - // spike in peak memory. By splitting the loop in half, we avoid this - // problem. By using read_directory instead of a directory_iterator above - // we hopefully make this all a bit more clear. + // to recurse into subdirectories on the fly; this left the memory + // describing _this_ directory pinned on the heap. Then our recursive + // call itself made another recursive call, etc., causing a huge spike in + // peak memory. By splitting the loop in half, we avoid this problem. // // [1] http://lkml.org/lkml/2006/2/24/215 + vector files, dirs; + read_directory(path, files, dirs); for (vector::const_iterator i = files.begin(); i != files.end(); ++i) { - // the fs::native is necessary here, or it will bomb out on any paths - // that look at it funny. (E.g., rcs files with "," in the name.) - fs::path rel_entry = relative / fs::path((*i)(), fs::native); - rel_entry.normalize(); - - file_path p; - if (!try_file_pathize(rel_entry, p)) - continue; - walker.visit_file(p); + file_path entry; + if (safe_compose(path, *i, false, entry)) + walker.visit_file(entry); } for (vector::const_iterator i = dirs.begin(); i != dirs.end(); ++i) { - // the fs::native is necessary here, or it will bomb out on any paths - // that look at it funny. (E.g., rcs files with "," in the name.) - fs::path entry = absolute / fs::path((*i)(), fs::native); - fs::path rel_entry = relative / fs::path((*i)(), fs::native); - entry.normalize(); - rel_entry.normalize(); - - // FIXME BUG: this utf8() cast is a total lie - if (bookkeeping_path::internal_string_is_bookkeeping_path(utf8(rel_entry.string()))) - { - L(FL("ignoring book keeping entry %s") % rel_entry.string()); - continue; - } - - file_path p; - if (!try_file_pathize(rel_entry, p)) - continue; - if (walker.visit_dir(p)) - walk_tree_recursive(entry, rel_entry, walker); + file_path entry; + if (safe_compose(path, *i, true, entry)) + if (walker.visit_dir(entry)) + walk_tree_recursive(entry, walker); } } -bool -tree_walker::visit_dir(file_path const & path) -{ - return true; -} - - // from some (safe) sub-entry of cwd void -walk_tree(file_path const & path, - tree_walker & walker) +walk_tree(file_path const & path, tree_walker & walker) { if (path.empty()) { - walk_tree_recursive(fs::current_path(), fs::path(), walker); + walk_tree_recursive(path, walker); return; } @@ -532,9 +518,7 @@ walk_tree(file_path const & path, break; case path::directory: if (walker.visit_dir(path)) - walk_tree_recursive(system_path(path).as_external(), - path.as_external(), - walker); + walk_tree_recursive(path, walker); break; } } ============================================================ --- key_store.cc 8aa35766f11519f5bc75d3787c5a261419fa13f9 +++ key_store.cc c15c1c54b12ba2e79540d132da465c88d48ada34 @@ -88,7 +88,7 @@ key_store::read_key_dir() { L(FL("reading keys from file '%s'") % (*i)); data dat; - read_data(key_dir / (*i)(), dat); + read_data(key_dir / *i, dat); istringstream is(dat()); read_packets(is, kr, app); } @@ -177,27 +177,18 @@ key_store::get_key_pair(rsa_keypair_id c kp = i->second; } -namespace -{ - // filename is the keypair id, except that some characters can't be put in - // filenames (especially on windows). - void - get_filename(rsa_keypair_id const & ident, string & filename) - { - filename = ident(); - for (unsigned int i = 0; i < filename.size(); ++i) - if (string("+").find(filename[i]) != string::npos) - filename.at(i) = '_'; - } -} - void key_store::get_key_file(rsa_keypair_id const & ident, system_path & file) { - string leaf; - get_filename(ident, leaf); - file = key_dir / leaf; + // filename is the keypair id, except that some characters can't be put in + // filenames (especially on windows). + string leaf = ident(); + for (unsigned int i = 0; i < leaf.size(); ++i) + if (leaf.at(i) == '+') + leaf.at(i) = '_'; + + file = key_dir / path_component(leaf); } void ============================================================ --- paths.cc 3ef5b269b34464ce341cc7acdb56f8e166690da5 +++ paths.cc 2de577ffde502496c4d1dcb088575fe00151ab6e @@ -439,6 +439,21 @@ any_path::basename() const return path_component(s, sep + 1); } +// this returns all but the last component of any path. It has to take +// care at the root. +any_path +any_path::dirname() const +{ + string const & s = data; + string::size_type sep = s.rfind('/'); + if (sep == string::npos) + return any_path(); + if (sep == s.size() - 1) // dirname() of the root directory is itself + return *this; + + return any_path(s, 0, sep); +} + // this returns all but the last component of a file_path. it is only // defined on file_paths because (a) that avoids problems at the root, // and (b) that's the only version that we use. @@ -608,17 +623,41 @@ file_path::operator /(file_path const & return file_path(data + "/" + to_append.as_internal(), 0, string::npos); } -// these take strings and do validation themselves. bookkeeping_path -bookkeeping_path::operator /(string const & to_append) const +bookkeeping_path::operator /(path_component const & to_append) const { + I(!to_append.empty()); + I(!empty()); + return bookkeeping_path(data + "/" + to_append(), 0, string::npos); +} + +system_path +system_path::operator /(path_component const & to_append) const +{ + I(!to_append.empty()); + I(!empty()); + return system_path(data + "/" + to_append(), 0, string::npos); +} + +any_path +any_path::operator /(path_component const & to_append) const +{ + I(!to_append.empty()); + I(!empty()); + return any_path(data + "/" + to_append(), 0, string::npos); +} + +// these take strings and validate +bookkeeping_path +bookkeeping_path::operator /(char const * to_append) const +{ I(!is_absolute_somewhere(to_append)); I(!empty()); return bookkeeping_path(data + "/" + to_append); } system_path -system_path::operator /(string const & to_append) const +system_path::operator /(char const * to_append) const { I(!empty()); I(!is_absolute_here(to_append)); @@ -652,7 +691,7 @@ system_path::system_path(any_path const wr = working_root.get(); else wr = working_root.get_but_unused(); - data = normalize_out_dots((wr / other.as_internal()).as_internal()); + data = normalize_out_dots(wr.as_internal() + "/" + other.as_internal()); } } @@ -663,7 +702,8 @@ static inline string const_system_path(u if (is_absolute_here(expanded)) return normalize_out_dots(expanded); else - return normalize_out_dots((initial_abs_path.get() / expanded).as_internal()); + return normalize_out_dots(initial_abs_path.get().as_internal() + + "/" + path()); } system_path::system_path(string const & path) @@ -1274,12 +1314,18 @@ UNIT_TEST(paths, bookkeeping) for (char const ** c = baddies; *c; ++c) { L(FL("test_bookkeeping_path baddie: trying '%s'") % *c); - UNIT_TEST_CHECK_THROW(bookkeeping_path(tmp_path_string.assign(*c)), logic_error); - UNIT_TEST_CHECK_THROW(bookkeeping_root / tmp_path_string.assign(*c), logic_error); + UNIT_TEST_CHECK_THROW(bookkeeping_path(tmp_path_string.assign(*c)), + logic_error); + UNIT_TEST_CHECK_THROW(bookkeeping_root / *c, logic_error); } - UNIT_TEST_CHECK_THROW(bookkeeping_path(tmp_path_string.assign("foo/bar")), logic_error); - UNIT_TEST_CHECK_THROW(bookkeeping_path(tmp_path_string.assign("a")), logic_error); + // these are legitimate as things to append to bookkeeping_root, but + // not as bookkeeping_paths in themselves. + UNIT_TEST_CHECK_THROW(bookkeeping_path("a"), logic_error); + UNIT_TEST_CHECK_NOT_THROW(bookkeeping_root / "a", logic_error); + UNIT_TEST_CHECK_THROW(bookkeeping_path("foo/bar"), logic_error); + UNIT_TEST_CHECK_NOT_THROW(bookkeeping_root / "foo/bar", logic_error); + check_bk_normalizes_to("a", "_MTN/a"); check_bk_normalizes_to("foo", "_MTN/foo"); check_bk_normalizes_to("foo/bar", "_MTN/foo/bar"); ============================================================ --- paths.hh 4d95cee5f8bb191423762ac0a7c8c6967b3f44a1 +++ paths.hh 0966af72ddd577e28330fe2f1615e29760f869e1 @@ -159,13 +159,28 @@ public: { return data.empty(); } // returns the trailing component of the path path_component basename() const; -protected: - std::string data; - any_path() {} + + // a few places need to manipulate any_paths (notably the low-level stuff + // in file_io.cc). + any_path operator /(path_component const &) const; + any_path dirname() const; + any_path(any_path const & other) : data(other.data) {} any_path & operator=(any_path const & other) { data = other.data; return *this; } + +protected: + std::string data; + any_path() {} + +private: + any_path(std::string const & path, + std::string::size_type start, + std::string::size_type stop = std::string::npos) + { + data = path.substr(start, stop); + } }; std::ostream & operator<<(std::ostream & o, any_path const & a); @@ -274,12 +289,14 @@ public: class bookkeeping_path : public any_path { public: - bookkeeping_path() {}; + bookkeeping_path() {} // path _should_ contain the leading _MTN/ // and _should_ look like an internal path // usually you should just use the / operator as a constructor! - bookkeeping_path(std::string const & path); - bookkeeping_path operator /(std::string const & to_append) const; + bookkeeping_path(std::string const &); + bookkeeping_path operator /(char const *) const; + bookkeeping_path operator /(path_component const &) const; + // exposed for the use of walk_tree and friends static bool internal_string_is_bookkeeping_path(utf8 const & path); static bool external_string_is_bookkeeping_path(utf8 const & path); @@ -288,6 +305,14 @@ public: bool operator <(const bookkeeping_path & other) const { return data < other.data; } + +private: + bookkeeping_path(std::string const & path, + std::string::size_type start, + std::string::size_type stop = std::string::npos) + { + data = path.substr(start, stop); + } }; extern bookkeeping_path const bookkeeping_root; @@ -318,7 +343,17 @@ public: // monotone started in. it should be in utf8. system_path(std::string const & path); system_path(utf8 const & path); - system_path operator /(std::string const & to_append) const; + + system_path operator /(path_component const & to_append) const; + system_path operator /(char const * to_append) const; + +private: + system_path(std::string const & path, + std::string::size_type start, + std::string::size_type stop = std::string::npos) + { + data = path.substr(start, stop); + } }; template <> void dump(file_path const & sp, std::string & out); ============================================================ --- platform.hh 4591a65680cb8f6cbbf3b4087c306906914ef246 +++ platform.hh bd5be744c791a66527b0184fa5dbc5d8ec94e223 @@ -130,6 +130,7 @@ void do_remove(std::string const & path) void rename_clobberingly(std::string const & from, std::string const & to); void do_remove(std::string const & path); +void do_mkdir(std::string const & path); void write_data_worker(std::string const & p, std::string const & dat, std::string const & tmpdir, ============================================================ --- unix/fs.cc 7ea18b19c14fd6ce9e70657b03785e1da1c45b64 +++ unix/fs.cc acfcf6c10807375e73504586d0f844f5264cb11a @@ -147,7 +147,11 @@ do_read_directory(string const & path, dirent_consumer & files, dirent_consumer & dirs) { - dirhandle dir(path); + string p(path); + if (p == "") + p = "."; + + dirhandle dir(p); struct dirent *d; struct stat st; int st_result; @@ -231,6 +235,15 @@ do_remove(string const & path) F("could not remove '%s': %s") % path % os_strerror(errno)); } +// Create the directory DIR. It will be world-accessible modulo umask. +// Caller is expected to check for the directory already existing. +void +do_mkdir(string const & path) +{ + E(!mkdir(path.c_str(), 0777), + F("could not create directory '%s': %s") % path % os_strerror(errno)); +} + // Create a temporary file in directory DIR, writing its name to NAME and // returning a read-write file descriptor for it. If unable to create // the file, throws an E(). @@ -264,8 +277,6 @@ make_temp_file(string const & dir, strin { u32 v = value; - tmp.at(tmp.size() - 11) = letters[v % base]; - v /= base; tmp.at(tmp.size() - 10) = letters[v % base]; v /= base; tmp.at(tmp.size() - 9) = letters[v % base]; @@ -276,6 +287,8 @@ make_temp_file(string const & dir, strin v /= base; tmp.at(tmp.size() - 6) = letters[v % base]; v /= base; + tmp.at(tmp.size() - 5) = letters[v % base]; + v /= base; int fd = open(tmp.c_str(), O_RDWR|O_CREAT|O_EXCL, mode); ============================================================ --- win32/fs.cc f7e4c47be8ae99b191aa36ecd70d423992bc7aba +++ win32/fs.cc 918ede5caf8f3f46fb54f462d29610713adf2339 @@ -239,6 +239,14 @@ do_remove(std::string const & path) F("could not remove '%s': %s") % path % os_strerror(GetLastError())); } +void +do_mkdir(std::string const & path) +{ + E(CreateDirectoryA(path.c_str(), 0) != 0, + F("could not create directory '%s': %s") + % path % os_strerror(GetLastError())); +} + static bool rename_clobberingly_impl(const char * from, const char * to) { @@ -340,8 +348,6 @@ make_temp_file(std::string const & dir, { u64 v = value; - tmp.at(tmp.size() - 11) = letters[v % base]; - v /= base; tmp.at(tmp.size() - 10) = letters[v % base]; v /= base; tmp.at(tmp.size() - 9) = letters[v % base]; @@ -352,6 +358,8 @@ make_temp_file(std::string const & dir, v /= base; tmp.at(tmp.size() - 6) = letters[v % base]; v /= base; + tmp.at(tmp.size() - 5) = letters[v % base]; + v /= base; HANDLE h = CreateFile(tmp.c_str(), GENERIC_READ|GENERIC_WRITE, 0, // exclusive access ============================================================ --- work.cc a3065afa293f68402807da156ea7d2243c27ec6d +++ work.cc d602424dc046f080220d23b5dc663b93b573284a @@ -44,11 +44,11 @@ using boost::lexical_cast; // workspace / book-keeping file code -static string const inodeprints_file_name("inodeprints"); -static string const local_dump_file_name("debug"); -static string const options_file_name("options"); -static string const user_log_file_name("log"); -static string const revision_file_name("revision"); +static char const inodeprints_file_name[] = "inodeprints"; +static char const local_dump_file_name[] = "debug"; +static char const options_file_name[] = "options"; +static char const user_log_file_name[] = "log"; +static char const revision_file_name[] = "revision"; static void get_revision_path(bookkeeping_path & m_path) @@ -67,7 +67,7 @@ get_options_path(system_path const & wor static void get_options_path(system_path const & workspace, system_path & o_path) { - o_path = workspace / bookkeeping_root.as_internal() / options_file_name; + o_path = workspace / bookkeeping_root_component / options_file_name; L(FL("options path is %s") % o_path); } @@ -733,7 +733,7 @@ path_for_detached_nid(node_id nid) static inline bookkeeping_path path_for_detached_nid(node_id nid) { - return path_for_detached_nids() / lexical_cast(nid); + return path_for_detached_nids() / path_component(lexical_cast(nid)); } // Attaching/detaching the root directory: @@ -769,11 +769,11 @@ editable_working_tree::detach_node(file_ read_directory(src_pth, files, dirs); for (vector::const_iterator i = files.begin(); i != files.end(); ++i) - move_file(src_pth / *i, dst_pth / (*i)()); + move_file(src_pth / *i, dst_pth / *i); for (vector::const_iterator i = dirs.begin(); i != dirs.end(); ++i) if (!bookkeeping_path::internal_string_is_bookkeeping_path(utf8((*i)()))) - move_dir(src_pth / *i, dst_pth / (*i)()); + move_dir(src_pth / *i, dst_pth / *i); root_dir_attached = false; } else @@ -843,13 +843,13 @@ editable_working_tree::attach_node(node_ i != files.end(); ++i) { I(!bookkeeping_path::internal_string_is_bookkeeping_path(utf8((*i)()))); - move_file(src_pth / (*i)(), dst_pth / *i); + move_file(src_pth / *i, dst_pth / *i); } for (vector::const_iterator i = dirs.begin(); i != dirs.end(); ++i) { I(!bookkeeping_path::internal_string_is_bookkeeping_path(utf8((*i)()))); - move_dir(src_pth / (*i)(), dst_pth / *i); + move_dir(src_pth / *i, dst_pth / *i); } delete_dir_shallow(src_pth); root_dir_attached = true;