The module 'cygpath' is used to convert file names in a Cygwin program
before passing them to a native Windows program.

The opposite situation is to convert file names in a native Windows program
that were received from a Cygwin program. This needs a different module.


2025-05-05  Bruno Haible  <br...@clisp.org>

        New module windows-cygpath.
        * lib/windows-cygpath.h: New file, based on lib/cygpath.h.
        * lib/windows-cygpath.c: New file, based on lib/cygpath.c.
        * modules/windows-cygpath: New file.

============================ lib/windows-cygpath.h ============================
/* Convert file names between Cygwin syntax and Windows syntax.
   Copyright (C) 2024-2025 Free Software Foundation, Inc.

   This file is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published
   by the Free Software Foundation, either version 3 of the License,
   or (at your option) any later version.

   This file is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */

/* Written by Bruno Haible <br...@clisp.org>, 2024.  */

#ifndef _WINDOWS_CYGPATH_H
#define _WINDOWS_CYGPATH_H

#ifdef __cplusplus
extern "C" {
#endif

/* On native Windows, this function converts a file name from Cygwin syntax to
   native Windows syntax, like 'cygpath -w' does (if available).
   Returns a freshly allocated file name.
   On the other platforms, it returns a freshly allocated copy of the
   argument file name.  */
extern char *windows_cygpath_w (const char *filename);

#ifdef __cplusplus
}
#endif

#endif /* _WINDOWS_CYGPATH_H */
============================ lib/windows-cygpath.c ============================
/* Convert file names between Cygwin syntax and Windows syntax.
   Copyright (C) 2024-2025 Free Software Foundation, Inc.

   This file is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published
   by the Free Software Foundation, either version 3 of the License,
   or (at your option) any later version.

   This file is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */

/* Written by Bruno Haible <br...@clisp.org>, 2024.  */

#include <config.h>

/* Specification.  */
#include "windows-cygpath.h"

#include "xalloc.h"
#include "gettext.h"

#define _(msgid) dgettext ("gnulib", msgid)

#if defined _WIN32 && !defined __CYGWIN__

/* Since Cygwin has its own notion of mount points (which can be defined by the
   user), it would be wrong to blindly convert '/cygdrive/c/foo' to 'C:\foo'.
   We really need to use the Cygwin API or the 'cygpath' program.
   Since under native Windows, the Cygwin API is not available, we need to
   invoke the 'cygpath' program.  */

/* Documentation:
   https://cygwin.com/cygwin-ug-net/cygpath.html  */

# include <errno.h>
# include <error.h>
# include <stdio.h>
# include <stdlib.h>

# include "spawn-pipe.h"
# include "wait-process.h"

/* Executes a program.
   Returns the first line of its output, as a freshly allocated string, or
   NULL.  */
static char *
execute_and_read_line (const char *progname,
                       const char *prog_path, const char * const *prog_argv)
{
  pid_t child;
  int fd[1];
  FILE *fp;
  char *line;
  size_t linesize;
  size_t linelen;

  /* Open a pipe to the program.  */
  child = create_pipe_in (progname, prog_path, prog_argv, NULL, NULL,
                          DEV_NULL, false, true, false, fd);

  if (child == -1)
    return NULL;

  /* Retrieve its result.  */
  fp = fdopen (fd[0], "r");
  if (fp == NULL)
    error (EXIT_FAILURE, errno, _("fdopen() failed"));

  line = NULL; linesize = 0;
  linelen = getline (&line, &linesize, fp);
  if (linelen == (size_t)(-1))
    {
      error (0, 0, _("%s subprocess I/O error"), progname);
      fclose (fp);
      wait_subprocess (child, progname, true, false, true, false, NULL);
    }
  else
    {
      int exitstatus;

      if (linelen > 0 && line[linelen - 1] == '\n')
        line[linelen - 1] = '\0';

      /* Read until EOF (otherwise the child process may get a SIGPIPE signal). 
 */
      while (getc (fp) != EOF)
        ;

      fclose (fp);

      /* Remove zombie process from process list, and retrieve exit status.  */
      exitstatus =
        wait_subprocess (child, progname, true, false, true, false, NULL);
      if (exitstatus == 0)
        return line;
    }
  free (line);
  return NULL;
}

char *
windows_cygpath_w (const char *filename)
{
  if (filename[0] == '/')
    {
      /* It's an absolute POSIX-style file name.  */
      const char *argv[4];

      argv[0] = "cygpath";
      argv[1] = "-w";
      argv[2] = filename;
      argv[3] = NULL;

      char *line = execute_and_read_line ("cygpath", "cygpath", argv);
      if (line == NULL || line[0] == '\0')
        error (EXIT_FAILURE, 0, _("%s invocation failed"), "cygpath");
      return line;
    }
  else
    /* It's a relative file name, or an absolute native Windows file name.
       No conversion is needed.  */
    return xstrdup (filename);
}

#else

char *
windows_cygpath_w (const char *filename)
{
  return xstrdup (filename);
}

#endif
=========================== modules/windows-cygpath ===========================
Description:
Convert file names between Cygwin syntax and Windows syntax.

Files:
lib/windows-cygpath.h
lib/windows-cygpath.c

Depends-on:
spawn-pipe
wait-process
getline
xalloc
free-posix
gettext-h
gnulib-i18n

configure.ac:

Makefile.am:
lib_SOURCES += windows-cygpath.c

Include:
"windows-cygpath.h"

License:
GPL

Maintainer:
all




Reply via email to