aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--e2fsprogs/e2fs_lib.c6
-rw-r--r--e2fsprogs/lsattr.c1
-rw-r--r--win32/mingw.c37
3 files changed, 43 insertions, 1 deletions
diff --git a/e2fsprogs/e2fs_lib.c b/e2fsprogs/e2fs_lib.c
index 031f5e06b..4a4db1a13 100644
--- a/e2fsprogs/e2fs_lib.c
+++ b/e2fsprogs/e2fs_lib.c
@@ -135,6 +135,9 @@ void print_e2flags_long(struct stat *sb)
135 case IO_REPARSE_TAG_MOUNT_POINT: 135 case IO_REPARSE_TAG_MOUNT_POINT:
136 ln = "Junction"; 136 ln = "Junction";
137 break; 137 break;
138 case IO_REPARSE_TAG_APPEXECLINK:
139 ln = "App_Exec_Link";
140 break;
138 } 141 }
139 } 142 }
140 fputs(ln, stdout); 143 fputs(ln, stdout);
@@ -174,6 +177,9 @@ void print_e2flags(struct stat *sb)
174 case IO_REPARSE_TAG_MOUNT_POINT: 177 case IO_REPARSE_TAG_MOUNT_POINT:
175 c = 'j'; 178 c = 'j';
176 break; 179 break;
180 case IO_REPARSE_TAG_APPEXECLINK:
181 c = 'A';
182 break;
177 } 183 }
178 } 184 }
179#endif 185#endif
diff --git a/e2fsprogs/lsattr.c b/e2fsprogs/lsattr.c
index a6c4a27e9..87fdb78b3 100644
--- a/e2fsprogs/lsattr.c
+++ b/e2fsprogs/lsattr.c
@@ -47,6 +47,7 @@
47//usage: "\n\nAttributes:\n" 47//usage: "\n\nAttributes:\n"
48//usage: "\n j Junction" 48//usage: "\n j Junction"
49//usage: "\n l Symbolic link" 49//usage: "\n l Symbolic link"
50//usage: "\n A App exec link"
50//usage: "\n R Reparse point" 51//usage: "\n R Reparse point"
51//usage: "\n o Offline" 52//usage: "\n o Offline"
52//usage: "\n e Encrypted" 53//usage: "\n e Encrypted"
diff --git a/win32/mingw.c b/win32/mingw.c
index 9e1cf5eea..be4fc7aa1 100644
--- a/win32/mingw.c
+++ b/win32/mingw.c
@@ -593,6 +593,7 @@ static DWORD get_symlink_data(DWORD attr, const char *pathname,
593 switch (fbuf->dwReserved0) { 593 switch (fbuf->dwReserved0) {
594 case IO_REPARSE_TAG_SYMLINK: 594 case IO_REPARSE_TAG_SYMLINK:
595 case IO_REPARSE_TAG_MOUNT_POINT: 595 case IO_REPARSE_TAG_MOUNT_POINT:
596 case IO_REPARSE_TAG_APPEXECLINK:
596 return fbuf->dwReserved0; 597 return fbuf->dwReserved0;
597 } 598 }
598 } 599 }
@@ -1602,6 +1603,23 @@ static wchar_t *normalize_ntpath(wchar_t *wbuf)
1602 return wbuf; 1603 return wbuf;
1603} 1604}
1604 1605
1606/*
1607 * This is the stucture required for reparse points with the tag
1608 * IO_REPARSE_TAG_APPEXECLINK. The Buffer member contains four
1609 * NUL-terminated, concatentated strings:
1610 *
1611 * package id, entry point, executable path and application type.
1612 *
1613 * https://www.tiraniddo.dev/2019/09/overview-of-windows-execution-aliases.html
1614 */
1615typedef struct {
1616 DWORD ReparseTag;
1617 USHORT ReparseDataLength;
1618 USHORT Reserved;
1619 ULONG Version;
1620 WCHAR Buffer[1];
1621} APPEXECLINK_BUFFER;
1622
1605#define SRPB rptr->SymbolicLinkReparseBuffer 1623#define SRPB rptr->SymbolicLinkReparseBuffer
1606ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) 1624ssize_t readlink(const char *pathname, char *buf, size_t bufsiz)
1607{ 1625{
@@ -1613,9 +1631,11 @@ ssize_t readlink(const char *pathname, char *buf, size_t bufsiz)
1613 DWORD nbytes; 1631 DWORD nbytes;
1614 BYTE rbuf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; 1632 BYTE rbuf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1615 PREPARSE_DATA_BUFFER rptr = (PREPARSE_DATA_BUFFER)rbuf; 1633 PREPARSE_DATA_BUFFER rptr = (PREPARSE_DATA_BUFFER)rbuf;
1634 APPEXECLINK_BUFFER *aptr = (APPEXECLINK_BUFFER *)rptr;
1616 BOOL status; 1635 BOOL status;
1617 size_t len; 1636 size_t len;
1618 WCHAR *name = NULL; 1637 WCHAR *name = NULL, *str[4], *s;
1638 int i;
1619 1639
1620 status = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, 1640 status = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0,
1621 rptr, sizeof(rbuf), &nbytes, NULL); 1641 rptr, sizeof(rbuf), &nbytes, NULL);
@@ -1627,6 +1647,21 @@ ssize_t readlink(const char *pathname, char *buf, size_t bufsiz)
1627 } else if (status && rptr->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { 1647 } else if (status && rptr->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
1628 len = MRPB.SubstituteNameLength/sizeof(WCHAR); 1648 len = MRPB.SubstituteNameLength/sizeof(WCHAR);
1629 name = MRPB.PathBuffer + MRPB.SubstituteNameOffset/sizeof(WCHAR); 1649 name = MRPB.PathBuffer + MRPB.SubstituteNameOffset/sizeof(WCHAR);
1650 } else if (status && rptr->ReparseTag == IO_REPARSE_TAG_APPEXECLINK) {
1651 // We only need the executable path but we determine all of
1652 // the strings as a sanity check.
1653 i = 0;
1654 s = aptr->Buffer;
1655 do {
1656 str[i] = s;
1657 while (*s++)
1658 ;
1659 } while (++i < 4);
1660
1661 if (s - aptr->Buffer < MAXIMUM_REPARSE_DATA_BUFFER_SIZE) {
1662 len = wcslen(str[2]);
1663 name = str[2];
1664 }
1630 } 1665 }
1631 1666
1632 if (name) { 1667 if (name) {