15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/self_cleaning_temp_dir.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/delete_after_reboot_helper.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace installer { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Populates |base_dir| with the topmost directory in the hierarchy of 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |temp_parent_dir| that does not exist. If |temp_parent_dir| exists, 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |base_dir| is cleared. 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SelfCleaningTempDir::GetTopDirToCreate( 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& temp_parent_dir, 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath* base_dir) { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(base_dir); 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (base::PathExists(temp_parent_dir)) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Empty base_dir means that we didn't create any extra directories. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base_dir->clear(); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath parent_dir(temp_parent_dir); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *base_dir = parent_dir; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent_dir = parent_dir.DirName(); 327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } while (parent_dir != *base_dir && !base::PathExists(parent_dir)); 337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch LOG_IF(WARNING, !base::DirectoryExists(parent_dir)) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "A non-directory is at the base of the path leading to a desired " 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "temp directory location: " << parent_dir.value(); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelfCleaningTempDir::SelfCleaningTempDir() { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelfCleaningTempDir::~SelfCleaningTempDir() { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!path().empty() && !Delete()) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Failed to clean temp dir in dtor " << path().value(); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SelfCleaningTempDir::Initialize(const base::FilePath& parent_dir, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const StringType& temp_name) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(parent_dir.IsAbsolute()); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!temp_name.empty()); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!path().empty()) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Attempting to re-initialize a SelfSelfCleaningTempDir."; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath temp_dir(parent_dir.Append(temp_name)); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath base_dir; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetTopDirToCreate(parent_dir, &base_dir); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (base::CreateDirectory(temp_dir)) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base_dir_ = base_dir; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_dir_ = temp_dir; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SelfCleaningTempDir::Delete() { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path().empty()) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Attempting to Delete an uninitialized SelfCleaningTempDir."; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath next_dir(path().DirName()); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool schedule_deletes = false; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First try to recursively delete the leaf directory managed by our 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // base::ScopedTempDir. 817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::DeleteFile(path(), true)) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // That failed, so schedule the temp dir and its contents for deletion after 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reboot. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Failed to delete temporary directory " << path().value() 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ". Scheduling for deletion at reboot."; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) schedule_deletes = true; 8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!ScheduleDirectoryForDeletion(path())) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Entirely unexpected failure (Schedule logs the reason). 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now delete or schedule all empty directories up to and including our 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // base_dir_. Any that can't be deleted are scheduled for deletion at reboot. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is safe since they'll only be deleted in that case if they're empty. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base_dir_.empty()) { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!schedule_deletes && !RemoveDirectory(next_dir.value().c_str())) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG_IF(WARNING, GetLastError() != ERROR_DIR_NOT_EMPTY) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Error removing directory " << next_dir.value().c_str(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) schedule_deletes = true; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (schedule_deletes) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignore the return code. If we fail to schedule, go ahead and add the 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // other parent directories anyway. 10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ScheduleFileSystemEntityForDeletion(next_dir); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_dir == base_dir_) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; // We just processed the topmost directory we created. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_dir = next_dir.DirName(); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (true); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base_dir_.clear(); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_dir_.clear(); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace installer 119