1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
//! `std::fs` 模块中原语的 Windows 特定扩展。

#![stable(feature = "rust1", since = "1.0.0")]

use crate::fs::{self, Metadata, OpenOptions};
use crate::io;
use crate::path::Path;
use crate::sys;
use crate::sys_common::{AsInner, AsInnerMut};

/// Windows 特定于 [`fs::File`] 的扩展。
#[stable(feature = "file_offset", since = "1.15.0")]
pub trait FileExt {
    /// 搜寻到给定位置并读取多个字节。
    ///
    /// 返回读取的字节数。
    ///
    /// 偏移量相对于文件的开始,因此独立于当前游标。
    ///
    /// 当前游标受此函数的影响,它被设置为读取的结尾。
    ///
    /// 超出文件末尾的读取将始终以 0\ 的长度返回。
    ///
    /// 请注意,类似于 `File::read`,短读返回不会出错。
    /// 从如此短的读取返回时,文件指针仍会更新。
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io;
    /// use std::fs::File;
    /// use std::os::windows::prelude::*;
    ///
    /// fn main() -> io::Result<()> {
    ///     let mut file = File::open("foo.txt")?;
    ///     let mut buffer = [0; 10];
    ///
    ///     // 从文件开头开始读取 10 个字节,从 72 个字节开始。
    /////
    ///     file.seek_read(&mut buffer[..], 72)?;
    ///     Ok(())
    /// }
    /// ```
    ///
    ///
    #[stable(feature = "file_offset", since = "1.15.0")]
    fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;

    /// 搜寻到给定位置并写入多个字节。
    ///
    /// 返回写入的字节数。
    ///
    /// 偏移量相对于文件的开始,因此独立于当前游标。
    /// 当前游标受此函数的影响,它被设置为写入结束。
    ///
    /// 当写入超出文件末尾时,文件将适当扩展,并且中间字节将保持未初始化状态。
    ///
    ///
    /// 请注意,与 `File::write` 相似,返回短写也不是错误。
    /// 从这么短的写入返回时,文件指针仍会更新。
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::fs::File;
    /// use std::os::windows::prelude::*;
    ///
    /// fn main() -> std::io::Result<()> {
    ///     let mut buffer = File::create("foo.txt")?;
    ///
    ///     // 从文件开头开始写一个字节字符串,从 72 个字节开始。
    /////
    ///     buffer.seek_write(b"some bytes", 72)?;
    ///     Ok(())
    /// }
    /// ```
    ///
    ///
    #[stable(feature = "file_offset", since = "1.15.0")]
    fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
}

#[stable(feature = "file_offset", since = "1.15.0")]
impl FileExt for fs::File {
    fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
        self.as_inner().read_at(buf, offset)
    }

    fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
        self.as_inner().write_at(buf, offset)
    }
}

/// Windows 特定于 [`fs::OpenOptions`] 的扩展。
#[stable(feature = "open_options_ext", since = "1.10.0")]
pub trait OpenOptionsExt {
    /// 将 `dwDesiredAccess` 参数覆盖为具有指定值的 [`CreateFile`]。
    ///
    /// 这将覆盖 `OpenOptions` 结构体上的 `read`,`write` 和 `append` 标志。
    /// 此方法提供对读取,写入和附加数据,属性 (如隐藏和系统) 和扩展属性的权限的细粒度控制。
    ///
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::fs::OpenOptions;
    /// use std::os::windows::prelude::*;
    ///
    /// // 在没有读写权限的情况下打开,例如,如果您只需要在文件上调用 `stat`
    /////
    /// let file = OpenOptions::new().access_mode(0).open("foo.txt");
    /// ```
    ///
    /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
    ///
    ///
    #[stable(feature = "open_options_ext", since = "1.10.0")]
    fn access_mode(&mut self, access: u32) -> &mut Self;

