Skip to content

Commit 1ae9c63

Browse files
kbleesdscho
authored andcommitted
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 <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]>
1 parent f79cf31 commit 1ae9c63

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

compat/mingw-posix.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,6 @@ struct utsname {
121121
* trivial stubs
122122
*/
123123

124-
static inline int readlink(const char *path UNUSED, char *buf UNUSED, size_t bufsiz UNUSED)
125-
{ errno = ENOSYS; return -1; }
126124
static inline int symlink(const char *oldpath UNUSED, const char *newpath UNUSED)
127125
{ errno = ENOSYS; return -1; }
128126
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);
197195
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
198196
int link(const char *oldpath, const char *newpath);
199197
int uname(struct utsname *buf);
198+
int readlink(const char *path, char *buf, size_t bufsiz);
200199

201200
/*
202201
* replacements of existing functions

compat/mingw.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2698,6 +2698,30 @@ int link(const char *oldpath, const char *newpath)
26982698
return 0;
26992699
}
27002700

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+
27012725
pid_t waitpid(pid_t pid, int *status, int options)
27022726
{
27032727
HANDLE h = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,

0 commit comments

Comments
 (0)