diff --git a/Configure b/Configure
index 24366f6..368f7ad 100755
--- a/Configure
+++ b/Configure
@@ -8731,10 +8731,10 @@
 			dflt=libperl.$so
 			;;
 		cygwin*) # ld links now against the dll directly
-			majmin="cygperl5_${patchlevel}_${subversion}.${so}"
+			majmin="msys-perl5_${patchlevel}_${subversion}.${so}"
 			majonly=`echo $patchlevel $subversion |
 				$awk '{printf "%03d%03d", $1, $2}'`
-			majonly=cygperl5.$majonly.$so
+			majonly=msys-perl5.$majonly.$so
 			dflt=$majmin
 			;;
 		*)	# Try to guess based on whether libc has major.minor.
@@ -23651,7 +23651,7 @@
 BSDCOMPAT bsdi BSD_4_3 BSD_4_4 BSD_NET2 BSD_TIME BSD_TYPES bull
 byteorder byte_order
 c cadmus clang clipper CMU COFF COMPILER_VERSION concurrent
-convex cpu CRAY cray CRAYMPP ctix CX_UX CYGWIN
+convex cpu CRAY cray CRAYMPP ctix CX_UX MSYS CYGWIN
 DECC DGUX DGUX_SOURCE DJGPP dmert DOLPHIN DPX2 DSO Dynix DynixPTX
 ELF encore EPI EXTENSIONS
 FAVOR_BSD FILE_OFFSET_BITS FORTIFY_SOURCE FreeBSD
diff --git a/Cross/Makefile-cross-SH b/Cross/Makefile-cross-SH
index a774f4a..26d4d61 100644
--- a/Cross/Makefile-cross-SH
+++ b/Cross/Makefile-cross-SH
@@ -56,7 +56,7 @@
 			     -install_name \$(shrpdir)/\$@"
 		;;
 	cygwin*)
-		linklibperl="-lperl"
+		linklibperl="-L. -lperl"
 		;;
 	sunos*)
 		linklibperl="-lperl"
@@ -940,7 +940,7 @@
 	-rm -f perl.third lib*.so.perl.third perl.3log t/perl.third t/perl.3log
 	-rm -f perl.pixie lib*.so.perl.pixie lib*.so.Addrs
 	-rm -f perl.Addrs perl.Counts t/perl.Addrs t/perl.Counts *perl.xok
-	-rm -f cygwin.c libperl*.def libperl*.dll cygperl*.dll *.exe.stackdump
+	-rm -f cygwin.c libperl*.def libperl*.dll cygperl*.dll msys-perl*.dll *.exe.stackdump
 	-rm -f perl$(EXE_EXT) miniperl$(EXE_EXT) $(LIBPERL) libperl.*
 	-rm -f config.over
 
diff --git a/Makefile.SH b/Makefile.SH
index e2490da..547bd49 100755
--- a/Makefile.SH
+++ b/Makefile.SH
@@ -1360,7 +1360,7 @@ _mopup:
 	-rm -f perl.exp ext.libs $(generated_pods) uni.data $(mini_only_objs) pod/roffitall
 	-rm -f perl.export perl.dll perl.libexp perl.map perl.def
 	-rm -f *perl.xok
-	-rm -f cygwin.c libperl*.def libperl*.dll cygperl*.dll *.exe.stackdump
+	-rm -f cygwin.c libperl*.def libperl*.dll cygperl*.dll msys-perl*.dll *.exe.stackdump
 	-rm -f $(PERL_EXE) $(MINIPERL_EXE) $(LIBPERL) libperl.*
 	-rm -f config.arch config.over $(DTRACE_H)
 
@@ -1524,7 +1524,7 @@ case "$targethost" in
 '') $spitshell >>$Makefile <<'!NO!SUBS!'
 test_prep test-prep: test_prep_pre $(MINIPERL_EXE) $(unidatafiles) $(PERL_EXE) \
 	$(dynamic_ext) $(TEST_PERL_DLL) runtests $(generated_pods) common_build
