I sent this patch in June (https://cygwin.com/pipermail/cygwin-patches/2024q2/012712.html), and I recently remembered I hadn't heard anything about it.
On Tue, 4 Jun 2024, Jeremy Drake via Cygwin-patches wrote: > In order for these formats to be machine-parseable, characters used as > delimiters must be escaped. Linux escapes space, tab, newline, > backslash, and hash (because code that parses mounts/mtab and fstab > would handle comments) using octal escapes. Replicate that behavior > here. > > Addresses: https://cygwin.com/pipermail/cygwin/2024-June/256082.html > Signed-off-by: Jeremy Drake <cyg...@jdrake.com> > --- > > Changes from original: > * forgot to include tab '\t' in characters that need escaping > * I mis-iterpreted how octal escapes work: they don't require a leading 0, > but Linux uses a fixed 3 digit format, which makes calculating the length > cleaner. > > winsup/cygwin/fhandler/process.cc | 76 +++++++++++++++++++++++++++---- > 1 file changed, 66 insertions(+), 10 deletions(-) > > diff --git a/winsup/cygwin/fhandler/process.cc > b/winsup/cygwin/fhandler/process.cc > index 37bdff84e3..db1763d702 100644 > --- a/winsup/cygwin/fhandler/process.cc > +++ b/winsup/cygwin/fhandler/process.cc > @@ -1317,9 +1317,39 @@ extern "C" { > struct mntent *getmntent (FILE *); > }; > > +static size_t > +escape_string_length (const char *str, const char *escapees) > +{ > + size_t i, len = 0; > + > + for (i = strcspn (str, escapees); > + str[i]; > + i += strcspn (str + i + 1, escapees) + 1) > + len += 3; > + return len + i; > +} > + > +static size_t > +escape_string (char *destbuf, const char *str, const char *escapees) > +{ > + size_t s, i; > + char *p = destbuf; > + > + for (s = 0, i = strcspn (str, escapees); > + str[i]; > + s = i + 1, i += strcspn (str + s, escapees) + 1) > + { > + p = stpncpy (p, str + s, i - s); > + p += __small_sprintf (p, "\\%03o", (int)(unsigned char) str[i]); > + } > + p = stpcpy (p, str + s); > + return (p - destbuf); > +} > + > static off_t > format_process_mountstuff (void *data, char *&destbuf, bool mountinfo) > { > + static const char MOUNTSTUFF_ESCAPEES[] = " \t\n\\#"; > _pinfo *p = (_pinfo *) data; > user_info *u_shared = NULL; > HANDLE u_hdl = NULL; > @@ -1369,9 +1399,9 @@ format_process_mountstuff (void *data, char *&destbuf, > bool mountinfo) > continue; > } > destbuf = (char *) crealloc_abort (destbuf, len > - + strlen (mnt->mnt_fsname) > - + strlen (mnt->mnt_dir) > - + strlen (mnt->mnt_type) > + + escape_string_length > (mnt->mnt_fsname, MOUNTSTUFF_ESCAPEES) > + + escape_string_length > (mnt->mnt_dir, MOUNTSTUFF_ESCAPEES) > + + escape_string_length > (mnt->mnt_type, MOUNTSTUFF_ESCAPEES) > + strlen (mnt->mnt_opts) > + 30); > if (mountinfo) > @@ -1380,18 +1410,44 @@ format_process_mountstuff (void *data, char > *&destbuf, bool mountinfo) > dev_t dev = pc.exists () ? pc.fs_serial_number () : -1; > > len += __small_sprintf (destbuf + len, > - "%d %d %d:%d / %s %s - %s %s %s\n", > + "%d %d %d:%d / ", > iteration, iteration, > - major (dev), minor (dev), > - mnt->mnt_dir, mnt->mnt_opts, > - mnt->mnt_type, mnt->mnt_fsname, > + major (dev), minor (dev)); > + len += escape_string (destbuf + len, > + mnt->mnt_dir, > + MOUNTSTUFF_ESCAPEES); > + len += __small_sprintf (destbuf + len, > + " %s - ", > + mnt->mnt_opts); > + len += escape_string (destbuf + len, > + mnt->mnt_type, > + MOUNTSTUFF_ESCAPEES); > + destbuf[len++] = ' '; > + len += escape_string (destbuf + len, > + mnt->mnt_fsname, > + MOUNTSTUFF_ESCAPEES); > + len += __small_sprintf (destbuf + len, > + " %s\n", > (pc.fs_flags () & FILE_READ_ONLY_VOLUME) > ? "ro" : "rw"); > } > else > - len += __small_sprintf (destbuf + len, "%s %s %s %s %d %d\n", > - mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type, > - mnt->mnt_opts, mnt->mnt_freq, mnt->mnt_passno); > + { > + len += escape_string (destbuf + len, > + mnt->mnt_fsname, > + MOUNTSTUFF_ESCAPEES); > + destbuf[len++] = ' '; > + len += escape_string (destbuf + len, > + mnt->mnt_dir, > + MOUNTSTUFF_ESCAPEES); > + destbuf[len++] = ' '; > + len += escape_string (destbuf + len, > + mnt->mnt_type, > + MOUNTSTUFF_ESCAPEES); > + len += __small_sprintf (destbuf + len, " %s %d %d\n", > + mnt->mnt_opts, mnt->mnt_freq, > + mnt->mnt_passno); > + } > } > > /* Restore available_drives */ >