deps/unrar/filcreat.cpp
// If we find a file, which short name is equal to 'Name', we try to change
// its short name, while preserving the long name. It helps when unpacking
// an archived file, which long name is equal to short name of already
// existing file. Otherwise we would overwrite the already existing file,
// even though its long name does not match the name of unpacking file.
If we find a file, which short name is equal to 'Name', we try to change
its short name, while preserving the long name. It helps when unpacking
an archived file, which long name is equal to short name of already
existing file. Otherwise we would overwrite the already existing file,
even though its long name does not match the name of unpacking file.
If we find a file which short name is equal to ' Name ' we try to change its short name while preserving the long name . It helps when unpacking an archived file which long name is equal to short name of already existing file . Otherwise we would overwrite the already existing file even though its long name does not match the name of unpacking file .
bool UpdateExistingShortName(const wchar *Name)
{
  wchar LongPathName[NM];
  DWORD Res=GetLongPathName(Name,LongPathName,ASIZE(LongPathName));
  if (Res==0 || Res>=ASIZE(LongPathName))
    return false;
  wchar ShortPathName[NM];
  Res=GetShortPathName(Name,ShortPathName,ASIZE(ShortPathName));
  if (Res==0 || Res>=ASIZE(ShortPathName))
    return false;
  wchar *LongName=PointToName(LongPathName);
  wchar *ShortName=PointToName(ShortPathName);
  if (*ShortName==0 || wcsicomp(LongName,ShortName)==0 ||
      wcsicomp(PointToName(Name),ShortName)!=0)
    return false;
  wchar NewName[NM];
  *NewName=0;
  for (int I=0;I<10000 && *NewName==0;I+=123)
  {
    wcsncpyz(NewName,Name,ASIZE(NewName));
    swprintf(PointToName(NewName),ASIZE(NewName),L"rtmp%d",I);
    if (FileExist(NewName))
      *NewName=0;
  }
  if (*NewName==0)
    return false;
  wchar FullName[NM];
  wcsncpyz(FullName,Name,ASIZE(FullName));
  SetName(FullName,LongName,ASIZE(FullName));
  if (!MoveFile(FullName,NewName))
    return false;
  File KeepShortFile;
  bool Created=false;
  if (!FileExist(Name))
    Created=KeepShortFile.Create(Name,FMF_WRITE|FMF_SHAREREAD);
  MoveFile(NewName,FullName);
  if (Created)
  {
    KeepShortFile.Close();
    KeepShortFile.Delete();
  }
  return true;
}
bool UpdateExistingShortName ( const wchar * Name ) { wchar LongPathName [ NM ] ; DWORD Res = GetLongPathName ( Name , LongPathName , ASIZE ( LongPathName ) ) ; if ( Res == 0 || Res >= ASIZE ( LongPathName ) ) return false ; wchar ShortPathName [ NM ] ; Res = GetShortPathName ( Name , ShortPathName , ASIZE ( ShortPathName ) ) ; if ( Res == 0 || Res >= ASIZE ( ShortPathName ) ) return false ; wchar * LongName = PointToName ( LongPathName ) ; wchar * ShortName = PointToName ( ShortPathName ) ; if ( * ShortName == 0 || wcsicomp ( LongName , ShortName ) == 0 || wcsicomp ( PointToName ( Name ) , ShortName ) != 0 ) return false ; wchar NewName [ NM ] ; * NewName = 0 ; for ( int I = 0 ; I < 10000 && * NewName == 0 ; I += 123 ) { wcsncpyz ( NewName , Name , ASIZE ( NewName ) ) ; swprintf ( PointToName ( NewName ) , ASIZE ( NewName ) , L" " , I ) ; if ( FileExist ( NewName ) ) * NewName = 0 ; } if ( * NewName == 0 ) return false ; wchar FullName [ NM ] ; wcsncpyz ( FullName , Name , ASIZE ( FullName ) ) ; SetName ( FullName , LongName , ASIZE ( FullName ) ) ; if ( ! MoveFile ( FullName , NewName ) ) return false ; File KeepShortFile ; bool Created = false ; if ( ! FileExist ( Name ) ) Created = KeepShortFile . Create ( Name , FMF_WRITE | FMF_SHAREREAD ) ; MoveFile ( NewName , FullName ) ; if ( Created ) { KeepShortFile . Close ( ) ; KeepShortFile . Delete ( ) ; } return true ; }
If we find a file, which short name is equal to 'Name', we try to change
its short name, while preserving the long name.
If we find a file which short name is equal to ' Name ' we try to change its short name while preserving the long name .
// We continue only if file has a short name, which does not match its // long name, and this short name is equal to name of file which we need // to create. // Generate the temporary new name for existing file. // Here we copy the path part of file to create. We'll make the temporary // file in the same folder. // Here we set the random name part. // If such file is already exist, try next random name. // If we could not generate the name not used by any other file, we return. // FastFind returns the name without path, but we need the fully qualified // name for renaming, so we use the path from file to create and long name // from existing file. // Rename the existing file to randomly generated name. Normally it changes // the short name too. // Now we need to create the temporary empty file with same name as // short name of our already existing file. We do it to occupy its previous // short name and not allow to use it again when renaming the file back to // its original long name. // Now we rename the existing file from temporary name to original long name. // Since its previous short name is occupied by another file, it should // get another short name. // Delete the temporary zero length file occupying the short name, // We successfully changed the short name. Maybe sometimes we'll simplify // this function by use of SetFileShortName Windows API call. // But SetFileShortName is not available in older Windows.