-	cd t && (rm -f $(PERL_EXE); $(LNS) ../$(PERL_EXE) $(PERL_EXE))
+	cd t && (rm -f $(PERL_EXE) $(LIBPERL); $(LNS) ../$(PERL_EXE) $(PERL_EXE); $(LNS) ../$(LIBPERL) $(LIBPERL))
 
 !NO!SUBS!
 ;;
diff --git a/configpm b/configpm
index 94a4778..284e322 100755
--- a/configpm
+++ b/configpm
@@ -459,8 +459,8 @@ EOT
 
 my $osname = fetch_string({}, 'osname');
 my $from = $osname eq 'VMS' ? 'PERLSHR image' : 'binary (from libperl)';
-my $env_cygwin = $osname eq 'cygwin'
-    ? 'push @env, "CYGWIN=\"$ENV{CYGWIN}\"" if $ENV{CYGWIN};' . "\n" : "";
+my $env_cygwin = $osname eq 'cygwin'
+    ? 'push @env, "MSYS=\"$ENV{MSYS}\"" if $ENV{MSYS};' . "\n" : "";
 
 $heavy_txt .= sprintf <<'ENDOFBEG', $osname, $osname, $from, $osname, $env_cygwin;
 # This file was created by configpm when Perl was built. Any changes
diff --git a/cpan/IPC-SysV/t/ipcsysv.t b/cpan/IPC-SysV/t/ipcsysv.t
index 8bbea07..a1a0b4e 100644
--- a/cpan/IPC-SysV/t/ipcsysv.t
+++ b/cpan/IPC-SysV/t/ipcsysv.t
@@ -49,11 +49,11 @@
 
 EOM
 
-      diag(<<EOM) unless exists $ENV{CYGWIN} && $ENV{CYGWIN} eq 'server';
+      diag(<<EOM) unless exists $ENV{MSYS} && $ENV{MSYS} eq 'server';
 You also may have to set the CYGWIN environment variable
 to 'server' before running the test suite:
 
-  export CYGWIN=server
+  export MSYS=server
 
 EOM
     }
diff --git a/cpan/Win32/Makefile.PL b/cpan/Win32/Makefile.PL
index 90ad660..f11de75 100644
--- a/cpan/Win32/Makefile.PL
+++ b/cpan/Win32/Makefile.PL
@@ -22,7 +22,7 @@
 $param{NO_META} = 1 if eval "$ExtUtils::MakeMaker::VERSION" >= 6.10_03;
 
 if ($^O eq 'cygwin') {
-    $param{LIBS} = ['-L/lib/w32api -lole32 -lversion -luserenv -lnetapi32 -lwinhttp']
+    $param{LIBS} = ['-L/usr/lib/w32api -lole32 -lversion -luserenv -lnetapi32 -lwinhttp']
 }
 else {
     $param{LIBS} = ['-luserenv -lwinhttp']

diff --git a/cpan/Win32/t/Unicode.t b/cpan/Win32/t/Unicode.t
index fa05188..c0f854d 100644
--- a/cpan/Win32/t/Unicode.t
+++ b/cpan/Win32/t/Unicode.t
@@ -47,7 +47,7 @@
 cleanup();
 END { cleanup() }
 
-plan tests => 12;
+plan tests => 11;
 
 # Create Unicode directory
 Win32::CreateDirectory($dir8);
@@ -91,9 +91,11 @@
     $subdir = decode "UTF-8", Cygwin::posix_to_win_path($subdir, 1);
 }
 $subdir =~ s,/,\\,g;
-# Cygwin64 no longer returns an ANSI name
-skip($^O eq "cygwin", Win32::GetLongPathName($subdir), $long);
-
-# We can chdir() into the Unicode directory if we use the ANSI name
-ok(chdir(Win32::GetANSIPathName($dir)));
-ok(Win32::GetLongPathName(Win32::GetCwd()), $long);
+# 
+SKIP: {
+    skip("Cygwin64 no longer returns an ANSI name", 2) if $^O eq "cygwin";
+
+    # We can chdir() into the Unicode directory if we use the ANSI name
+    ok(chdir(Win32::GetANSIPathName($dir)));
+    ok(Win32::GetLongPathName(Win32::GetCwd()), $long);
+}
diff --git a/cpan/autodie/t/chown.t b/cpan/autodie/t/chown.t
index 90c4d3b..7d118d4 100644
--- a/cpan/autodie/t/chown.t
+++ b/cpan/autodie/t/chown.t
@@ -4,7 +4,7 @@ use Test::More;
 use constant NO_SUCH_FILE => "this_file_had_better_not_exist";
 use autodie;
 
-if ($^O eq 'MSWin32') {
+if ($^O eq 'MSWin32' or $^O eq 'cygwin') {
     plan skip_all => 'chown() seems to always succeed on Windows';
 }
 
diff --git a/cpan/autodie/t/version_tag.t b/cpan/autodie/t/version_tag.t
index 4860a49..54c9e79 100644
--- a/cpan/autodie/t/version_tag.t
+++ b/cpan/autodie/t/version_tag.t
@@ -63,7 +63,7 @@ is($@,"","chown wasn't supported in 2.13");
 
 SKIP: {
 
-    if ($^O eq "MSWin32") { skip("chown() on Windows always succeeds.", 1) }
+    if ($^O eq "MSWin32" or $^O eq 'cygwin') { skip("chown() on Windows always succeeds.", 1) }
 
     eval {
         use autodie;
diff --git a/dist/Net-Ping/t/450_service.t b/dist/Net-Ping/t/450_service.t
index 203d86b..9246a21 100644
--- a/dist/Net-Ping/t/450_service.t
+++ b/dist/Net-Ping/t/450_service.t
@@ -78,7 +78,7 @@ is($p->ping("127.0.0.1"), 1, 'first port is reachable');
 $p->{port_num} = $port2;
 
 {
-    local $TODO = "Believed not to work on $^O" if $^O =~ /^(?:MSWin32|os390)$/;
+    local $TODO = "Believed not to work on $^O" if $^O =~ /^(?:MSWin32|cygwin|os390)$/;
     is($p->ping("127.0.0.1"), 1, 'second port is reachable');
 }
 
@@ -133,7 +133,7 @@ SKIP: {
 
   {
     local $TODO = "Believed not to work on $^O"
-      if $^O =~ /^(?:MSWin32|os390)$/;
+      if $^O =~ /^(?:MSWin32|cygwin|os390)$/;
     is($p->ack(), '127.0.0.1', 'IP should be reachable');
   }
 }
diff --git a/ext/DynaLoader/DynaLoader_pm.PL b/ext/DynaLoader/DynaLoader_pm.PL
index 93a858a..c881f91 100644
--- a/ext/DynaLoader/DynaLoader_pm.PL
+++ b/ext/DynaLoader/DynaLoader_pm.PL
@@ -482,6 +482,7 @@
             push(@names,"$_.$dl_dlext")    unless m/\.$dl_dlext$/o;
             push(@names,"$_.$dl_so")     unless m/\.$dl_so$/o;
 	    <<$^O-eq-cygwin>>
+            push(@names,"msys-$_.$dl_so")  unless m:/:;
             push(@names,"cyg$_.$dl_so")  unless m:/:;
 	    <</$^O-eq-cygwin>>
             push(@names,"lib$_.$dl_so")  unless m:/:;
diff --git a/ext/NDBM_File/Makefile.PL b/ext/NDBM_File/Makefile.PL
index fe2cb40..85e6f30 100644
--- a/ext/NDBM_File/Makefile.PL
+++ b/ext/NDBM_File/Makefile.PL
@@ -1,7 +1,7 @@
 use ExtUtils::MakeMaker;
 WriteMakefile(
     NAME	=> 'NDBM_File',
-    LIBS => ["-L/usr/local/lib -lndbm", "-ldbm -lucb"],
+    LIBS => ["-lgdbm -lgdbm_compat"],
     XSPROTOARG => '-noprototypes', 		# XXX remove later?
     VERSION_FROM => 'NDBM_File.pm',
 );
diff --git a/ext/ODBM_File/Makefile.PL b/ext/ODBM_File/Makefile.PL
index 0ae31f9..76f8f4f 100644
--- a/ext/ODBM_File/Makefile.PL
+++ b/ext/ODBM_File/Makefile.PL
@@ -1,7 +1,7 @@
 use ExtUtils::MakeMaker;
 WriteMakefile(
     NAME	=> 'ODBM_File',
-    LIBS => ["-ldbm -lucb"],
+    LIBS => ["-lgdbm -lgdbm_compat"],
     XSPROTOARG => '-noprototypes', 		# XXX remove later?
     VERSION_FROM => 'ODBM_File.pm', 
 );
diff --git a/ext/POSIX/t/wrappers.t b/ext/POSIX/t/wrappers.t
index e41b319..b26b203 100644
--- a/ext/POSIX/t/wrappers.t
+++ b/ext/POSIX/t/wrappers.t
@@ -179,7 +179,9 @@ foreach ([undef, 0, 'chdir', NOT_HERE],
     my $func = do {no strict 'refs'; \&{"POSIX::$name"}};
 
  SKIP: {
+        skip("chown() does not work with MSYS2", 2) if $name eq 'chown' and $^O eq 'cygwin';
         skip("$name() is not available", 2) if $skip && !$Config{$skip};
+
 	$! = 0;
 	is(&$func(@args), $expect, $name);
 	isnt($!, '', "$name reported an error");
diff --git a/t/io/fs.t b/t/io/fs.t
index 9cda3e9..243cb38 100644
--- a/t/io/fs.t
+++ b/t/io/fs.t
@@ -59,7 +59,7 @@ my $needs_fh_reopen =
 $needs_fh_reopen = 1 if (defined &Win32::IsWin95 && Win32::IsWin95());
 
 my $skip_mode_checks =
-    $^O eq 'cygwin' && $ENV{CYGWIN} !~ /ntsec/;
+    $^O eq 'cygwin' && $ENV{MSYS} !~ /ntsec/;
 
 plan tests => 61;
 
@@ -183,7 +183,10 @@ SKIP: {
 SKIP: {
     skip "no fchmod", 7 unless ($Config{d_fchmod} || "") eq "define";
     ok(open(my $fh, "<", "a"), "open a");
-    is(chmod(0, $fh), 1, "fchmod");
+    SKIP: {
+        skip "no mode checks", 1 if $skip_mode_checks;
+        is(chmod(0, $fh), 1, "fchmod");
+    }
     $mode = (stat "a")[2];
     SKIP: {
         skip "no mode checks", 1 if $skip_mode_checks;
@@ -396,7 +399,7 @@ SKIP: {
 # check if rename() can be used to just change case of filename
 SKIP: {
     skip "Works in Cygwin only if check_case is set to relaxed", 1
-      if ($ENV{'CYGWIN'} && ($ENV{'CYGWIN'} =~ /check_case:(?:adjust|strict)/));
+      if ($ENV{'MSYS'} && ($ENV{'MSYS'} =~ /check_case:(?:adjust|strict)/));
 
     chdir "./$tmpdir";
     open(FH,'>x') || die "Can't create x";
diff --git a/t/io/pvbm.t b/t/io/pvbm.t
index 2affbac..630de14 100644
--- a/t/io/pvbm.t
+++ b/t/io/pvbm.t
@@ -67,7 +67,7 @@ sub PVBM () { 'foo' }
     ok (!eval { chmod 0600, \$pvbm }, 'chmod(PVBM ref) fails');
 
     SKIP: {
-        skip('chown() not implemented on Win32', 2) if $^O eq 'MSWin32';
+        skip('chown() not implemented on Win32', 2) if $^O eq 'MSWin32' or $^O eq 'cygwin';
         ok (!eval { chown 0, 0, $pvbm }, 'chown(PVBM) fails');
         ok (!eval { chown 0, 0, \$pvbm }, 'chown(PVBM ref) fails');
     }
diff --git a/t/lib/cygwin.t b/t/lib/cygwin.t
index ba86170..0d316f3 100644
--- a/t/lib/cygwin.t
+++ b/t/lib/cygwin.t
@@ -41,7 +41,7 @@ chdir($pwd);
 is(Cygwin::win_to_posix_path($winpath, 1), "/", "win to absolute posix path");
 
 my $mount = join '', `/usr/bin/mount`;
-$mount =~ m|on /usr/bin type .+ \((\w+)[,\)]|m;
+$mount =~ m|on (?:/usr)?/bin type .+ \((\w+)[,\)]|m;
 my $binmode = $1 =~ /binmode|binary/;
 is(Cygwin::is_binmount("/"),  $binmode ? 1 : '', "check / for binmount");
 
diff --git a/t/op/require_errors.t b/t/op/require_errors.t
index 637457b..5aa250b 100644
--- a/t/op/require_errors.t
+++ b/t/op/require_errors.t
@@ -173,6 +173,7 @@
 
 SKIP: {
     skip_if_miniperl("these modules may not be available to miniperl", 2);
+    skip "Can't test permissions meaningfully using MSYS2", 2 if $^O eq 'cygwin';
 
     push @INC, '../lib';
     require Cwd;
diff --git a/t/op/stat.t b/t/op/stat.t
index b391dd0..03c5484 100644
--- a/t/op/stat.t
+++ b/t/op/stat.t
@@ -47,7 +47,7 @@ my $Is_MPRAS   = $^O =~ /svr4/ && -f '/etc/.relid';
 my $Is_Android = $^O =~ /android/;
 my $Is_Dfly    = $^O eq 'dragonfly';
 
-my $Is_Dosish  = $Is_OS2 || $Is_MSWin32;
+my $Is_Dosish  = $Is_OS2 || $Is_MSWin32 || $^O eq 'cygwin';
 
 my $ufs_no_ctime = ($Is_Dfly || $Is_Darwin) && (() = `df -t ufs . 2>/dev/null`) == 2;
 
@@ -193,7 +193,7 @@ ok(-s $tmpfile,     '   and -s');
 ok( chmod(0000, $tmpfile),     'chmod 0000' );
 
 SKIP: {
-    skip "-r, -w and -x have different meanings on VMS", 3 if $Is_VMS;
+    skip "-r, -w and -x have different meanings on VMS/DOS", 3 if $Is_VMS or $Is_Dosish;
 
     SKIP: {
         # Going to try to switch away from root.  Might not work.
@@ -564,7 +564,8 @@ SKIP: {
 	skip "Can't check if admin user in miniperl", 1
 	  if $^O =~ /^(cygwin|MSWin32|msys)$/ && is_miniperl();
 	skip "Readable by group/other means readable by me on $^O", 1 if $^O eq 'VMS'
-          or ($^O =~ /^(cygwin|MSWin32|msys)$/ and Win32::IsAdminUser());
+          or ($^O =~ /^(cygwin|MSWin32)$/ and Win32::IsAdminUser());
+	skip "Unix permissions are meaningless with MSYS2", 1 if $^O eq 'cygwin';
 	lstat($tmpfile);
 	-T _;
 	ok(eval { lstat _ },
diff --git a/t/porting/exec-bit.t b/t/porting/exec-bit.t
index 3e80f84..38174a4 100644
--- a/t/porting/exec-bit.t
+++ b/t/porting/exec-bit.t
@@ -18,7 +18,7 @@ sub has_shebang {
 }
 
 require './test.pl';
-if ( $^O eq "MSWin32" ) {
+if ( $^O eq "MSWin32" or $^O eq 'cygwin' ) {
   skip_all( "-x on MSWin32 only indicates file has executable suffix. Try Cygwin?" );
 }
 
diff --git a/t/porting/globvar.t b/t/porting/globvar.t
index 3e6d630..b4a9941 100644
--- a/t/porting/globvar.t
+++ b/t/porting/globvar.t
@@ -15,7 +15,7 @@ my %skip = map { ("PL_$_", 1) }
     qw(
 	  DBcv bitcount cshname generation lastgotoprobe
 	  mod_latin1_uc modcount no_symref_sv uudmap
-	  watchaddr watchok warn_uninit_sv hash_chars
+	  watchaddr watchok warn_uninit_sv hash_chars current_context
      );
 
 $skip{PL_hash_rand_bits}= $skip{PL_hash_rand_bits_enabled}= 1; # we can be compiled without these, so skip testing them
diff --git a/utils/perlbug.PL b/utils/perlbug.PL
index 4715e9d..5da0af0 100644
--- a/utils/perlbug.PL
+++ b/utils/perlbug.PL
@@ -76,7 +76,7 @@ BEGIN {
     eval { require Mail::Send;};
     $::HaveSend = ($@ eq "");
     eval { require Mail::Util; } ;
-    $::HaveUtil = ($@ eq "");
+    $::HaveUtil = (!$ENV{PERL_BUILD_PACKAGING} and $@ eq "");
     # use secure tempfiles wherever possible
     eval { require File::Temp; };
     $::HaveTemp = ($@ eq "");
@@ -727,7 +727,7 @@ EOF
     my @env =
         qw(PATH LD_LIBRARY_PATH LANG PERL_BADLANG SHELL HOME LOGDIR LANGUAGE);
     push @env, $Config{ldlibpthname} if $Config{ldlibpthname} ne '';
-    push @env, grep /^(?:PERL|LC_|LANG|CYGWIN)/, keys %ENV;
+    push @env, grep /^(?:PERL|LC_|LANG|CYGWIN|MSYS)/, keys %ENV;
     my %env;
     @env{@env} = @env;
     for my $env (sort keys %env) {
--- perl-5.38.2/hints/cygwin.sh.orig	2025-02-02 21:15:37.363852600 +0100
+++ perl-5.38.2/hints/cygwin.sh	2025-02-02 21:15:58.250835500 +0100
@@ -27,7 +27,7 @@
 libswanted=`echo " $libswanted " | sed -e 's/ util / /g'`
 ignore_versioned_solibs='y'
 usenm='no'
-libc='/usr/lib/libcygwin.a'
+libc='/usr/lib/libmsys-2.0.a'
 loclibpth=' '
 glibpth=' '
 plibpth=' '
@@ -38,9 +38,9 @@
 test -z "$optimize" && optimize='-O3'
 man3ext='3pm'
 test -z "$use64bitint" && use64bitint='define'
-test -z "$useithreads" && useithreads='define'
+test -z "$usethreads" && usethreads='define'
 test -z "$usemymalloc" && usemymalloc='undef'
-ccflags="$ccflags -U__STRICT_ANSI__ -D_GNU_SOURCE"
+ccflags="$ccflags -DPERL_USE_SAFE_PUTENV -U__STRICT_ANSI__ -D_GNU_SOURCE"
 # - otherwise i686-cygwin
 archname='cygwin'
 
@@ -96,12 +96,3 @@
 #ldflags="$ldflags -s"
 #ccdlflags="$ccdlflags -s"
 #lddlflags="$lddlflags -s"
-
-# Seems that exporting _Thread_local doesn't work on cygwin. This 6 year old
-# gcc bug suggests that maybe the problem really is binutils, but either way
-# it still doesn't work, despite our probes looking good:
-# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64697
-d_thread_local=undef
-
-# Broken: https://sourceware.org/pipermail/cygwin/2022-August/252043.html */
-d_newlocale=undef
