From da249e74e99cddfaa98832b577594031666f0129 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sat, 29 Aug 2009 22:49:43 +0000 Subject: [PATCH] Implement TODO: Check for non-empty directories before removing an entry. This fixes #4358, there changing the Tracker preferences causes some default directories to be created, like "home" and "config", which were previously simply killing off the real ones. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32822 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../layers/write_overlay/write_overlay.cpp | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/add-ons/kernel/file_systems/layers/write_overlay/write_overlay.cpp b/src/add-ons/kernel/file_systems/layers/write_overlay/write_overlay.cpp index 49bdb8e48d..d7139a0427 100644 --- a/src/add-ons/kernel/file_systems/layers/write_overlay/write_overlay.cpp +++ b/src/add-ons/kernel/file_systems/layers/write_overlay/write_overlay.cpp @@ -116,6 +116,8 @@ public: void SetParentDir(OverlayInode *parentDir); OverlayInode * ParentDir() { return fParentDir; } + bool IsNonEmptyDirectory(); + status_t Lookup(const char *name, ino_t *inodeNumber); void SetName(const char *name); status_t GetName(char *buffer, size_t bufferSize); @@ -287,6 +289,22 @@ OverlayInode::SetParentDir(OverlayInode *parentDir) } +bool +OverlayInode::IsNonEmptyDirectory() +{ + if (!fHasStat) + ReadStat(NULL); + + if (!S_ISDIR(fStat.st_mode)) + return false; + + if (!fHasDirents) + _PopulateDirents(); + + return fDirentCount > 2; // accounting for "." and ".." entries +} + + status_t OverlayInode::Lookup(const char *name, ino_t *inodeNumber) { @@ -829,10 +847,26 @@ OverlayInode::RemoveEntry(const char *name, overlay_dirent **_entry) if (!fHasDirents) _PopulateDirents(); - // TODO: we may not simply remove non-empty directories for (uint32 i = 0; i < fDirentCount; i++) { overlay_dirent *entry = fDirents[i]; if (strcmp(entry->name, name) == 0) { + if (_entry == NULL) { + // check for non-empty directories when trying + // to dispose the entry + OverlayInode *node = NULL; + status_t result = get_vnode(Volume(), entry->inode_number, + (void **)&node); + if (result != B_OK) + return result; + + if (node->IsNonEmptyDirectory()) + result = B_DIRECTORY_NOT_EMPTY; + + put_vnode(Volume(), entry->inode_number); + if (result != B_OK) + return result; + } + for (uint32 j = i + 1; j < fDirentCount; j++) fDirents[j - 1] = fDirents[j]; fDirentCount--;