text: #include "rar.hpp"
  
  // If NewFile==NULL, we delete created file after user confirmation.
  // It is useful we we need to overwrite an existing folder or file,
  // but need user confirmation for that.
  bool FileCreate(RAROptions *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize,
                  bool *UserReject,int64 FileSize,RarTime *FileTime,bool WriteOnly)
  {
    if (UserReject!=NULL)
      *UserReject=false;
  #ifdef _WIN_ALL
    bool ShortNameChanged=false;
  #endif
    while (FileExist(Name))
    {
  #ifdef _WIN_ALL
      if (!ShortNameChanged)
      {
        // Avoid the infinite loop if UpdateExistingShortName returns
        // the same name.
        ShortNameChanged=true;
  
        // Maybe our long name matches the short name of existing file.
        // Let's check if we can change the short name.
        if (UpdateExistingShortName(Name))
          continue;
      }
      // Allow short name check again. It is necessary, because rename and
      // autorename below can change the name, so we need to check it again.
      ShortNameChanged=false;
  #endif
      UIASKREP_RESULT Choice=uiAskReplaceEx(Cmd,Name,MaxNameSize,FileSize,FileTime,(NewFile==NULL ? UIASKREP_F_NORENAME:0));
  
      if (Choice==UIASKREP_R_REPLACE)
        break;
      if (Choice==UIASKREP_R_SKIP)
      {
        if (UserReject!=NULL)
          *UserReject=true;
        return false;
      }
      if (Choice==UIASKREP_R_CANCEL)
        ErrHandler.Exit(RARX_USERBREAK);
    }
  
    // Try to truncate the existing file first instead of delete,
    // so we preserve existing file permissions such as NTFS permissions.
    uint FileMode=WriteOnly ? FMF_WRITE|FMF_SHAREREAD:FMF_UPDATE|FMF_SHAREREAD;
    if (NewFile!=NULL && NewFile->Create(Name,FileMode))
      return true;
  
    CreatePath(Name,true);
    return NewFile!=NULL ? NewFile->Create(Name,FileMode):DelFile(Name);
  }
  
  
  bool GetAutoRenamedName(wchar *Name,size_t MaxNameSize)
  {
    wchar NewName[NM];
    size_t NameLength=wcslen(Name);
  #ifdef _ANDROID
    if (NameLength>ASIZE(NewName)-10)
      return false;
  #endif
    wchar *Ext=GetExt(Name);
    if (Ext==NULL)
      Ext=Name+NameLength;
    for (uint FileVer=1;;FileVer++)
    {
  #ifdef _ANDROID // No swprintf in Android prior to Android 5.0.
      uint NamePrefixLength=Ext-Name;
      wcsncpy(NewName,Name,NamePrefixLength);
      wcscpy(NewName+NamePrefixLength,L"(");
      itoa(FileVer,NewName+NamePrefixLength+1,ASIZE(NewName)-NamePrefixLength-1);
      wcsncatz(NewName,L")",ASIZE(NewName));
      wcsncatz(NewName,Ext,ASIZE(NewName));
  #else
      swprintf(NewName,ASIZE(NewName),L"%.*ls(%u)%ls",uint(Ext-Name),Name,FileVer,Ext);
  #endif
      if (!FileExist(NewName))
      {
        wcsncpyz(Name,NewName,MaxNameSize);
        break;
      }
      if (FileVer>=1000000)
        return false;
    }
    return true;
  }
  
  
  #ifdef _WIN_ALL
  // 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);
  
    // 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.
    if (*ShortName==0 || wcsicomp(LongName,ShortName)==0 ||
        wcsicomp(PointToName(Name),ShortName)!=0)
      return false;
  
    // Generate the temporary new name for existing file.
    wchar NewName[NM];
    *NewName=0;
    for (int I=0;I<10000 && *NewName==0;I+=123)
    {
      // Here we copy the path part of file to create. We'll make the temporary
      // file in the same folder.
      wcsncpyz(NewName,Name,ASIZE(NewName));
  
      // Here we set the random name part.
      swprintf(PointToName(NewName),ASIZE(NewName),L"rtmp%d",I);
      
      // If such file is already exist, try next random name.
      if (FileExist(NewName))
        *NewName=0;
    }
  
    // If we could not generate the name not used by any other file, we return.
    if (*NewName==0)
      return false;
    
    // 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.
    wchar FullName[NM];
    wcsncpyz(FullName,Name,ASIZE(FullName));
    SetName(FullName,LongName,ASIZE(FullName));
    
    // Rename the existing file to randomly generated name. Normally it changes
    // the short name too.
    if (!MoveFile(FullName,NewName))
      return false;
  
    // 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.
    File KeepShortFile;
    bool Created=false;
    if (!FileExist(Name))
      Created=KeepShortFile.Create(Name,FMF_WRITE|FMF_SHAREREAD);
  
    // 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.
    MoveFile(NewName,FullName);
  
    if (Created)
    {
      // Delete the temporary zero length file occupying the short name,
      KeepShortFile.Close();
      KeepShortFile.Delete();
    }
    // 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.
    return true;
  }
  #endif
  