1use std::{
2 borrow::Cow,
3 ffi::OsStr,
4 fs::{self, File, Metadata, ReadDir},
5 io::{self, Write},
6 path::{self, Path, PathBuf},
7};
8#[cfg(unix)]
9use std::{
10 fs::Permissions,
11 os::unix::{self, fs::PermissionsExt as _},
12};
13
14#[cfg(unix)]
15use pathdiff::diff_paths;
16
17use super::temp_path::TempPath;
18
19pub trait PathExt {
20 fn base(&self) -> io::Result<&Path>;
21 fn with_base(&self, base: impl AsRef<Path>) -> Cow<'_, Path>;
22
23 fn file_suffix(&self) -> Option<&OsStr>;
24
25 fn absolute(&self) -> io::Result<PathBuf>;
26
27 fn metadata(&self) -> io::Result<Metadata>;
28 fn symlink_metadata(&self) -> io::Result<Metadata>;
29 fn canonicalize(&self) -> io::Result<PathBuf>;
30 fn read_link(&self) -> io::Result<PathBuf>;
31 fn read_dir(&self) -> io::Result<ReadDir>;
32
33 fn try_exists(&self) -> io::Result<bool>;
34
35 fn try_is_file(&self) -> io::Result<bool>;
36 fn try_is_dir(&self) -> io::Result<bool>;
37 fn try_is_symlink(&self) -> io::Result<bool>;
38
39 fn metadata_if_exists(&self) -> io::Result<Option<Metadata>>;
40 fn symlink_metadata_if_exists(&self) -> io::Result<Option<Metadata>>;
41 fn canonicalize_if_exists(&self) -> io::Result<Option<PathBuf>>;
42 fn read_link_if_exists(&self) -> io::Result<Option<PathBuf>>;
43 fn read_dir_if_exists(&self) -> io::Result<Option<ReadDir>>;
44
45 fn exists_nofollow(&self) -> bool;
46 fn is_file_nofollow(&self) -> bool;
47 fn is_dir_nofollow(&self) -> bool;
48
49 fn try_exists_nofollow(&self) -> io::Result<bool>;
50 fn try_is_file_nofollow(&self) -> io::Result<bool>;
51 fn try_is_dir_nofollow(&self) -> io::Result<bool>;
52
53 fn try_is_read_dir_empty(&self) -> io::Result<bool>;
54 fn try_is_read_dir_empty_if_exists(&self) -> io::Result<Option<bool>>;
55
56 fn read(&self) -> io::Result<Vec<u8>>;
57 fn read_if_exists(&self) -> io::Result<Option<Vec<u8>>>;
58
59 fn read_to_string(&self) -> io::Result<String>;
60 fn read_to_string_if_exists(&self) -> io::Result<Option<String>>;
61
62 fn create_dir_all(self) -> io::Result<Self>
63 where
64 Self: Sized;
65
66 fn create_dir(self) -> io::Result<Self>
67 where
68 Self: Sized;
69 fn create_dir_if_not_exists(self) -> io::Result<Option<Self>>
70 where
71 Self: Sized;
72
73 fn write_new(self, contents: impl AsRef<[u8]>) -> io::Result<Self>
74 where
75 Self: Sized;
76 fn write_new_if_not_exists(self, contents: impl AsRef<[u8]>) -> io::Result<Option<Self>>
77 where
78 Self: Sized;
79
80 fn write(self, contents: impl AsRef<[u8]>) -> io::Result<Self>
81 where
82 Self: Sized;
83 fn write_if_exists(self, contents: impl AsRef<[u8]>) -> io::Result<Option<Self>>
84 where
85 Self: Sized;
86
87 fn append(self, contents: impl AsRef<[u8]>) -> io::Result<Self>
88 where
89 Self: Sized;
90 fn append_if_exists(self, contents: impl AsRef<[u8]>) -> io::Result<Option<Self>>
91 where
92 Self: Sized;
93
94 fn copy(self, to: impl AsRef<Path>) -> io::Result<Self>
95 where
96 Self: Sized;
97 fn copy_if_exists(self, to: impl AsRef<Path>) -> io::Result<Option<Self>>
98 where
99 Self: Sized;
100
101 fn rename(self, to: impl AsRef<Path>) -> io::Result<Self>
102 where
103 Self: Sized;
104 fn rename_if_exists(self, to: impl AsRef<Path>) -> io::Result<Option<Self>>
105 where
106 Self: Sized;
107
108 fn remove_file(self) -> io::Result<Self>
109 where
110 Self: Sized;
111 fn remove_file_if_exists(self) -> io::Result<Option<Self>>
112 where
113 Self: Sized;
114
115 fn remove_dir(self) -> io::Result<Self>
116 where
117 Self: Sized;
118 fn remove_dir_if_exists(self) -> io::Result<Option<Self>>
119 where
120 Self: Sized;
121
122 fn remove_dir_all(self) -> io::Result<Self>
123 where
124 Self: Sized;
125 fn remove_dir_all_if_exists(self) -> io::Result<Option<Self>>
126 where
127 Self: Sized;
128
129 fn hard_link(self, link: impl AsRef<Path>) -> io::Result<Self>
130 where
131 Self: Sized;
132 fn hard_link_atomic(self, link: impl AsRef<Path>) -> io::Result<Self>
133 where
134 Self: Sized;
135
136 #[cfg(unix)]
137 fn symlink(self, link: impl AsRef<Path>) -> io::Result<Self>
138 where
139 Self: Sized;
140 #[cfg(unix)]
141 fn symlink_atomic(self, link: impl AsRef<Path>) -> io::Result<Self>
142 where
143 Self: Sized;
144
145 #[cfg(unix)]
146 fn symlink_absolute(self, link: impl AsRef<Path>) -> io::Result<Self>
147 where
148 Self: Sized;
149 #[cfg(unix)]
150 fn symlink_absolute_atomic(self, link: impl AsRef<Path>) -> io::Result<Self>
151 where
152 Self: Sized;
153
154 #[cfg(unix)]
155 fn symlink_relative(self, link: impl AsRef<Path>) -> io::Result<Self>
156 where
157 Self: Sized;
158 #[cfg(unix)]
159 fn symlink_relative_atomic(self, link: impl AsRef<Path>) -> io::Result<Self>
160 where
161 Self: Sized;
162
163 #[cfg(unix)]
164 fn set_permissions(self, permissions: Permissions) -> io::Result<Self>
165 where
166 Self: Sized;
167
168 #[cfg(unix)]
169 fn set_permissions_mode(self, permissions_mode: u32) -> io::Result<Self>
170 where
171 Self: Sized;
172 #[cfg(unix)]
173 fn add_permissions_mode(self, permissions_mode: u32) -> io::Result<Self>
174 where
175 Self: Sized;
176 #[cfg(unix)]
177 fn remove_permissions_mode(self, permissions_mode: u32) -> io::Result<Self>
178 where
179 Self: Sized;
180}
181
182impl<T: AsRef<Path>> PathExt for T {
183 #[inline]
184 fn base(&self) -> io::Result<&Path> {
185 self.as_ref()
186 .parent()
187 .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "Path has no parent"))
188 }
189
190 #[inline]
191 fn with_base(&self, base: impl AsRef<Path>) -> Cow<'_, Path> {
192 if self.as_ref().is_relative() {
193 let path = base.as_ref().join(self);
194
195 Cow::Owned(path)
196 } else {
197 Cow::Borrowed(self.as_ref())
198 }
199 }
200
201 #[inline]
202 fn file_suffix(&self) -> Option<&OsStr> {
203 let file_name = self.as_ref().file_name()?;
204 let file_prefix = self.as_ref().file_prefix()?;
205
206 let bytes = file_name.as_encoded_bytes();
207
208 let start = file_prefix.as_encoded_bytes().len() + 1;
209
210 if start <= bytes.len() {
211 let slice = &bytes[start..];
212
213 let os_str = unsafe { OsStr::from_encoded_bytes_unchecked(slice) };
214
215 Some(os_str)
216 } else {
217 None
218 }
219 }
220
221 #[inline]
222 fn absolute(&self) -> io::Result<PathBuf> {
223 path::absolute(self)
224 }
225
226 #[inline]
227 fn metadata(&self) -> io::Result<Metadata> {
228 self.as_ref().metadata()
229 }
230
231 #[inline]
232 fn symlink_metadata(&self) -> io::Result<Metadata> {
233 self.as_ref().symlink_metadata()
234 }
235
236 #[inline]
237 fn canonicalize(&self) -> io::Result<PathBuf> {
238 self.as_ref().canonicalize()
239 }
240
241 #[inline]
242 fn read_link(&self) -> io::Result<PathBuf> {
243 self.as_ref().read_link()
244 }
245
246 #[inline]
247 fn read_dir(&self) -> io::Result<ReadDir> {
248 self.as_ref().read_dir()
249 }
250
251 #[inline]
252 fn try_exists(&self) -> io::Result<bool> {
253 self.as_ref().try_exists()
254 }
255
256 #[inline]
257 fn try_is_file(&self) -> io::Result<bool> {
258 self.metadata_if_exists().map(|metadata_opt| {
259 metadata_opt
260 .map(|metadata| metadata.is_file())
261 .unwrap_or(false)
262 })
263 }
264
265 #[inline]
266 fn try_is_dir(&self) -> io::Result<bool> {
267 self.metadata_if_exists().map(|metadata_opt| {
268 metadata_opt
269 .map(|metadata| metadata.is_dir())
270 .unwrap_or(false)
271 })
272 }
273
274 #[inline]
275 fn try_is_symlink(&self) -> io::Result<bool> {
276 self.symlink_metadata_if_exists().map(|metadata_opt| {
277 metadata_opt
278 .map(|metadata| metadata.is_symlink())
279 .unwrap_or(false)
280 })
281 }
282
283 #[inline]
284 fn metadata_if_exists(&self) -> io::Result<Option<Metadata>> {
285 match self.metadata() {
286 Ok(metadata) => Ok(Some(metadata)),
287 Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
288 Err(err) => Err(err),
289 }
290 }
291
292 #[inline]
293 fn symlink_metadata_if_exists(&self) -> io::Result<Option<Metadata>> {
294 match self.symlink_metadata() {
295 Ok(metadata) => Ok(Some(metadata)),
296 Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
297 Err(err) => Err(err),
298 }
299 }
300
301 #[inline]
302 fn canonicalize_if_exists(&self) -> io::Result<Option<PathBuf>> {
303 match self.canonicalize() {
304 Ok(path) => Ok(Some(path)),
305 Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
306 Err(err) => Err(err),
307 }
308 }
309
310 #[inline]
311 fn read_link_if_exists(&self) -> io::Result<Option<PathBuf>> {
312 match self.read_link() {
313 Ok(path) => Ok(Some(path)),
314 Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
315 Err(err) => Err(err),
316 }
317 }
318
319 #[inline]
320 fn read_dir_if_exists(&self) -> io::Result<Option<ReadDir>> {
321 match self.read_dir() {
322 Ok(entries) => Ok(Some(entries)),
323 Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
324 Err(err) => Err(err),
325 }
326 }
327
328 #[inline]
329 fn exists_nofollow(&self) -> bool {
330 self.symlink_metadata().is_ok()
331 }
332
333 #[inline]
334 fn is_file_nofollow(&self) -> bool {
335 self.symlink_metadata()
336 .map(|metadata| metadata.is_file())
337 .unwrap_or(false)
338 }
339
340 #[inline]
341 fn is_dir_nofollow(&self) -> bool {
342 self.symlink_metadata()
343 .map(|metadata| metadata.is_dir())
344 .unwrap_or(false)
345 }
346
347 #[inline]
348 fn try_exists_nofollow(&self) -> io::Result<bool> {
349 self.symlink_metadata_if_exists()
350 .map(|metadata_opt| metadata_opt.is_some())
351 }
352
353 #[inline]
354 fn try_is_file_nofollow(&self) -> io::Result<bool> {
355 self.symlink_metadata_if_exists().map(|metadata_opt| {
356 metadata_opt
357 .map(|metadata| metadata.is_file())
358 .unwrap_or(false)
359 })
360 }
361
362 #[inline]
363 fn try_is_dir_nofollow(&self) -> io::Result<bool> {
364 self.symlink_metadata_if_exists().map(|metadata_opt| {
365 metadata_opt
366 .map(|metadata| metadata.is_dir())
367 .unwrap_or(false)
368 })
369 }
370
371 #[inline]
372 fn try_is_read_dir_empty(&self) -> io::Result<bool> {
373 let mut entries = self.read_dir()?;
374
375 entries
376 .next()
377 .transpose()
378 .map(|entry_opt| entry_opt.is_none())
379 }
380
381 #[inline]
382 fn try_is_read_dir_empty_if_exists(&self) -> io::Result<Option<bool>> {
383 match self.try_is_read_dir_empty() {
384 Ok(is_empty) => Ok(Some(is_empty)),
385 Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
386 Err(err) => Err(err),
387 }
388 }
389
390 #[inline]
391 fn read(&self) -> io::Result<Vec<u8>> {
392 fs::read(self)
393 }
394
395 #[inline]
396 fn read_if_exists(&self) -> io::Result<Option<Vec<u8>>> {
397 match self.read() {
398 Ok(bytes) => Ok(Some(bytes)),
399 Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
400 Err(err) => Err(err),
401 }
402 }
403
404 #[inline]
405 fn read_to_string(&self) -> io::Result<String> {
406 fs::read_to_string(self)
407 }
408
409 #[inline]
410 fn read_to_string_if_exists(&self) -> io::Result<Option<String>> {
411 match self.read_to_string() {
412 Ok(string) => Ok(Some(string)),
413 Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
414 Err(err) => Err(err),
415 }
416 }
417
418 #[inline]
419 fn create_dir_all(self) -> io::Result<Self> {
420 fs::create_dir_all(self.as_ref())?;
421
422 Ok(self)
423 }
424
425 #[inline]
426 fn create_dir(self) -> io::Result<Self> {
427 fs::create_dir(self.as_ref())?;
428
429 Ok(self)
430 }
431
432 #[inline]
433 fn create_dir_if_not_exists(self) -> io::Result<Option<Self>> {
434 match self.as_ref().create_dir() {
435 Ok(_) => Ok(Some(self)),
436 Err(err) if err.kind() == io::ErrorKind::AlreadyExists => Ok(None),
437 Err(err) => Err(err),
438 }
439 }
440
441 #[inline]
442 fn write_new(self, contents: impl AsRef<[u8]>) -> io::Result<Self> {
443 let mut options = File::options();
444
445 options.write(true).create_new(true);
446
447 let mut file = options.open(self.as_ref())?;
448
449 file.write_all(contents.as_ref())?;
450
451 Ok(self)
452 }
453
454 #[inline]
455 fn write_new_if_not_exists(self, contents: impl AsRef<[u8]>) -> io::Result<Option<Self>> {
456 match self.as_ref().write_new(contents) {
457 Ok(_) => Ok(Some(self)),
458 Err(err) if err.kind() == io::ErrorKind::AlreadyExists => Ok(None),
459 Err(err) => Err(err),
460 }
461 }
462
463 #[inline]
464 fn write(self, contents: impl AsRef<[u8]>) -> io::Result<Self> {
465 fs::write(self.as_ref(), contents)?;
466
467 Ok(self)
468 }
469
470 #[inline]
471 fn write_if_exists(self, contents: impl AsRef<[u8]>) -> io::Result<Option<Self>> {
472 let mut options = File::options();
473
474 options.write(true).truncate(true);
475
476 match options.open(self.as_ref()) {
477 Ok(mut file) => {
478 file.write_all(contents.as_ref())?;
479
480 Ok(Some(self))
481 },
482 Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
483 Err(err) => Err(err),
484 }
485 }
486
487 #[inline]
488 fn append(self, contents: impl AsRef<[u8]>) -> io::Result<Self> {
489 let mut options = File::options();
490
491 options.append(true).create(true);
492
493 let mut file = options.open(self.as_ref())?;
494
495 file.write_all(contents.as_ref())?;
496
497 Ok(self)
498 }
499
500 #[inline]
501 fn append_if_exists(self, contents: impl AsRef<[u8]>) -> io::Result<Option<Self>> {
502 let mut options = File::options();
503
504 options.append(true);
505
506 match options.open(self.as_ref()) {
507 Ok(mut file) => {
508 file.write_all(contents.as_ref())?;
509
510 Ok(Some(self))
511 },
512 Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
513 Err(err) => Err(err),
514 }
515 }
516
517 #[inline]
518 fn copy(self, to: impl AsRef<Path>) -> io::Result<Self> {
519 fs::copy(self.as_ref(), to)?;
520
521 Ok(self)
522 }
523
524 #[inline]
525 fn copy_if_exists(self, to: impl AsRef<Path>) -> io::Result<Option<Self>> {
526 match self.as_ref().copy(to) {
527 Ok(_) => Ok(Some(self)),
528 Err(err) if err.kind() == io::ErrorKind::NotFound => {
529 if !self.try_exists()? {
530 Ok(None)
531 } else {
532 Err(err)
533 }
534 },
535 Err(err) => Err(err),
536 }
537 }
538
539 #[inline]
540 fn rename(self, to: impl AsRef<Path>) -> io::Result<Self> {
541 fs::rename(self.as_ref(), to)?;
542
543 Ok(self)
544 }
545
546 #[inline]
547 fn rename_if_exists(self, to: impl AsRef<Path>) -> io::Result<Option<Self>> {
548 match self.as_ref().rename(to) {
549 Ok(_) => Ok(Some(self)),
550 Err(err) if err.kind() == io::ErrorKind::NotFound => {
551 if !self.try_exists_nofollow()? {
552 Ok(None)
553 } else {
554 Err(err)
555 }
556 },
557 Err(err) => Err(err),
558 }
559 }
560
561 #[inline]
562 fn remove_file(self) -> io::Result<Self> {
563 fs::remove_file(self.as_ref())?;
564
565 Ok(self)
566 }
567
568 #[inline]
569 fn remove_file_if_exists(self) -> io::Result<Option<Self>> {
570 match self.as_ref().remove_file() {
571 Ok(_) => Ok(Some(self)),
572 Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
573 Err(err) => Err(err),
574 }
575 }
576
577 #[inline]
578 fn remove_dir(self) -> io::Result<Self> {
579 fs::remove_dir(self.as_ref())?;
580
581 Ok(self)
582 }
583
584 #[inline]
585 fn remove_dir_if_exists(self) -> io::Result<Option<Self>> {
586 match self.as_ref().remove_dir() {
587 Ok(_) => Ok(Some(self)),
588 Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
589 Err(err) => Err(err),
590 }
591 }
592
593 #[inline]
594 fn remove_dir_all(self) -> io::Result<Self> {
595 fs::remove_dir_all(self.as_ref())?;
596
597 Ok(self)
598 }
599
600 #[inline]
601 fn remove_dir_all_if_exists(self) -> io::Result<Option<Self>> {
602 match self.as_ref().remove_dir_all() {
603 Ok(_) => Ok(Some(self)),
604 Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
605 Err(err) => Err(err),
606 }
607 }
608
609 #[inline]
610 fn hard_link(self, link: impl AsRef<Path>) -> io::Result<Self> {
611 fs::hard_link(self.as_ref(), link)?;
612
613 Ok(self)
614 }
615
616 #[inline]
617 fn hard_link_atomic(self, link: impl AsRef<Path>) -> io::Result<Self> {
618 let temp = TempPath::try_from_path(link.as_ref())?;
619
620 self.as_ref().hard_link(temp.path())?;
621
622 temp.persist(link)?;
623
624 Ok(self)
625 }
626
627 #[cfg(unix)]
628 #[inline]
629 fn symlink(self, link: impl AsRef<Path>) -> io::Result<Self> {
630 unix::fs::symlink(self.as_ref(), link)?;
631
632 Ok(self)
633 }
634
635 #[cfg(unix)]
636 #[inline]
637 fn symlink_atomic(self, link: impl AsRef<Path>) -> io::Result<Self> {
638 let temp = TempPath::try_from_path(link.as_ref())?;
639
640 self.as_ref().symlink(temp.path())?;
641
642 temp.persist(link)?;
643
644 Ok(self)
645 }
646
647 #[cfg(unix)]
648 #[inline]
649 fn symlink_absolute(self, link: impl AsRef<Path>) -> io::Result<Self> {
650 #[expect(unstable_name_collisions)]
651 let absolute = self.as_ref().absolute()?;
652
653 absolute.symlink(link)?;
654
655 Ok(self)
656 }
657
658 #[cfg(unix)]
659 #[inline]
660 fn symlink_absolute_atomic(self, link: impl AsRef<Path>) -> io::Result<Self> {
661 #[expect(unstable_name_collisions)]
662 let absolute = self.as_ref().absolute()?;
663
664 absolute.symlink_atomic(link)?;
665
666 Ok(self)
667 }
668
669 #[cfg(unix)]
670 #[inline]
671 fn symlink_relative(self, link: impl AsRef<Path>) -> io::Result<Self> {
672 let base = link.base()?;
673
674 let relative = diff_paths(self.as_ref(), base)
675 .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "Failed to diff paths"))?;
676
677 relative.symlink(link)?;
678
679 Ok(self)
680 }
681
682 #[cfg(unix)]
683 #[inline]
684 fn symlink_relative_atomic(self, link: impl AsRef<Path>) -> io::Result<Self> {
685 let base = link.base()?;
686
687 let relative = diff_paths(self.as_ref(), base)
688 .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "Failed to diff paths"))?;
689
690 relative.symlink_atomic(link)?;
691
692 Ok(self)
693 }
694
695 #[cfg(unix)]
696 #[inline]
697 fn set_permissions(self, permissions: Permissions) -> io::Result<Self> {
698 fs::set_permissions(self.as_ref(), permissions)?;
699
700 Ok(self)
701 }
702
703 #[cfg(unix)]
704 #[inline]
705 fn set_permissions_mode(self, permissions_mode: u32) -> io::Result<Self> {
706 let metadata = self.metadata()?;
707
708 let mut permissions = metadata.permissions();
709
710 permissions.set_mode(permissions_mode);
711
712 self.set_permissions(permissions)
713 }
714
715 #[cfg(unix)]
716 #[inline]
717 fn add_permissions_mode(self, permissions_mode: u32) -> io::Result<Self> {
718 let metadata = self.metadata()?;
719
720 let mut permissions = metadata.permissions();
721
722 permissions.set_mode(permissions.mode() | permissions_mode);
723
724 self.set_permissions(permissions)
725 }
726
727 #[cfg(unix)]
728 #[inline]
729 fn remove_permissions_mode(self, permissions_mode: u32) -> io::Result<Self> {
730 let metadata = self.metadata()?;
731
732 let mut permissions = metadata.permissions();
733
734 permissions.set_mode(permissions.mode() & !permissions_mode);
735
736 self.set_permissions(permissions)
737 }
738}
739
740macro_rules! define_option_path_ext {
741 (
742 $(
743 $(#[$meta:meta])*
744 fn $method:ident(self $(, $arg:ident: $ty:ty)* $(,)*) -> $ret:ty;
745 )*
746 ) => {
747 pub trait OptionPathExt<T> {
748 $(
749 $(#[$meta])*
750 fn $method(self $(, $arg: $ty)*) -> $ret;
751 )*
752 }
753
754 impl<T: PathExt> OptionPathExt<T> for Option<T> {
755 $(
756 #[inline]
757 $(#[$meta])*
758 fn $method(self $(, $arg: $ty)*) -> $ret {
759 match self {
760 Some(path) => path.$method($($arg),*).map(Some),
761 None => Ok(None),
762 }
763 }
764 )*
765 }
766 };
767}
768
769define_option_path_ext! {
770 fn metadata(self) -> io::Result<Option<Metadata>>;
771 fn symlink_metadata(self) -> io::Result<Option<Metadata>>;
772 fn canonicalize(self) -> io::Result<Option<PathBuf>>;
773 fn read_link(self) -> io::Result<Option<PathBuf>>;
774 fn read_dir(self) -> io::Result<Option<ReadDir>>;
775
776 fn try_exists(self) -> io::Result<Option<bool>>;
777
778 fn try_is_file(self) -> io::Result<Option<bool>>;
779 fn try_is_dir(self) -> io::Result<Option<bool>>;
780 fn try_is_symlink(self) -> io::Result<Option<bool>>;
781
782 fn try_exists_nofollow(self) -> io::Result<Option<bool>>;
783 fn try_is_file_nofollow(self) -> io::Result<Option<bool>>;
784 fn try_is_dir_nofollow(self) -> io::Result<Option<bool>>;
785
786 fn try_is_read_dir_empty(self) -> io::Result<Option<bool>>;
787
788 fn read(self) -> io::Result<Option<Vec<u8>>>;
789
790 fn read_to_string(self) -> io::Result<Option<String>>;
791
792 fn create_dir_all(self) -> io::Result<Option<T>>;
793
794 fn create_dir(self) -> io::Result<Option<T>>;
795
796 fn write_new(self, contents: impl AsRef<[u8]>) -> io::Result<Option<T>>;
797
798 fn write(self, contents: impl AsRef<[u8]>) -> io::Result<Option<T>>;
799
800 fn append(self, contents: impl AsRef<[u8]>) -> io::Result<Option<T>>;
801
802 fn copy(self, to: impl AsRef<Path>) -> io::Result<Option<T>>;
803
804 fn rename(self, to: impl AsRef<Path>) -> io::Result<Option<T>>;
805
806 fn remove_file(self) -> io::Result<Option<T>>;
807
808 fn remove_dir(self) -> io::Result<Option<T>>;
809
810 fn remove_dir_all(self) -> io::Result<Option<T>>;
811
812 fn hard_link(self, link: impl AsRef<Path>) -> io::Result<Option<T>>;
813 fn hard_link_atomic(self, link: impl AsRef<Path>) -> io::Result<Option<T>>;
814
815 #[cfg(unix)]
816 fn symlink(self, link: impl AsRef<Path>) -> io::Result<Option<T>>;
817 #[cfg(unix)]
818 fn symlink_atomic(self, link: impl AsRef<Path>) -> io::Result<Option<T>>;
819
820 #[cfg(unix)]
821 fn symlink_absolute(self, link: impl AsRef<Path>) -> io::Result<Option<T>>;
822 #[cfg(unix)]
823 fn symlink_absolute_atomic(self, link: impl AsRef<Path>) -> io::Result<Option<T>>;
824
825 #[cfg(unix)]
826 fn symlink_relative(self, link: impl AsRef<Path>) -> io::Result<Option<T>>;
827 #[cfg(unix)]
828 fn symlink_relative_atomic(self, link: impl AsRef<Path>) -> io::Result<Option<T>>;
829
830 #[cfg(unix)]
831 fn set_permissions(self, permissions: Permissions) -> io::Result<Option<T>>;
832
833 #[cfg(unix)]
834 fn set_permissions_mode(self, permissions_mode: u32) -> io::Result<Option<T>>;
835 #[cfg(unix)]
836 fn add_permissions_mode(self, permissions_mode: u32) -> io::Result<Option<T>>;
837 #[cfg(unix)]
838 fn remove_permissions_mode(self, permissions_mode: u32) -> io::Result<Option<T>>;
839}