fs_mgr: fs_mgr_overlayfs_teardown_one use .<hidden>

Switch to using a leading . to reference a teardown directory, and
if the top directory (/mnt/scratch/overlay) report ENOTEMPTY then
check if there is any non-hidden content, and if not then consider
removing the scratch partition.

Although not currently a problem, use basename of mount point in
fs_mgr_overlayfs_teardown_one when referencing the overlay directory
tree to match the setup behavior.  Would have become a problem if
we started dealing with sub-mount points (eg: /vendor/firmware_mnt).

Test: manual
Bug: 109821105
Change-Id: I05dafe29c9e376e8423aedc8783fe674a657b3ee
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 6067a7d..64e9fb4 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -449,8 +449,10 @@
     if (!fs_mgr_access(top)) return fs_mgr_overlayfs_teardown_scratch(overlay, change);
 
     auto cleanup_all = mount_point.empty();
-    const auto oldpath = top + (cleanup_all ? "" : ("/" + mount_point));
-    const auto newpath = oldpath + ".teardown";
+    const auto partition_name = android::base::Basename(mount_point);
+    const auto oldpath = top + (cleanup_all ? "" : ("/" + partition_name));
+    const auto newpath = cleanup_all ? overlay + "/." + kOverlayTopDir.substr(1) + ".teardown"
+                                     : top + "/." + partition_name + ".teardown";
     auto ret = fs_mgr_rm_all(newpath);
     auto save_errno = errno;
     if (!rename(oldpath.c_str(), newpath.c_str())) {
@@ -476,12 +478,28 @@
         if (!rmdir(top.c_str())) {
             if (change) *change = true;
             cleanup_all = true;
-        } else if ((errno != ENOENT) && (errno != ENOTEMPTY)) {
+        } else if (errno == ENOTEMPTY) {
+            cleanup_all = true;
+            // cleanup all if the content is all hidden (leading .)
+            std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(top.c_str()), closedir);
+            if (!dir) {
+                PERROR << "opendir " << top;
+            } else {
+                dirent* entry;
+                while ((entry = readdir(dir.get()))) {
+                    if (entry->d_name[0] != '.') {
+                        cleanup_all = false;
+                        break;
+                    }
+                }
+            }
+            errno = save_errno;
+        } else if (errno == ENOENT) {
+            cleanup_all = true;
+            errno = save_errno;
+        } else {
             ret = false;
             PERROR << "rmdir " << top;
-        } else {
-            errno = save_errno;
-            cleanup_all = true;
         }
     }
     if (cleanup_all) ret &= fs_mgr_overlayfs_teardown_scratch(overlay, change);