# # # patch "platform.hh" # from [c1bed5059d0e2d277020e38680f33a7c070cce80] # to [d2dd265fc09896123e8bd579298c0aa8397b7dc0] # # patch "unix/fs.cc" # from [596c23f1dfd904b4e1b89808ed7ccfc69b0c8a22] # to [8c3cc49120e8aefc756371ce46e6684d6ff3481a] # # patch "win32/fs.cc" # from [bfa29f215a130b7ebeceaef079c359757c923c20] # to [4c87e1d1a39ab6ff39479086db3e67e66cddaffa] # ============================================================ --- platform.hh c1bed5059d0e2d277020e38680f33a7c070cce80 +++ platform.hh d2dd265fc09896123e8bd579298c0aa8397b7dc0 @@ -135,7 +135,16 @@ void rename_clobberingly(std::string con void make_accessible(std::string const & name); void rename_clobberingly(std::string const & from, std::string const & to); + +// path must be a file, not a directory void do_remove(std::string const & path); + +// This is platform-specific because it uses raw pathname strings +// internally; some raw pathnames cannot be represented as any_path objects. +// It may also be more efficient to let the OS do all of this. +// +// It is not an error to call this function on a path that doesn't exist, +// or is a file rather than a directory. void do_remove_recursive(std::string const & path); void do_mkdir(std::string const & path); ============================================================ --- unix/fs.cc 596c23f1dfd904b4e1b89808ed7ccfc69b0c8a22 +++ unix/fs.cc 8c3cc49120e8aefc756371ce46e6684d6ff3481a @@ -312,8 +312,6 @@ do_remove(string const & path) // For the reasons described in file_io.cc::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. -// It is not an error to call this function on a path that doesn't exist, -// or is a file rather than a directory. void do_remove_recursive(string const & path) { ============================================================ --- win32/fs.cc bfa29f215a130b7ebeceaef079c359757c923c20 +++ win32/fs.cc 4c87e1d1a39ab6ff39479086db3e67e66cddaffa @@ -251,16 +251,25 @@ do_remove_recursive(std::string const & void do_remove_recursive(std::string const & path) { + // IMPROVME: use Unicode APIs to support more pathnames. + // // SHFileOperation makes the weird requirement that its pFrom (and pTo) // arguments be terminated with *two* ASCII NULs. size_t pfLen = path.size(); - LPCTSTR pFrom = malloc(pfLen + 2); + LPSTR pFrom = (LPSTR)malloc(pfLen + 2); memcpy(pFrom, path.data(), pfLen); pFrom[pfLen] = '\0'; pFrom[pfLen+1] = '\0'; + // SHFileOperationA can't handle '/' + for (size_t i = 0; i < pfLen; i++) + { + if (pFrom[i] == '/') + pFrom[i] = '\\'; + }; + SHFILEOPSTRUCTA op; - op.hwnd = INVALID_HANDLE_VALUE; + op.hwnd = (HWND)INVALID_HANDLE_VALUE; op.wFunc = FO_DELETE; op.pFrom = pFrom; op.pTo = NULL; @@ -274,7 +283,11 @@ do_remove_recursive(std::string const & // http://msdn.microsoft.com/en-us/library/bb762164(VS.85).aspx // warns that the return codes from SHFileOperation are *not* normal // Win32 error codes; so we don't try to do os_strerror on them. - E(rc == 0, origin::system, + // + // 0x402 is "unknown error"; it occurs for a non-existing path, which is + // not an error in this function. It also occurs for other problems, like + // '/' as a directory separator. Sigh. + E(rc == 0 || rc == 0x402, origin::system, F("could not remove '%s' and contents: SHFileOperation error code 0x%x") % path % rc); E(!op.fAnyOperationsAborted, origin::system,