xref: /aosp_15_r20/external/lzma/CPP/Windows/FileLink.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // Windows/FileLink.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "../../C/CpuArch.h"
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #ifndef _WIN32
8*f6dc9357SAndroid Build Coastguard Worker #include <unistd.h>
9*f6dc9357SAndroid Build Coastguard Worker #endif
10*f6dc9357SAndroid Build Coastguard Worker 
11*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_DEVICE_FILE
12*f6dc9357SAndroid Build Coastguard Worker #include "../../C/Alloc.h"
13*f6dc9357SAndroid Build Coastguard Worker #endif
14*f6dc9357SAndroid Build Coastguard Worker 
15*f6dc9357SAndroid Build Coastguard Worker #include "../Common/UTFConvert.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StringConvert.h"
17*f6dc9357SAndroid Build Coastguard Worker 
18*f6dc9357SAndroid Build Coastguard Worker #include "FileDir.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "FileFind.h"
20*f6dc9357SAndroid Build Coastguard Worker #include "FileIO.h"
21*f6dc9357SAndroid Build Coastguard Worker #include "FileName.h"
22*f6dc9357SAndroid Build Coastguard Worker 
23*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_OLD_WIN_SDK
24*f6dc9357SAndroid Build Coastguard Worker #ifndef ERROR_INVALID_REPARSE_DATA
25*f6dc9357SAndroid Build Coastguard Worker #define ERROR_INVALID_REPARSE_DATA       4392L
26*f6dc9357SAndroid Build Coastguard Worker #endif
27*f6dc9357SAndroid Build Coastguard Worker #ifndef ERROR_REPARSE_TAG_INVALID
28*f6dc9357SAndroid Build Coastguard Worker #define ERROR_REPARSE_TAG_INVALID        4393L
29*f6dc9357SAndroid Build Coastguard Worker #endif
30*f6dc9357SAndroid Build Coastguard Worker #endif
31*f6dc9357SAndroid Build Coastguard Worker 
32*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
33*f6dc9357SAndroid Build Coastguard Worker extern bool g_IsNT;
34*f6dc9357SAndroid Build Coastguard Worker #endif
35*f6dc9357SAndroid Build Coastguard Worker 
36*f6dc9357SAndroid Build Coastguard Worker namespace NWindows {
37*f6dc9357SAndroid Build Coastguard Worker namespace NFile {
38*f6dc9357SAndroid Build Coastguard Worker 
39*f6dc9357SAndroid Build Coastguard Worker using namespace NName;
40*f6dc9357SAndroid Build Coastguard Worker 
41*f6dc9357SAndroid Build Coastguard Worker /*
42*f6dc9357SAndroid Build Coastguard Worker   Reparse Points (Junctions and Symbolic Links):
43*f6dc9357SAndroid Build Coastguard Worker   struct
44*f6dc9357SAndroid Build Coastguard Worker   {
45*f6dc9357SAndroid Build Coastguard Worker     UInt32 Tag;
46*f6dc9357SAndroid Build Coastguard Worker     UInt16 Size;     // not including starting 8 bytes
47*f6dc9357SAndroid Build Coastguard Worker     UInt16 Reserved; // = 0
48*f6dc9357SAndroid Build Coastguard Worker 
49*f6dc9357SAndroid Build Coastguard Worker     UInt16 SubstituteOffset; // offset in bytes from  start of namesChars
50*f6dc9357SAndroid Build Coastguard Worker     UInt16 SubstituteLen;    // size in bytes, it doesn't include tailed NUL
51*f6dc9357SAndroid Build Coastguard Worker     UInt16 PrintOffset;      // offset in bytes from  start of namesChars
52*f6dc9357SAndroid Build Coastguard Worker     UInt16 PrintLen;         // size in bytes, it doesn't include tailed NUL
53*f6dc9357SAndroid Build Coastguard Worker 
54*f6dc9357SAndroid Build Coastguard Worker     [UInt32] Flags;  // for Symbolic Links only.
55*f6dc9357SAndroid Build Coastguard Worker 
56*f6dc9357SAndroid Build Coastguard Worker     UInt16 namesChars[]
57*f6dc9357SAndroid Build Coastguard Worker   }
58*f6dc9357SAndroid Build Coastguard Worker 
59*f6dc9357SAndroid Build Coastguard Worker   MOUNT_POINT (Junction point):
60*f6dc9357SAndroid Build Coastguard Worker     1) there is NUL wchar after path
61*f6dc9357SAndroid Build Coastguard Worker     2) Default Order in table:
62*f6dc9357SAndroid Build Coastguard Worker          Substitute Path
63*f6dc9357SAndroid Build Coastguard Worker          Print Path
64*f6dc9357SAndroid Build Coastguard Worker     3) pathnames can not contain dot directory names
65*f6dc9357SAndroid Build Coastguard Worker 
66*f6dc9357SAndroid Build Coastguard Worker   SYMLINK:
67*f6dc9357SAndroid Build Coastguard Worker     1) there is no NUL wchar after path
68*f6dc9357SAndroid Build Coastguard Worker     2) Default Order in table:
69*f6dc9357SAndroid Build Coastguard Worker          Print Path
70*f6dc9357SAndroid Build Coastguard Worker          Substitute Path
71*f6dc9357SAndroid Build Coastguard Worker */
72*f6dc9357SAndroid Build Coastguard Worker 
73*f6dc9357SAndroid Build Coastguard Worker /*
74*f6dc9357SAndroid Build Coastguard Worker Win10 WSL2:
75*f6dc9357SAndroid Build Coastguard Worker admin rights + sudo: it creates normal windows symbolic link.
76*f6dc9357SAndroid Build Coastguard Worker in another cases   : it creates IO_REPARSE_TAG_LX_SYMLINK repare point.
77*f6dc9357SAndroid Build Coastguard Worker */
78*f6dc9357SAndroid Build Coastguard Worker 
79*f6dc9357SAndroid Build Coastguard Worker /*
80*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kReparseFlags_Alias       = (1 << 29);
81*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kReparseFlags_HighLatency = (1 << 30);
82*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kReparseFlags_Microsoft   = ((UInt32)1 << 31);
83*f6dc9357SAndroid Build Coastguard Worker 
84*f6dc9357SAndroid Build Coastguard Worker #define Z7_WIN_IO_REPARSE_TAG_HSM          (0xC0000004L)
85*f6dc9357SAndroid Build Coastguard Worker #define Z7_WIN_IO_REPARSE_TAG_HSM2         (0x80000006L)
86*f6dc9357SAndroid Build Coastguard Worker #define Z7_WIN_IO_REPARSE_TAG_SIS          (0x80000007L)
87*f6dc9357SAndroid Build Coastguard Worker #define Z7_WIN_IO_REPARSE_TAG_WIM          (0x80000008L)
88*f6dc9357SAndroid Build Coastguard Worker #define Z7_WIN_IO_REPARSE_TAG_CSV          (0x80000009L)
89*f6dc9357SAndroid Build Coastguard Worker #define Z7_WIN_IO_REPARSE_TAG_DFS          (0x8000000AL)
90*f6dc9357SAndroid Build Coastguard Worker #define Z7_WIN_IO_REPARSE_TAG_DFSR         (0x80000012L)
91*f6dc9357SAndroid Build Coastguard Worker */
92*f6dc9357SAndroid Build Coastguard Worker 
93*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) GetUi16(p)
94*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
95*f6dc9357SAndroid Build Coastguard Worker 
96*f6dc9357SAndroid Build Coastguard Worker static const wchar_t * const k_LinkPrefix = L"\\??\\";
97*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_LinkPrefix_Size = 4;
98*f6dc9357SAndroid Build Coastguard Worker 
IsLinkPrefix(const wchar_t * s)99*f6dc9357SAndroid Build Coastguard Worker static bool IsLinkPrefix(const wchar_t *s)
100*f6dc9357SAndroid Build Coastguard Worker {
101*f6dc9357SAndroid Build Coastguard Worker   return IsString1PrefixedByString2(s, k_LinkPrefix);
102*f6dc9357SAndroid Build Coastguard Worker }
103*f6dc9357SAndroid Build Coastguard Worker 
104*f6dc9357SAndroid Build Coastguard Worker /*
105*f6dc9357SAndroid Build Coastguard Worker static const wchar_t * const k_VolumePrefix = L"Volume{";
106*f6dc9357SAndroid Build Coastguard Worker static const bool IsVolumeName(const wchar_t *s)
107*f6dc9357SAndroid Build Coastguard Worker {
108*f6dc9357SAndroid Build Coastguard Worker   return IsString1PrefixedByString2(s, k_VolumePrefix);
109*f6dc9357SAndroid Build Coastguard Worker }
110*f6dc9357SAndroid Build Coastguard Worker */
111*f6dc9357SAndroid Build Coastguard Worker 
112*f6dc9357SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(UNDER_CE)
113*f6dc9357SAndroid Build Coastguard Worker 
114*f6dc9357SAndroid Build Coastguard Worker #define Set16(p, v) SetUi16(p, v)
115*f6dc9357SAndroid Build Coastguard Worker #define Set32(p, v) SetUi32(p, v)
116*f6dc9357SAndroid Build Coastguard Worker 
WriteString(Byte * dest,const wchar_t * path)117*f6dc9357SAndroid Build Coastguard Worker static void WriteString(Byte *dest, const wchar_t *path)
118*f6dc9357SAndroid Build Coastguard Worker {
119*f6dc9357SAndroid Build Coastguard Worker   for (;;)
120*f6dc9357SAndroid Build Coastguard Worker   {
121*f6dc9357SAndroid Build Coastguard Worker     wchar_t c = *path++;
122*f6dc9357SAndroid Build Coastguard Worker     if (c == 0)
123*f6dc9357SAndroid Build Coastguard Worker       return;
124*f6dc9357SAndroid Build Coastguard Worker     Set16(dest, (UInt16)c)
125*f6dc9357SAndroid Build Coastguard Worker     dest += 2;
126*f6dc9357SAndroid Build Coastguard Worker   }
127*f6dc9357SAndroid Build Coastguard Worker }
128*f6dc9357SAndroid Build Coastguard Worker 
FillLinkData(CByteBuffer & dest,const wchar_t * path,bool isSymLink,bool isWSL)129*f6dc9357SAndroid Build Coastguard Worker bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL)
130*f6dc9357SAndroid Build Coastguard Worker {
131*f6dc9357SAndroid Build Coastguard Worker   bool isAbs = IsAbsolutePath(path);
132*f6dc9357SAndroid Build Coastguard Worker   if (!isAbs && !isSymLink)
133*f6dc9357SAndroid Build Coastguard Worker     return false;
134*f6dc9357SAndroid Build Coastguard Worker 
135*f6dc9357SAndroid Build Coastguard Worker   if (isWSL)
136*f6dc9357SAndroid Build Coastguard Worker   {
137*f6dc9357SAndroid Build Coastguard Worker     // unsupported characters probably use Replacement Character UTF-16 0xFFFD
138*f6dc9357SAndroid Build Coastguard Worker     AString utf;
139*f6dc9357SAndroid Build Coastguard Worker     ConvertUnicodeToUTF8(path, utf);
140*f6dc9357SAndroid Build Coastguard Worker     const size_t size = 4 + utf.Len();
141*f6dc9357SAndroid Build Coastguard Worker     if (size != (UInt16)size)
142*f6dc9357SAndroid Build Coastguard Worker       return false;
143*f6dc9357SAndroid Build Coastguard Worker     dest.Alloc(8 + size);
144*f6dc9357SAndroid Build Coastguard Worker     Byte *p = dest;
145*f6dc9357SAndroid Build Coastguard Worker     Set32(p, Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK)
146*f6dc9357SAndroid Build Coastguard Worker     Set16(p + 4, (UInt16)(size))
147*f6dc9357SAndroid Build Coastguard Worker     Set16(p + 6, 0)
148*f6dc9357SAndroid Build Coastguard Worker     Set32(p + 8, Z7_WIN_LX_SYMLINK_FLAG)
149*f6dc9357SAndroid Build Coastguard Worker     memcpy(p + 12, utf.Ptr(), utf.Len());
150*f6dc9357SAndroid Build Coastguard Worker     return true;
151*f6dc9357SAndroid Build Coastguard Worker   }
152*f6dc9357SAndroid Build Coastguard Worker 
153*f6dc9357SAndroid Build Coastguard Worker   // usual symbolic LINK (NOT WSL)
154*f6dc9357SAndroid Build Coastguard Worker 
155*f6dc9357SAndroid Build Coastguard Worker   bool needPrintName = true;
156*f6dc9357SAndroid Build Coastguard Worker 
157*f6dc9357SAndroid Build Coastguard Worker   if (IsSuperPath(path))
158*f6dc9357SAndroid Build Coastguard Worker   {
159*f6dc9357SAndroid Build Coastguard Worker     path += kSuperPathPrefixSize;
160*f6dc9357SAndroid Build Coastguard Worker     if (!IsDrivePath(path))
161*f6dc9357SAndroid Build Coastguard Worker       needPrintName = false;
162*f6dc9357SAndroid Build Coastguard Worker   }
163*f6dc9357SAndroid Build Coastguard Worker 
164*f6dc9357SAndroid Build Coastguard Worker   const unsigned add_Prefix_Len = isAbs ? k_LinkPrefix_Size : 0;
165*f6dc9357SAndroid Build Coastguard Worker 
166*f6dc9357SAndroid Build Coastguard Worker   size_t len2 = (size_t)MyStringLen(path) * 2;
167*f6dc9357SAndroid Build Coastguard Worker   const size_t len1 = len2 + add_Prefix_Len * 2;
168*f6dc9357SAndroid Build Coastguard Worker   if (!needPrintName)
169*f6dc9357SAndroid Build Coastguard Worker     len2 = 0;
170*f6dc9357SAndroid Build Coastguard Worker 
171*f6dc9357SAndroid Build Coastguard Worker   size_t totalNamesSize = (len1 + len2);
172*f6dc9357SAndroid Build Coastguard Worker 
173*f6dc9357SAndroid Build Coastguard Worker   /* some WIM imagex software uses old scheme for symbolic links.
174*f6dc9357SAndroid Build Coastguard Worker      so we can old scheme for byte to byte compatibility */
175*f6dc9357SAndroid Build Coastguard Worker 
176*f6dc9357SAndroid Build Coastguard Worker   bool newOrderScheme = isSymLink;
177*f6dc9357SAndroid Build Coastguard Worker   // newOrderScheme = false;
178*f6dc9357SAndroid Build Coastguard Worker 
179*f6dc9357SAndroid Build Coastguard Worker   if (!newOrderScheme)
180*f6dc9357SAndroid Build Coastguard Worker     totalNamesSize += 2 * 2;
181*f6dc9357SAndroid Build Coastguard Worker 
182*f6dc9357SAndroid Build Coastguard Worker   const size_t size = 8 + 8 + (isSymLink ? 4 : 0) + totalNamesSize;
183*f6dc9357SAndroid Build Coastguard Worker   if (size != (UInt16)size)
184*f6dc9357SAndroid Build Coastguard Worker     return false;
185*f6dc9357SAndroid Build Coastguard Worker   dest.Alloc(size);
186*f6dc9357SAndroid Build Coastguard Worker   memset(dest, 0, size);
187*f6dc9357SAndroid Build Coastguard Worker   const UInt32 tag = isSymLink ?
188*f6dc9357SAndroid Build Coastguard Worker       Z7_WIN_IO_REPARSE_TAG_SYMLINK :
189*f6dc9357SAndroid Build Coastguard Worker       Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT;
190*f6dc9357SAndroid Build Coastguard Worker   Byte *p = dest;
191*f6dc9357SAndroid Build Coastguard Worker   Set32(p, tag)
192*f6dc9357SAndroid Build Coastguard Worker   Set16(p + 4, (UInt16)(size - 8))
193*f6dc9357SAndroid Build Coastguard Worker   Set16(p + 6, 0)
194*f6dc9357SAndroid Build Coastguard Worker   p += 8;
195*f6dc9357SAndroid Build Coastguard Worker 
196*f6dc9357SAndroid Build Coastguard Worker   unsigned subOffs = 0;
197*f6dc9357SAndroid Build Coastguard Worker   unsigned printOffs = 0;
198*f6dc9357SAndroid Build Coastguard Worker   if (newOrderScheme)
199*f6dc9357SAndroid Build Coastguard Worker     subOffs = (unsigned)len2;
200*f6dc9357SAndroid Build Coastguard Worker   else
201*f6dc9357SAndroid Build Coastguard Worker     printOffs = (unsigned)len1 + 2;
202*f6dc9357SAndroid Build Coastguard Worker 
203*f6dc9357SAndroid Build Coastguard Worker   Set16(p + 0, (UInt16)subOffs)
204*f6dc9357SAndroid Build Coastguard Worker   Set16(p + 2, (UInt16)len1)
205*f6dc9357SAndroid Build Coastguard Worker   Set16(p + 4, (UInt16)printOffs)
206*f6dc9357SAndroid Build Coastguard Worker   Set16(p + 6, (UInt16)len2)
207*f6dc9357SAndroid Build Coastguard Worker 
208*f6dc9357SAndroid Build Coastguard Worker   p += 8;
209*f6dc9357SAndroid Build Coastguard Worker   if (isSymLink)
210*f6dc9357SAndroid Build Coastguard Worker   {
211*f6dc9357SAndroid Build Coastguard Worker     UInt32 flags = isAbs ? 0 : Z7_WIN_SYMLINK_FLAG_RELATIVE;
212*f6dc9357SAndroid Build Coastguard Worker     Set32(p, flags)
213*f6dc9357SAndroid Build Coastguard Worker     p += 4;
214*f6dc9357SAndroid Build Coastguard Worker   }
215*f6dc9357SAndroid Build Coastguard Worker 
216*f6dc9357SAndroid Build Coastguard Worker   if (add_Prefix_Len != 0)
217*f6dc9357SAndroid Build Coastguard Worker     WriteString(p + subOffs, k_LinkPrefix);
218*f6dc9357SAndroid Build Coastguard Worker   WriteString(p + subOffs + add_Prefix_Len * 2, path);
219*f6dc9357SAndroid Build Coastguard Worker   if (needPrintName)
220*f6dc9357SAndroid Build Coastguard Worker     WriteString(p + printOffs, path);
221*f6dc9357SAndroid Build Coastguard Worker   return true;
222*f6dc9357SAndroid Build Coastguard Worker }
223*f6dc9357SAndroid Build Coastguard Worker 
224*f6dc9357SAndroid Build Coastguard Worker #endif // defined(_WIN32) && !defined(UNDER_CE)
225*f6dc9357SAndroid Build Coastguard Worker 
226*f6dc9357SAndroid Build Coastguard Worker 
GetString(const Byte * p,unsigned len,UString & res)227*f6dc9357SAndroid Build Coastguard Worker static void GetString(const Byte *p, unsigned len, UString &res)
228*f6dc9357SAndroid Build Coastguard Worker {
229*f6dc9357SAndroid Build Coastguard Worker   wchar_t *s = res.GetBuf(len);
230*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
231*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < len; i++)
232*f6dc9357SAndroid Build Coastguard Worker   {
233*f6dc9357SAndroid Build Coastguard Worker     wchar_t c = Get16(p + i * 2);
234*f6dc9357SAndroid Build Coastguard Worker     if (c == 0)
235*f6dc9357SAndroid Build Coastguard Worker       break;
236*f6dc9357SAndroid Build Coastguard Worker     s[i] = c;
237*f6dc9357SAndroid Build Coastguard Worker   }
238*f6dc9357SAndroid Build Coastguard Worker   s[i] = 0;
239*f6dc9357SAndroid Build Coastguard Worker   res.ReleaseBuf_SetLen(i);
240*f6dc9357SAndroid Build Coastguard Worker }
241*f6dc9357SAndroid Build Coastguard Worker 
Parse(const Byte * p,size_t size)242*f6dc9357SAndroid Build Coastguard Worker bool CReparseAttr::Parse(const Byte *p, size_t size)
243*f6dc9357SAndroid Build Coastguard Worker {
244*f6dc9357SAndroid Build Coastguard Worker   ErrorCode = (DWORD)ERROR_INVALID_REPARSE_DATA;
245*f6dc9357SAndroid Build Coastguard Worker   HeaderError = true;
246*f6dc9357SAndroid Build Coastguard Worker   TagIsUnknown = true;
247*f6dc9357SAndroid Build Coastguard Worker   MinorError = false;
248*f6dc9357SAndroid Build Coastguard Worker 
249*f6dc9357SAndroid Build Coastguard Worker   if (size < 8)
250*f6dc9357SAndroid Build Coastguard Worker     return false;
251*f6dc9357SAndroid Build Coastguard Worker   Tag = Get32(p);
252*f6dc9357SAndroid Build Coastguard Worker   if (Get16(p + 6) != 0) // padding
253*f6dc9357SAndroid Build Coastguard Worker     return false;
254*f6dc9357SAndroid Build Coastguard Worker   unsigned len = Get16(p + 4);
255*f6dc9357SAndroid Build Coastguard Worker   p += 8;
256*f6dc9357SAndroid Build Coastguard Worker   size -= 8;
257*f6dc9357SAndroid Build Coastguard Worker   if (len != size)
258*f6dc9357SAndroid Build Coastguard Worker   // if (len > size)
259*f6dc9357SAndroid Build Coastguard Worker     return false;
260*f6dc9357SAndroid Build Coastguard Worker   /*
261*f6dc9357SAndroid Build Coastguard Worker   if ((type & kReparseFlags_Alias) == 0 ||
262*f6dc9357SAndroid Build Coastguard Worker       (type & kReparseFlags_Microsoft) == 0 ||
263*f6dc9357SAndroid Build Coastguard Worker       (type & 0xFFFF) != 3)
264*f6dc9357SAndroid Build Coastguard Worker   */
265*f6dc9357SAndroid Build Coastguard Worker 
266*f6dc9357SAndroid Build Coastguard Worker 
267*f6dc9357SAndroid Build Coastguard Worker   HeaderError = false;
268*f6dc9357SAndroid Build Coastguard Worker 
269*f6dc9357SAndroid Build Coastguard Worker   if (   Tag != Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT
270*f6dc9357SAndroid Build Coastguard Worker       && Tag != Z7_WIN_IO_REPARSE_TAG_SYMLINK
271*f6dc9357SAndroid Build Coastguard Worker       && Tag != Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK)
272*f6dc9357SAndroid Build Coastguard Worker   {
273*f6dc9357SAndroid Build Coastguard Worker     // for unsupported reparse points
274*f6dc9357SAndroid Build Coastguard Worker     ErrorCode = (DWORD)ERROR_REPARSE_TAG_INVALID; // ERROR_REPARSE_TAG_MISMATCH
275*f6dc9357SAndroid Build Coastguard Worker     // errorCode = ERROR_REPARSE_TAG_MISMATCH; // ERROR_REPARSE_TAG_INVALID
276*f6dc9357SAndroid Build Coastguard Worker     return false;
277*f6dc9357SAndroid Build Coastguard Worker   }
278*f6dc9357SAndroid Build Coastguard Worker 
279*f6dc9357SAndroid Build Coastguard Worker   TagIsUnknown = false;
280*f6dc9357SAndroid Build Coastguard Worker 
281*f6dc9357SAndroid Build Coastguard Worker   if (Tag == Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK)
282*f6dc9357SAndroid Build Coastguard Worker   {
283*f6dc9357SAndroid Build Coastguard Worker     if (len < 4)
284*f6dc9357SAndroid Build Coastguard Worker       return false;
285*f6dc9357SAndroid Build Coastguard Worker     Flags = Get32(p); // maybe it's not Flags
286*f6dc9357SAndroid Build Coastguard Worker     if (Flags != Z7_WIN_LX_SYMLINK_FLAG)
287*f6dc9357SAndroid Build Coastguard Worker       return false;
288*f6dc9357SAndroid Build Coastguard Worker     len -= 4;
289*f6dc9357SAndroid Build Coastguard Worker     p += 4;
290*f6dc9357SAndroid Build Coastguard Worker     char *s = WslName.GetBuf(len);
291*f6dc9357SAndroid Build Coastguard Worker     unsigned i;
292*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < len; i++)
293*f6dc9357SAndroid Build Coastguard Worker     {
294*f6dc9357SAndroid Build Coastguard Worker       char c = (char)p[i];
295*f6dc9357SAndroid Build Coastguard Worker       s[i] = c;
296*f6dc9357SAndroid Build Coastguard Worker       if (c == 0)
297*f6dc9357SAndroid Build Coastguard Worker         break;
298*f6dc9357SAndroid Build Coastguard Worker     }
299*f6dc9357SAndroid Build Coastguard Worker     WslName.ReleaseBuf_SetEnd(i);
300*f6dc9357SAndroid Build Coastguard Worker     MinorError = (i != len);
301*f6dc9357SAndroid Build Coastguard Worker     ErrorCode = 0;
302*f6dc9357SAndroid Build Coastguard Worker     return true;
303*f6dc9357SAndroid Build Coastguard Worker   }
304*f6dc9357SAndroid Build Coastguard Worker 
305*f6dc9357SAndroid Build Coastguard Worker   if (len < 8)
306*f6dc9357SAndroid Build Coastguard Worker     return false;
307*f6dc9357SAndroid Build Coastguard Worker   unsigned subOffs = Get16(p);
308*f6dc9357SAndroid Build Coastguard Worker   unsigned subLen = Get16(p + 2);
309*f6dc9357SAndroid Build Coastguard Worker   unsigned printOffs = Get16(p + 4);
310*f6dc9357SAndroid Build Coastguard Worker   unsigned printLen = Get16(p + 6);
311*f6dc9357SAndroid Build Coastguard Worker   len -= 8;
312*f6dc9357SAndroid Build Coastguard Worker   p += 8;
313*f6dc9357SAndroid Build Coastguard Worker 
314*f6dc9357SAndroid Build Coastguard Worker   Flags = 0;
315*f6dc9357SAndroid Build Coastguard Worker   if (Tag == Z7_WIN_IO_REPARSE_TAG_SYMLINK)
316*f6dc9357SAndroid Build Coastguard Worker   {
317*f6dc9357SAndroid Build Coastguard Worker     if (len < 4)
318*f6dc9357SAndroid Build Coastguard Worker       return false;
319*f6dc9357SAndroid Build Coastguard Worker     Flags = Get32(p);
320*f6dc9357SAndroid Build Coastguard Worker     len -= 4;
321*f6dc9357SAndroid Build Coastguard Worker     p += 4;
322*f6dc9357SAndroid Build Coastguard Worker   }
323*f6dc9357SAndroid Build Coastguard Worker 
324*f6dc9357SAndroid Build Coastguard Worker   if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen)
325*f6dc9357SAndroid Build Coastguard Worker     return false;
326*f6dc9357SAndroid Build Coastguard Worker   if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen)
327*f6dc9357SAndroid Build Coastguard Worker     return false;
328*f6dc9357SAndroid Build Coastguard Worker   GetString(p + subOffs, subLen >> 1, SubsName);
329*f6dc9357SAndroid Build Coastguard Worker   GetString(p + printOffs, printLen >> 1, PrintName);
330*f6dc9357SAndroid Build Coastguard Worker 
331*f6dc9357SAndroid Build Coastguard Worker   ErrorCode = 0;
332*f6dc9357SAndroid Build Coastguard Worker   return true;
333*f6dc9357SAndroid Build Coastguard Worker }
334*f6dc9357SAndroid Build Coastguard Worker 
335*f6dc9357SAndroid Build Coastguard Worker 
Parse(const Byte * p,size_t size)336*f6dc9357SAndroid Build Coastguard Worker bool CReparseShortInfo::Parse(const Byte *p, size_t size)
337*f6dc9357SAndroid Build Coastguard Worker {
338*f6dc9357SAndroid Build Coastguard Worker   const Byte *start = p;
339*f6dc9357SAndroid Build Coastguard Worker   Offset= 0;
340*f6dc9357SAndroid Build Coastguard Worker   Size = 0;
341*f6dc9357SAndroid Build Coastguard Worker   if (size < 8)
342*f6dc9357SAndroid Build Coastguard Worker     return false;
343*f6dc9357SAndroid Build Coastguard Worker   UInt32 Tag = Get32(p);
344*f6dc9357SAndroid Build Coastguard Worker   UInt32 len = Get16(p + 4);
345*f6dc9357SAndroid Build Coastguard Worker   if (len + 8 > size)
346*f6dc9357SAndroid Build Coastguard Worker     return false;
347*f6dc9357SAndroid Build Coastguard Worker   /*
348*f6dc9357SAndroid Build Coastguard Worker   if ((type & kReparseFlags_Alias) == 0 ||
349*f6dc9357SAndroid Build Coastguard Worker       (type & kReparseFlags_Microsoft) == 0 ||
350*f6dc9357SAndroid Build Coastguard Worker       (type & 0xFFFF) != 3)
351*f6dc9357SAndroid Build Coastguard Worker   */
352*f6dc9357SAndroid Build Coastguard Worker   if (Tag != Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT &&
353*f6dc9357SAndroid Build Coastguard Worker       Tag != Z7_WIN_IO_REPARSE_TAG_SYMLINK)
354*f6dc9357SAndroid Build Coastguard Worker     // return true;
355*f6dc9357SAndroid Build Coastguard Worker     return false;
356*f6dc9357SAndroid Build Coastguard Worker 
357*f6dc9357SAndroid Build Coastguard Worker   if (Get16(p + 6) != 0) // padding
358*f6dc9357SAndroid Build Coastguard Worker     return false;
359*f6dc9357SAndroid Build Coastguard Worker 
360*f6dc9357SAndroid Build Coastguard Worker   p += 8;
361*f6dc9357SAndroid Build Coastguard Worker   size -= 8;
362*f6dc9357SAndroid Build Coastguard Worker 
363*f6dc9357SAndroid Build Coastguard Worker   if (len != size) // do we need that check?
364*f6dc9357SAndroid Build Coastguard Worker     return false;
365*f6dc9357SAndroid Build Coastguard Worker 
366*f6dc9357SAndroid Build Coastguard Worker   if (len < 8)
367*f6dc9357SAndroid Build Coastguard Worker     return false;
368*f6dc9357SAndroid Build Coastguard Worker   unsigned subOffs = Get16(p);
369*f6dc9357SAndroid Build Coastguard Worker   unsigned subLen = Get16(p + 2);
370*f6dc9357SAndroid Build Coastguard Worker   unsigned printOffs = Get16(p + 4);
371*f6dc9357SAndroid Build Coastguard Worker   unsigned printLen = Get16(p + 6);
372*f6dc9357SAndroid Build Coastguard Worker   len -= 8;
373*f6dc9357SAndroid Build Coastguard Worker   p += 8;
374*f6dc9357SAndroid Build Coastguard Worker 
375*f6dc9357SAndroid Build Coastguard Worker   // UInt32 Flags = 0;
376*f6dc9357SAndroid Build Coastguard Worker   if (Tag == Z7_WIN_IO_REPARSE_TAG_SYMLINK)
377*f6dc9357SAndroid Build Coastguard Worker   {
378*f6dc9357SAndroid Build Coastguard Worker     if (len < 4)
379*f6dc9357SAndroid Build Coastguard Worker       return false;
380*f6dc9357SAndroid Build Coastguard Worker     // Flags = Get32(p);
381*f6dc9357SAndroid Build Coastguard Worker     len -= 4;
382*f6dc9357SAndroid Build Coastguard Worker     p += 4;
383*f6dc9357SAndroid Build Coastguard Worker   }
384*f6dc9357SAndroid Build Coastguard Worker 
385*f6dc9357SAndroid Build Coastguard Worker   if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen)
386*f6dc9357SAndroid Build Coastguard Worker     return false;
387*f6dc9357SAndroid Build Coastguard Worker   if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen)
388*f6dc9357SAndroid Build Coastguard Worker     return false;
389*f6dc9357SAndroid Build Coastguard Worker 
390*f6dc9357SAndroid Build Coastguard Worker   Offset = (unsigned)(p - start) + subOffs;
391*f6dc9357SAndroid Build Coastguard Worker   Size = subLen;
392*f6dc9357SAndroid Build Coastguard Worker   return true;
393*f6dc9357SAndroid Build Coastguard Worker }
394*f6dc9357SAndroid Build Coastguard Worker 
IsOkNamePair() const395*f6dc9357SAndroid Build Coastguard Worker bool CReparseAttr::IsOkNamePair() const
396*f6dc9357SAndroid Build Coastguard Worker {
397*f6dc9357SAndroid Build Coastguard Worker   if (IsLinkPrefix(SubsName))
398*f6dc9357SAndroid Build Coastguard Worker   {
399*f6dc9357SAndroid Build Coastguard Worker     if (!IsDrivePath(SubsName.Ptr(k_LinkPrefix_Size)))
400*f6dc9357SAndroid Build Coastguard Worker       return PrintName.IsEmpty();
401*f6dc9357SAndroid Build Coastguard Worker     if (wcscmp(SubsName.Ptr(k_LinkPrefix_Size), PrintName) == 0)
402*f6dc9357SAndroid Build Coastguard Worker       return true;
403*f6dc9357SAndroid Build Coastguard Worker   }
404*f6dc9357SAndroid Build Coastguard Worker   return wcscmp(SubsName, PrintName) == 0;
405*f6dc9357SAndroid Build Coastguard Worker }
406*f6dc9357SAndroid Build Coastguard Worker 
407*f6dc9357SAndroid Build Coastguard Worker /*
408*f6dc9357SAndroid Build Coastguard Worker bool CReparseAttr::IsVolume() const
409*f6dc9357SAndroid Build Coastguard Worker {
410*f6dc9357SAndroid Build Coastguard Worker   if (!IsLinkPrefix(SubsName))
411*f6dc9357SAndroid Build Coastguard Worker     return false;
412*f6dc9357SAndroid Build Coastguard Worker   return IsVolumeName(SubsName.Ptr(k_LinkPrefix_Size));
413*f6dc9357SAndroid Build Coastguard Worker }
414*f6dc9357SAndroid Build Coastguard Worker */
415*f6dc9357SAndroid Build Coastguard Worker 
GetPath() const416*f6dc9357SAndroid Build Coastguard Worker UString CReparseAttr::GetPath() const
417*f6dc9357SAndroid Build Coastguard Worker {
418*f6dc9357SAndroid Build Coastguard Worker   if (IsSymLink_WSL())
419*f6dc9357SAndroid Build Coastguard Worker   {
420*f6dc9357SAndroid Build Coastguard Worker     UString u;
421*f6dc9357SAndroid Build Coastguard Worker     // if (CheckUTF8(attr.WslName)
422*f6dc9357SAndroid Build Coastguard Worker     if (!ConvertUTF8ToUnicode(WslName, u))
423*f6dc9357SAndroid Build Coastguard Worker       MultiByteToUnicodeString2(u, WslName);
424*f6dc9357SAndroid Build Coastguard Worker     return u;
425*f6dc9357SAndroid Build Coastguard Worker   }
426*f6dc9357SAndroid Build Coastguard Worker 
427*f6dc9357SAndroid Build Coastguard Worker   UString s (SubsName);
428*f6dc9357SAndroid Build Coastguard Worker   if (IsLinkPrefix(s))
429*f6dc9357SAndroid Build Coastguard Worker   {
430*f6dc9357SAndroid Build Coastguard Worker     s.ReplaceOneCharAtPos(1, '\\'); // we normalize prefix from "\??\" to "\\?\"
431*f6dc9357SAndroid Build Coastguard Worker     if (IsDrivePath(s.Ptr(k_LinkPrefix_Size)))
432*f6dc9357SAndroid Build Coastguard Worker       s.DeleteFrontal(k_LinkPrefix_Size);
433*f6dc9357SAndroid Build Coastguard Worker   }
434*f6dc9357SAndroid Build Coastguard Worker   return s;
435*f6dc9357SAndroid Build Coastguard Worker }
436*f6dc9357SAndroid Build Coastguard Worker 
437*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_DEVICE_FILE
438*f6dc9357SAndroid Build Coastguard Worker 
439*f6dc9357SAndroid Build Coastguard Worker namespace NSystem
440*f6dc9357SAndroid Build Coastguard Worker {
441*f6dc9357SAndroid Build Coastguard Worker bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);
442*f6dc9357SAndroid Build Coastguard Worker }
443*f6dc9357SAndroid Build Coastguard Worker #endif // Z7_DEVICE_FILE
444*f6dc9357SAndroid Build Coastguard Worker 
445*f6dc9357SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(UNDER_CE)
446*f6dc9357SAndroid Build Coastguard Worker 
447*f6dc9357SAndroid Build Coastguard Worker namespace NIO {
448*f6dc9357SAndroid Build Coastguard Worker 
GetReparseData(CFSTR path,CByteBuffer & reparseData,BY_HANDLE_FILE_INFORMATION * fileInfo)449*f6dc9357SAndroid Build Coastguard Worker bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo)
450*f6dc9357SAndroid Build Coastguard Worker {
451*f6dc9357SAndroid Build Coastguard Worker   reparseData.Free();
452*f6dc9357SAndroid Build Coastguard Worker   CInFile file;
453*f6dc9357SAndroid Build Coastguard Worker   if (!file.OpenReparse(path))
454*f6dc9357SAndroid Build Coastguard Worker     return false;
455*f6dc9357SAndroid Build Coastguard Worker 
456*f6dc9357SAndroid Build Coastguard Worker   if (fileInfo)
457*f6dc9357SAndroid Build Coastguard Worker     file.GetFileInformation(fileInfo);
458*f6dc9357SAndroid Build Coastguard Worker 
459*f6dc9357SAndroid Build Coastguard Worker   const unsigned kBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
460*f6dc9357SAndroid Build Coastguard Worker   CByteArr buf(kBufSize);
461*f6dc9357SAndroid Build Coastguard Worker   DWORD returnedSize;
462*f6dc9357SAndroid Build Coastguard Worker   if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize))
463*f6dc9357SAndroid Build Coastguard Worker     return false;
464*f6dc9357SAndroid Build Coastguard Worker   reparseData.CopyFrom(buf, returnedSize);
465*f6dc9357SAndroid Build Coastguard Worker   return true;
466*f6dc9357SAndroid Build Coastguard Worker }
467*f6dc9357SAndroid Build Coastguard Worker 
CreatePrefixDirOfFile(CFSTR path)468*f6dc9357SAndroid Build Coastguard Worker static bool CreatePrefixDirOfFile(CFSTR path)
469*f6dc9357SAndroid Build Coastguard Worker {
470*f6dc9357SAndroid Build Coastguard Worker   FString path2 (path);
471*f6dc9357SAndroid Build Coastguard Worker   int pos = path2.ReverseFind_PathSepar();
472*f6dc9357SAndroid Build Coastguard Worker   if (pos < 0)
473*f6dc9357SAndroid Build Coastguard Worker     return true;
474*f6dc9357SAndroid Build Coastguard Worker   #ifdef _WIN32
475*f6dc9357SAndroid Build Coastguard Worker   if (pos == 2 && path2[1] == L':')
476*f6dc9357SAndroid Build Coastguard Worker     return true; // we don't create Disk folder;
477*f6dc9357SAndroid Build Coastguard Worker   #endif
478*f6dc9357SAndroid Build Coastguard Worker   path2.DeleteFrom((unsigned)pos);
479*f6dc9357SAndroid Build Coastguard Worker   return NDir::CreateComplexDir(path2);
480*f6dc9357SAndroid Build Coastguard Worker }
481*f6dc9357SAndroid Build Coastguard Worker 
482*f6dc9357SAndroid Build Coastguard Worker 
OutIoReparseData(DWORD controlCode,CFSTR path,void * data,DWORD size)483*f6dc9357SAndroid Build Coastguard Worker static bool OutIoReparseData(DWORD controlCode, CFSTR path, void *data, DWORD size)
484*f6dc9357SAndroid Build Coastguard Worker {
485*f6dc9357SAndroid Build Coastguard Worker   COutFile file;
486*f6dc9357SAndroid Build Coastguard Worker   if (!file.Open(path,
487*f6dc9357SAndroid Build Coastguard Worker       FILE_SHARE_WRITE,
488*f6dc9357SAndroid Build Coastguard Worker       OPEN_EXISTING,
489*f6dc9357SAndroid Build Coastguard Worker       FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS))
490*f6dc9357SAndroid Build Coastguard Worker     return false;
491*f6dc9357SAndroid Build Coastguard Worker 
492*f6dc9357SAndroid Build Coastguard Worker   DWORD returnedSize;
493*f6dc9357SAndroid Build Coastguard Worker   return file.DeviceIoControl(controlCode, data, size, NULL, 0, &returnedSize);
494*f6dc9357SAndroid Build Coastguard Worker }
495*f6dc9357SAndroid Build Coastguard Worker 
496*f6dc9357SAndroid Build Coastguard Worker 
497*f6dc9357SAndroid Build Coastguard Worker // If there is Reparse data already, it still writes new Reparse data
SetReparseData(CFSTR path,bool isDir,const void * data,DWORD size)498*f6dc9357SAndroid Build Coastguard Worker bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size)
499*f6dc9357SAndroid Build Coastguard Worker {
500*f6dc9357SAndroid Build Coastguard Worker   NFile::NFind::CFileInfo fi;
501*f6dc9357SAndroid Build Coastguard Worker   if (fi.Find(path))
502*f6dc9357SAndroid Build Coastguard Worker   {
503*f6dc9357SAndroid Build Coastguard Worker     if (fi.IsDir() != isDir)
504*f6dc9357SAndroid Build Coastguard Worker     {
505*f6dc9357SAndroid Build Coastguard Worker       ::SetLastError(ERROR_DIRECTORY);
506*f6dc9357SAndroid Build Coastguard Worker       return false;
507*f6dc9357SAndroid Build Coastguard Worker     }
508*f6dc9357SAndroid Build Coastguard Worker   }
509*f6dc9357SAndroid Build Coastguard Worker   else
510*f6dc9357SAndroid Build Coastguard Worker   {
511*f6dc9357SAndroid Build Coastguard Worker     if (isDir)
512*f6dc9357SAndroid Build Coastguard Worker     {
513*f6dc9357SAndroid Build Coastguard Worker       if (!NDir::CreateComplexDir(path))
514*f6dc9357SAndroid Build Coastguard Worker         return false;
515*f6dc9357SAndroid Build Coastguard Worker     }
516*f6dc9357SAndroid Build Coastguard Worker     else
517*f6dc9357SAndroid Build Coastguard Worker     {
518*f6dc9357SAndroid Build Coastguard Worker       CreatePrefixDirOfFile(path);
519*f6dc9357SAndroid Build Coastguard Worker       COutFile file;
520*f6dc9357SAndroid Build Coastguard Worker       if (!file.Create_NEW(path))
521*f6dc9357SAndroid Build Coastguard Worker         return false;
522*f6dc9357SAndroid Build Coastguard Worker     }
523*f6dc9357SAndroid Build Coastguard Worker   }
524*f6dc9357SAndroid Build Coastguard Worker 
525*f6dc9357SAndroid Build Coastguard Worker   return OutIoReparseData(my_FSCTL_SET_REPARSE_POINT, path, (void *)(const Byte *)(data), size);
526*f6dc9357SAndroid Build Coastguard Worker }
527*f6dc9357SAndroid Build Coastguard Worker 
528*f6dc9357SAndroid Build Coastguard Worker 
DeleteReparseData(CFSTR path)529*f6dc9357SAndroid Build Coastguard Worker bool DeleteReparseData(CFSTR path)
530*f6dc9357SAndroid Build Coastguard Worker {
531*f6dc9357SAndroid Build Coastguard Worker   CByteBuffer reparseData;
532*f6dc9357SAndroid Build Coastguard Worker   if (!GetReparseData(path, reparseData, NULL))
533*f6dc9357SAndroid Build Coastguard Worker     return false;
534*f6dc9357SAndroid Build Coastguard Worker   /* MSDN: The tag specified in the ReparseTag member of this structure
535*f6dc9357SAndroid Build Coastguard Worker      must match the tag of the reparse point to be deleted,
536*f6dc9357SAndroid Build Coastguard Worker      and the ReparseDataLength member must be zero */
537*f6dc9357SAndroid Build Coastguard Worker   #define my_REPARSE_DATA_BUFFER_HEADER_SIZE 8
538*f6dc9357SAndroid Build Coastguard Worker   if (reparseData.Size() < my_REPARSE_DATA_BUFFER_HEADER_SIZE)
539*f6dc9357SAndroid Build Coastguard Worker   {
540*f6dc9357SAndroid Build Coastguard Worker     SetLastError(ERROR_INVALID_REPARSE_DATA);
541*f6dc9357SAndroid Build Coastguard Worker     return false;
542*f6dc9357SAndroid Build Coastguard Worker   }
543*f6dc9357SAndroid Build Coastguard Worker   BYTE buf[my_REPARSE_DATA_BUFFER_HEADER_SIZE];
544*f6dc9357SAndroid Build Coastguard Worker   memset(buf, 0, sizeof(buf));
545*f6dc9357SAndroid Build Coastguard Worker   memcpy(buf, reparseData, 4); // tag
546*f6dc9357SAndroid Build Coastguard Worker   return OutIoReparseData(my_FSCTL_DELETE_REPARSE_POINT, path, buf, sizeof(buf));
547*f6dc9357SAndroid Build Coastguard Worker }
548*f6dc9357SAndroid Build Coastguard Worker 
549*f6dc9357SAndroid Build Coastguard Worker }
550*f6dc9357SAndroid Build Coastguard Worker 
551*f6dc9357SAndroid Build Coastguard Worker #endif //  defined(_WIN32) && !defined(UNDER_CE)
552*f6dc9357SAndroid Build Coastguard Worker 
553*f6dc9357SAndroid Build Coastguard Worker 
554*f6dc9357SAndroid Build Coastguard Worker #ifndef _WIN32
555*f6dc9357SAndroid Build Coastguard Worker 
556*f6dc9357SAndroid Build Coastguard Worker namespace NIO {
557*f6dc9357SAndroid Build Coastguard Worker 
GetReparseData(CFSTR path,CByteBuffer & reparseData)558*f6dc9357SAndroid Build Coastguard Worker bool GetReparseData(CFSTR path, CByteBuffer &reparseData)
559*f6dc9357SAndroid Build Coastguard Worker {
560*f6dc9357SAndroid Build Coastguard Worker   reparseData.Free();
561*f6dc9357SAndroid Build Coastguard Worker 
562*f6dc9357SAndroid Build Coastguard Worker   #define MAX_PATHNAME_LEN 1024
563*f6dc9357SAndroid Build Coastguard Worker   char buf[MAX_PATHNAME_LEN + 2];
564*f6dc9357SAndroid Build Coastguard Worker   const size_t request = sizeof(buf) - 1;
565*f6dc9357SAndroid Build Coastguard Worker 
566*f6dc9357SAndroid Build Coastguard Worker   // printf("\nreadlink() path = %s \n", path);
567*f6dc9357SAndroid Build Coastguard Worker   const ssize_t size = readlink(path, buf, request);
568*f6dc9357SAndroid Build Coastguard Worker   // there is no tail zero
569*f6dc9357SAndroid Build Coastguard Worker 
570*f6dc9357SAndroid Build Coastguard Worker   if (size < 0)
571*f6dc9357SAndroid Build Coastguard Worker     return false;
572*f6dc9357SAndroid Build Coastguard Worker   if ((size_t)size >= request)
573*f6dc9357SAndroid Build Coastguard Worker   {
574*f6dc9357SAndroid Build Coastguard Worker     SetLastError(EINVAL); // check it: ENAMETOOLONG
575*f6dc9357SAndroid Build Coastguard Worker     return false;
576*f6dc9357SAndroid Build Coastguard Worker   }
577*f6dc9357SAndroid Build Coastguard Worker 
578*f6dc9357SAndroid Build Coastguard Worker   // printf("\nreadlink() res = %s size = %d \n", buf, (int)size);
579*f6dc9357SAndroid Build Coastguard Worker   reparseData.CopyFrom((const Byte *)buf, (size_t)size);
580*f6dc9357SAndroid Build Coastguard Worker   return true;
581*f6dc9357SAndroid Build Coastguard Worker }
582*f6dc9357SAndroid Build Coastguard Worker 
583*f6dc9357SAndroid Build Coastguard Worker 
584*f6dc9357SAndroid Build Coastguard Worker /*
585*f6dc9357SAndroid Build Coastguard Worker // If there is Reparse data already, it still writes new Reparse data
586*f6dc9357SAndroid Build Coastguard Worker bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size)
587*f6dc9357SAndroid Build Coastguard Worker {
588*f6dc9357SAndroid Build Coastguard Worker   // AString s;
589*f6dc9357SAndroid Build Coastguard Worker   // s.SetFrom_CalcLen(data, size);
590*f6dc9357SAndroid Build Coastguard Worker   // return (symlink(s, path) == 0);
591*f6dc9357SAndroid Build Coastguard Worker   UNUSED_VAR(path)
592*f6dc9357SAndroid Build Coastguard Worker   UNUSED_VAR(isDir)
593*f6dc9357SAndroid Build Coastguard Worker   UNUSED_VAR(data)
594*f6dc9357SAndroid Build Coastguard Worker   UNUSED_VAR(size)
595*f6dc9357SAndroid Build Coastguard Worker   SetLastError(ENOSYS);
596*f6dc9357SAndroid Build Coastguard Worker   return false;
597*f6dc9357SAndroid Build Coastguard Worker }
598*f6dc9357SAndroid Build Coastguard Worker */
599*f6dc9357SAndroid Build Coastguard Worker 
SetSymLink(CFSTR from,CFSTR to)600*f6dc9357SAndroid Build Coastguard Worker bool SetSymLink(CFSTR from, CFSTR to)
601*f6dc9357SAndroid Build Coastguard Worker {
602*f6dc9357SAndroid Build Coastguard Worker   // printf("\nsymlink() %s -> %s\n", from, to);
603*f6dc9357SAndroid Build Coastguard Worker   int ir;
604*f6dc9357SAndroid Build Coastguard Worker   // ir = unlink(path);
605*f6dc9357SAndroid Build Coastguard Worker   // if (ir == 0)
606*f6dc9357SAndroid Build Coastguard Worker   ir = symlink(to, from);
607*f6dc9357SAndroid Build Coastguard Worker   return (ir == 0);
608*f6dc9357SAndroid Build Coastguard Worker }
609*f6dc9357SAndroid Build Coastguard Worker 
SetSymLink_UString(CFSTR from,const UString & to)610*f6dc9357SAndroid Build Coastguard Worker bool SetSymLink_UString(CFSTR from, const UString &to)
611*f6dc9357SAndroid Build Coastguard Worker {
612*f6dc9357SAndroid Build Coastguard Worker   AString utf;
613*f6dc9357SAndroid Build Coastguard Worker   ConvertUnicodeToUTF8(to, utf);
614*f6dc9357SAndroid Build Coastguard Worker   return SetSymLink(from, utf);
615*f6dc9357SAndroid Build Coastguard Worker }
616*f6dc9357SAndroid Build Coastguard Worker 
617*f6dc9357SAndroid Build Coastguard Worker }
618*f6dc9357SAndroid Build Coastguard Worker 
619*f6dc9357SAndroid Build Coastguard Worker #endif // !_WIN32
620*f6dc9357SAndroid Build Coastguard Worker 
621*f6dc9357SAndroid Build Coastguard Worker }}
622