]> Savannah Git Hosting - gnulib.git/commitdiff
cygpath: New module.
authorBruno Haible <bruno@clisp.org>
Mon, 7 Oct 2024 18:10:16 +0000 (20:10 +0200)
committerBruno Haible <bruno@clisp.org>
Wed, 16 Oct 2024 12:03:36 +0000 (14:03 +0200)
* lib/cygpath.h: New file.
* lib/cygpath.c: New file, based on lib/javaversion.c.
* modules/cygpath: New file.

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

index d36b122092c13d0b15dd815eaf97a52bc542afff..152ace80c43de0e7b29cc76978d431409ed85f2a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2024-10-07  Bruno Haible  <bruno@clisp.org>
+
+       cygpath: New module.
+       * lib/cygpath.h: New file.
+       * lib/cygpath.c: New file, based on lib/javaversion.c.
+       * modules/cygpath: New file.
+
 2024-10-06  Bruno Haible  <bruno@clisp.org>
 
        javacomp, javaversion: Fix resource leak.
diff --git a/lib/cygpath.c b/lib/cygpath.c
new file mode 100644 (file)
index 0000000..7461706
--- /dev/null
@@ -0,0 +1,163 @@
+/* Convert file names between Cygwin syntax and Windows syntax.
+   Copyright (C) 2024 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 "cygpath.h"
+
+#include <stdlib.h>
+
+#include "xalloc.h"
+#include "gettext.h"
+
+#define _(str) gettext (str)
+
+#ifdef __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.  */
+
+# include <errno.h>
+# include <error.h>
+
+# if 1
+
+/* Documentation:
+   https://cygwin.com/cygwin-api/func-cygwin-conv-path.html  */
+
+#  include <sys/cygwin.h>
+
+char *
+cygpath_w (const char *filename)
+{
+  int repeat;
+
+  /* Try several times, since there is a small time window during which the
+     size returned by the previous call may not be sufficient, namely when a
+     directory gets renamed.  */
+  for (repeat = 3; repeat > 0; repeat--)
+    {
+      ssize_t size = cygwin_conv_path (CCP_POSIX_TO_WIN_A | CCP_RELATIVE, filename, NULL, 0);
+      if (size < 0)
+        error (EXIT_FAILURE, errno, _("cannot convert file name '%s' to Windows syntax"), filename);
+      char *result = (char *) xmalloc (size);
+      if (cygwin_conv_path (CCP_POSIX_TO_WIN_A | CCP_RELATIVE, filename, result, size) == 0)
+        return result;
+      free (result);
+    }
+  error (EXIT_FAILURE, errno, _("cygwin_conv_path failed"));
+  return NULL;
+}
+
+# else
+/* Alternative implementation (slower)  */
+
+/* Documentation:
+   https://cygwin.com/cygwin-ug-net/cygpath.html  */
+
+#  include <stdio.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,
+                          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 *
+cygpath_w (const char *filename)
+{
+  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;
+}
+
+# endif
+
+#else
+
+char *
+cygpath_w (const char *filename)
+{
+  return xstrdup (filename);
+}
+
+#endif
diff --git a/lib/cygpath.h b/lib/cygpath.h
new file mode 100644 (file)
index 0000000..0843347
--- /dev/null
@@ -0,0 +1,37 @@
+/* Convert file names between Cygwin syntax and Windows syntax.
+   Copyright (C) 2024 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 _CYGPATH_H
+#define _CYGPATH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* On Cygwin, this function converts a file name from Cygwin syntax to
+   native Windows syntax, like 'cygpath -w' does.
+   Returns a freshly allocated file name.
+   On the other platforms, it returns a freshly allocated copy of the
+   argument file name.  */
+extern char *cygpath_w (const char *filename);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CYGPATH_H */
diff --git a/modules/cygpath b/modules/cygpath
new file mode 100644 (file)
index 0000000..dc48848
--- /dev/null
@@ -0,0 +1,25 @@
+Description:
+Convert file names between Cygwin syntax and Windows syntax.
+
+Files:
+lib/cygpath.h
+lib/cygpath.c
+
+Depends-on:
+xalloc
+free-posix
+gettext-h
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += cygpath.c
+
+Include:
+"cygpath.h"
+
+License:
+GPL
+
+Maintainer:
+all