1370b324cSopenharmony_ci// Windows/FileLink.cpp 2370b324cSopenharmony_ci 3370b324cSopenharmony_ci#include "StdAfx.h" 4370b324cSopenharmony_ci 5370b324cSopenharmony_ci#include "../../C/CpuArch.h" 6370b324cSopenharmony_ci 7370b324cSopenharmony_ci#ifndef _WIN32 8370b324cSopenharmony_ci#include <unistd.h> 9370b324cSopenharmony_ci#endif 10370b324cSopenharmony_ci 11370b324cSopenharmony_ci#ifdef Z7_DEVICE_FILE 12370b324cSopenharmony_ci#include "../../C/Alloc.h" 13370b324cSopenharmony_ci#endif 14370b324cSopenharmony_ci 15370b324cSopenharmony_ci#include "../Common/UTFConvert.h" 16370b324cSopenharmony_ci#include "../Common/StringConvert.h" 17370b324cSopenharmony_ci 18370b324cSopenharmony_ci#include "FileDir.h" 19370b324cSopenharmony_ci#include "FileFind.h" 20370b324cSopenharmony_ci#include "FileIO.h" 21370b324cSopenharmony_ci#include "FileName.h" 22370b324cSopenharmony_ci 23370b324cSopenharmony_ci#ifdef Z7_OLD_WIN_SDK 24370b324cSopenharmony_ci#ifndef ERROR_INVALID_REPARSE_DATA 25370b324cSopenharmony_ci#define ERROR_INVALID_REPARSE_DATA 4392L 26370b324cSopenharmony_ci#endif 27370b324cSopenharmony_ci#ifndef ERROR_REPARSE_TAG_INVALID 28370b324cSopenharmony_ci#define ERROR_REPARSE_TAG_INVALID 4393L 29370b324cSopenharmony_ci#endif 30370b324cSopenharmony_ci#endif 31370b324cSopenharmony_ci 32370b324cSopenharmony_ci#ifndef _UNICODE 33370b324cSopenharmony_ciextern bool g_IsNT; 34370b324cSopenharmony_ci#endif 35370b324cSopenharmony_ci 36370b324cSopenharmony_cinamespace NWindows { 37370b324cSopenharmony_cinamespace NFile { 38370b324cSopenharmony_ci 39370b324cSopenharmony_ciusing namespace NName; 40370b324cSopenharmony_ci 41370b324cSopenharmony_ci/* 42370b324cSopenharmony_ci Reparse Points (Junctions and Symbolic Links): 43370b324cSopenharmony_ci struct 44370b324cSopenharmony_ci { 45370b324cSopenharmony_ci UInt32 Tag; 46370b324cSopenharmony_ci UInt16 Size; // not including starting 8 bytes 47370b324cSopenharmony_ci UInt16 Reserved; // = 0 48370b324cSopenharmony_ci 49370b324cSopenharmony_ci UInt16 SubstituteOffset; // offset in bytes from start of namesChars 50370b324cSopenharmony_ci UInt16 SubstituteLen; // size in bytes, it doesn't include tailed NUL 51370b324cSopenharmony_ci UInt16 PrintOffset; // offset in bytes from start of namesChars 52370b324cSopenharmony_ci UInt16 PrintLen; // size in bytes, it doesn't include tailed NUL 53370b324cSopenharmony_ci 54370b324cSopenharmony_ci [UInt32] Flags; // for Symbolic Links only. 55370b324cSopenharmony_ci 56370b324cSopenharmony_ci UInt16 namesChars[] 57370b324cSopenharmony_ci } 58370b324cSopenharmony_ci 59370b324cSopenharmony_ci MOUNT_POINT (Junction point): 60370b324cSopenharmony_ci 1) there is NUL wchar after path 61370b324cSopenharmony_ci 2) Default Order in table: 62370b324cSopenharmony_ci Substitute Path 63370b324cSopenharmony_ci Print Path 64370b324cSopenharmony_ci 3) pathnames can not contain dot directory names 65370b324cSopenharmony_ci 66370b324cSopenharmony_ci SYMLINK: 67370b324cSopenharmony_ci 1) there is no NUL wchar after path 68370b324cSopenharmony_ci 2) Default Order in table: 69370b324cSopenharmony_ci Print Path 70370b324cSopenharmony_ci Substitute Path 71370b324cSopenharmony_ci*/ 72370b324cSopenharmony_ci 73370b324cSopenharmony_ci/* 74370b324cSopenharmony_ciWin10 WSL2: 75370b324cSopenharmony_ciadmin rights + sudo: it creates normal windows symbolic link. 76370b324cSopenharmony_ciin another cases : it creates IO_REPARSE_TAG_LX_SYMLINK repare point. 77370b324cSopenharmony_ci*/ 78370b324cSopenharmony_ci 79370b324cSopenharmony_ci/* 80370b324cSopenharmony_cistatic const UInt32 kReparseFlags_Alias = (1 << 29); 81370b324cSopenharmony_cistatic const UInt32 kReparseFlags_HighLatency = (1 << 30); 82370b324cSopenharmony_cistatic const UInt32 kReparseFlags_Microsoft = ((UInt32)1 << 31); 83370b324cSopenharmony_ci 84370b324cSopenharmony_ci#define Z7_WIN_IO_REPARSE_TAG_HSM (0xC0000004L) 85370b324cSopenharmony_ci#define Z7_WIN_IO_REPARSE_TAG_HSM2 (0x80000006L) 86370b324cSopenharmony_ci#define Z7_WIN_IO_REPARSE_TAG_SIS (0x80000007L) 87370b324cSopenharmony_ci#define Z7_WIN_IO_REPARSE_TAG_WIM (0x80000008L) 88370b324cSopenharmony_ci#define Z7_WIN_IO_REPARSE_TAG_CSV (0x80000009L) 89370b324cSopenharmony_ci#define Z7_WIN_IO_REPARSE_TAG_DFS (0x8000000AL) 90370b324cSopenharmony_ci#define Z7_WIN_IO_REPARSE_TAG_DFSR (0x80000012L) 91370b324cSopenharmony_ci*/ 92370b324cSopenharmony_ci 93370b324cSopenharmony_ci#define Get16(p) GetUi16(p) 94370b324cSopenharmony_ci#define Get32(p) GetUi32(p) 95370b324cSopenharmony_ci 96370b324cSopenharmony_cistatic const wchar_t * const k_LinkPrefix = L"\\??\\"; 97370b324cSopenharmony_cistatic const unsigned k_LinkPrefix_Size = 4; 98370b324cSopenharmony_ci 99370b324cSopenharmony_cistatic bool IsLinkPrefix(const wchar_t *s) 100370b324cSopenharmony_ci{ 101370b324cSopenharmony_ci return IsString1PrefixedByString2(s, k_LinkPrefix); 102370b324cSopenharmony_ci} 103370b324cSopenharmony_ci 104370b324cSopenharmony_ci/* 105370b324cSopenharmony_cistatic const wchar_t * const k_VolumePrefix = L"Volume{"; 106370b324cSopenharmony_cistatic const bool IsVolumeName(const wchar_t *s) 107370b324cSopenharmony_ci{ 108370b324cSopenharmony_ci return IsString1PrefixedByString2(s, k_VolumePrefix); 109370b324cSopenharmony_ci} 110370b324cSopenharmony_ci*/ 111370b324cSopenharmony_ci 112370b324cSopenharmony_ci#if defined(_WIN32) && !defined(UNDER_CE) 113370b324cSopenharmony_ci 114370b324cSopenharmony_ci#define Set16(p, v) SetUi16(p, v) 115370b324cSopenharmony_ci#define Set32(p, v) SetUi32(p, v) 116370b324cSopenharmony_ci 117370b324cSopenharmony_cistatic void WriteString(Byte *dest, const wchar_t *path) 118370b324cSopenharmony_ci{ 119370b324cSopenharmony_ci for (;;) 120370b324cSopenharmony_ci { 121370b324cSopenharmony_ci wchar_t c = *path++; 122370b324cSopenharmony_ci if (c == 0) 123370b324cSopenharmony_ci return; 124370b324cSopenharmony_ci Set16(dest, (UInt16)c) 125370b324cSopenharmony_ci dest += 2; 126370b324cSopenharmony_ci } 127370b324cSopenharmony_ci} 128370b324cSopenharmony_ci 129370b324cSopenharmony_cibool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL) 130370b324cSopenharmony_ci{ 131370b324cSopenharmony_ci bool isAbs = IsAbsolutePath(path); 132370b324cSopenharmony_ci if (!isAbs && !isSymLink) 133370b324cSopenharmony_ci return false; 134370b324cSopenharmony_ci 135370b324cSopenharmony_ci if (isWSL) 136370b324cSopenharmony_ci { 137370b324cSopenharmony_ci // unsupported characters probably use Replacement Character UTF-16 0xFFFD 138370b324cSopenharmony_ci AString utf; 139370b324cSopenharmony_ci ConvertUnicodeToUTF8(path, utf); 140370b324cSopenharmony_ci const size_t size = 4 + utf.Len(); 141370b324cSopenharmony_ci if (size != (UInt16)size) 142370b324cSopenharmony_ci return false; 143370b324cSopenharmony_ci dest.Alloc(8 + size); 144370b324cSopenharmony_ci Byte *p = dest; 145370b324cSopenharmony_ci Set32(p, Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK) 146370b324cSopenharmony_ci Set16(p + 4, (UInt16)(size)) 147370b324cSopenharmony_ci Set16(p + 6, 0) 148370b324cSopenharmony_ci Set32(p + 8, Z7_WIN_LX_SYMLINK_FLAG) 149370b324cSopenharmony_ci memcpy(p + 12, utf.Ptr(), utf.Len()); 150370b324cSopenharmony_ci return true; 151370b324cSopenharmony_ci } 152370b324cSopenharmony_ci 153370b324cSopenharmony_ci // usual symbolic LINK (NOT WSL) 154370b324cSopenharmony_ci 155370b324cSopenharmony_ci bool needPrintName = true; 156370b324cSopenharmony_ci 157370b324cSopenharmony_ci if (IsSuperPath(path)) 158370b324cSopenharmony_ci { 159370b324cSopenharmony_ci path += kSuperPathPrefixSize; 160370b324cSopenharmony_ci if (!IsDrivePath(path)) 161370b324cSopenharmony_ci needPrintName = false; 162370b324cSopenharmony_ci } 163370b324cSopenharmony_ci 164370b324cSopenharmony_ci const unsigned add_Prefix_Len = isAbs ? k_LinkPrefix_Size : 0; 165370b324cSopenharmony_ci 166370b324cSopenharmony_ci size_t len2 = (size_t)MyStringLen(path) * 2; 167370b324cSopenharmony_ci const size_t len1 = len2 + add_Prefix_Len * 2; 168370b324cSopenharmony_ci if (!needPrintName) 169370b324cSopenharmony_ci len2 = 0; 170370b324cSopenharmony_ci 171370b324cSopenharmony_ci size_t totalNamesSize = (len1 + len2); 172370b324cSopenharmony_ci 173370b324cSopenharmony_ci /* some WIM imagex software uses old scheme for symbolic links. 174370b324cSopenharmony_ci so we can old scheme for byte to byte compatibility */ 175370b324cSopenharmony_ci 176370b324cSopenharmony_ci bool newOrderScheme = isSymLink; 177370b324cSopenharmony_ci // newOrderScheme = false; 178370b324cSopenharmony_ci 179370b324cSopenharmony_ci if (!newOrderScheme) 180370b324cSopenharmony_ci totalNamesSize += 2 * 2; 181370b324cSopenharmony_ci 182370b324cSopenharmony_ci const size_t size = 8 + 8 + (isSymLink ? 4 : 0) + totalNamesSize; 183370b324cSopenharmony_ci if (size != (UInt16)size) 184370b324cSopenharmony_ci return false; 185370b324cSopenharmony_ci dest.Alloc(size); 186370b324cSopenharmony_ci memset(dest, 0, size); 187370b324cSopenharmony_ci const UInt32 tag = isSymLink ? 188370b324cSopenharmony_ci Z7_WIN_IO_REPARSE_TAG_SYMLINK : 189370b324cSopenharmony_ci Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT; 190370b324cSopenharmony_ci Byte *p = dest; 191370b324cSopenharmony_ci Set32(p, tag) 192370b324cSopenharmony_ci Set16(p + 4, (UInt16)(size - 8)) 193370b324cSopenharmony_ci Set16(p + 6, 0) 194370b324cSopenharmony_ci p += 8; 195370b324cSopenharmony_ci 196370b324cSopenharmony_ci unsigned subOffs = 0; 197370b324cSopenharmony_ci unsigned printOffs = 0; 198370b324cSopenharmony_ci if (newOrderScheme) 199370b324cSopenharmony_ci subOffs = (unsigned)len2; 200370b324cSopenharmony_ci else 201370b324cSopenharmony_ci printOffs = (unsigned)len1 + 2; 202370b324cSopenharmony_ci 203370b324cSopenharmony_ci Set16(p + 0, (UInt16)subOffs) 204370b324cSopenharmony_ci Set16(p + 2, (UInt16)len1) 205370b324cSopenharmony_ci Set16(p + 4, (UInt16)printOffs) 206370b324cSopenharmony_ci Set16(p + 6, (UInt16)len2) 207370b324cSopenharmony_ci 208370b324cSopenharmony_ci p += 8; 209370b324cSopenharmony_ci if (isSymLink) 210370b324cSopenharmony_ci { 211370b324cSopenharmony_ci UInt32 flags = isAbs ? 0 : Z7_WIN_SYMLINK_FLAG_RELATIVE; 212370b324cSopenharmony_ci Set32(p, flags) 213370b324cSopenharmony_ci p += 4; 214370b324cSopenharmony_ci } 215370b324cSopenharmony_ci 216370b324cSopenharmony_ci if (add_Prefix_Len != 0) 217370b324cSopenharmony_ci WriteString(p + subOffs, k_LinkPrefix); 218370b324cSopenharmony_ci WriteString(p + subOffs + add_Prefix_Len * 2, path); 219370b324cSopenharmony_ci if (needPrintName) 220370b324cSopenharmony_ci WriteString(p + printOffs, path); 221370b324cSopenharmony_ci return true; 222370b324cSopenharmony_ci} 223370b324cSopenharmony_ci 224370b324cSopenharmony_ci#endif // defined(_WIN32) && !defined(UNDER_CE) 225370b324cSopenharmony_ci 226370b324cSopenharmony_ci 227370b324cSopenharmony_cistatic void GetString(const Byte *p, unsigned len, UString &res) 228370b324cSopenharmony_ci{ 229370b324cSopenharmony_ci wchar_t *s = res.GetBuf(len); 230370b324cSopenharmony_ci unsigned i; 231370b324cSopenharmony_ci for (i = 0; i < len; i++) 232370b324cSopenharmony_ci { 233370b324cSopenharmony_ci wchar_t c = Get16(p + i * 2); 234370b324cSopenharmony_ci if (c == 0) 235370b324cSopenharmony_ci break; 236370b324cSopenharmony_ci s[i] = c; 237370b324cSopenharmony_ci } 238370b324cSopenharmony_ci s[i] = 0; 239370b324cSopenharmony_ci res.ReleaseBuf_SetLen(i); 240370b324cSopenharmony_ci} 241370b324cSopenharmony_ci 242370b324cSopenharmony_cibool CReparseAttr::Parse(const Byte *p, size_t size) 243370b324cSopenharmony_ci{ 244370b324cSopenharmony_ci ErrorCode = (DWORD)ERROR_INVALID_REPARSE_DATA; 245370b324cSopenharmony_ci HeaderError = true; 246370b324cSopenharmony_ci TagIsUnknown = true; 247370b324cSopenharmony_ci MinorError = false; 248370b324cSopenharmony_ci 249370b324cSopenharmony_ci if (size < 8) 250370b324cSopenharmony_ci return false; 251370b324cSopenharmony_ci Tag = Get32(p); 252370b324cSopenharmony_ci UInt32 len = Get16(p + 4); 253370b324cSopenharmony_ci if (len + 8 != size) 254370b324cSopenharmony_ci // if (len + 8 > size) 255370b324cSopenharmony_ci return false; 256370b324cSopenharmony_ci /* 257370b324cSopenharmony_ci if ((type & kReparseFlags_Alias) == 0 || 258370b324cSopenharmony_ci (type & kReparseFlags_Microsoft) == 0 || 259370b324cSopenharmony_ci (type & 0xFFFF) != 3) 260370b324cSopenharmony_ci */ 261370b324cSopenharmony_ci 262370b324cSopenharmony_ci if (Get16(p + 6) != 0) // padding 263370b324cSopenharmony_ci return false; 264370b324cSopenharmony_ci 265370b324cSopenharmony_ci HeaderError = false; 266370b324cSopenharmony_ci 267370b324cSopenharmony_ci if ( Tag != Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT 268370b324cSopenharmony_ci && Tag != Z7_WIN_IO_REPARSE_TAG_SYMLINK 269370b324cSopenharmony_ci && Tag != Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK) 270370b324cSopenharmony_ci { 271370b324cSopenharmony_ci // for unsupported reparse points 272370b324cSopenharmony_ci ErrorCode = (DWORD)ERROR_REPARSE_TAG_INVALID; // ERROR_REPARSE_TAG_MISMATCH 273370b324cSopenharmony_ci // errorCode = ERROR_REPARSE_TAG_MISMATCH; // ERROR_REPARSE_TAG_INVALID 274370b324cSopenharmony_ci return false; 275370b324cSopenharmony_ci } 276370b324cSopenharmony_ci 277370b324cSopenharmony_ci TagIsUnknown = false; 278370b324cSopenharmony_ci 279370b324cSopenharmony_ci p += 8; 280370b324cSopenharmony_ci size -= 8; 281370b324cSopenharmony_ci 282370b324cSopenharmony_ci if (Tag == Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK) 283370b324cSopenharmony_ci { 284370b324cSopenharmony_ci if (len < 4) 285370b324cSopenharmony_ci return false; 286370b324cSopenharmony_ci Flags = Get32(p); // maybe it's not Flags 287370b324cSopenharmony_ci if (Flags != Z7_WIN_LX_SYMLINK_FLAG) 288370b324cSopenharmony_ci return false; 289370b324cSopenharmony_ci len -= 4; 290370b324cSopenharmony_ci p += 4; 291370b324cSopenharmony_ci char *s = WslName.GetBuf(len); 292370b324cSopenharmony_ci unsigned i; 293370b324cSopenharmony_ci for (i = 0; i < len; i++) 294370b324cSopenharmony_ci { 295370b324cSopenharmony_ci char c = (char)p[i]; 296370b324cSopenharmony_ci s[i] = c; 297370b324cSopenharmony_ci if (c == 0) 298370b324cSopenharmony_ci break; 299370b324cSopenharmony_ci } 300370b324cSopenharmony_ci WslName.ReleaseBuf_SetEnd(i); 301370b324cSopenharmony_ci MinorError = (i != len); 302370b324cSopenharmony_ci ErrorCode = 0; 303370b324cSopenharmony_ci return true; 304370b324cSopenharmony_ci } 305370b324cSopenharmony_ci 306370b324cSopenharmony_ci if (len < 8) 307370b324cSopenharmony_ci return false; 308370b324cSopenharmony_ci unsigned subOffs = Get16(p); 309370b324cSopenharmony_ci unsigned subLen = Get16(p + 2); 310370b324cSopenharmony_ci unsigned printOffs = Get16(p + 4); 311370b324cSopenharmony_ci unsigned printLen = Get16(p + 6); 312370b324cSopenharmony_ci len -= 8; 313370b324cSopenharmony_ci p += 8; 314370b324cSopenharmony_ci 315370b324cSopenharmony_ci Flags = 0; 316370b324cSopenharmony_ci if (Tag == Z7_WIN_IO_REPARSE_TAG_SYMLINK) 317370b324cSopenharmony_ci { 318370b324cSopenharmony_ci if (len < 4) 319370b324cSopenharmony_ci return false; 320370b324cSopenharmony_ci Flags = Get32(p); 321370b324cSopenharmony_ci len -= 4; 322370b324cSopenharmony_ci p += 4; 323370b324cSopenharmony_ci } 324370b324cSopenharmony_ci 325370b324cSopenharmony_ci if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen) 326370b324cSopenharmony_ci return false; 327370b324cSopenharmony_ci if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen) 328370b324cSopenharmony_ci return false; 329370b324cSopenharmony_ci GetString(p + subOffs, subLen >> 1, SubsName); 330370b324cSopenharmony_ci GetString(p + printOffs, printLen >> 1, PrintName); 331370b324cSopenharmony_ci 332370b324cSopenharmony_ci ErrorCode = 0; 333370b324cSopenharmony_ci return true; 334370b324cSopenharmony_ci} 335370b324cSopenharmony_ci 336370b324cSopenharmony_ci 337370b324cSopenharmony_cibool CReparseShortInfo::Parse(const Byte *p, size_t size) 338370b324cSopenharmony_ci{ 339370b324cSopenharmony_ci const Byte *start = p; 340370b324cSopenharmony_ci Offset= 0; 341370b324cSopenharmony_ci Size = 0; 342370b324cSopenharmony_ci if (size < 8) 343370b324cSopenharmony_ci return false; 344370b324cSopenharmony_ci UInt32 Tag = Get32(p); 345370b324cSopenharmony_ci UInt32 len = Get16(p + 4); 346370b324cSopenharmony_ci if (len + 8 > size) 347370b324cSopenharmony_ci return false; 348370b324cSopenharmony_ci /* 349370b324cSopenharmony_ci if ((type & kReparseFlags_Alias) == 0 || 350370b324cSopenharmony_ci (type & kReparseFlags_Microsoft) == 0 || 351370b324cSopenharmony_ci (type & 0xFFFF) != 3) 352370b324cSopenharmony_ci */ 353370b324cSopenharmony_ci if (Tag != Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT && 354370b324cSopenharmony_ci Tag != Z7_WIN_IO_REPARSE_TAG_SYMLINK) 355370b324cSopenharmony_ci // return true; 356370b324cSopenharmony_ci return false; 357370b324cSopenharmony_ci 358370b324cSopenharmony_ci if (Get16(p + 6) != 0) // padding 359370b324cSopenharmony_ci return false; 360370b324cSopenharmony_ci 361370b324cSopenharmony_ci p += 8; 362370b324cSopenharmony_ci size -= 8; 363370b324cSopenharmony_ci 364370b324cSopenharmony_ci if (len != size) // do we need that check? 365370b324cSopenharmony_ci return false; 366370b324cSopenharmony_ci 367370b324cSopenharmony_ci if (len < 8) 368370b324cSopenharmony_ci return false; 369370b324cSopenharmony_ci unsigned subOffs = Get16(p); 370370b324cSopenharmony_ci unsigned subLen = Get16(p + 2); 371370b324cSopenharmony_ci unsigned printOffs = Get16(p + 4); 372370b324cSopenharmony_ci unsigned printLen = Get16(p + 6); 373370b324cSopenharmony_ci len -= 8; 374370b324cSopenharmony_ci p += 8; 375370b324cSopenharmony_ci 376370b324cSopenharmony_ci // UInt32 Flags = 0; 377370b324cSopenharmony_ci if (Tag == Z7_WIN_IO_REPARSE_TAG_SYMLINK) 378370b324cSopenharmony_ci { 379370b324cSopenharmony_ci if (len < 4) 380370b324cSopenharmony_ci return false; 381370b324cSopenharmony_ci // Flags = Get32(p); 382370b324cSopenharmony_ci len -= 4; 383370b324cSopenharmony_ci p += 4; 384370b324cSopenharmony_ci } 385370b324cSopenharmony_ci 386370b324cSopenharmony_ci if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen) 387370b324cSopenharmony_ci return false; 388370b324cSopenharmony_ci if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen) 389370b324cSopenharmony_ci return false; 390370b324cSopenharmony_ci 391370b324cSopenharmony_ci Offset = (unsigned)(p - start) + subOffs; 392370b324cSopenharmony_ci Size = subLen; 393370b324cSopenharmony_ci return true; 394370b324cSopenharmony_ci} 395370b324cSopenharmony_ci 396370b324cSopenharmony_cibool CReparseAttr::IsOkNamePair() const 397370b324cSopenharmony_ci{ 398370b324cSopenharmony_ci if (IsLinkPrefix(SubsName)) 399370b324cSopenharmony_ci { 400370b324cSopenharmony_ci if (!IsDrivePath(SubsName.Ptr(k_LinkPrefix_Size))) 401370b324cSopenharmony_ci return PrintName.IsEmpty(); 402370b324cSopenharmony_ci if (wcscmp(SubsName.Ptr(k_LinkPrefix_Size), PrintName) == 0) 403370b324cSopenharmony_ci return true; 404370b324cSopenharmony_ci } 405370b324cSopenharmony_ci return wcscmp(SubsName, PrintName) == 0; 406370b324cSopenharmony_ci} 407370b324cSopenharmony_ci 408370b324cSopenharmony_ci/* 409370b324cSopenharmony_cibool CReparseAttr::IsVolume() const 410370b324cSopenharmony_ci{ 411370b324cSopenharmony_ci if (!IsLinkPrefix(SubsName)) 412370b324cSopenharmony_ci return false; 413370b324cSopenharmony_ci return IsVolumeName(SubsName.Ptr(k_LinkPrefix_Size)); 414370b324cSopenharmony_ci} 415370b324cSopenharmony_ci*/ 416370b324cSopenharmony_ci 417370b324cSopenharmony_ciUString CReparseAttr::GetPath() const 418370b324cSopenharmony_ci{ 419370b324cSopenharmony_ci if (IsSymLink_WSL()) 420370b324cSopenharmony_ci { 421370b324cSopenharmony_ci UString u; 422370b324cSopenharmony_ci // if (CheckUTF8(attr.WslName) 423370b324cSopenharmony_ci if (!ConvertUTF8ToUnicode(WslName, u)) 424370b324cSopenharmony_ci MultiByteToUnicodeString2(u, WslName); 425370b324cSopenharmony_ci return u; 426370b324cSopenharmony_ci } 427370b324cSopenharmony_ci 428370b324cSopenharmony_ci UString s (SubsName); 429370b324cSopenharmony_ci if (IsLinkPrefix(s)) 430370b324cSopenharmony_ci { 431370b324cSopenharmony_ci s.ReplaceOneCharAtPos(1, '\\'); // we normalize prefix from "\??\" to "\\?\" 432370b324cSopenharmony_ci if (IsDrivePath(s.Ptr(k_LinkPrefix_Size))) 433370b324cSopenharmony_ci s.DeleteFrontal(k_LinkPrefix_Size); 434370b324cSopenharmony_ci } 435370b324cSopenharmony_ci return s; 436370b324cSopenharmony_ci} 437370b324cSopenharmony_ci 438370b324cSopenharmony_ci#ifdef Z7_DEVICE_FILE 439370b324cSopenharmony_ci 440370b324cSopenharmony_cinamespace NSystem 441370b324cSopenharmony_ci{ 442370b324cSopenharmony_cibool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); 443370b324cSopenharmony_ci} 444370b324cSopenharmony_ci#endif // Z7_DEVICE_FILE 445370b324cSopenharmony_ci 446370b324cSopenharmony_ci#if defined(_WIN32) && !defined(UNDER_CE) 447370b324cSopenharmony_ci 448370b324cSopenharmony_cinamespace NIO { 449370b324cSopenharmony_ci 450370b324cSopenharmony_cibool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo) 451370b324cSopenharmony_ci{ 452370b324cSopenharmony_ci reparseData.Free(); 453370b324cSopenharmony_ci CInFile file; 454370b324cSopenharmony_ci if (!file.OpenReparse(path)) 455370b324cSopenharmony_ci return false; 456370b324cSopenharmony_ci 457370b324cSopenharmony_ci if (fileInfo) 458370b324cSopenharmony_ci file.GetFileInformation(fileInfo); 459370b324cSopenharmony_ci 460370b324cSopenharmony_ci const unsigned kBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; 461370b324cSopenharmony_ci CByteArr buf(kBufSize); 462370b324cSopenharmony_ci DWORD returnedSize; 463370b324cSopenharmony_ci if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize)) 464370b324cSopenharmony_ci return false; 465370b324cSopenharmony_ci reparseData.CopyFrom(buf, returnedSize); 466370b324cSopenharmony_ci return true; 467370b324cSopenharmony_ci} 468370b324cSopenharmony_ci 469370b324cSopenharmony_cistatic bool CreatePrefixDirOfFile(CFSTR path) 470370b324cSopenharmony_ci{ 471370b324cSopenharmony_ci FString path2 (path); 472370b324cSopenharmony_ci int pos = path2.ReverseFind_PathSepar(); 473370b324cSopenharmony_ci if (pos < 0) 474370b324cSopenharmony_ci return true; 475370b324cSopenharmony_ci #ifdef _WIN32 476370b324cSopenharmony_ci if (pos == 2 && path2[1] == L':') 477370b324cSopenharmony_ci return true; // we don't create Disk folder; 478370b324cSopenharmony_ci #endif 479370b324cSopenharmony_ci path2.DeleteFrom((unsigned)pos); 480370b324cSopenharmony_ci return NDir::CreateComplexDir(path2); 481370b324cSopenharmony_ci} 482370b324cSopenharmony_ci 483370b324cSopenharmony_ci 484370b324cSopenharmony_cistatic bool OutIoReparseData(DWORD controlCode, CFSTR path, void *data, DWORD size) 485370b324cSopenharmony_ci{ 486370b324cSopenharmony_ci COutFile file; 487370b324cSopenharmony_ci if (!file.Open(path, 488370b324cSopenharmony_ci FILE_SHARE_WRITE, 489370b324cSopenharmony_ci OPEN_EXISTING, 490370b324cSopenharmony_ci FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS)) 491370b324cSopenharmony_ci return false; 492370b324cSopenharmony_ci 493370b324cSopenharmony_ci DWORD returnedSize; 494370b324cSopenharmony_ci return file.DeviceIoControl(controlCode, data, size, NULL, 0, &returnedSize); 495370b324cSopenharmony_ci} 496370b324cSopenharmony_ci 497370b324cSopenharmony_ci 498370b324cSopenharmony_ci// If there is Reparse data already, it still writes new Reparse data 499370b324cSopenharmony_cibool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size) 500370b324cSopenharmony_ci{ 501370b324cSopenharmony_ci NFile::NFind::CFileInfo fi; 502370b324cSopenharmony_ci if (fi.Find(path)) 503370b324cSopenharmony_ci { 504370b324cSopenharmony_ci if (fi.IsDir() != isDir) 505370b324cSopenharmony_ci { 506370b324cSopenharmony_ci ::SetLastError(ERROR_DIRECTORY); 507370b324cSopenharmony_ci return false; 508370b324cSopenharmony_ci } 509370b324cSopenharmony_ci } 510370b324cSopenharmony_ci else 511370b324cSopenharmony_ci { 512370b324cSopenharmony_ci if (isDir) 513370b324cSopenharmony_ci { 514370b324cSopenharmony_ci if (!NDir::CreateComplexDir(path)) 515370b324cSopenharmony_ci return false; 516370b324cSopenharmony_ci } 517370b324cSopenharmony_ci else 518370b324cSopenharmony_ci { 519370b324cSopenharmony_ci CreatePrefixDirOfFile(path); 520370b324cSopenharmony_ci COutFile file; 521370b324cSopenharmony_ci if (!file.Create(path, CREATE_NEW)) 522370b324cSopenharmony_ci return false; 523370b324cSopenharmony_ci } 524370b324cSopenharmony_ci } 525370b324cSopenharmony_ci 526370b324cSopenharmony_ci return OutIoReparseData(my_FSCTL_SET_REPARSE_POINT, path, (void *)(const Byte *)(data), size); 527370b324cSopenharmony_ci} 528370b324cSopenharmony_ci 529370b324cSopenharmony_ci 530370b324cSopenharmony_cibool DeleteReparseData(CFSTR path) 531370b324cSopenharmony_ci{ 532370b324cSopenharmony_ci CByteBuffer reparseData; 533370b324cSopenharmony_ci if (!GetReparseData(path, reparseData, NULL)) 534370b324cSopenharmony_ci return false; 535370b324cSopenharmony_ci /* MSDN: The tag specified in the ReparseTag member of this structure 536370b324cSopenharmony_ci must match the tag of the reparse point to be deleted, 537370b324cSopenharmony_ci and the ReparseDataLength member must be zero */ 538370b324cSopenharmony_ci #define my_REPARSE_DATA_BUFFER_HEADER_SIZE 8 539370b324cSopenharmony_ci if (reparseData.Size() < my_REPARSE_DATA_BUFFER_HEADER_SIZE) 540370b324cSopenharmony_ci { 541370b324cSopenharmony_ci SetLastError(ERROR_INVALID_REPARSE_DATA); 542370b324cSopenharmony_ci return false; 543370b324cSopenharmony_ci } 544370b324cSopenharmony_ci BYTE buf[my_REPARSE_DATA_BUFFER_HEADER_SIZE]; 545370b324cSopenharmony_ci memset(buf, 0, sizeof(buf)); 546370b324cSopenharmony_ci memcpy(buf, reparseData, 4); // tag 547370b324cSopenharmony_ci return OutIoReparseData(my_FSCTL_DELETE_REPARSE_POINT, path, buf, sizeof(buf)); 548370b324cSopenharmony_ci} 549370b324cSopenharmony_ci 550370b324cSopenharmony_ci} 551370b324cSopenharmony_ci 552370b324cSopenharmony_ci#endif // defined(_WIN32) && !defined(UNDER_CE) 553370b324cSopenharmony_ci 554370b324cSopenharmony_ci 555370b324cSopenharmony_ci#ifndef _WIN32 556370b324cSopenharmony_ci 557370b324cSopenharmony_cinamespace NIO { 558370b324cSopenharmony_ci 559370b324cSopenharmony_cibool GetReparseData(CFSTR path, CByteBuffer &reparseData) 560370b324cSopenharmony_ci{ 561370b324cSopenharmony_ci reparseData.Free(); 562370b324cSopenharmony_ci 563370b324cSopenharmony_ci #define MAX_PATHNAME_LEN 1024 564370b324cSopenharmony_ci char buf[MAX_PATHNAME_LEN + 2]; 565370b324cSopenharmony_ci const size_t request = sizeof(buf) - 1; 566370b324cSopenharmony_ci 567370b324cSopenharmony_ci // printf("\nreadlink() path = %s \n", path); 568370b324cSopenharmony_ci const ssize_t size = readlink(path, buf, request); 569370b324cSopenharmony_ci // there is no tail zero 570370b324cSopenharmony_ci 571370b324cSopenharmony_ci if (size < 0) 572370b324cSopenharmony_ci return false; 573370b324cSopenharmony_ci if ((size_t)size >= request) 574370b324cSopenharmony_ci { 575370b324cSopenharmony_ci SetLastError(EINVAL); // check it: ENAMETOOLONG 576370b324cSopenharmony_ci return false; 577370b324cSopenharmony_ci } 578370b324cSopenharmony_ci 579370b324cSopenharmony_ci // printf("\nreadlink() res = %s size = %d \n", buf, (int)size); 580370b324cSopenharmony_ci reparseData.CopyFrom((const Byte *)buf, (size_t)size); 581370b324cSopenharmony_ci return true; 582370b324cSopenharmony_ci} 583370b324cSopenharmony_ci 584370b324cSopenharmony_ci 585370b324cSopenharmony_ci/* 586370b324cSopenharmony_ci// If there is Reparse data already, it still writes new Reparse data 587370b324cSopenharmony_cibool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size) 588370b324cSopenharmony_ci{ 589370b324cSopenharmony_ci // AString s; 590370b324cSopenharmony_ci // s.SetFrom_CalcLen(data, size); 591370b324cSopenharmony_ci // return (symlink(s, path) == 0); 592370b324cSopenharmony_ci UNUSED_VAR(path) 593370b324cSopenharmony_ci UNUSED_VAR(isDir) 594370b324cSopenharmony_ci UNUSED_VAR(data) 595370b324cSopenharmony_ci UNUSED_VAR(size) 596370b324cSopenharmony_ci SetLastError(ENOSYS); 597370b324cSopenharmony_ci return false; 598370b324cSopenharmony_ci} 599370b324cSopenharmony_ci*/ 600370b324cSopenharmony_ci 601370b324cSopenharmony_cibool SetSymLink(CFSTR from, CFSTR to) 602370b324cSopenharmony_ci{ 603370b324cSopenharmony_ci // printf("\nsymlink() %s -> %s\n", from, to); 604370b324cSopenharmony_ci int ir; 605370b324cSopenharmony_ci // ir = unlink(path); 606370b324cSopenharmony_ci // if (ir == 0) 607370b324cSopenharmony_ci ir = symlink(to, from); 608370b324cSopenharmony_ci return (ir == 0); 609370b324cSopenharmony_ci} 610370b324cSopenharmony_ci 611370b324cSopenharmony_cibool SetSymLink_UString(CFSTR from, const UString &to) 612370b324cSopenharmony_ci{ 613370b324cSopenharmony_ci AString utf; 614370b324cSopenharmony_ci ConvertUnicodeToUTF8(to, utf); 615370b324cSopenharmony_ci return SetSymLink(from, utf); 616370b324cSopenharmony_ci} 617370b324cSopenharmony_ci 618370b324cSopenharmony_ci} 619370b324cSopenharmony_ci 620370b324cSopenharmony_ci#endif // !_WIN32 621370b324cSopenharmony_ci 622370b324cSopenharmony_ci}} 623