aboutsummaryrefslogtreecommitdiff
path: root/compat/mingw.c
diff options
context:
space:
mode:
authorKarsten Blees <karsten.blees@gmail.com>2026-01-09 20:05:10 +0000
committerJunio C Hamano <gitster@pobox.com>2026-01-09 18:32:55 -0800
commit980852dbff657a14eecc4a8a72a2874dad2bad71 (patch)
tree6c8b7dfae701fa6daec879c16babdadcc541391e /compat/mingw.c
parent43745a7d55daa1aa0937a3c6e8b521bd026a31f1 (diff)
downloadgit-980852dbff657a14eecc4a8a72a2874dad2bad71.tar.xz
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>
Diffstat (limited to 'compat/mingw.c')
-rw-r--r--compat/mingw.c24
1 files changed, 24 insertions, 0 deletions
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,