    /// 将 `dwShareMode` 参数覆盖为具有指定值的 [`CreateFile`]。
    ///
    /// 默认情况下,`share_mode` 设置为 `FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE`。
    /// 这允许其他进程在打开文件时读取,写入和 delete/rename。
    /// 删除任何标志将阻止其他进程执行相应的操作,直到关闭文件句柄为止。
    ///
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::fs::OpenOptions;
    /// use std::os::windows::prelude::*;
    ///
    /// // 当我们打开该文件以供写入时,请勿允许他人读取或修改此文件。
    /////
    /// let file = OpenOptions::new()
    ///     .write(true)
    ///     .share_mode(0)
    ///     .open("foo.txt");
    /// ```
    ///
    /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
    ///
    ///
    ///
    #[stable(feature = "open_options_ext", since = "1.10.0")]
    fn share_mode(&mut self, val: u32) -> &mut Self;

    /// 将 `dwFileFlags` 参数的额外标志设置为 [`CreateFile2`] 的指定值 (或将其与 `attributes` 和 `security_qos_flags` 组合以将 `dwFlagsAndAttributes` 设置为 [`CreateFile`])。
    ///
    ///
    /// 自定义标志只能设置标志,而不能删除 Rust 选项设置的标志。
    /// 此选项将覆盖以前设置的所有自定义标志。
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # #[cfg(for_demonstration_only)]
    /// extern crate winapi;
    /// # mod winapi { pub const FILE_FLAG_DELETE_ON_CLOSE: u32 = 0x04000000; }
    ///
    /// use std::fs::OpenOptions;
    /// use std::os::windows::prelude::*;
    ///
    /// let file = OpenOptions::new()
    ///     .create(true)
    ///     .write(true)
    ///     .custom_flags(winapi::FILE_FLAG_DELETE_ON_CLOSE)
    ///     .open("foo.txt");
    /// ```
    ///
    /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
    /// [`CreateFile2`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2
    ///
    ///
    #[stable(feature = "open_options_ext", since = "1.10.0")]
    fn custom_flags(&mut self, flags: u32) -> &mut Self;

    /// 将 `dwFileAttributes` 参数设置为 [`CreateFile2`] 的指定值 (或将其与 `custom_flags` 和 `security_qos_flags` 组合以将 `dwFlagsAndAttributes` 设置为 [`CreateFile`])。
    ///
    ///
    /// 如果由于 _new_ 文件尚不存在而创建了 _new_ 文件,并且已指定 `.create(true)` 或 `.create_new(true)`,则将为新文件提供 `.attributes()` 声明的属性。
    ///
    /// 如果使用 `.create(true).truncate(true)` 打开 _existing_ 文件,则将保留其现有属性并将其与 `.attributes()` 声明的属性合并。
    ///
    /// 在所有其他情况下,属性将被忽略。
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # #[cfg(for_demonstration_only)]
    /// extern crate winapi;
    /// # mod winapi { pub const FILE_ATTRIBUTE_HIDDEN: u32 = 2; }
    ///
    /// use std::fs::OpenOptions;
    /// use std::os::windows::prelude::*;
    ///
    /// let file = OpenOptions::new()
    ///     .write(true)
    ///     .create(true)
    ///     .attributes(winapi::FILE_ATTRIBUTE_HIDDEN)
    ///     .open("foo.txt");
    /// ```
    ///
    /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
    /// [`CreateFile2`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2
    ///
    ///
    ///
    ///
    ///
    ///
    #[stable(feature = "open_options_ext", since = "1.10.0")]
    fn attributes(&mut self, val: u32) -> &mut Self;

