autofs-5.1.9 - make rmdir_path() more informative

From: Ian Kent <raven@themaw.net>

If a symlink is encountered and it's removal succeeds we should procceed
to the next component, fix that.

Also rmdir_path() is very fussy because it tries hard to make certain
only directories within an autofs file system were removed. But in
addition we need more information about errors that happen too.

Signed-off-by: Ian Kent <raven@themaw.net>
---
 CHANGELOG          |    1 +
 daemon/automount.c |   17 ++++++++++++++---
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index f1162eee8..c9916f0c3 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -52,6 +52,7 @@
 - fix multiply defined proximity.
 - fix incorrect call in dev_ioctl_requester().
 - use nobind instead of nosymlink.
+- make rmdir_path() more informative.
 
 02/11/2023 autofs-5.1.9
 - fix kernel mount status notification.
diff --git a/daemon/automount.c b/daemon/automount.c
index 5e43455f2..e7c905063 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -273,6 +273,7 @@ int rmdir_path(struct autofs_point *ap, const char *path, dev_t dev)
 	do {
 		*cp = '\0';
 
+		errno = 0;
 		/*
 		 *  Before removing anything, perform some sanity checks to
 		 *  ensure that we are looking at files in the automount
@@ -280,7 +281,11 @@ int rmdir_path(struct autofs_point *ap, const char *path, dev_t dev)
 		 */
 		memset(&st, 0, sizeof(st));
 		if (lstat(buf, &st) != 0) {
-			crit(ap->logopt, "lstat of %s failed", buf);
+			if (errno == ENOENT) {
+				info(ap->logopt, "ENOENT return from lstat of %s", buf);
+				goto next;
+			}
+			crit(ap->logopt, "lstat of %s failed (errno %d)", buf, errno);
 			return -1;
 		}
 
@@ -288,8 +293,13 @@ int rmdir_path(struct autofs_point *ap, const char *path, dev_t dev)
 		if (st.st_dev != dev)
 			return 0;
 
+		memset(&fs, 0, sizeof(fs));
 		if (statfs(buf, &fs) != 0) {
-			error(ap->logopt, "could not stat fs of %s", buf);
+			if (errno == ENOENT) {
+				info(ap->logopt, "ENOENT return from lstat of %s", buf);
+				goto next;
+			}
+			error(ap->logopt, "could not stat fs of %s (errno %d)", buf, errno);
 			return -1;
 		}
 
@@ -316,6 +326,7 @@ int rmdir_path(struct autofs_point *ap, const char *path, dev_t dev)
 				if (S_ISLNK(st.st_mode)) {
 					if (unlink(buf) == -1)
 						return -1;
+					goto next;
 				} else {
 					crit(ap->logopt,
 					   "file \"%s\" is neither a directory"
@@ -331,7 +342,7 @@ int rmdir_path(struct autofs_point *ap, const char *path, dev_t dev)
 			 */
 			return -1;
 		}
-
+next:
 		first = 0;
 	} while ((cp = strrchr(buf, '/')) != NULL && cp != buf);
 
