@@ -576,12 +576,11 @@ absl::StatusOr<std::vector<FileName>> ListDirectory(const FileName& dir) {
576576#endif 
577577
578578#ifdef  _WIN32
579- static  absl::Status CopyTreeWindows (const  std::wstring& from,
580-                                     const  std::wstring& to) {
581-   if  (!::CreateDirectoryExW (Pointer (from), Pointer (to), nullptr )) {
579+ static  absl::Status CopyTreeWindows (const  FileName& from, const  FileName& to) {
580+   if  (!::CreateDirectoryExW (from.pointer (), to.pointer (), nullptr )) {
582581    return  WindowsStatus (" CreateDirectoryExW" nullptr );
583582  }
584-   const  std::wstring pattern = from + L" \\ *" 
583+   const  std::wstring pattern = from. string ()  + L" \\ *" 
585584  WIN32_FIND_DATAW data;
586585  const  HANDLE handle = ::FindFirstFileW (Pointer (pattern), &data);
587586  if  (handle == INVALID_HANDLE_VALUE) {
@@ -593,18 +592,20 @@ static absl::Status CopyTreeWindows(const std::wstring& from,
593592    if  (!::FindClose (handle)) LOG (ERROR) << WindowsStatus (" FindClose" 
594593  };
595594  do  {
596-     const  std::wstring  name = data.cFileName ;
595+     const  std::wstring_view  name = data.cFileName ;
597596    if  (name == L" ." L" .." continue ;
598-     const  std::wstring from_entry = from + L' \\ ' 
599-     const  std::wstring to_entry = to + L' \\ ' 
597+     const  absl::StatusOr<FileName> from_entry = from.Child (name);
598+     if  (!from_entry.ok ()) return  from_entry.status ();
599+     const  absl::StatusOr<FileName> to_entry = to.Child (name);
600+     if  (!to_entry.ok ()) return  to_entry.status ();
600601    if  (data.dwFileAttributes  & FILE_ATTRIBUTE_DIRECTORY) {
601-       const  absl::Status status = CopyTreeWindows (from_entry, to_entry);
602+       const  absl::Status status = CopyTreeWindows (* from_entry, * to_entry);
602603      if  (!status.ok ()) return  status;
603604    } else  {
604605      constexpr  DWORD flags = COPY_FILE_FAIL_IF_EXISTS | COPY_FILE_COPY_SYMLINK;
605-       if  (!::CopyFileExW (Pointer ( from_entry), Pointer ( to_entry), nullptr ,
606+       if  (!::CopyFileExW (from_entry-> pointer ( ), to_entry-> pointer ( ), nullptr ,
606607                         nullptr , nullptr , flags)) {
607-         return  WindowsStatus (" CopyFileExW" nullptr ,
608+         return  WindowsStatus (" CopyFileExW" * from_entry, * to_entry, nullptr ,
608609                             nullptr , nullptr , absl::Hex (flags));
609610      }
610611    }
@@ -618,16 +619,16 @@ static absl::Status CopyTreeWindows(const std::wstring& from,
618619
619620#ifdef  RULES_ELISP_COPY_TREE_POSIX
620621static  absl::Status CopyFilePosix (const  int  from_parent, const  int  to_parent,
621-                                   const  std::string & name,
622+                                   const  FileName & name,
622623                                  const  struct  stat & from_stat) {
623-   CHECK (! name.empty () );
624-   CHECK_NE (name, " ." 
625-   CHECK_NE (name,  " .. " ); 
626-   CHECK_EQ (name. find ( ' / ' ), name. npos )  << " invalid name " 
624+   CHECK_NE ( name.string (),  " . " 
625+   CHECK_NE (name. string () , " . ." 
626+   CHECK_EQ (name. string (). find ( ' / ' ), name. string (). npos ) 
627+        << " invalid name " 
627628  CHECK (S_ISREG (from_stat.st_mode )) << " file " "  is not regular" 
628629
629630  constexpr  int  from_flags = O_RDONLY | O_CLOEXEC | O_NOCTTY | O_NOFOLLOW;
630-   const  int  from_fd = openat (from_parent, Pointer ( name), from_flags);
631+   const  int  from_fd = openat (from_parent, name. pointer ( ), from_flags);
631632  if  (from_fd < 0 ) {
632633    return  ErrnoStatus (" openat" absl::Hex (from_flags));
633634  }
@@ -638,7 +639,7 @@ static absl::Status CopyFilePosix(const int from_parent, const int to_parent,
638639  const  mode_t  mode = from_stat.st_mode ;
639640  constexpr  int  to_flags =
640641      O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC | O_NOCTTY | O_NOFOLLOW;
641-   const  int  to_fd = openat (to_parent, Pointer ( name), to_flags, mode);
642+   const  int  to_fd = openat (to_parent, name. pointer ( ), to_flags, mode);
642643  if  (to_fd < 0 ) {
643644    return  ErrnoStatus (" openat" Oct (mode));
644645  }
@@ -664,7 +665,7 @@ static absl::Status CopyFilePosix(const int from_parent, const int to_parent,
664665      if  (written == 0 ) {
665666        //  Prevent infinite loop.
666667        return  absl::DataLossError (absl::StrFormat (
667-             " Cannot write %d bytes to %s " size (), name));
668+             " Cannot write %d bytes to %v " size (), name));
668669      }
669670      remaining.remove_prefix (
670671          CastNumber<std::string_view::size_type>(written).value ());
@@ -681,25 +682,25 @@ static absl::Status CopyFilePosix(const int from_parent, const int to_parent,
681682}
682683
683684static  absl::Status CopyTreePosix (const  int  from_parent,
684-                                   const  std::string & from_name,
685+                                   const  FileName & from_name,
685686                                  std::optional<struct  stat > from_stat,
686687                                  const  int  to_parent,
687-                                   const  std::string & to_name) {
688-   CHECK (! from_name.empty () );
689-   CHECK_NE (from_name, " ." 
690-   CHECK_NE (from_name,  " .. " ); 
691-   CHECK (from_parent == AT_FDCWD ||  from_name.find (' /' npos )
688+                                   const  FileName & to_name) {
689+   CHECK_NE ( from_name.string (),  " . " 
690+   CHECK_NE (from_name. string () , " . ." 
691+   CHECK (from_parent == AT_FDCWD || 
692+          from_name.string (). find (' /' . string () .npos )
692693      << " invalid source name " 
693694
694-   CHECK (! to_name.empty () );
695-   CHECK_NE (to_name, " ." 
696-   CHECK_NE (to_name,  " .. " ); 
697-   CHECK (to_parent == AT_FDCWD ||  to_name.find (' /' npos )
695+   CHECK_NE ( to_name.string (),  " . " 
696+   CHECK_NE (to_name. string () , " . ." 
697+   CHECK (to_parent == AT_FDCWD || 
698+          to_name.string (). find (' /' . string () .npos )
698699      << " invalid target name " 
699700
700701  const  int  from_flags =
701702      O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC | O_NOCTTY;
702-   const  int  from_fd = openat (from_parent, Pointer ( from_name), from_flags);
703+   const  int  from_fd = openat (from_parent, from_name. pointer ( ), from_flags);
703704  if  (from_fd < 0 ) {
704705    return  ErrnoStatus (" openat" absl::Hex (from_flags));
705706  }
@@ -714,7 +715,7 @@ static absl::Status CopyTreePosix(const int from_parent,
714715    if  (fstat (from_fd, &buffer) != 0 ) return  ErrnoStatus (" fstat" 
715716    if  (!S_ISDIR (buffer.st_mode )) {
716717      return  absl::FailedPreconditionError (
717-           absl::StrFormat (" Source %s  is not a directory" 
718+           absl::StrFormat (" Source %v  is not a directory" 
718719    }
719720    from_stat = buffer;
720721  }
@@ -729,12 +730,12 @@ static absl::Status CopyTreePosix(const int from_parent,
729730  };
730731
731732  const  mode_t  mode = from_stat->st_mode  | S_IWUSR;
732-   const  int  result = mkdirat (to_parent, Pointer ( to_name), mode);
733+   const  int  result = mkdirat (to_parent, to_name. pointer ( ), mode);
733734  if  (result != 0 ) return  ErrnoStatus (" mkdirat" Oct (mode));
734735
735736  constexpr  int  to_flags =
736737      O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC | O_NOCTTY;
737-   const  int  to_fd = openat (to_parent, Pointer ( to_name), to_flags);
738+   const  int  to_fd = openat (to_parent, to_name. pointer ( ), to_flags);
738739  if  (to_fd < 0 ) {
739740    return  ErrnoStatus (" openat" absl::Hex (to_flags));
740741  }
@@ -749,8 +750,10 @@ static absl::Status CopyTreePosix(const int from_parent,
749750      if  (errno != 0 ) return  ErrnoStatus (" readdir" 
750751      break ;
751752    }
752-     const  std::string  name = entry->d_name ;
753+     const  std::string_view  name = entry->d_name ;
753754    if  (name == " ." " .." continue ;
755+     const  absl::StatusOr<FileName> file = FileName::FromString (name);
756+     if  (!file.ok ()) return  file.status ();
754757
755758    struct  stat  buffer;
756759    constexpr  int  stat_flags = AT_SYMLINK_NOFOLLOW;
@@ -761,10 +764,10 @@ static absl::Status CopyTreePosix(const int from_parent,
761764    const  mode_t  mode = buffer.st_mode ;
762765    if  (S_ISDIR (mode)) {
763766      const  absl::Status status =
764-           CopyTreePosix (from_fd, name , buffer, to_fd, name );
767+           CopyTreePosix (from_fd, *file , buffer, to_fd, *file );
765768      if  (!status.ok ()) return  status;
766769    } else  if  (S_ISREG (mode)) {
767-       const  absl::Status status = CopyFilePosix (from_fd, to_fd, name , buffer);
770+       const  absl::Status status = CopyFilePosix (from_fd, to_fd, *file , buffer);
768771      if  (!status.ok ()) return  status;
769772    } else  {
770773      return  absl::FailedPreconditionError (absl::StrFormat (
@@ -780,78 +783,56 @@ static absl::Status CopyTreePosix(const int from_parent,
780783}
781784#endif 
782785
783- absl::Status CopyTree (NativeStringView from, NativeStringView to) {
784-   if  (from.empty ()) {
785-     return  absl::InvalidArgumentError (" Empty source directory name" 
786-   }
787-   if  (ContainsNull (from)) {
788-     return  absl::InvalidArgumentError (absl::StrFormat (
789-         " Source directory name %s contains null character" 
790-   }
791-   if  (to.empty ()) {
792-     return  absl::InvalidArgumentError (" Empty destination directory name" 
793-   }
794-   if  (ContainsNull (to)) {
795-     return  absl::InvalidArgumentError (absl::StrFormat (
796-         " Destination directory name %s contains null character" 
797-   }
798- 
786+ absl::Status CopyTree (const  FileName& from, const  FileName& to) {
799787#if  defined _WIN32
800-   const  absl::StatusOr<FileName> from_name = FileName::FromString (from);
801-   if  (!from_name.ok ()) return  from_name.status ();
802-   const  absl::StatusOr<FileName> from_abs = from_name->MakeAbsolute ();
788+   const  absl::StatusOr<FileName> from_abs = from.MakeAbsolute ();
803789  if  (!from_abs.ok ()) return  from_abs.status ();
804790  if  (from_abs->string ().length () < 4 ) {
805791    return  absl::InvalidArgumentError (
806792        absl::StrFormat (" Cannot copy drive %v" 
807793  }
808-   const  absl::StatusOr<FileName> to_name = FileName::FromString (to);
809-   if  (!to_name.ok ()) return  to_name.status ();
810-   const  absl::StatusOr<FileName> to_abs = to_name->MakeAbsolute ();
794+   const  absl::StatusOr<FileName> to_abs = to.MakeAbsolute ();
811795  if  (!to_abs.ok ()) return  to_abs.status ();
812796  if  (to_abs->string ().length () < 4 ) {
813797    return  absl::AlreadyExistsError (
814798        absl::StrFormat (" Cannot copy over drive %v" 
815799  }
816-   return  CopyTreeWindows (from_abs-> string (),  to_abs-> string () );
800+   return  CopyTreeWindows (* from_abs, * to_abs);
817801#elif  defined __APPLE__
802+   std::string from_str = from.string ();
818803  //  The behavior of copyfile changes if the source directory name ends in a
819804  //  slash, see the man page copyfile(3).  We need to remove trailing slashes to
820805  //  get the expected behavior.
821-   const  std::string_view::size_type i = from.find_last_not_of (' /' 
822-   from.remove_suffix (from.size () - (i == from.npos  ? 0  : i + 1 ));
823-   if  (from.empty ()) {
806+   while  (from_str.back () == ' /' pop_back ();
807+   if  (from_str.empty ()) {
824808    //  If the source directory name is empty, it has consisted only of slashes.
825809    return  absl::InvalidArgumentError (" Cannot copy from root directory" 
826810  }
827-   const  std::string from_str (from);
828-   const  std::string to_str (to);
829811  //  The behavior of copyfile changes if the destination directory already
830812  //  exists, see the man page copyfile(3).
831813  struct  stat  buffer;
832-   if  (lstat (Pointer (to_str ), &buffer) == 0 ) {
814+   if  (lstat (to. pointer ( ), &buffer) == 0 ) {
833815    return  absl::AlreadyExistsError (
834-         absl::StrFormat (" Destination directory %s  already exists" to_str ));
816+         absl::StrFormat (" Destination directory %v  already exists" to ));
835817  }
836-   if  (errno != ENOENT) return  ErrnoStatus (" lstat" to_str );
818+   if  (errno != ENOENT) return  ErrnoStatus (" lstat" to );
837819  constexpr  copyfile_flags_t  flags = COPYFILE_ALL | COPYFILE_RECURSIVE |
838820                                     COPYFILE_EXCL | COPYFILE_NOFOLLOW |
839821                                     COPYFILE_CLONE | COPYFILE_DATA_SPARSE;
840-   if  (copyfile (Pointer (from_str), Pointer (to_str ), nullptr , flags) != 0 ) {
841-     return  ErrnoStatus (" copyfile" to_str , nullptr , absl::Hex (flags));
822+   if  (copyfile (Pointer (from_str), to. pointer ( ), nullptr , flags) != 0 ) {
823+     return  ErrnoStatus (" copyfile" to , nullptr , absl::Hex (flags));
842824  }
843825  return  absl::OkStatus ();
844826#elif  defined RULES_ELISP_COPY_TREE_POSIX
845-   if  (from.find_first_not_of (' /' npos ) {
827+   if  (from.string (). find_first_not_of (' /' . string () .npos ) {
846828    return  absl::InvalidArgumentError (
847-         absl::StrFormat (" Cannot copy from root directory %s " 
829+         absl::StrFormat (" Cannot copy from root directory %v " 
848830  }
849-   if  (to.find_first_not_of (' /' npos ) {
831+   if  (to.string (). find_first_not_of (' /' . string () .npos ) {
850832    return  absl::AlreadyExistsError (
851-         absl::StrFormat (" Cannot overwrite root directory %s " 
833+         absl::StrFormat (" Cannot overwrite root directory %v " 
852834  }
853-   return  CopyTreePosix (AT_FDCWD, std::string (from), std::nullopt , AT_FDCWD,
854-                        std::string (to));
835+   return  CopyTreePosix (AT_FDCWD, from, std::nullopt , AT_FDCWD, to);
855836#else 
856837#  error  CopyTree not implemented on this system
857838#endif 
0 commit comments