1+ // This file is part of the uutils coreutils package.
2+ //
3+ // For the full copyright and license information, please view the LICENSE
4+ // file that was distributed with this source code.
5+ //
16// Safe directory traversal using openat() and related syscalls
27// This module provides TOCTOU-safe filesystem operations for recursive traversal
8+ //
39// Only available on Linux
10+ //
411// spell-checker:ignore CLOEXEC RDONLY TOCTOU closedir dirp fdopendir fstatat openat REMOVEDIR unlinkat smallfile
5- // spell-checker:ignore RAII dirfd
12+ // spell-checker:ignore RAII dirfd
613
714#![ cfg( target_os = "linux" ) ]
815
@@ -126,7 +133,6 @@ pub struct DirFd {
126133impl DirFd {
127134 /// Open a directory and return a file descriptor
128135 pub fn open ( path : & Path ) -> io:: Result < Self > {
129- let path_str = path. to_string_lossy ( ) ;
130136 let path_cstr = CString :: new ( path. as_os_str ( ) . as_bytes ( ) )
131137 . map_err ( |_| SafeTraversalError :: PathContainsNull ) ?;
132138
@@ -139,7 +145,7 @@ impl DirFd {
139145
140146 if fd < 0 {
141147 Err ( SafeTraversalError :: OpenFailed {
142- path : path_str . to_string ( ) ,
148+ path : path . to_string_lossy ( ) . into_owned ( ) ,
143149 source : io:: Error :: last_os_error ( ) ,
144150 }
145151 . into ( ) )
@@ -150,7 +156,6 @@ impl DirFd {
150156
151157 /// Open a subdirectory relative to this directory
152158 pub fn open_subdir ( & self , name : & OsStr ) -> io:: Result < Self > {
153- let name_str = name. to_string_lossy ( ) ;
154159 let name_cstr =
155160 CString :: new ( name. as_bytes ( ) ) . map_err ( |_| SafeTraversalError :: PathContainsNull ) ?;
156161
@@ -164,7 +169,7 @@ impl DirFd {
164169
165170 if fd < 0 {
166171 Err ( SafeTraversalError :: OpenFailed {
167- path : name_str . to_string ( ) ,
172+ path : name . to_string_lossy ( ) . into_owned ( ) ,
168173 source : io:: Error :: last_os_error ( ) ,
169174 }
170175 . into ( ) )
@@ -175,7 +180,6 @@ impl DirFd {
175180
176181 /// Get raw stat data for a file relative to this directory
177182 pub fn stat_at ( & self , name : & OsStr , follow_symlinks : bool ) -> io:: Result < libc:: stat > {
178- let name_str = name. to_string_lossy ( ) ;
179183 let name_cstr =
180184 CString :: new ( name. as_bytes ( ) ) . map_err ( |_| SafeTraversalError :: PathContainsNull ) ?;
181185
@@ -190,7 +194,7 @@ impl DirFd {
190194
191195 if ret < 0 {
192196 Err ( SafeTraversalError :: StatFailed {
193- path : name_str . to_string ( ) ,
197+ path : name . to_string_lossy ( ) . into_owned ( ) ,
194198 source : io:: Error :: last_os_error ( ) ,
195199 }
196200 . into ( ) )
@@ -257,7 +261,6 @@ impl DirFd {
257261
258262 /// Remove a file or empty directory relative to this directory
259263 pub fn unlink_at ( & self , name : & OsStr , is_dir : bool ) -> io:: Result < ( ) > {
260- let name_str = name. to_string_lossy ( ) ;
261264 let name_cstr =
262265 CString :: new ( name. as_bytes ( ) ) . map_err ( |_| SafeTraversalError :: PathContainsNull ) ?;
263266 let flags = if is_dir { libc:: AT_REMOVEDIR } else { 0 } ;
@@ -266,7 +269,7 @@ impl DirFd {
266269
267270 if ret < 0 {
268271 Err ( SafeTraversalError :: UnlinkFailed {
269- path : name_str . to_string ( ) ,
272+ path : name . to_string_lossy ( ) . into_owned ( ) ,
270273 source : io:: Error :: last_os_error ( ) ,
271274 }
272275 . into ( ) )
@@ -427,7 +430,6 @@ impl Metadata {
427430}
428431
429432// Add MetadataExt trait implementation for compatibility
430- #[ cfg( not( windows) ) ]
431433impl std:: os:: unix:: fs:: MetadataExt for Metadata {
432434 fn dev ( & self ) -> u64 {
433435 self . stat . st_dev
0 commit comments