mingw: implement `readlink()`
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. Signed-off-by: Karsten Blees <karsten.blees@gmail.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Karsten Blees committed
Jan 9, 2026 at 20:05 UTC
980852dbff657a14eecc4a8a72a2874dad2bad71
2 files changed
+25
-2
compat/mingw-posix.h
+1
-2
@@ -121,8 +121,6 @@ struct utsname {
121
* trivial stubs
122
*/
123
124
-static inline int readlink(const char *path UNUSED, char *buf UNUSED, size_t bufsiz UNUSED)
125
-{ errno = ENOSYS; return -1; }
124
static inline int symlink(const char *oldpath UNUSED, const char *newpath UNUSED)
125
{ errno = ENOSYS; return -1; }
126
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);
195
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
196
int link(const char *oldpath, const char *newpath);
197
int uname(struct utsname *buf);
198
+int readlink(const char *path, char *buf, size_t bufsiz);
199
200
/*
201
* replacements of existing functions
compat/mingw.c
+24
@@ -2698,6 +2698,30 @@ int link(const char *oldpath, const char *newpath)
2698
return 0;
2699
}
2700
2701
+int readlink(const char *path, char *buf, size_t bufsiz)
2702
+{
2703
+ WCHAR wpath[MAX_PATH];
2704
+ char tmpbuf[MAX_PATH];
2705
+ int len;
2706
+ DWORD tag;
2707
+
2708
+ if (xutftowcs_path(wpath, path) < 0)
2709
+ return -1;
2710
+
2711
+ if (read_reparse_point(wpath, TRUE, tmpbuf, &len, &tag) < 0)
2712
+ return -1;
2713
+
2714
+ /*
2715
+ * Adapt to strange readlink() API: Copy up to bufsiz *bytes*, potentially
2716
+ * cutting off a UTF-8 sequence. Insufficient bufsize is *not* a failure
2717
+ * condition. There is no conversion function that produces invalid UTF-8,
2718
+ * so convert to a (hopefully large enough) temporary buffer, then memcpy
2719
+ * the requested number of bytes (including '\0' for robustness).
2720
+ */
2721
+ memcpy(buf, tmpbuf, min(bufsiz, len + 1));
2722
+ return min(bufsiz, len);
2723
+}
2724
+
2725
pid_t waitpid(pid_t pid, int *status, int options)
2726
{
2727
HANDLE h = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,