Re: [PATCH 13/18] mingw: implement `readlink()`
- From
Johannes Sixt <j6t@kdbg.org>
- Date
- Dec 18, 2025, 18:13 UTC
- Message-ID
- <8826825b-79ad-4700-aeb5-71e7847ca5dc@kdbg.org>
- In-Reply-To
- <8fef8220f4d60b48358882fbc961c4604eab3abf.1765980535.git.gitgitgadget@gmail.com>
Am 17.12.25 um 15:08 schrieb Karsten Blees via GitGitGadget:
Show 6 quoted lines
> From: Karsten Blees <blees@dcon.de> > > Implement `readlink()` by reading NTFS reparse points via the > `read_reparse_point()` function that was introduced earlier to determine > the length of symlink targets. Works for symlinks and directory > junctions. If symlinks are disabled, fail with `ENOSYS`.
This last sentence is obsolete, I think, because I cannot see how the patch achieves a failure with ENOSYS.
Show 64 quoted lines
>
> Signed-off-by: Karsten Blees <blees@dcon.de>
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
> compat/mingw-posix.h | 3 +--
> compat/mingw.c | 24 ++++++++++++++++++++++++
> 2 files changed, 25 insertions(+), 2 deletions(-)
>
> diff --git a/compat/mingw-posix.h b/compat/mingw-posix.h
> index 0939feff27..896aa976b1 100644
> --- a/compat/mingw-posix.h
> +++ b/compat/mingw-posix.h
> @@ -121,8 +121,6 @@ struct utsname {
> * trivial stubs
> */
>
> -static inline int readlink(const char *path UNUSED, char *buf UNUSED, size_t bufsiz UNUSED)
> -{ errno = ENOSYS; return -1; }
> static inline int symlink(const char *oldpath UNUSED, const char *newpath UNUSED)
> { errno = ENOSYS; return -1; }
> static inline int fchmod(int fildes UNUSED, mode_t mode UNUSED)
> @@ -197,6 +195,7 @@ int setitimer(int type, struct itimerval *in, struct itimerval *out);
> int sigaction(int sig, struct sigaction *in, struct sigaction *out);
> int link(const char *oldpath, const char *newpath);
> int uname(struct utsname *buf);
> +int readlink(const char *path, char *buf, size_t bufsiz);
>
> /*
> * replacements of existing functions
> diff --git a/compat/mingw.c b/compat/mingw.c
> index 5d2a8c247c..b407a2ac07 100644
> --- a/compat/mingw.c
> +++ b/compat/mingw.c
> @@ -2698,6 +2698,30 @@ int link(const char *oldpath, const char *newpath)
> return 0;
> }
>
> +int readlink(const char *path, char *buf, size_t bufsiz)
> +{
> + WCHAR wpath[MAX_PATH];
> + char tmpbuf[MAX_PATH];
> + int len;
> + DWORD tag;
> +
> + if (xutftowcs_path(wpath, path) < 0)
> + return -1;
> +
> + if (read_reparse_point(wpath, TRUE, tmpbuf, &len, &tag) < 0)
> + return -1;
> +
> + /*
> + * Adapt to strange readlink() API: Copy up to bufsiz *bytes*, potentially
> + * cutting off a UTF-8 sequence. Insufficient bufsize is *not* a failure
> + * condition. There is no conversion function that produces invalid UTF-8,
> + * so convert to a (hopefully large enough) temporary buffer, then memcpy
> + * the requested number of bytes (including '\0' for robustness).
> + */
> + memcpy(buf, tmpbuf, min(bufsiz, len + 1));
> + return min(bufsiz, len);
> +}
> +
> pid_t waitpid(pid_t pid, int *status, int options)
> {
> HANDLE h = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,-- Hannes