Recent

Author Topic: Update short filename on a file?  (Read 5757 times)

snorkel

  • Hero Member
  • *****
  • Posts: 817
Update short filename on a file?
« on: October 16, 2017, 09:51:46 pm »
anyone know how to update a files short path name on NTFS with FPC?
See this article if you don't know what I mean:
https://guyrleech.wordpress.com/2014/04/15/ntfs-8-3-short-names-solving-the-issues/#comment-296

we copied a huge amount of files from one server to the other, however we forgot to enable 8.3 naming on the new windows server and now a bunch of the files are not accessible because the path is too large.  It took weeks to copy all the data so we enabled the 8.3 on the new server however it's only applied automatically when files are created, so all the stuff we already copied does not have the short path name when we view the properties on it.
apparently the short path name is some kind of meta tag NTFS uses but I dont' see how to access it with the standard file utils.
***Snorkel***
If I forget, I always use the latest stable 32bit version of Lazarus and FPC. At the time of this signature that is Laz 3.0RC2 and FPC 3.2.2
OS: Windows 10 64 bit

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1312
    • Lebeau Software
Re: Update short filename on a file?
« Reply #1 on: October 17, 2017, 12:57:28 am »
You don't have direct access to set the 8.3 filename.  Just rename the existing files and let NTFS generate new 8.3 names for them.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Update short filename on a file?
« Reply #2 on: October 17, 2017, 06:37:36 am »
anyone know how to update a files short path name on NTFS with FPC?
See this article if you don't know what I mean:
https://guyrleech.wordpress.com/2014/04/15/ntfs-8-3-short-names-solving-the-issues/#comment-296

we copied a huge amount of files from one server to the other, however we forgot to enable 8.3 naming on the new windows server and now a bunch of the files are not accessible because the path is too large.  It took weeks to copy all the data so we enabled the 8.3 on the new server however it's only applied automatically when files are created, so all the stuff we already copied does not have the short path name when we view the properties on it.
apparently the short path name is some kind of meta tag NTFS uses but I dont' see how to access it with the standard file utils.

What's wrong with the tool provided in the article?

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Update short filename on a file?
« Reply #3 on: October 17, 2017, 10:13:34 am »
If it is one place that you access it, you could prefix it with \\?\

Afaik windows 10 has a way to remove the 260 lfn limit all together.

munair

  • Hero Member
  • *****
  • Posts: 798
  • compiler developer @SharpBASIC
    • SharpBASIC
Re: Update short filename on a file?
« Reply #4 on: October 17, 2017, 12:42:59 pm »
What's wrong with the tool provided in the article?
I was wondering the same thing.
keep it simple

snorkel

  • Hero Member
  • *****
  • Posts: 817
Re: Update short filename on a file?
« Reply #5 on: October 17, 2017, 07:29:24 pm »
You don't have direct access to set the 8.3 filename.  Just rename the existing files and let NTFS generate new 8.3 names for them.

Remy, we tried that, it does not work.  It's not the filename that's the problem, it's the directory names.  The parent directories need to have the short names.
The entire directory tree needs to be recreated for that to work.  It took weeks to copy the data.

The MS utility program does work and I could just shell out to it but I am concerned it will be super slow vs using the API (SetFileShortNameW) as in just some of the possible sub dirs there are over 700,000 folders.
***Snorkel***
If I forget, I always use the latest stable 32bit version of Lazarus and FPC. At the time of this signature that is Laz 3.0RC2 and FPC 3.2.2
OS: Windows 10 64 bit

snorkel

  • Hero Member
  • *****
  • Posts: 817
Re: Update short filename on a file?
« Reply #6 on: October 17, 2017, 07:43:18 pm »
I came up with some code, but apparently some privilege for back up and restore needs to be set?
I get an error saying "A required privilege is not held by the client"

