# Copyright (c) 2023 Yuki Kimoto
# MIT License
class Sys::IO::Windows {
version_from Sys;
use Sys::IO::Stat;
# This is a resource class
use Sys::Resource::Windows;
# Class Methods
native static method unlink : int ($pathname : string);
native static method rename : int ($oldpath : string, $newpath : string);
native static method symlink : int ($oldpath : string, $newpath : string);
native static method win_readlink : string ($path : string);
native static method realpath : string ($path : string, $resolved_path : mutable string);
native static method is_symlink : int ($path : string);
# Only used from Sys/IO/Stat.c and realpath method
static method _follow_symlinks_to : string ($path : string) {
# $path is absolute
unless ($path->[0] == '\\' || $path->[0] == '/' || (length $path >= 2 && $path->[1] == ':')) {
my $cwd = Sys->_getcwd;
$path = "$cwd/$path";
}
my $resolved_path = $path;
my $symlink_follow_limit = 63;
my $link_count = 0;
while (1) {
my $link_text = (string)undef;
eval { $link_text = &win_readlink($resolved_path); }
if ($@) {
last;
}
if ($link_count++ >= $symlink_follow_limit) {
die "Symbolic link nesting limit exceeded.";
}
if ($link_text->[0] == '\\' || $link_text->[0] == '/' || (length $link_text >= 2 && $link_text->[1] == ':')) {
# $link_text is absolute
$resolved_path = $link_text;
}
else {
my $last_sep_index = -1;
for (my $i = length $resolved_path - 1; $i >= 0; $i--) {
my $char = $resolved_path->[$i];
if ($char == '\\' || $char == '/') {
$last_sep_index = $i;
last;
}
}
unless ($last_sep_index >= 0) {
die "[Unpexpexted Erro]$link_text is not an absolute path.";
}
my $resolved_dir = Fn->substr($resolved_path, $last_sep_index + 1);
$resolved_path = "$resolved_dir/$link_text";
}
}
return $resolved_path;
}
}