@@ -284,12 +284,14 @@ static NativeChar* absl_nonnull Pointer(
284284  return  string.data ();
285285}
286286
287+ #ifdef  _WIN32
287288static  const  NativeChar* absl_nonnull Pointer (
288289    const  NativeString& string ABSL_ATTRIBUTE_LIFETIME_BOUND) {
289290  CHECK (!ContainsNull (string))
290291      << absl::StrFormat (" %s contains null character" 
291292  return  string.data ();
292293}
294+ #endif 
293295
294296#ifndef  _WIN32
295297static  std::vector<char * absl_nullable> Pointers (
@@ -622,12 +624,11 @@ absl::StatusOr<std::vector<FileName>> ListDirectory(const FileName& dir) {
622624#endif 
623625
624626#ifdef  _WIN32
625- static  absl::Status CopyTreeWindows (const  std::wstring& from,
626-                                     const  std::wstring& to) {
627-   if  (!::CreateDirectoryExW (Pointer (from), Pointer (to), nullptr )) {
627+ static  absl::Status CopyTreeWindows (const  FileName& from, const  FileName& to) {
628+   if  (!::CreateDirectoryExW (from.pointer (), to.pointer (), nullptr )) {
628629    return  WindowsStatus (" CreateDirectoryExW" nullptr );
629630  }
630-   const  std::wstring pattern = from + L" \\ *" 
631+   const  std::wstring pattern = from. string ()  + L" \\ *" 
631632  WIN32_FIND_DATAW data;
632633  const  HANDLE handle = ::FindFirstFileW (Pointer (pattern), &data);
633634  if  (handle == INVALID_HANDLE_VALUE) {
@@ -639,18 +640,20 @@ static absl::Status CopyTreeWindows(const std::wstring& from,
639640    if  (!::FindClose (handle)) LOG (ERROR) << WindowsStatus (" FindClose" 
640641  };
641642  do  {
642-     const  std::wstring  name = data.cFileName ;
643+     const  std::wstring_view  name = data.cFileName ;
643644    if  (name == L" ." L" .." continue ;
644-     const  std::wstring from_entry = from + L' \\ ' 
645-     const  std::wstring to_entry = to + L' \\ ' 
645+     const  absl::StatusOr<FileName> from_entry = from.Child (name);
646+     if  (!from_entry.ok ()) return  from_entry.status ();
647+     const  absl::StatusOr<FileName> to_entry = to.Child (name);
648+     if  (!to_entry.ok ()) return  to_entry.status ();
646649    if  (data.dwFileAttributes  & FILE_ATTRIBUTE_DIRECTORY) {
647-       const  absl::Status status = CopyTreeWindows (from_entry, to_entry);
650+       const  absl::Status status = CopyTreeWindows (* from_entry, * to_entry);
648651      if  (!status.ok ()) return  status;
649652    } else  {
650653      constexpr  DWORD flags = COPY_FILE_FAIL_IF_EXISTS | COPY_FILE_COPY_SYMLINK;
651-       if  (!::CopyFileExW (Pointer ( from_entry), Pointer ( to_entry), nullptr ,
654+       if  (!::CopyFileExW (from_entry-> pointer ( ), to_entry-> pointer ( ), nullptr ,
652655                         nullptr , nullptr , flags)) {
653-         return  WindowsStatus (" CopyFileExW" nullptr ,
656+         return  WindowsStatus (" CopyFileExW" * from_entry, * to_entry, nullptr ,
654657                             nullptr , nullptr , absl::Hex (flags));
655658      }
656659    }
@@ -664,16 +667,16 @@ static absl::Status CopyTreeWindows(const std::wstring& from,
664667
665668#ifdef  RULES_ELISP_COPY_TREE_POSIX
666669static  absl::Status CopyFilePosix (const  int  from_parent, const  int  to_parent,
667-                                   const  std::string & name,
670+                                   const  FileName & name,
668671                                  const  struct  stat & from_stat) {
669-   CHECK (! name.empty () );
670-   CHECK_NE (name, " ." 
671-   CHECK_NE (name,  " .. " ); 
672-   CHECK_EQ (name. find ( ' / ' ), name. npos )  << " invalid name " 
672+   CHECK_NE ( name.string (),  " . " 
673+   CHECK_NE (name. string () , " . ." 
674+   CHECK_EQ (name. string (). find ( ' / ' ), name. string (). npos ) 
675+        << " invalid name " 
673676  CHECK (S_ISREG (from_stat.st_mode )) << " file " "  is not regular" 
674677
675678  constexpr  int  from_flags = O_RDONLY | O_CLOEXEC | O_NOCTTY | O_NOFOLLOW;
676-   const  int  from_fd = openat (from_parent, Pointer ( name), from_flags);
679+   const  int  from_fd = openat (from_parent, name. pointer ( ), from_flags);
677680  if  (from_fd < 0 ) {
678681    return  ErrnoStatus (" openat" absl::Hex (from_flags));
679682  }
@@ -684,7 +687,7 @@ static absl::Status CopyFilePosix(const int from_parent, const int to_parent,
684687  const  mode_t  mode = from_stat.st_mode ;
685688  constexpr  int  to_flags =
686689      O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC | O_NOCTTY | O_NOFOLLOW;
687-   const  int  to_fd = openat (to_parent, Pointer ( name), to_flags, mode);
690+   const  int  to_fd = openat (to_parent, name. pointer ( ), to_flags, mode);
688691  if  (to_fd < 0 ) {
689692    return  ErrnoStatus (" openat" Oct (mode));
690693  }
@@ -710,7 +713,7 @@ static absl::Status CopyFilePosix(const int from_parent, const int to_parent,
710713      if  (written == 0 ) {
711714        //  Prevent infinite loop.
712715        return  absl::DataLossError (absl::StrFormat (
713-             " Cannot write %d bytes to %s " size (), name));
716+             " Cannot write %d bytes to %v " size (), name));
714717      }
715718      remaining.remove_prefix (
716719          CastNumber<std::string_view::size_type>(written).value ());
@@ -727,25 +730,25 @@ static absl::Status CopyFilePosix(const int from_parent, const int to_parent,
727730}
728731
729732static  absl::Status CopyTreePosix (const  int  from_parent,
730-                                   const  std::string & from_name,
733+                                   const  FileName & from_name,
731734                                  std::optional<struct  stat > from_stat,
732735                                  const  int  to_parent,
733-                                   const  std::string & to_name) {
734-   CHECK (! from_name.empty () );
735-   CHECK_NE (from_name, " ." 
736-   CHECK_NE (from_name,  " .. " ); 
737-   CHECK (from_parent == AT_FDCWD ||  from_name.find (' /' npos )
736+                                   const  FileName & to_name) {
737+   CHECK_NE ( from_name.string (),  " . " 
738+   CHECK_NE (from_name. string () , " . ." 
739+   CHECK (from_parent == AT_FDCWD || 
740+          from_name.string (). find (' /' . string () .npos )
738741      << " invalid source name " 
739742
740-   CHECK (! to_name.empty () );
741-   CHECK_NE (to_name, " ." 
742-   CHECK_NE (to_name,  " .. " ); 
743-   CHECK (to_parent == AT_FDCWD ||  to_name.find (' /' npos )
743+   CHECK_NE ( to_name.string (),  " . " 
744+   CHECK_NE (to_name. string () , " . ." 
745+   CHECK (to_parent == AT_FDCWD || 
746+          to_name.string (). find (' /' . string () .npos )
744747      << " invalid target name " 
745748
746749  const  int  from_flags =
747750      O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC | O_NOCTTY;
748-   const  int  from_fd = openat (from_parent, Pointer ( from_name), from_flags);
751+   const  int  from_fd = openat (from_parent, from_name. pointer ( ), from_flags);
749752  if  (from_fd < 0 ) {
750753    return  ErrnoStatus (" openat" absl::Hex (from_flags));
751754  }
@@ -760,7 +763,7 @@ static absl::Status CopyTreePosix(const int from_parent,
760763    if  (fstat (from_fd, &buffer) != 0 ) return  ErrnoStatus (" fstat" 
761764    if  (!S_ISDIR (buffer.st_mode )) {
762765      return  absl::FailedPreconditionError (
763-           absl::StrFormat (" Source %s  is not a directory" 
766+           absl::StrFormat (" Source %v  is not a directory" 
764767    }
765768    from_stat = buffer;
766769  }
@@ -775,12 +778,12 @@ static absl::Status CopyTreePosix(const int from_parent,
775778  };
776779
777780  const  mode_t  mode = from_stat->st_mode  | S_IWUSR;
778-   const  int  result = mkdirat (to_parent, Pointer ( to_name), mode);
781+   const  int  result = mkdirat (to_parent, to_name. pointer ( ), mode);
779782  if  (result != 0 ) return  ErrnoStatus (" mkdirat" Oct (mode));
780783
781784  constexpr  int  to_flags =
782785      O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC | O_NOCTTY;
783-   const  int  to_fd = openat (to_parent, Pointer ( to_name), to_flags);
786+   const  int  to_fd = openat (to_parent, to_name. pointer ( ), to_flags);
784787  if  (to_fd < 0 ) {
785788    return  ErrnoStatus (" openat" absl::Hex (to_flags));
786789  }
@@ -795,8 +798,10 @@ static absl::Status CopyTreePosix(const int from_parent,
795798      if  (errno != 0 ) return  ErrnoStatus (" readdir" 
796799      break ;
797800    }
798-     const  std::string  name = entry->d_name ;
801+     const  std::string_view  name = entry->d_name ;
799802    if  (name == " ." " .." continue ;
803+     const  absl::StatusOr<FileName> file = FileName::FromString (name);
804+     if  (!file.ok ()) return  file.status ();
800805
801806    struct  stat  buffer;
802807    constexpr  int  stat_flags = AT_SYMLINK_NOFOLLOW;
@@ -807,10 +812,10 @@ static absl::Status CopyTreePosix(const int from_parent,
807812    const  mode_t  mode = buffer.st_mode ;
808813    if  (S_ISDIR (mode)) {
809814      const  absl::Status status =
810-           CopyTreePosix (from_fd, name , buffer, to_fd, name );
815+           CopyTreePosix (from_fd, *file , buffer, to_fd, *file );
811816      if  (!status.ok ()) return  status;
812817    } else  if  (S_ISREG (mode)) {
813-       const  absl::Status status = CopyFilePosix (from_fd, to_fd, name , buffer);
818+       const  absl::Status status = CopyFilePosix (from_fd, to_fd, *file , buffer);
814819      if  (!status.ok ()) return  status;
815820    } else  {
816821      return  absl::FailedPreconditionError (absl::StrFormat (
@@ -826,78 +831,56 @@ static absl::Status CopyTreePosix(const int from_parent,
826831}
827832#endif 
828833
829- absl::Status CopyTree (NativeStringView from, NativeStringView to) {
830-   if  (from.empty ()) {
831-     return  absl::InvalidArgumentError (" Empty source directory name" 
832-   }
833-   if  (ContainsNull (from)) {
834-     return  absl::InvalidArgumentError (absl::StrFormat (
835-         " Source directory name %s contains null character" 
836-   }
837-   if  (to.empty ()) {
838-     return  absl::InvalidArgumentError (" Empty destination directory name" 
839-   }
840-   if  (ContainsNull (to)) {
841-     return  absl::InvalidArgumentError (absl::StrFormat (
842-         " Destination directory name %s contains null character" 
843-   }
844- 
834+ absl::Status CopyTree (const  FileName& from, const  FileName& to) {
845835#if  defined _WIN32
846-   const  absl::StatusOr<FileName> from_name = FileName::FromString (from);
847-   if  (!from_name.ok ()) return  from_name.status ();
848-   const  absl::StatusOr<FileName> from_abs = from_name->MakeAbsolute ();
836+   const  absl::StatusOr<FileName> from_abs = from.MakeAbsolute ();
849837  if  (!from_abs.ok ()) return  from_abs.status ();
850838  if  (from_abs->string ().length () < 4 ) {
851839    return  absl::InvalidArgumentError (
852840        absl::StrFormat (" Cannot copy drive %v" 
853841  }
854-   const  absl::StatusOr<FileName> to_name = FileName::FromString (to);
855-   if  (!to_name.ok ()) return  to_name.status ();
856-   const  absl::StatusOr<FileName> to_abs = to_name->MakeAbsolute ();
842+   const  absl::StatusOr<FileName> to_abs = to.MakeAbsolute ();
857843  if  (!to_abs.ok ()) return  to_abs.status ();
858844  if  (to_abs->string ().length () < 4 ) {
859845    return  absl::AlreadyExistsError (
860846        absl::StrFormat (" Cannot copy over drive %v" 
861847  }
862-   return  CopyTreeWindows (from_abs-> string (),  to_abs-> string () );
848+   return  CopyTreeWindows (* from_abs, * to_abs);
863849#elif  defined __APPLE__
850+   std::string from_str = from.string ();
864851  //  The behavior of copyfile changes if the source directory name ends in a
865852  //  slash, see the man page copyfile(3).  We need to remove trailing slashes to
866853  //  get the expected behavior.
867-   const  std::string_view::size_type i = from.find_last_not_of (' /' 
868-   from.remove_suffix (from.size () - (i == from.npos  ? 0  : i + 1 ));
869-   if  (from.empty ()) {
854+   while  (from_str.back () == ' /' pop_back ();
855+   if  (from_str.empty ()) {
870856    //  If the source directory name is empty, it has consisted only of slashes.
871857    return  absl::InvalidArgumentError (" Cannot copy from root directory" 
872858  }
873-   const  std::string from_str (from);
874-   const  std::string to_str (to);
875859  //  The behavior of copyfile changes if the destination directory already
876860  //  exists, see the man page copyfile(3).
877861  struct  stat  buffer;
878-   if  (lstat (Pointer (to_str ), &buffer) == 0 ) {
862+   if  (lstat (to. pointer ( ), &buffer) == 0 ) {
879863    return  absl::AlreadyExistsError (
880-         absl::StrFormat (" Destination directory %s  already exists" to_str ));
864+         absl::StrFormat (" Destination directory %v  already exists" to ));
881865  }
882-   if  (errno != ENOENT) return  ErrnoStatus (" lstat" to_str );
866+   if  (errno != ENOENT) return  ErrnoStatus (" lstat" to );
883867  constexpr  copyfile_flags_t  flags = COPYFILE_ALL | COPYFILE_RECURSIVE |
884868                                     COPYFILE_EXCL | COPYFILE_NOFOLLOW |
885869                                     COPYFILE_CLONE | COPYFILE_DATA_SPARSE;
886-   if  (copyfile (Pointer (from_str), Pointer (to_str ), nullptr , flags) != 0 ) {
887-     return  ErrnoStatus (" copyfile" to_str , nullptr , absl::Hex (flags));
870+   if  (copyfile (Pointer (from_str), to. pointer ( ), nullptr , flags) != 0 ) {
871+     return  ErrnoStatus (" copyfile" to , nullptr , absl::Hex (flags));
888872  }
889873  return  absl::OkStatus ();
890874#elif  defined RULES_ELISP_COPY_TREE_POSIX
891-   if  (from.find_first_not_of (' /' npos ) {
875+   if  (from.string (). find_first_not_of (' /' . string () .npos ) {
892876    return  absl::InvalidArgumentError (
893-         absl::StrFormat (" Cannot copy from root directory %s " 
877+         absl::StrFormat (" Cannot copy from root directory %v " 
894878  }
895-   if  (to.find_first_not_of (' /' npos ) {
879+   if  (to.string (). find_first_not_of (' /' . string () .npos ) {
896880    return  absl::AlreadyExistsError (
897-         absl::StrFormat (" Cannot overwrite root directory %s " 
881+         absl::StrFormat (" Cannot overwrite root directory %v " 
898882  }
899-   return  CopyTreePosix (AT_FDCWD, std::string (from), std::nullopt , AT_FDCWD,
900-                        std::string (to));
883+   return  CopyTreePosix (AT_FDCWD, from, std::nullopt , AT_FDCWD, to);
901884#else 
902885#  error  CopyTree not implemented on this system
903886#endif 
0 commit comments