Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/UI/FileManager/LinkDialog.cpp')
-rw-r--r--CPP/7zip/UI/FileManager/LinkDialog.cpp117
1 files changed, 81 insertions, 36 deletions
diff --git a/CPP/7zip/UI/FileManager/LinkDialog.cpp b/CPP/7zip/UI/FileManager/LinkDialog.cpp
index ddef365c..07f1f061 100644
--- a/CPP/7zip/UI/FileManager/LinkDialog.cpp
+++ b/CPP/7zip/UI/FileManager/LinkDialog.cpp
@@ -36,46 +36,50 @@ static const UInt32 kLangIDs[] =
IDR_LINK_TYPE_HARD,
IDR_LINK_TYPE_SYM_FILE,
IDR_LINK_TYPE_SYM_DIR,
- IDR_LINK_TYPE_JUNCTION
+ IDR_LINK_TYPE_JUNCTION,
+ IDR_LINK_TYPE_WSL
};
#endif
-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))
+static bool GetSymLink(CFSTR path, CReparseAttr &attr, UString &errorMessage)
+{
+ CByteBuffer buf;
+ if (!NIO::GetReparseData(path, buf, NULL))
return false;
- DWORD errorCode = 0;
- if (!attr.Parse(buf, returnedSize, errorCode))
+ if (!attr.Parse(buf, buf.Size()))
+ {
+ SetLastError(attr.ErrorCode);
return false;
+ }
CByteBuffer data2;
- if (!FillLinkData(data2, attr.GetPath(), attr.IsSymLink()))
+ if (!FillLinkData(data2, attr.GetPath(),
+ !attr.IsMountPoint(), attr.IsSymLink_WSL()))
+ {
+ errorMessage = "Cannot reproduce reparse point";
return false;
+ }
- if (data2.Size() != returnedSize ||
- memcmp(data2, buf, returnedSize) != 0)
+ if (data2.Size() != buf.Size() ||
+ memcmp(data2, buf, buf.Size()) != 0)
+ {
+ errorMessage = "mismatch for reproduced reparse point";
return false;
+ }
return true;
}
+
static const int k_LinkType_Buttons[] =
{
IDR_LINK_TYPE_HARD,
IDR_LINK_TYPE_SYM_FILE,
IDR_LINK_TYPE_SYM_DIR,
- IDR_LINK_TYPE_JUNCTION
+ IDR_LINK_TYPE_JUNCTION,
+ IDR_LINK_TYPE_WSL
};
void CLinkDialog::Set_LinkType_Radio(int idb)
@@ -104,16 +108,33 @@ bool CLinkDialog::OnInit()
if (fi.HasReparsePoint())
{
CReparseAttr attr;
- bool res = GetSymLink(us2fs(FilePath), attr);
+ UString error;
+ bool res = GetSymLink(us2fs(FilePath), attr, error);
+ if (!res && error.IsEmpty())
+ {
+ DWORD lastError = GetLastError();
+ if (lastError != 0)
+ error = NError::MyFormatMessage(lastError);
+ }
- UString s = attr.PrintName;
+ UString s = attr.GetPath();
+ if (!attr.IsSymLink_WSL())
if (!attr.IsOkNamePair())
{
s += " : ";
- s += attr.SubsName;
+ s += attr.PrintName;
}
+
if (!res)
+ {
s.Insert(0, L"ERROR: ");
+ if (!error.IsEmpty())
+ {
+ s += " : ";
+ s += error;
+ }
+ }
+
SetItemText(IDT_LINK_PATH_TO_CUR, s);
@@ -121,11 +142,13 @@ bool CLinkDialog::OnInit()
_pathFromCombo.SetText(FilePath);
_pathToCombo.SetText(destPath);
- if (res)
+ // if (res)
{
if (attr.IsMountPoint())
linkType = IDR_LINK_TYPE_JUNCTION;
- if (attr.IsSymLink())
+ else if (attr.IsSymLink_WSL())
+ linkType = IDR_LINK_TYPE_WSL;
+ else if (attr.IsSymLink_Win())
{
linkType =
fi.IsDir() ?
@@ -140,6 +163,7 @@ bool CLinkDialog::OnInit()
}
else
{
+ // no ReparsePoint
_pathFromCombo.SetText(AnotherPath);
_pathToCombo.SetText(FilePath);
if (fi.IsDir())
@@ -258,15 +282,18 @@ void CLinkDialog::OnButton_Link()
}
NFind::CFileInfo info1, info2;
- bool finded1 = info1.Find(us2fs(from));
- bool finded2 = info2.Find(us2fs(to));
+ const bool finded1 = info1.Find(us2fs(from));
+ const bool finded2 = info2.Find(us2fs(to));
- bool isDirLink = (
+ const bool isDirLink = (
idb == IDR_LINK_TYPE_SYM_DIR ||
idb == IDR_LINK_TYPE_JUNCTION);
- if (finded1 && info1.IsDir() != isDirLink ||
- finded2 && info2.IsDir() != isDirLink)
+ const bool isWSL = (idb == IDR_LINK_TYPE_WSL);
+
+ if (!isWSL)
+ if ((finded1 && info1.IsDir() != isDirLink) ||
+ (finded2 && info2.IsDir() != isDirLink))
{
ShowError(L"Incorrect link type");
return;
@@ -282,25 +309,41 @@ void CLinkDialog::OnButton_Link()
}
else
{
- bool isSymLink = (idb != IDR_LINK_TYPE_JUNCTION);
+ if (finded1 && !info1.IsDir() && !info1.HasReparsePoint() && info1.Size != 0)
+ {
+ UString s ("WARNING: reparse point will hide the data of existing file");
+ s.Add_LF();
+ s += from;
+ ShowError(s);
+ return;
+ }
+
+ const bool isSymLink = (idb != IDR_LINK_TYPE_JUNCTION);
CByteBuffer data;
- if (!FillLinkData(data, to, isSymLink))
+ if (!FillLinkData(data, to, isSymLink, isWSL))
{
ShowError(L"Incorrect link");
return;
}
CReparseAttr attr;
- DWORD errorCode = 0;
- if (!attr.Parse(data, data.Size(), errorCode))
+ if (!attr.Parse(data, data.Size()))
{
ShowError(L"Internal conversion error");
return;
}
-
-
- if (!NIO::SetReparseData(us2fs(from), isDirLink, data, (DWORD)data.Size()))
+
+ bool res;
+ if (to.IsEmpty())
+ {
+ // res = NIO::SetReparseData(us2fs(from), isDirLink, NULL, 0);
+ res = NIO::DeleteReparseData(us2fs(from));
+ }
+ else
+ res = NIO::SetReparseData(us2fs(from), isDirLink, data, (DWORD)data.Size());
+
+ if (!res)
{
ShowLastErrorMessage();
return;
@@ -350,5 +393,7 @@ void CApp::Link()
if (dlg.Create(srcPanel.GetParent()) != IDOK)
return;
+ // fix it: we should refresh panel with changed link
+
RefreshTitleAlways();
}