Also posted the patch to savannah.gnu.org but I am unsure if it is
actively monitored. Hence I am posting to the mailing list as well -
apologies if, somehow, you received this twice.
--------

In Kodi we use libcdio to eject/unmount disks. According to this bug
report (https://github.com/xbmc/xbmc/issues/20935) kodi/libcdio fails
to unmount the disk whenever the disk label contains spaces. In the
/proc/mounts file spaces are octal escaped, like the example below:

/dev/sr0 /run/media/arch/Lawrence\040of\040Arabia udf
ro,nosuid,nodev,relatime,uid=1000,gid=1000,iocharset=utf8 0 0

The root cause of the problem is in the way libcdio gets the mountpath
- using regular file I/O. According to the linux documentation
(https://man7.org/linux/man-pages/man3/getmntent.3.html) when parsing
fstab/mtab/mounts getmtent and setmtent (and the mtent struct) should
be used instead:

```
Since fields in the mtab and fstab files are separated by
whitespace, octal escapes are used to represent the characters
space (\040), tab (\011), newline (\012), and backslash (\\) in those
files when they occur in one of the four strings in a
mntent structure.  The routines addmntent() and getmntent() will
convert from string representation to escaped representation and
back.  When converting from escaped representation, the sequence
\134 is also converted to a backslash.
```

Patch file attached, runtime tested.

Regards,

Miguel Borges de Freitas
From 4269867d959cbadd28bbb33ed5c52dc0c90d43f5 Mon Sep 17 00:00:00 2001
From: Miguel Borges de Freitas <ene...@kodi.tv>
Date: Wed, 2 Feb 2022 20:47:02 +0000
Subject: [PATCH] [Linux] Use getmntent/setmntent for reading mounts

Since fields in the mtab and fstab files are separated by
whitespace, octal escapes are used to represent the characters
space (\040), tab (\011), newline (\012), and backslash (\\) in
those files when they occur in one of the four strings in a
mntent structure.  The routines addmntent() and getmntent() will
convert from string representation to escaped representation and
back.  When converting from escaped representation, the sequence
\134 is also converted to a backslash.
---
 lib/driver/gnu_linux.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/lib/driver/gnu_linux.c b/lib/driver/gnu_linux.c
index 6a6aa4dd..dddf333c 100644
--- a/lib/driver/gnu_linux.c
+++ b/lib/driver/gnu_linux.c
@@ -672,13 +672,13 @@ static int is_mounted (const char * device, char * target) {
   char real_device_1[PATH_MAX];
   char real_device_2[PATH_MAX];
 
-  char file_device[PATH_MAX];
-  char file_target[PATH_MAX];
+  struct mntent *fs;
+
+  fp = setmntent("/proc/mounts", "r");
 
-  fp = fopen ( "/proc/mounts", "r");
   /* Older systems just have /etc/mtab */
   if(!fp)
-    fp = fopen ( "/etc/mtab", "r");
+    fp = setmntent("/etc/mtab", "r");
 
   /* Neither /proc/mounts nor /etc/mtab could be opened, give up here */
   if(!fp) return 0;
@@ -691,19 +691,19 @@ static int is_mounted (const char * device, char * target) {
 
   /* Read entries */
 
-  while ( fscanf(fp, "%s %s %*s %*s %*d %*d\n", file_device, file_target) != EOF ) {
-      if (NULL == cdio_realpath(file_device, real_device_2)) {
+  while ((fs = getmntent(fp)) != NULL) {
+      if (NULL == cdio_realpath(fs->mnt_fsname, real_device_2)) {
           cdio_debug("Problems resolving device %s: %s\n",
-                     file_device, strerror(errno));
+                     fs->mnt_fsname, strerror(errno));
       }
     if(!strcmp(real_device_1, real_device_2)) {
-      strcpy(target, file_target);
-      fclose(fp);
+      strcpy(target, fs->mnt_dir);
+      endmntent(fp);
       return 1;
     }
 
   }
-  fclose(fp);
+  endmntent(fp);
   return 0;
 }
 
-- 
2.35.1

Reply via email to