    /// 将 `dwSecurityQosFlags` 参数设置为 [`CreateFile2`] 的指定值 (或将其与 `custom_flags` 和 `attributes` 组合以将 `dwFlagsAndAttributes` 设置为 [`CreateFile`])。
    ///
    /// 默认情况下,未设置 `security_qos_flags`。
    /// 在打开命名管道时应指定此名称,以控制服务器进程可以代表客户端进程执行的程度 (安全模拟级别)。
    ///
    /// 如果未设置 `security_qos_flags`,则恶意程序可以通过诱使程序打开命名管道来允许其打开用户指定的路径,从而获得权限 Rust 进程的提升的权限。
    ///
    /// 因此可以说在打开任意路径时也应设置 `security_qos_flags`。
    /// 但是,这些位可能会与其他标志 (特别是 `FILE_FLAG_OPEN_NO_RECALL`) 发生冲突。
    ///
    /// 有关可能的值的信息,请参见 Windows Dev Center 网站上的 [Impersonation Levels]。使用此方法时,`SECURITY_SQOS_PRESENT` 标志会自动设置。
    ///
    ///
    ///
    ///
    ///
    ///
    ///

    /// # Examples
    ///
    /// ```no_run
    /// # #[cfg(for_demonstration_only)]
    /// extern crate winapi;
    /// # mod winapi { pub const SECURITY_IDENTIFICATION: u32 = 0; }
    /// use std::fs::OpenOptions;
    /// use std::os::windows::prelude::*;
    ///
    /// let file = OpenOptions::new()
    ///     .write(true)
    ///     .create(true)
    ///
    ///     // 将标志值设置为 `SecurityIdentification`。
    ///     .security_qos_flags(winapi::SECURITY_IDENTIFICATION)
    ///
    ///     .open(r"\\.\pipe\MyPipe");
    /// ```
    ///
    /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
    /// [`CreateFile2`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2
    /// [Impersonation Levels]:
    ///     https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-security_impersonation_level
    #[stable(feature = "open_options_ext", since = "1.10.0")]
    fn security_qos_flags(&mut self, flags: u32) -> &mut Self;
}

#[stable(feature = "open_options_ext", since = "1.10.0")]
impl OpenOptionsExt for OpenOptions {
    fn access_mode(&mut self, access: u32) -> &mut OpenOptions {
        self.as_inner_mut().access_mode(access);
        self
    }

    fn share_mode(&mut self, share: u32) -> &mut OpenOptions {
        self.as_inner_mut().share_mode(share);
        self
    }

    fn custom_flags(&mut self, flags: u32) -> &mut OpenOptions {
        self.as_inner_mut().custom_flags(flags);
        self
    }

    fn attributes(&mut self, attributes: u32) -> &mut OpenOptions {
        self.as_inner_mut().attributes(attributes);
        self
    }

    fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions {
        self.as_inner_mut().security_qos_flags(flags);
        self
    }
}

