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);
}
Exemple #2
0
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();
}
Exemple #4
0
bool CLinkDialog::OnInit()
{
  #ifdef LANG
  LangSetWindowText(*this, IDD_LINK);
  LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
  #endif
  
  _pathFromCombo.Attach(GetItem(IDC_LINK_PATH_FROM));
  _pathToCombo.Attach(GetItem(IDC_LINK_PATH_TO));
  
  if (!FilePath.IsEmpty())
  {
    NFind::CFileInfo fi;
    int linkType = 0;
    if (!fi.Find(us2fs(FilePath)))
      linkType = IDR_LINK_TYPE_SYM_FILE;
    else
    {
      if (fi.HasReparsePoint())
      {
        CReparseAttr attr;
        bool res = GetSymLink(us2fs(FilePath), attr);
        
        UString s = attr.PrintName;
        if (!attr.IsOkNamePair())
        {
          s += L" : ";
          s += attr.SubsName;
        }
        if (!res)
          s = L"ERROR: " + s;
        
        SetItemText(IDT_LINK_PATH_TO_CUR, s);
        
        UString destPath = attr.GetPath();
        _pathFromCombo.SetText(FilePath);
        _pathToCombo.SetText(destPath);
        
        if (res)
        {
          if (attr.IsMountPoint())
            linkType = IDR_LINK_TYPE_JUNCTION;
          if (attr.IsSymLink())
          {
            linkType =
              fi.IsDir() ?
                IDR_LINK_TYPE_SYM_DIR :
                IDR_LINK_TYPE_SYM_FILE;
            // if (attr.IsRelative()) linkType = IDR_LINK_TYPE_SYM_RELATIVE;
          }
          
          if (linkType != 0)
            Set_LinkType_Radio(linkType);
        }
      }
      else
      {
        _pathFromCombo.SetText(AnotherPath);
        _pathToCombo.SetText(FilePath);
        if (fi.IsDir())
          linkType = g_SymLink_Supported ?
              IDR_LINK_TYPE_SYM_DIR :
              IDR_LINK_TYPE_JUNCTION;
        else
          linkType = IDR_LINK_TYPE_HARD;
      }
    }
    if (linkType != 0)
      Set_LinkType_Radio(linkType);
  }

  NormalizeSize();
  return CModalDialog::OnInit();
}
Exemple #5
0
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
}