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
//! LiteboxFS is a modern POSIX filesystem in a SQLite database.
//!
//! ```
//! use std::io::{Read, Write, Seek, SeekFrom};
//!
//! use liteboxfs::{Connection, CreateOptions, FileKind, Owner};
//!
//! fn main() -> liteboxfs::Result<()> {
//! let mut conn = Connection::open_in_memory(&CreateOptions::new())?;
//!
//! let buf = conn.exec(|fs| {
//! let mut file = fs.create("example.txt", FileKind::Regular, Owner::current())?;
//!
//! file.write_all(b"Hello, world!")?;
//! file.seek(SeekFrom::Start(0))?;
//!
//! let mut buf = Vec::new();
//! file.read_to_end(&mut buf)?;
//!
//! liteboxfs::Result::Ok(buf)
//! })?;
//!
//! assert_eq!(buf, b"Hello, world!");
//!
//! Ok(())
//! }
//! ```
//!
//! # Getting Started
//!
//! A litebox is a SQLite database containing a filesystem.
//!
//! [`Filesystem`] is the main type you will use to interact with LiteboxFS. To access the
//! filesystem, you will first need to open a [`Connection`] and start a transaction.
//!
//! # Roots
//!
//! Unlike a traditional POSIX filesystem, LiteboxFS supports multiple root directories, each
//! identified by a universally unique [`RootId`]. This allows for multiple independent logical
//! filesystems to coexist within the same database and deduplicate data between them. This feature
//! can also be used to create copy-on-write snapshots of a filesystem.
//!
//! In addition to their UUID, roots can optionally have a name, which is a UTF-8 string that is
//! unique within the litebox.
//!
//! When you create a litebox, it will automatically create a default root with name
//! [`DEFAULT_ROOT_NAME`]. The default root always exists; it cannot be deleted.
//!
//! # Metadata
//!
//! A litebox can have [user-defined metadata](crate::UserMetadata) associated with it in the form
//! of key-value pairs. This metadata is stored persistently in the database and is not touched by
//! LiteboxFS, so applications or downstream libraries can use it for any purpose.
//!
//! Each root can also have its own user-defined metadata.
//!
//! # Compression and Deduplication
//!
//! LiteboxFS has two optional features to improve storage efficiency at the cost of performance:
//! [transparent compression](crate::CreateOptions::compression) and [content-defined
//! chunking](crate::CreateOptions::chunking).
//!
//! Files in a litebox are deduplicated at the block level, including between roots. When enabled,
//! content-defined chunking can improve deduplication ratios between files that are similar but
//! not identical.
//!
//! These features are configurable per-litebox, not per-root. Both these features are
//! feature-gated and disabled by default.
//!
//! # Transactions and Concurrency
//!
//! LiteboxFS is _transactional_, with the same fundamental guarantees and caveats as SQLite.
//!
//! This API makes transaction explicit, which means you can use them to maintain invariants in
//! your application, just like you would with a database.
//!
//! Internally, LiteboxFS uses savepoints to ensure that individual filesystem operations like
//! copying a file, deleting a file, writing data to a file, etc. are atomic and consistent, with
//! the transaction providing the isolation and durability.
//!
//! Like SQLite, the concurrency model of LiteboxFS depends on the [journal
//! mode](crate::JournalMode).
//!
//! - In the default mode, readers block writers and writers block readers.
//! - In [WAL mode](crate::JournalMode::Wal), reading and writing can happen concurrently.
//!
//! In both cases, you can only have a single write transaction active at a time, which means that
//! holding a long-running write transaction will block other connections from writing (and
//! possibly reading) to the litebox.
//!
//! Like SQLite, once a write happens, the transaction is implicitly upgraded to a write
//! transaction and stays that way until it is committed or rolled back. LiteboxFS generally tries
//! to avoid writing to the database unless you tell it to; opening and reading a file should not
//! require a write transaction, for example.
//!
//! # Encryption
//!
//! LiteboxFS supports optional encryption via [SQLCipher](https://github.com/sqlcipher/sqlcipher).
//! If SQLCipher support is enabled (via Cargo features), you can specify either a password or an
//! encryption key when creating or opening a litebox. The password/key can be changed later.
//!
//! # FUSE Support
//!
//! On Linux, a litebox can be mounted in the host filesystem via FUSE. This allows for accessing
//! the contents of a litebox root as if it were any other directory on the host system.
//!
//! Mounting a litebox acquires an exclusive lock on the database for the duration of the mount.
//!
//! You can mount a litebox root using [`Connection::mount`] or via the CLI.
//!
//! # Features
//!
//! | Feature | Default | Description |
//! | --- | --- | --- |
//! | `fs` | Yes | Enable features that require interacting with the host filesystem. |
//! | `compression` | No | Enable support for [transparent compression](crate::CreateOptions::compression) of file contents using Zstandard (zstd). |
//! | `chunking` | No | Enable support for [content-defined chunking](crate::CreateOptions::chunking) of file contents using FastCDC. |
//! | `fuse` | No | Enable support for mounting a litebox as a FUSE filesystem. |
//! | `bundled-sqlite` | No | Use a bundled version of SQLite instead of linking to it. |
//! | `sqlcipher` | No | Link to SQLCipher instead of SQLite. This searches for and links against a system-installed crypto library. |
//! | `bundled-sqlcipher` | No | Use a bundled version of SQLCipher instead of linking to it. This searches for and links against a system-installed crypto library. |
//! | `bundled-sqlcipher-vendored-openssl` | No | Use a bundled version of SQLCipher with a vendored version of OpenSSL. |
// You can define lints in `Cargo.toml`, but then it applies to integration tests as well, which
// isn't what we want.
/// Types for representing file metadata.
/// Types for user-defined metadata associated with filesystems and roots.
/// Types for working with filesystem roots.
/// Error types.
/// Types for database connections, transactions, and the filesystem.
/// Types for working with files and file contents.
/// Types for walking the filesystem.
/// Types for interacting with the host filesystem.
pub use Connection;
pub use ;
pub use File;
pub use Filesystem;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;