#endif
+#if @GNULIB_WGETCWD@ && (defined _WIN32 && !defined __CYGWIN__)
+/* Gets the name of the current working directory.
+ (a) If BUF is non-NULL, it is assumed to have room for SIZE wide characters.
+ This function stores the working directory (NUL-terminated) in BUF and
+ returns BUF.
+ (b) If BUF is NULL, an array is allocated with 'malloc'. The array is SIZE
+ wide characters long, unless SIZE == 0, in which case it is as big as
+ necessary.
+ If the directory couldn't be determined or SIZE was too small, this function
+ returns NULL and sets errno. For a directory of length LEN, SIZE should be
+ >= LEN + 3 in case (a) or >= LEN + 1 in case (b).
+ Possible errno values include:
+ - ERANGE if SIZE is too small.
+ - ENOMEM if the memory could no be allocated. */
+_GL_FUNCDECL_SYS (wgetcwd, wchar_t *, (wchar_t *buf, size_t size));
+#endif
+
+
#endif /* _@GUARD_PREFIX@_WCHAR_H */
#endif /* _@GUARD_PREFIX@_WCHAR_H */
#endif
--- /dev/null
+/* Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ This file is part of gnulib.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification */
+#include <wchar.h>
+
+#include <errno.h>
+#include <stdlib.h>
+
+#if defined _WIN32 && !defined __CYGWIN__
+
+wchar_t *
+wgetcwd (wchar_t *buf, size_t size)
+{
+ wchar_t *result;
+
+ /* Uses _wgetcwd.
+ Documentation:
+ <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/getcwd-wgetcwd>
+ Note that for a directory consisting of LEN wide characters, the SIZE
+ argument to _wgetcwd needs to be >= LEN + 3, not only >= LEN + 1, with
+ some versions of the Microsoft runtime libraries. */
+
+ /* Handle single size operations. */
+ if (buf)
+ {
+ /* Check SIZE argument. */
+ if (!size)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+ /* Invoke _wgetcwd as-is. In this case, the caller does not expect
+ an ENOMEM error; therefore don't use temporary memory. */
+ return _wgetcwd (buf, size);
+ }
+
+ if (size)
+ {
+ /* Allocate room for two more wide characters, so that directory names
+ of length <= SIZE - 1 can be returned. */
+ buf = malloc ((size + 2) * sizeof (wchar_t));
+ if (!buf)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ result = _wgetcwd (buf, size + 2);
+ if (!result)
+ {
+ free (buf);
+ return NULL;
+ }
+ if (wcslen (result) >= size)
+ {
+ free (buf);
+ errno = ERANGE;
+ return NULL;
+ }
+ /* Shrink result before returning it. */
+ wchar_t *shrinked_result = realloc (result, size * sizeof (wchar_t));
+ if (shrinked_result != NULL)
+ result = shrinked_result;
+ return result;
+ }
+
+ /* Flexible sizing requested. Avoid over-allocation for the common
+ case of a name that fits within a 4k page, minus some space for
+ local variables, to be sure we don't skip over a guard page. */
+ {
+ wchar_t tmp[4032 / sizeof (wchar_t)];
+ size = sizeof tmp / sizeof (wchar_t);
+ wchar_t *ptr = _wgetcwd (tmp, size);
+ if (ptr)
+ {
+ result = _wcsdup (ptr);
+ if (!result)
+ errno = ENOMEM;
+ return result;
+ }
+ if (errno != ERANGE)
+ return NULL;
+ }
+
+ /* My what a large directory name we have. */
+ do
+ {
+ size <<= 1;
+ wchar_t *ptr = realloc (buf, size * sizeof (wchar_t));
+ if (ptr == NULL)
+ {
+ free (buf);
+ errno = ENOMEM;
+ return NULL;
+ }
+ buf = ptr;
+ result = _wgetcwd (buf, size);
+ }
+ while (!result && errno == ERANGE);
+
+ if (!result)
+ free (buf);
+ else
+ {
+ /* Here result == buf. */
+ /* Shrink result before returning it. */
+ size_t actual_size = wcslen (result) + 1;
+ if (actual_size < size)
+ {
+ wchar_t *shrinked_result =
+ realloc (result, actual_size * sizeof (wchar_t));
+ if (shrinked_result != NULL)
+ result = shrinked_result;
+ }
+ }
+ return result;
+}
+
+#endif