-
-
Couldn't load subscription status.
- Fork 1.7k
Description
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
pathwith"\\\\?\\#{File.expand_path(path)}"at the Win32 API boundary; - Set the
Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabledregistry key to 1 and link a manifest containing thelongPathAwareelement 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
endThe 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
Labels
Type
Projects
Status