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
/*
    diskit – Utilities for intercepting disk requests.
    Copyright (C) 2022  Matthias Kaak

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

#![warn(
    clippy::all,
    clippy::pedantic,
    clippy::nursery,
    rustdoc::missing_crate_level_docs,
    missing_docs,
    clippy::cargo_common_metadata
)]
// Anachronism
#![allow(clippy::non_ascii_literal)]
// More or less manual checked and documentation agrees with me that
// it's usually not needed.
#![allow(
    clippy::cast_possible_truncation,
    clippy::cast_sign_loss,
    clippy::cast_precision_loss,
    clippy::cast_lossless,
    clippy::cast_possible_wrap
)]
// Currently this only warns on function which are just replicas of
// stdlib functions and they all link to their original functions
// (which does have an "error" section).  Since I think that's it
// obvious that these function have the same error condition this is a
// false positive.  Due to the number of such functions I don't want
// to add this to every one on it's own.  TODO: Regularly remove this
// temporarily to check if it still only warns on these functions.
#![allow(clippy::missing_errors_doc)]
// It's ridiculous that this hasn't landed yet and these error codes
// are really practical here.  Since `diskit` isn't 1.0 yet, I don't
// need to give stability guarantees, so it's fine that I use rustc
// nightly.
#![feature(io_error_more)]
// A lot of structs and similar are completely pub so that others can
// also implement diskits and if then not all fields are documented
// this lint warns.  But this is often (somewhat) wrong, since they're
// already documented at the struct (or similar) level or at a linked
// place.  Because of this I believe that these are false positives,
// even though I try to fix all of them over time.
// #[allow(missing_docs)]
// This nursery lint has a lot of false positives.
// TODO: Remove once lint is out of nursery.
#![allow(clippy::significant_drop_tightening)]

//! Utilities for intercepting disk requests
//!
//! Diskit (short for "**Dis**c root **kit**") attempts to be an
//! intransparent, rust-style root kit for intercepting and modifying
//! requests to the hard drive.  To use it, decide what you want to do
//! with the intercepted requests and choose the appropriate diskit
//! (e.g.: no interception -> [`StdDiskit`]; redirect to virtual file
//! system -> [`VirtualDiskit`]; logging all requests ->
//! [`LogDiskit`]), then route all requests through it:
//! ```
//! use std::io::{Read, Write};
//! use diskit::{diskit_extend::DiskitExt, Diskit, VirtualDiskit};
//!
//! # fn main() -> Result<(), std::io::Error>
//! # {
//! // All requests are redircted to a virtual file system.
//! let diskit = VirtualDiskit::default();
//!
//! // This writes "Hello, World!" in the newly created file "test.txt".
//! let mut file1 = diskit.create("test.txt")?;
//! file1.write_all(b"Hello, World!")?;
//!
//! // You can close `file1` and it still works:
//! // file1.close()?;
//!
//! // This reads the just created file.
//! let mut file2 = diskit.open("test.txt")?;
//! let mut buf = String::new();
//! file2.read_to_string(&mut buf)?;
//!
//! assert_eq!(buf, "Hello, World!");
//!
//! # Ok(())
//! # }
//! ```
//! If you want to see how diskit would be used in a full program, see
//! [legacylisten](https://codeberg.org/zvavybir/legacylisten), the
//! program I wrote diskit for.
//! # Making your own diskit
//! You can make your own diskit by implementing the [`Diskit`] trait.
//!
//! Because a lot of [stdlib](std) types are intransparent, there are
//! transparent replicas of them here that you're going to have to
//! use.  Most of these types have an inner type
//! (e.g. [`File`](file::File) has [`FileInner`](file::FileInner)) to
//! make the [`Diskit`] trait object-safe and this library easy to
//! use.
//!
//! To make [`StdDiskit`] as overheadless as possible most types have an
//! `Option<StdsVersionOfThisType>`, which should be [`None`] in your
//! implementation.
//!
//! If your diskit internally still needs to access the disk, please
//! consider delegating these to an other diskit like [`LogDiskit`]
//! does.
//! # Size of a diskit
//! Diskits *should* (there is no way or reason to enforce it) be as
//! small and cheaply [clone](Clone)able as possible.  This is because
//! this library should be optimized for [`StdDiskit`] (as this is
//! expected to be it's most used – albeit most useless – diskit) and
//! while adding diskit support to
//! [legacylisten](https://crates.io/crates/legacylisten) it became
//! apparent that for good usability and performance diskits are
//! [clone](Clone)d often and passed by value.
//!
//! If your diskit is bigger than one [`usize`] consider wrapping it
//! in an [`Arc`](std::sync::Arc).
//! # Stability
//! Diskit is still in a very early version and nothing is stable,
//! although I *try* to keep it stable.
//! # Contributing
//! I have written that library specifically for
//! [legacylisten](https://crates.io/crates/legacylisten) and added
//! (mostly) only what I needed for that, so it's still lacking in a
//! lot for normal usage.  If you need an additional feature (or
//! features) or otherwise have an idea how to make it better, please
//! don't hesitate to
//! [share](https://codeberg.org/zvavybir/diskit/issues/new) it or
//! [implement](https://codeberg.org/zvavybir/diskit/pulls) it
//! yourself.

pub mod dir_entry;
pub mod diskit;
pub mod diskit_extend;
pub mod file;
pub mod log_diskit;
pub mod metadata;
pub mod open_options;
pub mod std_diskit;
pub mod virtual_diskit;
pub mod void_diskit;
pub mod walkdir;

pub use crate::diskit::Diskit;
pub use log_diskit::LogDiskit;
pub use std_diskit::StdDiskit;
pub use virtual_diskit::VirtualDiskit;
pub use void_diskit::VoidDiskit;