]>
Commit | Line | Data |
---|---|---|
416331ca XL |
1 | #![stable(feature = "rust1", since = "1.0.0")] |
2 | ||
3 | use crate::fs::{self, Permissions}; | |
4 | use crate::io; | |
416331ca XL |
5 | use crate::path::Path; |
6 | use crate::sys; | |
416331ca | 7 | use crate::sys::platform::fs::MetadataExt as UnixMetadataExt; |
60c5eb7d | 8 | use crate::sys_common::{AsInner, AsInnerMut, FromInner}; |
416331ca | 9 | |
3dfed10e | 10 | /// Unix-specific extensions to [`fs::File`]. |
416331ca XL |
11 | #[stable(feature = "file_offset", since = "1.15.0")] |
12 | pub trait FileExt { | |
13 | /// Reads a number of bytes starting from a given offset. | |
14 | /// | |
15 | /// Returns the number of bytes read. | |
16 | /// | |
17 | /// The offset is relative to the start of the file and thus independent | |
18 | /// from the current cursor. | |
19 | /// | |
20 | /// The current file cursor is not affected by this function. | |
21 | /// | |
22 | /// Note that similar to [`File::read`], it is not an error to return with a | |
23 | /// short read. | |
24 | /// | |
3dfed10e | 25 | /// [`File::read`]: fs::File::read |
416331ca XL |
26 | /// |
27 | /// # Examples | |
28 | /// | |
29 | /// ```no_run | |
30 | /// use std::io; | |
31 | /// use std::fs::File; | |
32 | /// use std::os::unix::prelude::FileExt; | |
33 | /// | |
34 | /// fn main() -> io::Result<()> { | |
35 | /// let mut buf = [0u8; 8]; | |
36 | /// let file = File::open("foo.txt")?; | |
37 | /// | |
38 | /// // We now read 8 bytes from the offset 10. | |
39 | /// let num_bytes_read = file.read_at(&mut buf, 10)?; | |
40 | /// println!("read {} bytes: {:?}", num_bytes_read, buf); | |
41 | /// Ok(()) | |
42 | /// } | |
43 | /// ``` | |
44 | #[stable(feature = "file_offset", since = "1.15.0")] | |
45 | fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>; | |
46 | ||
47 | /// Reads the exact number of byte required to fill `buf` from the given offset. | |
48 | /// | |
49 | /// The offset is relative to the start of the file and thus independent | |
50 | /// from the current cursor. | |
51 | /// | |
52 | /// The current file cursor is not affected by this function. | |
53 | /// | |
54 | /// Similar to [`Read::read_exact`] but uses [`read_at`] instead of `read`. | |
55 | /// | |
3dfed10e XL |
56 | /// [`Read::read_exact`]: io::Read::read_exact |
57 | /// [`read_at`]: FileExt::read_at | |
416331ca XL |
58 | /// |
59 | /// # Errors | |
60 | /// | |
61 | /// If this function encounters an error of the kind | |
62 | /// [`ErrorKind::Interrupted`] then the error is ignored and the operation | |
63 | /// will continue. | |
64 | /// | |
65 | /// If this function encounters an "end of file" before completely filling | |
66 | /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`]. | |
67 | /// The contents of `buf` are unspecified in this case. | |
68 | /// | |
69 | /// If any other read error is encountered then this function immediately | |
70 | /// returns. The contents of `buf` are unspecified in this case. | |
71 | /// | |
72 | /// If this function returns an error, it is unspecified how many bytes it | |
73 | /// has read, but it will never read more than would be necessary to | |
74 | /// completely fill the buffer. | |
75 | /// | |
3dfed10e XL |
76 | /// [`ErrorKind::Interrupted`]: io::ErrorKind::Interrupted |
77 | /// [`ErrorKind::UnexpectedEof`]: io::ErrorKind::UnexpectedEof | |
416331ca XL |
78 | /// |
79 | /// # Examples | |
80 | /// | |
81 | /// ```no_run | |
82 | /// #![feature(rw_exact_all_at)] | |
83 | /// use std::io; | |
84 | /// use std::fs::File; | |
85 | /// use std::os::unix::prelude::FileExt; | |
86 | /// | |
87 | /// fn main() -> io::Result<()> { | |
88 | /// let mut buf = [0u8; 8]; | |
89 | /// let file = File::open("foo.txt")?; | |
90 | /// | |
91 | /// // We now read exactly 8 bytes from the offset 10. | |
92 | /// file.read_exact_at(&mut buf, 10)?; | |
93 | /// println!("read {} bytes: {:?}", buf.len(), buf); | |
94 | /// Ok(()) | |
95 | /// } | |
96 | /// ``` | |
97 | #[stable(feature = "rw_exact_all_at", since = "1.33.0")] | |
98 | fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> { | |
99 | while !buf.is_empty() { | |
100 | match self.read_at(buf, offset) { | |
101 | Ok(0) => break, | |
102 | Ok(n) => { | |
103 | let tmp = buf; | |
104 | buf = &mut tmp[n..]; | |
105 | offset += n as u64; | |
106 | } | |
107 | Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} | |
108 | Err(e) => return Err(e), | |
109 | } | |
110 | } | |
111 | if !buf.is_empty() { | |
60c5eb7d | 112 | Err(io::Error::new(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer")) |
416331ca XL |
113 | } else { |
114 | Ok(()) | |
115 | } | |
116 | } | |
117 | ||
118 | /// Writes a number of bytes starting from a given offset. | |
119 | /// | |
120 | /// Returns the number of bytes written. | |
121 | /// | |
122 | /// The offset is relative to the start of the file and thus independent | |
123 | /// from the current cursor. | |
124 | /// | |
125 | /// The current file cursor is not affected by this function. | |
126 | /// | |
127 | /// When writing beyond the end of the file, the file is appropriately | |
128 | /// extended and the intermediate bytes are initialized with the value 0. | |
129 | /// | |
130 | /// Note that similar to [`File::write`], it is not an error to return a | |
131 | /// short write. | |
132 | /// | |
3dfed10e | 133 | /// [`File::write`]: fs::File::write |
416331ca XL |
134 | /// |
135 | /// # Examples | |
136 | /// | |
137 | /// ```no_run | |
138 | /// use std::fs::File; | |
139 | /// use std::io; | |
140 | /// use std::os::unix::prelude::FileExt; | |
141 | /// | |
142 | /// fn main() -> io::Result<()> { | |
143 | /// let file = File::open("foo.txt")?; | |
144 | /// | |
145 | /// // We now write at the offset 10. | |
146 | /// file.write_at(b"sushi", 10)?; | |
147 | /// Ok(()) | |
148 | /// } | |
149 | /// ``` | |
150 | #[stable(feature = "file_offset", since = "1.15.0")] | |
151 | fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>; | |
152 | ||
153 | /// Attempts to write an entire buffer starting from a given offset. | |
154 | /// | |
155 | /// The offset is relative to the start of the file and thus independent | |
156 | /// from the current cursor. | |
157 | /// | |
158 | /// The current file cursor is not affected by this function. | |
159 | /// | |
160 | /// This method will continuously call [`write_at`] until there is no more data | |
161 | /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is | |
162 | /// returned. This method will not return until the entire buffer has been | |
163 | /// successfully written or such an error occurs. The first error that is | |
164 | /// not of [`ErrorKind::Interrupted`] kind generated from this method will be | |
165 | /// returned. | |
166 | /// | |
167 | /// # Errors | |
168 | /// | |
169 | /// This function will return the first error of | |
170 | /// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns. | |
171 | /// | |
3dfed10e XL |
172 | /// [`ErrorKind::Interrupted`]: io::ErrorKind::Interrupted |
173 | /// [`write_at`]: FileExt::write_at | |
416331ca XL |
174 | /// |
175 | /// # Examples | |
176 | /// | |
177 | /// ```no_run | |
178 | /// #![feature(rw_exact_all_at)] | |
179 | /// use std::fs::File; | |
180 | /// use std::io; | |
181 | /// use std::os::unix::prelude::FileExt; | |
182 | /// | |
183 | /// fn main() -> io::Result<()> { | |
184 | /// let file = File::open("foo.txt")?; | |
185 | /// | |
186 | /// // We now write at the offset 10. | |
187 | /// file.write_all_at(b"sushi", 10)?; | |
188 | /// Ok(()) | |
189 | /// } | |
190 | /// ``` | |
191 | #[stable(feature = "rw_exact_all_at", since = "1.33.0")] | |
192 | fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> { | |
193 | while !buf.is_empty() { | |
194 | match self.write_at(buf, offset) { | |
60c5eb7d XL |
195 | Ok(0) => { |
196 | return Err(io::Error::new( | |
197 | io::ErrorKind::WriteZero, | |
198 | "failed to write whole buffer", | |
199 | )); | |
200 | } | |
416331ca XL |
201 | Ok(n) => { |
202 | buf = &buf[n..]; | |
203 | offset += n as u64 | |
204 | } | |
205 | Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} | |
206 | Err(e) => return Err(e), | |
207 | } | |
208 | } | |
209 | Ok(()) | |
210 | } | |
211 | } | |
212 | ||
213 | #[stable(feature = "file_offset", since = "1.15.0")] | |
214 | impl FileExt for fs::File { | |
215 | fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> { | |
216 | self.as_inner().read_at(buf, offset) | |
217 | } | |
218 | fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> { | |
219 | self.as_inner().write_at(buf, offset) | |
220 | } | |
221 | } | |
222 | ||
223 | /// Unix-specific extensions to [`fs::Permissions`]. | |
416331ca XL |
224 | #[stable(feature = "fs_ext", since = "1.1.0")] |
225 | pub trait PermissionsExt { | |
226 | /// Returns the underlying raw `st_mode` bits that contain the standard | |
227 | /// Unix permissions for this file. | |
228 | /// | |
229 | /// # Examples | |
230 | /// | |
231 | /// ```no_run | |
232 | /// use std::fs::File; | |
233 | /// use std::os::unix::fs::PermissionsExt; | |
234 | /// | |
235 | /// fn main() -> std::io::Result<()> { | |
236 | /// let f = File::create("foo.txt")?; | |
237 | /// let metadata = f.metadata()?; | |
238 | /// let permissions = metadata.permissions(); | |
239 | /// | |
240 | /// println!("permissions: {}", permissions.mode()); | |
241 | /// Ok(()) } | |
242 | /// ``` | |
243 | #[stable(feature = "fs_ext", since = "1.1.0")] | |
244 | fn mode(&self) -> u32; | |
245 | ||
246 | /// Sets the underlying raw bits for this set of permissions. | |
247 | /// | |
248 | /// # Examples | |
249 | /// | |
250 | /// ```no_run | |
251 | /// use std::fs::File; | |
252 | /// use std::os::unix::fs::PermissionsExt; | |
253 | /// | |
254 | /// fn main() -> std::io::Result<()> { | |
255 | /// let f = File::create("foo.txt")?; | |
256 | /// let metadata = f.metadata()?; | |
257 | /// let mut permissions = metadata.permissions(); | |
258 | /// | |
259 | /// permissions.set_mode(0o644); // Read/write for owner and read for others. | |
260 | /// assert_eq!(permissions.mode(), 0o644); | |
261 | /// Ok(()) } | |
262 | /// ``` | |
263 | #[stable(feature = "fs_ext", since = "1.1.0")] | |
264 | fn set_mode(&mut self, mode: u32); | |
265 | ||
266 | /// Creates a new instance of `Permissions` from the given set of Unix | |
267 | /// permission bits. | |
268 | /// | |
269 | /// # Examples | |
270 | /// | |
271 | /// ``` | |
272 | /// use std::fs::Permissions; | |
273 | /// use std::os::unix::fs::PermissionsExt; | |
274 | /// | |
275 | /// // Read/write for owner and read for others. | |
276 | /// let permissions = Permissions::from_mode(0o644); | |
277 | /// assert_eq!(permissions.mode(), 0o644); | |
278 | /// ``` | |
279 | #[stable(feature = "fs_ext", since = "1.1.0")] | |
280 | fn from_mode(mode: u32) -> Self; | |
281 | } | |
282 | ||
283 | #[stable(feature = "fs_ext", since = "1.1.0")] | |
284 | impl PermissionsExt for Permissions { | |
285 | fn mode(&self) -> u32 { | |
286 | self.as_inner().mode() | |
287 | } | |
288 | ||
289 | fn set_mode(&mut self, mode: u32) { | |
290 | *self = Permissions::from_inner(FromInner::from_inner(mode)); | |
291 | } | |
292 | ||
293 | fn from_mode(mode: u32) -> Permissions { | |
294 | Permissions::from_inner(FromInner::from_inner(mode)) | |
295 | } | |
296 | } | |
297 | ||
298 | /// Unix-specific extensions to [`fs::OpenOptions`]. | |
416331ca XL |
299 | #[stable(feature = "fs_ext", since = "1.1.0")] |
300 | pub trait OpenOptionsExt { | |
301 | /// Sets the mode bits that a new file will be created with. | |
302 | /// | |
60c5eb7d | 303 | /// If a new file is created as part of an `OpenOptions::open` call then this |
416331ca XL |
304 | /// specified `mode` will be used as the permission bits for the new file. |
305 | /// If no `mode` is set, the default of `0o666` will be used. | |
60c5eb7d | 306 | /// The operating system masks out bits with the system's `umask`, to produce |
416331ca XL |
307 | /// the final permissions. |
308 | /// | |
309 | /// # Examples | |
310 | /// | |
311 | /// ```no_run | |
312 | /// use std::fs::OpenOptions; | |
313 | /// use std::os::unix::fs::OpenOptionsExt; | |
314 | /// | |
315 | /// # fn main() { | |
316 | /// let mut options = OpenOptions::new(); | |
317 | /// options.mode(0o644); // Give read/write for owner and read for others. | |
318 | /// let file = options.open("foo.txt"); | |
319 | /// # } | |
320 | /// ``` | |
321 | #[stable(feature = "fs_ext", since = "1.1.0")] | |
322 | fn mode(&mut self, mode: u32) -> &mut Self; | |
323 | ||
324 | /// Pass custom flags to the `flags` argument of `open`. | |
325 | /// | |
326 | /// The bits that define the access mode are masked out with `O_ACCMODE`, to | |
327 | /// ensure they do not interfere with the access mode set by Rusts options. | |
328 | /// | |
329 | /// Custom flags can only set flags, not remove flags set by Rusts options. | |
330 | /// This options overwrites any previously set custom flags. | |
331 | /// | |
332 | /// # Examples | |
333 | /// | |
334 | /// ```no_run | |
335 | /// # #![feature(libc)] | |
336 | /// extern crate libc; | |
337 | /// use std::fs::OpenOptions; | |
338 | /// use std::os::unix::fs::OpenOptionsExt; | |
339 | /// | |
340 | /// # fn main() { | |
341 | /// let mut options = OpenOptions::new(); | |
342 | /// options.write(true); | |
343 | /// if cfg!(unix) { | |
344 | /// options.custom_flags(libc::O_NOFOLLOW); | |
345 | /// } | |
346 | /// let file = options.open("foo.txt"); | |
347 | /// # } | |
348 | /// ``` | |
349 | #[stable(feature = "open_options_ext", since = "1.10.0")] | |
350 | fn custom_flags(&mut self, flags: i32) -> &mut Self; | |
351 | } | |
352 | ||
353 | /*#[stable(feature = "fs_ext", since = "1.1.0")] | |
354 | impl OpenOptionsExt for OpenOptions { | |
355 | fn mode(&mut self, mode: u32) -> &mut OpenOptions { | |
356 | self.as_inner_mut().mode(mode); self | |
357 | } | |
358 | ||
359 | fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions { | |
360 | self.as_inner_mut().custom_flags(flags); self | |
361 | } | |
362 | } | |
363 | */ | |
364 | ||
365 | /// Unix-specific extensions to [`fs::Metadata`]. | |
416331ca XL |
366 | #[stable(feature = "metadata_ext", since = "1.1.0")] |
367 | pub trait MetadataExt { | |
368 | /// Returns the ID of the device containing the file. | |
369 | /// | |
370 | /// # Examples | |
371 | /// | |
372 | /// ```no_run | |
373 | /// use std::io; | |
374 | /// use std::fs; | |
375 | /// use std::os::unix::fs::MetadataExt; | |
376 | /// | |
377 | /// fn main() -> io::Result<()> { | |
378 | /// let meta = fs::metadata("some_file")?; | |
379 | /// let dev_id = meta.dev(); | |
380 | /// Ok(()) | |
381 | /// } | |
382 | /// ``` | |
383 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
384 | fn dev(&self) -> u64; | |
385 | /// Returns the inode number. | |
386 | /// | |
387 | /// # Examples | |
388 | /// | |
389 | /// ```no_run | |
390 | /// use std::fs; | |
391 | /// use std::os::unix::fs::MetadataExt; | |
392 | /// use std::io; | |
393 | /// | |
394 | /// fn main() -> io::Result<()> { | |
395 | /// let meta = fs::metadata("some_file")?; | |
396 | /// let inode = meta.ino(); | |
397 | /// Ok(()) | |
398 | /// } | |
399 | /// ``` | |
400 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
401 | fn ino(&self) -> u64; | |
402 | /// Returns the rights applied to this file. | |
403 | /// | |
404 | /// # Examples | |
405 | /// | |
406 | /// ```no_run | |
407 | /// use std::fs; | |
408 | /// use std::os::unix::fs::MetadataExt; | |
409 | /// use std::io; | |
410 | /// | |
411 | /// fn main() -> io::Result<()> { | |
412 | /// let meta = fs::metadata("some_file")?; | |
413 | /// let mode = meta.mode(); | |
414 | /// let user_has_write_access = mode & 0o200; | |
415 | /// let user_has_read_write_access = mode & 0o600; | |
416 | /// let group_has_read_access = mode & 0o040; | |
417 | /// let others_have_exec_access = mode & 0o001; | |
418 | /// Ok(()) | |
419 | /// } | |
420 | /// ``` | |
421 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
422 | fn mode(&self) -> u32; | |
423 | /// Returns the number of hard links pointing to this file. | |
424 | /// | |
425 | /// # Examples | |
426 | /// | |
427 | /// ```no_run | |
428 | /// use std::fs; | |
429 | /// use std::os::unix::fs::MetadataExt; | |
1b1a35ee | 430 | /// use std::io; |
416331ca XL |
431 | /// |
432 | /// fn main() -> io::Result<()> { | |
433 | /// let meta = fs::metadata("some_file")?; | |
434 | /// let nb_hard_links = meta.nlink(); | |
435 | /// Ok(()) | |
436 | /// } | |
437 | /// ``` | |
438 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
439 | fn nlink(&self) -> u64; | |
440 | /// Returns the user ID of the owner of this file. | |
441 | /// | |
442 | /// # Examples | |
443 | /// | |
444 | /// ```no_run | |
445 | /// use std::fs; | |
446 | /// use std::os::unix::fs::MetadataExt; | |
447 | /// use std::io; | |
448 | /// | |
449 | /// fn main() -> io::Result<()> { | |
450 | /// let meta = fs::metadata("some_file")?; | |
451 | /// let user_id = meta.uid(); | |
452 | /// Ok(()) | |
453 | /// } | |
454 | /// ``` | |
455 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
456 | fn uid(&self) -> u32; | |
457 | /// Returns the group ID of the owner of this file. | |
458 | /// | |
459 | /// # Examples | |
460 | /// | |
461 | /// ```no_run | |
462 | /// use std::fs; | |
463 | /// use std::os::unix::fs::MetadataExt; | |
464 | /// use std::io; | |
465 | /// | |
466 | /// fn main() -> io::Result<()> { | |
467 | /// let meta = fs::metadata("some_file")?; | |
468 | /// let group_id = meta.gid(); | |
469 | /// Ok(()) | |
470 | /// } | |
471 | /// ``` | |
472 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
473 | fn gid(&self) -> u32; | |
474 | /// Returns the device ID of this file (if it is a special one). | |
475 | /// | |
476 | /// # Examples | |
477 | /// | |
478 | /// ```no_run | |
479 | /// use std::fs; | |
480 | /// use std::os::unix::fs::MetadataExt; | |
481 | /// use std::io; | |
482 | /// | |
483 | /// fn main() -> io::Result<()> { | |
484 | /// let meta = fs::metadata("some_file")?; | |
485 | /// let device_id = meta.rdev(); | |
486 | /// Ok(()) | |
487 | /// } | |
488 | /// ``` | |
489 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
490 | fn rdev(&self) -> u64; | |
491 | /// Returns the total size of this file in bytes. | |
492 | /// | |
493 | /// # Examples | |
494 | /// | |
495 | /// ```no_run | |
496 | /// use std::fs; | |
497 | /// use std::os::unix::fs::MetadataExt; | |
498 | /// use std::io; | |
499 | /// | |
500 | /// fn main() -> io::Result<()> { | |
501 | /// let meta = fs::metadata("some_file")?; | |
502 | /// let file_size = meta.size(); | |
503 | /// Ok(()) | |
504 | /// } | |
505 | /// ``` | |
506 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
507 | fn size(&self) -> u64; | |
508 | /// Returns the time of the last access to the file. | |
509 | /// | |
510 | /// # Examples | |
511 | /// | |
512 | /// ```no_run | |
513 | /// use std::fs; | |
514 | /// use std::os::unix::fs::MetadataExt; | |
515 | /// use std::io; | |
516 | /// | |
517 | /// fn main() -> io::Result<()> { | |
518 | /// let meta = fs::metadata("some_file")?; | |
519 | /// let last_access_time = meta.atime(); | |
520 | /// Ok(()) | |
521 | /// } | |
522 | /// ``` | |
523 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
524 | fn atime(&self) -> i64; | |
525 | /// Returns the time of the last access to the file in nanoseconds. | |
526 | /// | |
527 | /// # Examples | |
528 | /// | |
529 | /// ```no_run | |
530 | /// use std::fs; | |
531 | /// use std::os::unix::fs::MetadataExt; | |
532 | /// use std::io; | |
533 | /// | |
534 | /// fn main() -> io::Result<()> { | |
535 | /// let meta = fs::metadata("some_file")?; | |
536 | /// let nano_last_access_time = meta.atime_nsec(); | |
537 | /// Ok(()) | |
538 | /// } | |
539 | /// ``` | |
540 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
541 | fn mtime(&self) -> i64; | |
542 | /// Returns the time of the last modification of the file in nanoseconds. | |
543 | /// | |
544 | /// # Examples | |
545 | /// | |
546 | /// ```no_run | |
547 | /// use std::fs; | |
548 | /// use std::os::unix::fs::MetadataExt; | |
549 | /// use std::io; | |
550 | /// | |
551 | /// fn main() -> io::Result<()> { | |
552 | /// let meta = fs::metadata("some_file")?; | |
553 | /// let nano_last_modification_time = meta.mtime_nsec(); | |
554 | /// Ok(()) | |
555 | /// } | |
556 | /// ``` | |
557 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
558 | fn ctime(&self) -> i64; | |
559 | /// Returns the time of the last status change of the file in nanoseconds. | |
560 | /// | |
561 | /// # Examples | |
562 | /// | |
563 | /// ```no_run | |
564 | /// use std::fs; | |
565 | /// use std::os::unix::fs::MetadataExt; | |
566 | /// use std::io; | |
567 | /// | |
568 | /// fn main() -> io::Result<()> { | |
569 | /// let meta = fs::metadata("some_file")?; | |
570 | /// let nano_last_status_change_time = meta.ctime_nsec(); | |
571 | /// Ok(()) | |
572 | /// } | |
573 | /// ``` | |
574 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
575 | fn blksize(&self) -> u64; | |
576 | /// Returns the number of blocks allocated to the file, in 512-byte units. | |
577 | /// | |
578 | /// Please note that this may be smaller than `st_size / 512` when the file has holes. | |
579 | /// | |
580 | /// # Examples | |
581 | /// | |
582 | /// ```no_run | |
583 | /// use std::fs; | |
584 | /// use std::os::unix::fs::MetadataExt; | |
585 | /// use std::io; | |
586 | /// | |
587 | /// fn main() -> io::Result<()> { | |
588 | /// let meta = fs::metadata("some_file")?; | |
589 | /// let blocks = meta.blocks(); | |
590 | /// Ok(()) | |
591 | /// } | |
592 | /// ``` | |
593 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
594 | fn blocks(&self) -> u64; | |
595 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
596 | fn attrib(&self) -> u8; | |
597 | } | |
598 | ||
599 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
600 | impl MetadataExt for fs::Metadata { | |
60c5eb7d XL |
601 | fn dev(&self) -> u64 { |
602 | self.st_dev() | |
603 | } | |
604 | fn ino(&self) -> u64 { | |
605 | self.st_ino() | |
606 | } | |
607 | fn mode(&self) -> u32 { | |
608 | self.st_mode() | |
609 | } | |
610 | fn nlink(&self) -> u64 { | |
611 | self.st_nlink() | |
612 | } | |
613 | fn uid(&self) -> u32 { | |
614 | self.st_uid() | |
615 | } | |
616 | fn gid(&self) -> u32 { | |
617 | self.st_gid() | |
618 | } | |
619 | fn rdev(&self) -> u64 { | |
620 | self.st_rdev() | |
621 | } | |
622 | fn size(&self) -> u64 { | |
623 | self.st_size() | |
624 | } | |
625 | fn atime(&self) -> i64 { | |
626 | self.st_atime() | |
627 | } | |
628 | fn mtime(&self) -> i64 { | |
629 | self.st_mtime() | |
630 | } | |
631 | fn ctime(&self) -> i64 { | |
632 | self.st_ctime() | |
633 | } | |
634 | fn blksize(&self) -> u64 { | |
635 | self.st_blksize() | |
636 | } | |
637 | fn blocks(&self) -> u64 { | |
638 | self.st_blocks() | |
639 | } | |
640 | fn attrib(&self) -> u8 { | |
641 | self.st_attrib() | |
642 | } | |
416331ca XL |
643 | } |
644 | ||
3dfed10e | 645 | /// Unix-specific extensions for [`fs::FileType`]. |
416331ca XL |
646 | /// |
647 | /// Adds support for special Unix file types such as block/character devices, | |
648 | /// pipes, and sockets. | |
416331ca XL |
649 | #[stable(feature = "file_type_ext", since = "1.5.0")] |
650 | pub trait FileTypeExt { | |
651 | /// Returns whether this file type is a block device. | |
652 | /// | |
653 | /// # Examples | |
654 | /// | |
655 | /// ```no_run | |
656 | /// use std::fs; | |
657 | /// use std::os::unix::fs::FileTypeExt; | |
658 | /// use std::io; | |
659 | /// | |
660 | /// fn main() -> io::Result<()> { | |
661 | /// let meta = fs::metadata("block_device_file")?; | |
662 | /// let file_type = meta.file_type(); | |
663 | /// assert!(file_type.is_block_device()); | |
664 | /// Ok(()) | |
665 | /// } | |
666 | /// ``` | |
667 | #[stable(feature = "file_type_ext", since = "1.5.0")] | |
668 | fn is_block_device(&self) -> bool; | |
669 | /// Returns whether this file type is a char device. | |
670 | /// | |
671 | /// # Examples | |
672 | /// | |
673 | /// ```no_run | |
674 | /// use std::fs; | |
675 | /// use std::os::unix::fs::FileTypeExt; | |
676 | /// use std::io; | |
677 | /// | |
678 | /// fn main() -> io::Result<()> { | |
679 | /// let meta = fs::metadata("char_device_file")?; | |
680 | /// let file_type = meta.file_type(); | |
681 | /// assert!(file_type.is_char_device()); | |
682 | /// Ok(()) | |
683 | /// } | |
684 | /// ``` | |
685 | #[stable(feature = "file_type_ext", since = "1.5.0")] | |
686 | fn is_char_device(&self) -> bool; | |
687 | /// Returns whether this file type is a fifo. | |
688 | /// | |
689 | /// # Examples | |
690 | /// | |
691 | /// ```no_run | |
692 | /// use std::fs; | |
693 | /// use std::os::unix::fs::FileTypeExt; | |
694 | /// use std::io; | |
695 | /// | |
696 | /// fn main() -> io::Result<()> { | |
697 | /// let meta = fs::metadata("fifo_file")?; | |
698 | /// let file_type = meta.file_type(); | |
699 | /// assert!(file_type.is_fifo()); | |
700 | /// Ok(()) | |
701 | /// } | |
702 | /// ``` | |
703 | #[stable(feature = "file_type_ext", since = "1.5.0")] | |
704 | fn is_fifo(&self) -> bool; | |
705 | /// Returns whether this file type is a socket. | |
706 | /// | |
707 | /// # Examples | |
708 | /// | |
709 | /// ```no_run | |
710 | /// use std::fs; | |
711 | /// use std::os::unix::fs::FileTypeExt; | |
712 | /// use std::io; | |
713 | /// | |
714 | /// fn main() -> io::Result<()> { | |
715 | /// let meta = fs::metadata("unix.socket")?; | |
716 | /// let file_type = meta.file_type(); | |
717 | /// assert!(file_type.is_socket()); | |
718 | /// Ok(()) | |
719 | /// } | |
720 | /// ``` | |
721 | #[stable(feature = "file_type_ext", since = "1.5.0")] | |
722 | fn is_socket(&self) -> bool; | |
723 | } | |
724 | ||
725 | #[stable(feature = "file_type_ext", since = "1.5.0")] | |
726 | impl FileTypeExt for fs::FileType { | |
60c5eb7d XL |
727 | fn is_block_device(&self) -> bool { |
728 | self.as_inner().is(libc::S_IFBLK) | |
729 | } | |
730 | fn is_char_device(&self) -> bool { | |
731 | self.as_inner().is(libc::S_IFCHR) | |
732 | } | |
733 | fn is_fifo(&self) -> bool { | |
734 | self.as_inner().is(libc::S_IFIFO) | |
735 | } | |
736 | fn is_socket(&self) -> bool { | |
737 | self.as_inner().is(libc::S_IFSOCK) | |
738 | } | |
416331ca XL |
739 | } |
740 | ||
741 | /// Unix-specific extension methods for [`fs::DirEntry`]. | |
416331ca XL |
742 | #[stable(feature = "dir_entry_ext", since = "1.1.0")] |
743 | pub trait DirEntryExt { | |
744 | /// Returns the underlying `d_ino` field in the contained `dirent` | |
745 | /// structure. | |
746 | /// | |
747 | /// # Examples | |
748 | /// | |
749 | /// ``` | |
750 | /// use std::fs; | |
751 | /// use std::os::unix::fs::DirEntryExt; | |
752 | /// | |
753 | /// if let Ok(entries) = fs::read_dir(".") { | |
754 | /// for entry in entries { | |
755 | /// if let Ok(entry) = entry { | |
756 | /// // Here, `entry` is a `DirEntry`. | |
757 | /// println!("{:?}: {}", entry.file_name(), entry.ino()); | |
758 | /// } | |
759 | /// } | |
760 | /// } | |
761 | /// ``` | |
762 | #[stable(feature = "dir_entry_ext", since = "1.1.0")] | |
763 | fn ino(&self) -> u64; | |
764 | } | |
765 | ||
766 | #[stable(feature = "dir_entry_ext", since = "1.1.0")] | |
767 | impl DirEntryExt for fs::DirEntry { | |
60c5eb7d XL |
768 | fn ino(&self) -> u64 { |
769 | self.as_inner().ino() | |
770 | } | |
416331ca XL |
771 | } |
772 | ||
773 | /// Creates a new symbolic link on the filesystem. | |
774 | /// | |
775 | /// The `dst` path will be a symbolic link pointing to the `src` path. | |
776 | /// | |
416331ca XL |
777 | /// # Examples |
778 | /// | |
779 | /// ```no_run | |
780 | /// use std::os::unix::fs; | |
781 | /// | |
782 | /// fn main() -> std::io::Result<()> { | |
783 | /// fs::symlink("a.txt", "b.txt")?; | |
784 | /// Ok(()) | |
785 | /// } | |
786 | /// ``` | |
787 | #[stable(feature = "symlink", since = "1.1.0")] | |
60c5eb7d | 788 | pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> { |
416331ca XL |
789 | sys::fs::symlink(src.as_ref(), dst.as_ref()) |
790 | } | |
791 | ||
792 | /// Unix-specific extensions to [`fs::DirBuilder`]. | |
416331ca XL |
793 | #[stable(feature = "dir_builder", since = "1.6.0")] |
794 | pub trait DirBuilderExt { | |
795 | /// Sets the mode to create new directories with. This option defaults to | |
796 | /// 0o777. | |
797 | /// | |
798 | /// # Examples | |
799 | /// | |
800 | /// ```no_run | |
801 | /// use std::fs::DirBuilder; | |
802 | /// use std::os::unix::fs::DirBuilderExt; | |
803 | /// | |
804 | /// let mut builder = DirBuilder::new(); | |
805 | /// builder.mode(0o755); | |
806 | /// ``` | |
807 | #[stable(feature = "dir_builder", since = "1.6.0")] | |
808 | fn mode(&mut self, mode: u32) -> &mut Self; | |
809 | } | |
810 | ||
811 | #[stable(feature = "dir_builder", since = "1.6.0")] | |
812 | impl DirBuilderExt for fs::DirBuilder { | |
813 | fn mode(&mut self, mode: u32) -> &mut fs::DirBuilder { | |
814 | self.as_inner_mut().set_mode(mode); | |
815 | self | |
816 | } | |
817 | } |