]> git.ipfire.org Git - thirdparty/gnulib.git/commitdiff
New module windows-cygpath.
authorBruno Haible <bruno@clisp.org>
Mon, 5 May 2025 09:37:16 +0000 (11:37 +0200)
committerBruno Haible <bruno@clisp.org>
Mon, 5 May 2025 09:52:27 +0000 (11:52 +0200)
* 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.

ChangeLog
lib/windows-cygpath.c [new file with mode: 0644]
lib/windows-cygpath.h [new file with mode: 0644]
modules/windows-cygpath [new file with mode: 0644]

index 29a66a4b7635b299f367e42a95e87756afe23666..7c790cdff30149b4fb8c2d2dad67022cf60a7651 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2025-05-05  Bruno Haible  <bruno@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.
+
 2025-05-05  Bruno Haible  <bruno@clisp.org>
 
        obstack: Relicense under LGPLv2+.
diff --git a/lib/windows-cygpath.c b/lib/windows-cygpath.c
new file mode 100644 (file)
index 0000000..f0f1a88
--- /dev/null
@@ -0,0 +1,137 @@
+/* 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 <bruno@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
diff --git a/lib/windows-cygpath.h b/lib/windows-cygpath.h
new file mode 100644 (file)
index 0000000..eb870d2
--- /dev/null
@@ -0,0 +1,37 @@
+/* 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 <bruno@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 */
diff --git a/modules/windows-cygpath b/modules/windows-cygpath
new file mode 100644 (file)
index 0000000..6575f49
--- /dev/null
@@ -0,0 +1,29 @@
+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