Skip to content

Windows long path support #13420

@HertzDevil

Description

@HertzDevil

By default, filenames on Windows cannot be longer than 256 characters, excluding the drive name. There are two ways to overcome this since Windows 10 version 1607:

  • Replace path with "\\\\?\\#{File.expand_path(path)}" at the Win32 API boundary;
  • Set the Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled registry key to 1 and link a manifest containing the longPathAware element into every program.

MSVC can only embed one manifest into an executable, so if the user provides their own manifest, they have to merge their own manifest with the one generated by Crystal, or Crystal's CLI has to support manifests specifically. There is also no guarantee that the registry key can be set by a user. Therefore, the first option is probably more suitable for the standard library, as all we need to do is trying the extended name if the original name fails:

module Crystal::System::Dir
  def self.create(path : String, mode : Int32) : Nil
    if LibC._wmkdir(System.to_wstr(path)) == -1
      if LibC._wmkdir(System.to_wstr("\\\\?\\#{File.expand_path(path)}")) == -1
        raise ::File::Error.from_errno("Unable to create directory", file: path)
      end
    end
  end
end

The second call can most likely be skipped too if path already begins with something like \\.\. (The standard library does not publicly state that those names are usable in the file APIs, but in most cases those String paths are passed unmodified all the way to the Win32 API functions.)

Although not mentioned in the linked article, it seems C runtime functions also support long paths in this manner. It might be better to switch to their Win32 equivalents whenever possible though (CreateDirectoryW in this example).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions