In perl.git, the branch blead has been updated

<http://perl5.git.perl.org/perl.git/commitdiff/269a3b2e76d9e7b398d9faa62b30dc6d93dd9476?hp=ac1ba09e8362c54848dc27d3484a5882c4b28f43>

- Log -----------------------------------------------------------------
commit 269a3b2e76d9e7b398d9faa62b30dc6d93dd9476
Merge: ac1ba09e83 b416949bcc
Author: Tony Cook <t...@develop-help.com>
Date:   Mon Sep 18 11:18:55 2017 +1000

    (127663) fix some portability issues with the new in-place edit
    
    - renameat() is present but broken for absolute paths on FreeBSD 11,
      add a workaround.
      https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=222258
    
    - the new implementation uses linkat() but the availability checks
      in doio.c and the tests didn't check for it.
-----------------------------------------------------------------------

Summary of changes:
 doio.c           | 31 ++++++++++++++++++++++++++++---
 t/run/switches.t | 17 ++++++++++++++++-
 2 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/doio.c b/doio.c
index 8c08455eda..7b6c43531b 100644
--- a/doio.c
+++ b/doio.c
@@ -863,7 +863,8 @@ S_openindirtemp(pTHX_ GV *gv, SV *orig_name, SV 
*temp_out_name) {
 }
 
 #if defined(HAS_UNLINKAT) && defined(HAS_RENAMEAT) && defined(HAS_FCHMODAT) && 
\
-    (defined(HAS_DIRFD) || defined(HAS_DIR_DD_FD)) && 
!defined(NO_USE_ATFUNCTIONS)
+    (defined(HAS_DIRFD) || defined(HAS_DIR_DD_FD)) && 
!defined(NO_USE_ATFUNCTIONS) && \
+    defined(HAS_LINKAT)
 #  define ARGV_USE_ATFUNCTIONS
 #endif
 
@@ -1191,6 +1192,30 @@ Perl_nextargv(pTHX_ GV *gv, bool nomagicopen)
     return NULL;
 }
 
+#ifdef ARGV_USE_ATFUNCTIONS
+#  if defined(__FreeBSD__)
+
+/* FreeBSD 11 renameat() mis-behaves strangely with absolute paths in cases 
where the
+ * equivalent rename() succeeds
+ */
+static int
+S_my_renameat(int olddfd, const char *oldpath, int newdfd, const char 
*newpath) {
+    /* this is intended only for use in Perl_do_close() */
+    assert(olddfd == newdfd);
+    assert(PERL_FILE_IS_ABSOLUTE(oldpath) == PERL_FILE_IS_ABSOLUTE(newpath));
+    if (PERL_FILE_IS_ABSOLUTE(oldpath)) {
+        return PerlLIO_rename(oldpath, newpath);
+    }
+    else {
+        return renameat(olddfd, oldpath, newdfd, newpath);
+    }
+}
+
+#  else
+#    define S_my_renameat(dh1, pv1, dh2, pv2) renameat((dh1), (pv1), (dh2), 
(pv2))
+#  endif /* if defined(__FreeBSD__) */
+#endif
+
 /* explicit renamed to avoid C++ conflict    -- kja */
 bool
 Perl_do_close(pTHX_ GV *gv, bool not_implicit)
@@ -1320,7 +1345,7 @@ Perl_do_close(pTHX_ GV *gv, bool not_implicit)
 #ifdef HAS_RENAME
                     if (
 #  ifdef ARGV_USE_ATFUNCTIONS
-                        renameat(dfd, orig_pv, dfd, SvPVX(*back_psv)) < 0
+                        S_my_renameat(dfd, orig_pv, dfd, SvPVX(*back_psv)) < 0
 #  else
                         PerlLIO_rename(orig_pv, SvPVX(*back_psv)) < 0
 #  endif
@@ -1360,7 +1385,7 @@ Perl_do_close(pTHX_ GV *gv, bool not_implicit)
             if (
 #ifdef HAS_RENAME
 #  ifdef ARGV_USE_ATFUNCTIONS
-                renameat(dfd, SvPVX(*temp_psv), dfd, orig_pv) < 0
+               S_my_renameat(dfd, SvPVX(*temp_psv), dfd, orig_pv) < 0
 #  else
                 PerlLIO_rename(SvPVX(*temp_psv), orig_pv) < 0
 #  endif
diff --git a/t/run/switches.t b/t/run/switches.t
index 6725f8fd35..ffc8fabc0d 100644
--- a/t/run/switches.t
+++ b/t/run/switches.t
@@ -12,7 +12,7 @@ BEGIN {
 
 BEGIN { require "./test.pl";  require "./loc_tools.pl"; }
 
-plan(tests => 136);
+plan(tests => 137);
 
 use Config;
 
@@ -468,6 +468,7 @@ __EOF__
         skip "Not enough *at functions", 3
           unless $Config{d_unlinkat} && $Config{d_renameat} && 
$Config{d_fchmodat}
               && ($Config{d_dirfd} || $Config{d_dir_dd_fd})
+              && $Config{d_linkat}
               && $Config{ccflags} !~ /-DNO_USE_ATFUNCTIONS\b/;
         fresh_perl_is(<<'CODE', "ok\n", { },
 @ARGV = ("inplacetmp/foo");
@@ -552,6 +553,19 @@ CODE
         rmdir "$work.bak" or die "Cannot remove mask backup directory: $!";
     }
 
+    {
+        # test with absolute paths, this was failing on FreeBSD 11ish due
+        # to a bug in renameat()
+        my $abs_work = File::Spec->rel2abs($work);
+        fresh_perl_is(<<'CODE', "",
+while (<>) {
+  print;
+}
+CODE
+                      { stderr => 1, args => [ $abs_work ], switches => [ "-i" 
] },
+                      "abs paths");
+    }
+
     # we now use temp files for in-place editing, make sure we didn't leave
     # any behind in the above test
     opendir my $d, "inplacetmp" or die "Cannot opendir inplacetmp: $!";
@@ -594,6 +608,7 @@ CODE
         skip "Testing without *at functions", 1
           if $Config{d_unlinkat} && $Config{d_renameat} && $Config{d_fchmodat}
               && ($Config{d_dirfd} || $Config{d_dir_dd_fd})
+              && $Config{d_linkat}
               && $Config{ccflags} !~ /-DNO_USE_ATFUNCTIONS\b/;
         fresh_perl_like(<<'CODE', qr/^Cannot complete in-place edit of 
inplacetmp\/foo: .* - line 5, <> line \d+\./, { },
 @ARGV = ("inplacetmp/foo");

--
Perl5 Master Repository

Reply via email to