Code: Pascal  [Select][+][-]
  1. procedure TMainForm.SetShortPathNameClick(Sender: TObject);
  2. var
  3.   filename:unicodestring;
  4.   HFileRes: HFILE;
  5. begin
  6.    filename:=filelistbox.items[FileListBox.ItemIndex];
  7.    //following needed to work with Unicode API functions i.e.  paths must be prefixed with \\?\UNC\
  8.    filename:=StringReplace(filename,'\\','\\?\UNC\',[]);
  9.    hfileres:=CreateFileW(pwidechar(filename),
  10.                     GENERIC_ALL,
  11.                     FILE_SHARE_WRITE + FILE_SHARE_READ + FILE_SHARE_DELETE,
  12.                     Nil,
  13.                     OPEN_EXISTING,
  14.                     FILE_FLAG_BACKUP_SEMANTICS,
  15.                     0);
  16.    if  HFileRes > 0 then
  17.        if not SetFileShortNameW(HFileRes,'AshortName') then     //SetFileShortNameW is in jwawinbase
  18.                MessageDlg('Set Short Path Error',SysErrorMessageUTF8(windows.GetLastError),mtError,[mbOK],0)
  19. end;
  20.  
***Snorkel***
If I forget, I always use the latest stable 32bit version of Lazarus and FPC. At the time of this signature that is Laz 3.0RC2 and FPC 3.2.2
OS: Windows 10 64 bit

snorkel

  • Hero Member
  • *****
  • Posts: 817
Re: Update short filename on a file?
« Reply #7 on: October 17, 2017, 08:00:12 pm »
ok, found some example delphi code to set the privilege,:
http://www.swissdelphicenter.com/en/showcode.php?id=1177

having some issues getting in working in Laz:
doesn't like this line: TokenPriv.Privileges[0].Luid) then
and ReturnLength in the call to AdjustTokenPrivileges

Update:  jwawinbase versions of the functions have issues. prefixing them with windows. allowed it to compile.
« Last Edit: October 17, 2017, 08:16:28 pm by snorkel »
***Snorkel***
If I forget, I always use the latest stable 32bit version of Lazarus and FPC. At the time of this signature that is Laz 3.0RC2 and FPC 3.2.2
OS: Windows 10 64 bit

snorkel

  • Hero Member
  • *****
  • Posts: 817
Re: Update short filename on a file?
« Reply #8 on: October 17, 2017, 10:01:44 pm »
Just in case anyone is following this, I did get it working :-)
It was fairly confusing as SetFileShortNamew does not work on the file itself, just folders.
so what you do is use createfile to get the handle to a folder and then call SetFileShortNameW
Code: Pascal  [Select][+][-]
  1.    if  HFileRes <> INVALID_HANDLE_VALUE then
  2.        if not SetFileShortNamew(HFileRes,pwidechar(shortfilename)) then     //SetFileShortNameW is in jwawinbase
  3.                MessageDlg('Set Short Path Error',SysErrorMessageUTF8(windows.GetLastError),mtError,[mbOK],0)  

You can set the shortname of a folder to anything as long as it's unique on the system.

So what I will do now is recursively loop through all the folders on the source location and if the folder has a shortname clone it on the new server using  SetFileShortNameW
***Snorkel***
If I forget, I always use the latest stable 32bit version of Lazarus and FPC. At the time of this signature that is Laz 3.0RC2 and FPC 3.2.2
OS: Windows 10 64 bit

ASerge

  • Hero Member
  • *****
  • Posts: 2222