/// Windows 特定于 [`fs::Metadata`] 的扩展。
///
/// trait 公开的数据成员与 [`BY_HANDLE_FILE_INFORMATION`] 结构体的成员相对应。
///
///
/// [`BY_HANDLE_FILE_INFORMATION`]:
///     https://docs.microsoft.com/en-us/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
    /// 返回此元数据的 `dwFileAttributes` 字段的值。
    ///
    /// 该字段包含文件或目录的文件系统属性信息。
    /// 有关可能的值及其说明,请参见 Windows 开发人员中心中的 [File Attribute Constants]。
    ///
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io;
    /// use std::fs;
    /// use std::os::windows::prelude::*;
    ///
    /// fn main() -> io::Result<()> {
    ///     let metadata = fs::metadata("foo.txt")?;
    ///     let attributes = metadata.file_attributes();
    ///     Ok(())
    /// }
    /// ```
    ///
    /// [File Attribute Constants]:
    ///     https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants
    #[stable(feature = "metadata_ext", since = "1.1.0")]
    fn file_attributes(&self) -> u32;

    /// 返回此元数据的 `ftCreationTime` 字段的值。
    ///
    /// 返回的 64 位值等效于 [`FILETIME`] 结构体,它表示自 1601 年 1 月 1 日以来的 100 纳秒间隔 (UTC)。
    /// 建议将结构体自动转换为 `u64` 值。
    ///
    /// 如果基础文件系统不支持创建时间,则返回值为 0。
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io;
    /// use std::fs;
    /// use std::os::windows::prelude::*;
    ///
    /// fn main() -> io::Result<()> {
    ///     let metadata = fs::metadata("foo.txt")?;
    ///     let creation_time = metadata.creation_time();
    ///     Ok(())
    /// }
    /// ```
    ///
    /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime
    ///
    ///
    ///
    ///
    #[stable(feature = "metadata_ext", since = "1.1.0")]
    fn creation_time(&self) -> u64;

    /// 返回此元数据的 `ftLastAccessTime` 字段的值。
    ///
    /// 返回的 64 位值等效于 [`FILETIME`] 结构体,它表示自 1601 年 1 月 1 日以来的 100 纳秒间隔 (UTC)。
    ///
    /// 建议将结构体自动转换为 `u64` 值。
    ///
    /// 对于文件,该值指定最后一次读取或写入文件的时间。
    /// 对于目录,该值指定创建目录的时间。
    /// 对于文件和目录,指定的日期都是正确的,但是一天中的时间始终设置为午夜。
    ///
    /// 如果基础文件系统不支持上次访问时间,则返回值为 0。
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io;
    /// use std::fs;
    /// use std::os::windows::prelude::*;
    ///
    /// fn main() -> io::Result<()> {
    ///     let metadata = fs::metadata("foo.txt")?;
    ///     let last_access_time = metadata.last_access_time();
    ///     Ok(())
    /// }
    /// ```
    ///
    /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime
    ///
    ///
    ///
    ///
    ///
    #[stable(feature = "metadata_ext", since = "1.1.0")]
    fn last_access_time(&self) -> u64;

    /// 返回此元数据的 `ftLastWriteTime` 字段的值。
    ///
    /// 返回的 64 位值等效于 [`FILETIME`] 结构体,它表示自 1601 年 1 月 1 日以来的 100 纳秒间隔 (UTC)。
    /// 建议将结构体自动转换为 `u64` 值。
    ///
    /// 对于文件,该值指定文件的最后写入时间。对于目录,结构体指定目录的创建时间。
    ///
    /// 如果基础文件系统不支持上次写入时间,则返回值为 0。
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io;
    /// use std::fs;
    /// use std::os::windows::prelude::*;
    ///
    /// fn main() -> io::Result<()> {
    ///     let metadata = fs::metadata("foo.txt")?;
    ///     let last_write_time = metadata.last_write_time();
    ///     Ok(())
    /// }
    /// ```
    ///
    /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime
    ///
    ///
    ///
    ///
    ///
    ///
    #[stable(feature = "metadata_ext", since = "1.1.0")]
    fn last_write_time(&self) -> u64;

    /// 返回此元数据的 `nFileSize{High,Low}` 字段的值。
    ///
    ///
    /// 返回的值对目录没有意义。
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io;
    /// use std::fs;
    /// use std::os::windows::prelude::*;
    ///
    /// fn main() -> io::Result<()> {
    ///     let metadata = fs::metadata("foo.txt")?;
    ///     let file_size = metadata.file_size();
    ///     Ok(())
    /// }
    /// ```
    #[stable(feature = "metadata_ext", since = "1.1.0")]
    fn file_size(&self) -> u64;

    /// 返回此元数据的 `dwVolumeSerialNumber` 字段的值。
    ///
    /// 如果 `Metadata` 实例是从调用创建到 `DirEntry::metadata`,则将返回 `None`。
    /// 如果此 `Metadata` 是使用 `fs::metadata` 或 `File::metadata` 创建的,则它将返回 `Some`。
    ///
    ///
    #[unstable(feature = "windows_by_handle", issue = "63010")]
    fn volume_serial_number(&self) -> Option<u32>;

    /// 返回此元数据的 `nNumberOfLinks` 字段的值。
    ///
    /// 如果 `Metadata` 实例是从调用创建到 `DirEntry::metadata`,则将返回 `None`。
    /// 如果此 `Metadata` 是使用 `fs::metadata` 或 `File::metadata` 创建的,则它将返回 `Some`。
    ///
    ///
    #[unstable(feature = "windows_by_handle", issue = "63010")]
    fn number_of_links(&self) -> Option<u32>;

    /// 返回此元数据的 `nFileIndex{Low,High}` 字段的值。
    ///
    /// 如果 `Metadata` 实例是从调用创建到 `DirEntry::metadata`,则将返回 `None`。
    /// 如果此 `Metadata` 是使用 `fs::metadata` 或 `File::metadata` 创建的,则它将返回 `Some`。
    ///
    ///
    #[unstable(feature = "windows_by_handle", issue = "63010")]
    fn file_index(&self) -> Option<u64>;
}

