CacheItem.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * Copyright (C) 2017 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "CacheItem.h"
  17. #include <inttypes.h>
  18. #include <stdint.h>
  19. #include <sys/xattr.h>
  20. #include <android-base/logging.h>
  21. #include <android-base/stringprintf.h>
  22. #include "utils.h"
  23. using android::base::StringPrintf;
  24. namespace android {
  25. namespace installd {
  26. CacheItem::CacheItem(FTSENT* p) {
  27. level = p->fts_level;
  28. directory = S_ISDIR(p->fts_statp->st_mode);
  29. size = p->fts_statp->st_blocks * 512;
  30. modified = p->fts_statp->st_mtime;
  31. mParent = static_cast<CacheItem*>(p->fts_parent->fts_pointer);
  32. if (mParent) {
  33. group = mParent->group;
  34. tombstone = mParent->tombstone;
  35. mName = p->fts_name;
  36. mName.insert(0, "/");
  37. } else {
  38. group = false;
  39. tombstone = false;
  40. mName = p->fts_path;
  41. }
  42. }
  43. CacheItem::~CacheItem() {
  44. }
  45. std::string CacheItem::toString() {
  46. return StringPrintf("%s size=%" PRId64 " mod=%ld", buildPath().c_str(), size, modified);
  47. }
  48. std::string CacheItem::buildPath() {
  49. std::string res = mName;
  50. CacheItem* parent = mParent;
  51. while (parent) {
  52. res.insert(0, parent->mName);
  53. parent = parent->mParent;
  54. }
  55. return res;
  56. }
  57. int CacheItem::purge() {
  58. int res = 0;
  59. auto path = buildPath();
  60. if (directory) {
  61. FTS *fts;
  62. FTSENT *p;
  63. char *argv[] = { (char*) path.c_str(), nullptr };
  64. if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) {
  65. PLOG(WARNING) << "Failed to fts_open " << path;
  66. return -1;
  67. }
  68. while ((p = fts_read(fts)) != nullptr) {
  69. switch (p->fts_info) {
  70. case FTS_D:
  71. if (p->fts_level == 0) {
  72. p->fts_number = tombstone;
  73. } else {
  74. p->fts_number = p->fts_parent->fts_number
  75. | (getxattr(p->fts_path, kXattrCacheTombstone, nullptr, 0) >= 0);
  76. }
  77. break;
  78. case FTS_F:
  79. if (p->fts_parent->fts_number) {
  80. if (truncate(p->fts_path, 0) != 0) {
  81. PLOG(WARNING) << "Failed to truncate " << p->fts_path;
  82. res = -1;
  83. }
  84. } else {
  85. if (unlink(p->fts_path) != 0) {
  86. PLOG(WARNING) << "Failed to unlink " << p->fts_path;
  87. res = -1;
  88. }
  89. }
  90. break;
  91. case FTS_DEFAULT:
  92. case FTS_SL:
  93. case FTS_SLNONE:
  94. if (unlink(p->fts_path) != 0) {
  95. PLOG(WARNING) << "Failed to unlink " << p->fts_path;
  96. res = -1;
  97. }
  98. break;
  99. case FTS_DP:
  100. if (rmdir(p->fts_path) != 0) {
  101. PLOG(WARNING) << "Failed to rmdir " << p->fts_path;
  102. res = -1;
  103. }
  104. break;
  105. }
  106. }
  107. } else {
  108. if (tombstone) {
  109. if (truncate(path.c_str(), 0) != 0) {
  110. PLOG(WARNING) << "Failed to truncate " << path;
  111. res = -1;
  112. }
  113. } else {
  114. if (unlink(path.c_str()) != 0) {
  115. PLOG(WARNING) << "Failed to unlink " << path;
  116. res = -1;
  117. }
  118. }
  119. }
  120. return res;
  121. }
  122. } // namespace installd
  123. } // namespace android