FileUtilsImpl.h (3683B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_cache_FileUtilsImpl_h 8 #define mozilla_dom_cache_FileUtilsImpl_h 9 10 #include "mozilla/dom/FlippedOnce.h" 11 #include "mozilla/dom/cache/FileUtils.h" 12 #include "mozilla/dom/quota/ResultExtensions.h" 13 14 namespace mozilla::dom::cache { 15 16 template <typename Func> 17 nsresult BodyTraverseFilesForCleanup( 18 const Maybe<CacheDirectoryMetadata>& aDirectoryMetadata, nsIFile& aBodyDir, 19 const Func& aHandleFileFunc) { 20 MOZ_DIAGNOSTIC_ASSERT(aDirectoryMetadata.isSome()); 21 22 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED 23 { 24 nsCOMPtr<nsIFile> parentFile; 25 nsresult rv = aBodyDir.GetParent(getter_AddRefs(parentFile)); 26 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); 27 MOZ_DIAGNOSTIC_ASSERT(parentFile); 28 29 nsAutoCString nativeLeafName; 30 rv = parentFile->GetNativeLeafName(nativeLeafName); 31 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); 32 33 MOZ_DIAGNOSTIC_ASSERT(StringEndsWith(nativeLeafName, "morgue"_ns)); 34 } 35 #endif 36 37 FlippedOnce<true> isEmpty; 38 QM_TRY(quota::CollectEachFile( 39 aBodyDir, 40 [&isEmpty, &aDirectoryMetadata, &aHandleFileFunc]( 41 const nsCOMPtr<nsIFile>& file) -> Result<Ok, nsresult> { 42 QM_TRY_INSPECT(const auto& dirEntryKind, quota::GetDirEntryKind(*file)); 43 44 switch (dirEntryKind) { 45 case quota::nsIFileKind::ExistsAsDirectory: { 46 // If it's a directory somehow, try to remove it and move on 47 DebugOnly<nsresult> result = RemoveNsIFileRecursively( 48 aDirectoryMetadata, *file, /* aTrackQuota */ false); 49 MOZ_ASSERT(NS_SUCCEEDED(result)); 50 break; 51 } 52 53 case quota::nsIFileKind::ExistsAsFile: { 54 nsAutoCString leafName; 55 QM_TRY(MOZ_TO_RESULT(file->GetNativeLeafName(leafName))); 56 57 // Delete all tmp files regardless of known bodies. These are all 58 // considered orphans. 59 if (StringEndsWith(leafName, ".tmp"_ns)) { 60 DebugOnly<nsresult> result = RemoveNsIFile( 61 aDirectoryMetadata, *file, /* aTrackQuota */ true); 62 MOZ_ASSERT(NS_SUCCEEDED(result)); 63 return Ok{}; 64 } 65 // Otherwise, it must be a .final file. 66 QM_WARNONLY_TRY_UNWRAP(const auto maybeEndingOk, 67 OkIf(StringEndsWith(leafName, ".final"_ns))); 68 69 // If its not, try to remove it and move on. 70 if (!maybeEndingOk) { 71 DebugOnly<nsresult> result = RemoveNsIFile( 72 aDirectoryMetadata, *file, /* aTrackQuota */ false); 73 MOZ_ASSERT(NS_SUCCEEDED(result)); 74 return Ok{}; 75 } 76 77 QM_TRY_INSPECT(const bool& fileDeleted, 78 aHandleFileFunc(*file, leafName)); 79 if (fileDeleted) { 80 return Ok{}; 81 } 82 83 isEmpty.EnsureFlipped(); 84 break; 85 } 86 87 case quota::nsIFileKind::DoesNotExist: 88 // Ignore files that got removed externally while iterating. 89 break; 90 } 91 92 return Ok{}; 93 })); 94 95 if (isEmpty) { 96 DebugOnly<nsresult> result = RemoveNsIFileRecursively( 97 aDirectoryMetadata, aBodyDir, /* aTrackQuota */ false); 98 MOZ_ASSERT(NS_SUCCEEDED(result)); 99 } 100 101 return NS_OK; 102 } 103 104 } // namespace mozilla::dom::cache 105 106 #endif // mozilla_dom_cache_FileUtilsImpl_h