Re: Update short filename on a file?
« Reply #9 on: October 18, 2017, 03:25:16 pm »
It seems late :(. OK, then here's a working sample :P
Code: Pascal  [Select][+][-]
  1. {$MODE OBJFPC}
  2. {$APPTYPE CONSOLE}
  3. program Project1;
  4.  
  5. uses jwaWinBase, Windows, SysUtils;
  6.  
  7. function SetPrivilge(Privilige: PWideChar; Enable: Boolean): Boolean;
  8. var
  9.   TokenHandle: THandle;
  10.   NewPriv: TTokenPrivileges;
  11. begin
  12.   Result := LookupPrivilegeValueW(nil, Privilige, @NewPriv.Privileges[0].Luid) and
  13.     OpenProcessToken(GetCurrentProcess, TOKEN_QUERY or TOKEN_ADJUST_PRIVILEGES, @TokenHandle);
  14.   if Result then
  15.   begin
  16.     NewPriv.PrivilegeCount := 1;
  17.     if Enable then
  18.       NewPriv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
  19.     else
  20.       NewPriv.Privileges[0].Attributes := 0;
  21.     Result := AdjustTokenPrivileges(TokenHandle, False, @NewPriv,
  22.       SizeOf(NewPriv), nil, nil) and (GetLastError = ERROR_SUCCESS);
  23.     CloseHandle(TokenHandle);
  24.   end;
  25. end;
  26.  
  27. function GetShortPath(const LongPath: UnicodeString): UnicodeString;
  28. var
  29.   Len: DWORD;
  30. begin
  31.   Len := GetShortPathNameW(PWideChar(LongPath), nil, 0);
  32.   SetLength(Result, Len);
  33.   Len := GetShortPathNameW(PWideChar(LongPath), PWideChar(Result), Len);
  34.   SetLength(Result, Len);
  35. end;
  36.  
  37. function SetShortName(const LongPath, ShortNameOnly: UnicodeString): Boolean;
  38. const
  39.   DELETE = $10000;
  40. var
  41.   HFile: THandle;
  42. begin
  43.   HFile := CreateFileW(PWideChar(LongPath), GENERIC_WRITE or DELETE, 0, nil,
  44.     OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
  45.   if HFile <> INVALID_HANDLE_VALUE then
  46.   begin
  47.     Result := SetFileShortNameW(HFile, PWideChar(ShortNameOnly));
  48.     CloseHandle(HFile);
  49.   end;
  50. end;
  51.  
  52. const
  53.   CFileName = 'VeryLongName.txt';
  54.   CShortName = 'SHORT.TXT';
  55. begin
  56.   if SetPrivilge(SE_RESTORE_NAME, True) then
  57.   begin
  58.     Writeln('Create new file ', CFileName);
  59.     FileClose(FileCreate(CFileName));
  60.     Writeln('Short name before: ', GetShortPath(CFileName));
  61.     Write('Change short name... ');
  62.     if SetShortName(CFileName, CShortName) then
  63.       Writeln('short name after: ', GetShortPath(CFileName))
  64.     else
  65.       Writeln('error: ', SysErrorMessage(GetLastError));
  66.     Writeln('Delete file ', CFileName);
  67.     DeleteFile(CFileName);
  68.     SetPrivilge(SE_RESTORE_NAME, False);
  69.   end
  70.   else
  71.     Writeln('Could not get SE_RESTORE_NAME privilege: ', SysErrorMessage(GetLastError));
  72.   Readln;
  73. end.

snorkel

  • Hero Member
  • *****
  • Posts: 817
Re: Update short filename on a file?
« Reply #10 on: October 23, 2017, 06:56:42 pm »
Made a nice GUI utility app to scan for files greater than 260 chars and the ability to clone the original short path name for a folder from one server to another given the same structure except for the server name.
Works great and saved many many hours of recopying the data to generate the filenames after 8.3 support was enabled on the new server.
***Snorkel***
If I forget, I always use the latest stable 32bit version of Lazarus and FPC. At the time of this signature that is Laz 3.0RC2 and FPC 3.2.2
OS: Windows 10 64 bit

breikers

  • Newbie
  • Posts: 1
Re: Update short filename on a file?
« Reply #11 on: December 19, 2018, 06:30:03 pm »
Hi, is there any way we could obtain that GUI tool ? We are having the same problems with a fileserver migration. Would be much appreciated

Regards

Jack

 

TinyPortal © 2005-2018