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 */
>

Reply via email to