HRESULT CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi, const FString &phyPrefix) { if (!SymLinks || !fi.HasReparsePoint()) return S_OK; const FString path = phyPrefix + fi.Name; CByteBuffer &buf = dirItem.ReparseData; DWORD res = 0; if (NIO::GetReparseData(path, buf)) { CReparseAttr attr; if (attr.Parse(buf, buf.Size(), res)) return S_OK; // we ignore unknown reparse points if (res != ERROR_INVALID_REPARSE_DATA) res = 0; } else { res = ::GetLastError(); if (res == 0) res = ERROR_INVALID_FUNCTION; } buf.Free(); if (res == 0) return S_OK; return AddError(path, res); }
static bool GetSymLink(CFSTR path, CReparseAttr &attr) { NIO::CInFile file; if (!file.Open(path, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS)) return false; const unsigned kBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; CByteArr buf(kBufSize); DWORD returnedSize; if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize)) return false; if (!attr.Parse(buf, returnedSize)) return false; CByteBuffer data2; if (!FillLinkData(data2, attr.GetPath(), attr.IsSymLink())) return false; if (data2.Size() != returnedSize || memcmp(data2, buf, returnedSize) != 0) return false; return true; }
void CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi, const FString &phyPrefix) { if (!SymLinks || !fi.HasReparsePoint()) return; const FString path = phyPrefix + fi.Name; CByteBuffer &buf = dirItem.ReparseData; if (NIO::GetReparseData(path, buf)) { CReparseAttr attr; if (attr.Parse(buf, buf.Size())) return; } AddError(path); buf.Free(); }
void CLinkDialog::OnButton_Link() { UString from, to; _pathFromCombo.GetText(from); _pathToCombo.GetText(to); if (from.IsEmpty()) return; if (!NName::IsAbsolutePath(from)) from.Insert(0, CurDirPrefix); int idb = -1; for (unsigned i = 0;; i++) { if (i >= ARRAY_SIZE(k_LinkType_Buttons)) return; idb = k_LinkType_Buttons[i]; if (IsButtonCheckedBool(idb)) break; } NFind::CFileInfo info1, info2; bool finded1 = info1.Find(us2fs(from)); bool finded2 = info2.Find(us2fs(to)); bool isDirLink = ( idb == IDR_LINK_TYPE_SYM_DIR || idb == IDR_LINK_TYPE_JUNCTION); if (finded1 && info1.IsDir() != isDirLink || finded2 && info2.IsDir() != isDirLink) { ShowError(L"Incorrect link type"); return; } if (idb == IDR_LINK_TYPE_HARD) { if (!NDir::MyCreateHardLink(us2fs(from), us2fs(to))) { ShowLastErrorMessage(); return; } } else { bool isSymLink = (idb != IDR_LINK_TYPE_JUNCTION); CByteBuffer data; if (!FillLinkData(data, to, isSymLink)) { ShowError(L"Incorrect link"); return; } CReparseAttr attr; if (!attr.Parse(data, data.Size())) { ShowError(L"Internal conversion error"); return; } if (!NIO::SetReparseData(us2fs(from), isDirLink, data, (DWORD)data.Size())) { ShowLastErrorMessage(); return; } } End(IDOK); }
STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN const CUpdatePair2 &up = (*UpdatePairs)[index]; NCOM::CPropVariant prop; if (up.NewData) { /* if (propID == kpidIsHardLink) { prop = _isHardLink; prop.Detach(value); return S_OK; } */ if (propID == kpidSymLink) { if (index == _hardIndex_From) { prop.Detach(value); return S_OK; } if (up.DirIndex >= 0) { #ifndef UNDER_CE const CDirItem &di = DirItems->Items[up.DirIndex]; // if (di.IsDir()) { CReparseAttr attr; DWORD errorCode = 0; if (attr.Parse(di.ReparseData, di.ReparseData.Size(), errorCode)) { UString simpleName = attr.GetPath(); if (attr.IsRelative()) prop = simpleName; else { const FString phyPath = DirItems->GetPhyPath(up.DirIndex); FString fullPath; if (NDir::MyGetFullPathName(phyPath, fullPath)) { prop = GetRelativePath(simpleName, fs2us(fullPath)); } } prop.Detach(value); return S_OK; } } #endif } } else if (propID == kpidHardLink) { if (index == _hardIndex_From) { const CKeyKeyValPair &pair = _map[_hardIndex_To]; const CUpdatePair2 &up2 = (*UpdatePairs)[pair.Value]; prop = DirItems->GetLogPath(up2.DirIndex); prop.Detach(value); return S_OK; } if (up.DirIndex >= 0) { prop.Detach(value); return S_OK; } } } if (up.IsAnti && propID != kpidIsDir && propID != kpidPath && propID != kpidIsAltStream) { switch (propID) { case kpidSize: prop = (UInt64)0; break; case kpidIsAnti: prop = true; break; } } else if (propID == kpidPath && up.NewNameIndex >= 0) prop = (*NewNames)[up.NewNameIndex]; else if (propID == kpidComment && CommentIndex >= 0 && (unsigned)CommentIndex == index && Comment) prop = *Comment; else if (propID == kpidShortName && up.NewNameIndex >= 0 && up.IsMainRenameItem) { // we can generate new ShortName here; } else if ((up.UseArcProps || (KeepOriginalItemNames && (propID == kpidPath || propID == kpidIsAltStream))) && up.ExistInArchive() && Archive) return Archive->GetProperty(ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex, propID, value); else if (up.ExistOnDisk()) { const CDirItem &di = DirItems->Items[up.DirIndex]; switch (propID) { case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break; case kpidIsDir: prop = di.IsDir(); break; case kpidSize: prop = di.IsDir() ? (UInt64)0 : di.Size; break; case kpidAttrib: prop = di.Attrib; break; case kpidCTime: prop = di.CTime; break; case kpidATime: prop = di.ATime; break; case kpidMTime: prop = di.MTime; break; case kpidIsAltStream: prop = di.IsAltStream; break; #if defined(_WIN32) && !defined(UNDER_CE) // case kpidShortName: prop = di.ShortName; break; #endif } } prop.Detach(value); return S_OK; COM_TRY_END }