#[stable(feature = "metadata_ext", since = "1.1.0")]
impl MetadataExt for Metadata {
    fn file_attributes(&self) -> u32 {
        self.as_inner().attrs()
    }
    fn creation_time(&self) -> u64 {
        self.as_inner().created_u64()
    }
    fn last_access_time(&self) -> u64 {
        self.as_inner().accessed_u64()
    }
    fn last_write_time(&self) -> u64 {
        self.as_inner().modified_u64()
    }
    fn file_size(&self) -> u64 {
        self.as_inner().size()
    }
    fn volume_serial_number(&self) -> Option<u32> {
        self.as_inner().volume_serial_number()
    }
    fn number_of_links(&self) -> Option<u32> {
        self.as_inner().number_of_links()
    }
    fn file_index(&self) -> Option<u64> {
        self.as_inner().file_index()
    }
}

/// Windows 特定于 [`fs::FileType`] 的扩展。
///
/// 在 Windows 上,符号链接知道它是文件还是目录。
#[unstable(feature = "windows_file_type_ext", issue = "none")]
pub trait FileTypeExt {
    /// 如果此文件类型是也是目录的符号链接,则返回 `true`。
    #[unstable(feature = "windows_file_type_ext", issue = "none")]
    fn is_symlink_dir(&self) -> bool;
    /// 如果此文件类型是也是文件的符号链接,则返回 `true`。
    #[unstable(feature = "windows_file_type_ext", issue = "none")]
    fn is_symlink_file(&self) -> bool;
}

#[unstable(feature = "windows_file_type_ext", issue = "none")]
impl FileTypeExt for fs::FileType {
    fn is_symlink_dir(&self) -> bool {
        self.as_inner().is_symlink_dir()
    }
    fn is_symlink_file(&self) -> bool {
        self.as_inner().is_symlink_file()
    }
}

/// 在文件系统上创建一个新的文件符号链接。
///
/// `link` 路径将是指向 `original` 路径的文件符号链接。
///
///
/// # Examples
///
/// ```no_run
/// use std::os::windows::fs;
///
/// fn main() -> std::io::Result<()> {
///     fs::symlink_file("a.txt", "b.txt")?;
///     Ok(())
/// }
/// ```
#[stable(feature = "symlink", since = "1.1.0")]
pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
    sys::fs::symlink_inner(original.as_ref(), link.as_ref(), false)
}

/// 在文件系统上创建一个新的目录符号链接。
///
/// `link` 路径将是指向 `original` 路径的目录符号链接。
///
///
/// # Examples
///
/// ```no_run
/// use std::os::windows::fs;
///
/// fn main() -> std::io::Result<()> {
///     fs::symlink_dir("a", "b")?;
///     Ok(())
/// }
/// ```
#[stable(feature = "symlink", since = "1.1.0")]
pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
    sys::fs::symlink_inner(original.as_ref(), link.as_ref(), true)
}