Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • redox-os/redoxfs
  • jD91mZM2/redoxfs
  • microcolonel/redoxfs
  • rm-dr/redoxfs
  • deepaksirone/redoxfs
  • sevenEng/redoxfs
  • mortona/redoxfs
  • potatogim/redoxfs
  • 4lDO2/redoxfs
  • malandrakisgeo/redoxfs
  • ssd/redoxfs
  • dahc/redoxfs
  • ashton/redoxfs
  • usapmz/redoxfs
  • vadorovsky/redoxfs
  • bjorn3/redoxfs
  • rw_van/redoxfs
  • mkroening/redoxfs
  • emaxx-g/redoxfs
  • CILP/redoxfs
  • AnandSMain/redoxfs
  • aaronjanse/redoxfs
  • liamnprg/redoxfs
  • coolreader18/redoxfs
  • freewilll/redoxfs
  • adi-g15/redoxfs
  • andrey.turkin/redoxfs
  • matlik/redoxfs
28 results
Show changes
Commits on Source (42)
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 4
[[package]] [[package]]
name = "aes" name = "aes"
...@@ -24,43 +24,75 @@ dependencies = [ ...@@ -24,43 +24,75 @@ dependencies = [
] ]
[[package]] [[package]]
name = "argon2" name = "anstream"
version = "0.3.4" version = "0.6.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25df3c03f1040d0069fcd3907e24e36d59f9b6fa07ba49be0eb25a794f036ba7" checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338"
dependencies = [ dependencies = [
"base64ct", "anstyle",
"blake2", "anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
] ]
[[package]] [[package]]
name = "atty" name = "anstyle"
version = "0.2.14" version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56"
[[package]]
name = "anstyle-parse"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [ dependencies = [
"hermit-abi", "utf8parse",
"libc",
"winapi",
] ]
[[package]] [[package]]
name = "base64ct" name = "anstyle-query"
version = "1.6.0" version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys",
]
[[package]] [[package]]
name = "bitflags" name = "anstyle-wincon"
version = "1.3.2" version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
dependencies = [
"anstyle",
"windows-sys",
]
[[package]]
name = "argon2"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db4ce4441f99dbd377ca8a8f57b698c44d0d6e712d8329b5040da5a64aa1ce73"
dependencies = [
"base64ct",
"blake2",
]
[[package]]
name = "base64ct"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.5.0" version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]] [[package]]
name = "blake2" name = "blake2"
...@@ -101,11 +133,17 @@ dependencies = [ ...@@ -101,11 +133,17 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "colorchoice"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]] [[package]]
name = "cpufeatures" name = "cpufeatures"
version = "0.2.12" version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
dependencies = [ dependencies = [
"libc", "libc",
] ]
...@@ -120,6 +158,15 @@ dependencies = [ ...@@ -120,6 +158,15 @@ dependencies = [
"typenum", "typenum",
] ]
[[package]]
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
]
[[package]] [[package]]
name = "digest" name = "digest"
version = "0.10.7" version = "0.10.7"
...@@ -133,28 +180,38 @@ dependencies = [ ...@@ -133,28 +180,38 @@ dependencies = [
[[package]] [[package]]
name = "endian-num" name = "endian-num"
version = "0.1.1" version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8f59926911ef34d1efb9ea1ee8ca78385df62ce700ccf2bcb149011bd226888"
[[package]]
name = "env_filter"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad847bb2094f110bbdd6fa564894ca4556fd978958e93985420d680d3cb6d14" checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab"
dependencies = [
"log",
"regex",
]
[[package]] [[package]]
name = "env_logger" name = "env_logger"
version = "0.9.3" version = "0.11.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d"
dependencies = [ dependencies = [
"atty", "anstream",
"anstyle",
"env_filter",
"humantime", "humantime",
"log", "log",
"regex",
"termcolor",
] ]
[[package]] [[package]]
name = "fuser" name = "fuser"
version = "0.12.0" version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5910691a0ececcc6eba8bb14029025c2d123e96a53db1533f6a4602861a5aaf7" checksum = "2e697f6f62c20b6fad1ba0f84ae909f25971cf16e735273524e3977c94604cf8"
dependencies = [ dependencies = [
"libc", "libc",
"log", "log",
...@@ -162,7 +219,6 @@ dependencies = [ ...@@ -162,7 +219,6 @@ dependencies = [
"page_size", "page_size",
"pkg-config", "pkg-config",
"smallvec", "smallvec",
"users",
"zerocopy", "zerocopy",
] ]
...@@ -178,22 +234,13 @@ dependencies = [ ...@@ -178,22 +234,13 @@ dependencies = [
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.12" version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"wasi 0.11.0+wasi-snapshot-preview1", "wasi",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
] ]
[[package]] [[package]]
...@@ -203,21 +250,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" ...@@ -203,21 +250,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]] [[package]]
name = "libc" name = "is_terminal_polyfill"
version = "0.2.153" version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]] [[package]]
name = "libredox" name = "libc"
version = "0.0.2" version = "0.2.161"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
dependencies = [
"bitflags 2.5.0",
"libc",
"redox_syscall 0.4.1",
]
[[package]] [[package]]
name = "libredox" name = "libredox"
...@@ -225,28 +267,34 @@ version = "0.1.3" ...@@ -225,28 +267,34 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags",
"libc", "libc",
"redox_syscall 0.5.1", "redox_syscall",
] ]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.21" version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.2" version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]] [[package]]
name = "numtoa" name = "num-conv"
version = "0.1.0" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "numtoa"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6aa2c4e539b869820a2b82e1aef6ff40aa85e65decdd5185e83fb4b1249cd00f"
[[package]] [[package]]
name = "opaque-debug" name = "opaque-debug"
...@@ -256,9 +304,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" ...@@ -256,9 +304,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]] [[package]]
name = "page_size" name = "page_size"
version = "0.4.2" version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eebde548fbbf1ea81a99b128872779c437752fb99f217c45245e1a61dcd9edcd" checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da"
dependencies = [ dependencies = [
"libc", "libc",
"winapi", "winapi",
...@@ -266,24 +314,30 @@ dependencies = [ ...@@ -266,24 +314,30 @@ dependencies = [
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.30" version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.79" version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.35" version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
...@@ -301,21 +355,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" ...@@ -301,21 +355,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "436d45c2b6a5b159d43da708e62b25be3a4a3d5550d654b72216ade4c4bfd717" checksum = "436d45c2b6a5b159d43da708e62b25be3a4a3d5550d654b72216ade4c4bfd717"
[[package]] [[package]]
name = "redox_syscall" name = "redox-scheme"
version = "0.4.1" version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" checksum = "6143c4d307e1c99ac14f60b5b07b2dccaf9d17137f7cee4e4e29977dd8014a1b"
dependencies = [ dependencies = [
"bitflags 1.3.2", "libredox",
"redox_syscall",
] ]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.5.1" version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags",
] ]
[[package]] [[package]]
...@@ -326,7 +381,7 @@ checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb" ...@@ -326,7 +381,7 @@ checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb"
[[package]] [[package]]
name = "redoxfs" name = "redoxfs"
version = "0.6.3" version = "0.6.9"
dependencies = [ dependencies = [
"aes", "aes",
"argon2", "argon2",
...@@ -336,11 +391,12 @@ dependencies = [ ...@@ -336,11 +391,12 @@ dependencies = [
"fuser", "fuser",
"getrandom", "getrandom",
"libc", "libc",
"libredox 0.1.3", "libredox",
"log", "log",
"range-tree", "range-tree",
"redox-path", "redox-path",
"redox_syscall 0.5.1", "redox-scheme",
"redox_syscall",
"seahash", "seahash",
"termion", "termion",
"time", "time",
...@@ -349,9 +405,9 @@ dependencies = [ ...@@ -349,9 +405,9 @@ dependencies = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.10.4" version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
...@@ -361,9 +417,9 @@ dependencies = [ ...@@ -361,9 +417,9 @@ dependencies = [
[[package]] [[package]]
name = "regex-automata" name = "regex-automata"
version = "0.4.6" version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
...@@ -372,9 +428,9 @@ dependencies = [ ...@@ -372,9 +428,9 @@ dependencies = [
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.8.3" version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]] [[package]]
name = "seahash" name = "seahash"
...@@ -382,6 +438,26 @@ version = "4.1.0" ...@@ -382,6 +438,26 @@ version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]]
name = "serde"
version = "1.0.214"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.214"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.13.2" version = "1.13.2"
...@@ -390,53 +466,52 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" ...@@ -390,53 +466,52 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]] [[package]]
name = "subtle" name = "subtle"
version = "2.5.0" version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.57" version = "2.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35" checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]] [[package]]
name = "termion" name = "termion"
version = "2.0.3" version = "4.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4648c7def6f2043b2568617b9f9b75eae88ca185dbc1f1fda30e95a85d49d7d" checksum = "7eaa98560e51a2cf4f0bb884d8b2098a9ea11ecf3b7078e9c68242c74cc923a7"
dependencies = [ dependencies = [
"libc", "libc",
"libredox 0.0.2", "libredox",
"numtoa", "numtoa",
"redox_termios", "redox_termios",
] ]
[[package]] [[package]]
name = "time" name = "time"
version = "0.1.45" version = "0.3.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [ dependencies = [
"libc", "deranged",
"wasi 0.10.0+wasi-snapshot-preview1", "num-conv",
"winapi", "powerfmt",
"serde",
"time-core",
] ]
[[package]]
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.17.0" version = "1.17.0"
...@@ -445,40 +520,30 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" ...@@ -445,40 +520,30 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.12" version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]] [[package]]
name = "users" name = "utf8parse"
version = "0.11.0" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
dependencies = [
"libc",
"log",
]
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.8.0" version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a"
dependencies = [ dependencies = [
"getrandom", "getrandom",
] ]
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.4" version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]] [[package]]
name = "wasi" name = "wasi"
...@@ -503,25 +568,89 @@ source = "registry+https://github.com/rust-lang/crates.io-index" ...@@ -503,25 +568,89 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]] [[package]]
name = "winapi-util" name = "winapi-x86_64-pc-windows-gnu"
version = "0.1.6" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [ dependencies = [
"winapi", "windows-targets",
] ]
[[package]] [[package]]
name = "winapi-x86_64-pc-windows-gnu" name = "windows-targets"
version = "0.4.0" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]] [[package]]
name = "zerocopy" name = "zerocopy"
version = "0.6.6" version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "854e949ac82d619ee9a14c66a1b674ac730422372ccb759ce0c39cabcf2bf8e6" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"zerocopy-derive", "zerocopy-derive",
...@@ -529,9 +658,9 @@ dependencies = [ ...@@ -529,9 +658,9 @@ dependencies = [
[[package]] [[package]]
name = "zerocopy-derive" name = "zerocopy-derive"
version = "0.6.6" version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "125139de3f6b9d625c39e2efdd73d41bdac468ccd556556440e322be0e1bbd91" checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
name = "redoxfs" name = "redoxfs"
description = "The Redox Filesystem" description = "The Redox Filesystem"
repository = "https://gitlab.redox-os.org/redox-os/redoxfs" repository = "https://gitlab.redox-os.org/redox-os/redoxfs"
version = "0.6.3" version = "0.6.9"
license-file = "LICENSE" license-file = "LICENSE"
readme = "README.md" readme = "README.md"
authors = ["Jeremy Soller <jackpot51@gmail.com>"] authors = ["Jeremy Soller <jackpot51@gmail.com>"]
...@@ -32,20 +32,21 @@ required-features = ["std"] ...@@ -32,20 +32,21 @@ required-features = ["std"]
[dependencies] [dependencies]
aes = { version = "=0.7.5", default-features = false } aes = { version = "=0.7.5", default-features = false }
argon2 = { version = "0.3.4", default-features = false, features = ["alloc"] } argon2 = { version = "0.4", default-features = false, features = ["alloc"] }
base64ct = { version = "1", default-features = false } base64ct = { version = "1", default-features = false }
env_logger = { version = "0.9", optional = true } env_logger = { version = "0.11", optional = true }
endian-num = "0.1" endian-num = "0.1"
getrandom = { version = "0.2.5", optional = true } getrandom = { version = "0.2.5", optional = true }
libc = "0.2" libc = "0.2"
log = { version = "0.4.14", default-features = false, optional = true} log = { version = "0.4.14", default-features = false, optional = true}
redox_syscall = "0.5" redox_syscall = { version = "0.5" }
range-tree = { version = "0.1", optional = true } range-tree = { version = "0.1", optional = true }
seahash = { version = "4.1.0", default-features = false } seahash = { version = "4.1.0", default-features = false }
termion = { version = "2", optional = true } termion = { version = "4", optional = true }
uuid = { version = "1.4", default-features = false } uuid = { version = "1.4", default-features = false }
redox-path = "0.3.0" redox-path = "0.3.0"
libredox = { version = "0.1.3", optional = true } libredox = { version = "0.1.3", optional = true }
redox-scheme = { version = "0.2.1", optional = true }
[features] [features]
default = ["std", "log"] default = ["std", "log"]
...@@ -61,10 +62,15 @@ std = [ ...@@ -61,10 +62,15 @@ std = [
"range-tree", "range-tree",
"termion", "termion",
"time", "time",
"uuid/v4" "uuid/v4",
"redox_syscall/std",
"redox-scheme"
] ]
[target.'cfg(not(target_os = "redox"))'.dependencies] [target.'cfg(not(target_os = "redox"))'.dependencies]
fuser = { version = "0.12.0", optional = true } fuser = { version = "0.14", optional = true }
libc = { version = "0.2", optional = true } libc = { version = "0.2", optional = true }
time = { version = "0.1", optional = true } time = { version = "0.3", optional = true }
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(fuzzing)'] }
...@@ -18,6 +18,32 @@ Current features: ...@@ -18,6 +18,32 @@ Current features:
Being MIT licensed, RedoxFS can be bundled on GPL-licensed operating systems (Linux, for example). Being MIT licensed, RedoxFS can be bundled on GPL-licensed operating systems (Linux, for example).
### How to mount a partition
- Install RedoxFS
```sh
cargo install redoxfs
```
You can also build RedoxFS from this repository.
- Configure your storage device to allow rootless usage
If you are on Linux you need root permission to acess block devices (storage), but it's recommended to run RedoxFS as rootless.
To do that you need to configure your storage device permission to your user with the following command:
```sh
sudo setfacl -m u:your-username:rw /path/to/disk
```
- Mount your RedoxFS partition
```sh
redoxfs /path/to/disk /path/to/mount
```
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
[![crates.io](http://meritbadge.herokuapp.com/redoxfs)](https://crates.io/crates/redoxfs) [![crates.io](http://meritbadge.herokuapp.com/redoxfs)](https://crates.io/crates/redoxfs)
[![docs.rs](https://docs.rs/redoxfs/badge.svg)](https://docs.rs/redoxfs) [![docs.rs](https://docs.rs/redoxfs/badge.svg)](https://docs.rs/redoxfs)
target
corpus
artifacts
coverage
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aes"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
"opaque-debug",
]
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "anyhow"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "arbitrary"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
dependencies = [
"derive_arbitrary",
]
[[package]]
name = "argon2"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25df3c03f1040d0069fcd3907e24e36d59f9b6fa07ba49be0eb25a794f036ba7"
dependencies = [
"base64ct",
"blake2",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "base64ct"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "blake2"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
dependencies = [
"digest",
]
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695"
dependencies = [
"jobserver",
"libc",
"once_cell",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cfg_aliases"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "cipher"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
dependencies = [
"generic-array",
]
[[package]]
name = "cpufeatures"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "derive_arbitrary"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
"subtle",
]
[[package]]
name = "endian-num"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad847bb2094f110bbdd6fa564894ca4556fd978958e93985420d680d3cb6d14"
[[package]]
name = "env_logger"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "errno"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "fastrand"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
[[package]]
name = "fuser"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5910691a0ececcc6eba8bb14029025c2d123e96a53db1533f6a4602861a5aaf7"
dependencies = [
"libc",
"log",
"memchr",
"page_size",
"pkg-config",
"smallvec",
"users",
"zerocopy",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "jobserver"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e"
dependencies = [
"libc",
]
[[package]]
name = "libc"
version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "libfuzzer-sys"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7"
dependencies = [
"arbitrary",
"cc",
"once_cell",
]
[[package]]
name = "libredox"
version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607"
dependencies = [
"bitflags 2.5.0",
"libc",
"redox_syscall 0.4.1",
]
[[package]]
name = "libredox"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags 2.5.0",
"libc",
"redox_syscall 0.5.2",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]]
name = "log"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "nix"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
dependencies = [
"bitflags 2.5.0",
"cfg-if",
"cfg_aliases",
"libc",
]
[[package]]
name = "numtoa"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "opaque-debug"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "page_size"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eebde548fbbf1ea81a99b128872779c437752fb99f217c45245e1a61dcd9edcd"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "pkg-config"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]]
name = "proc-macro2"
version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "range-tree"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384c2842d4e069d5ccacf5fe1dca4ef8d07a5444329715f0fc3c61813502d4d1"
[[package]]
name = "redox-path"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "436d45c2b6a5b159d43da708e62b25be3a4a3d5550d654b72216ade4c4bfd717"
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_syscall"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
dependencies = [
"bitflags 2.5.0",
]
[[package]]
name = "redox_termios"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb"
[[package]]
name = "redoxfs"
version = "0.6.4"
dependencies = [
"aes",
"argon2",
"base64ct",
"endian-num",
"env_logger",
"fuser",
"getrandom",
"libc",
"libredox 0.1.3",
"log",
"range-tree",
"redox-path",
"redox_syscall 0.5.2",
"seahash",
"termion",
"time",
"uuid",
]
[[package]]
name = "redoxfs-fuzz"
version = "0.0.0"
dependencies = [
"anyhow",
"arbitrary",
"fuser",
"libfuzzer-sys",
"nix",
"redoxfs",
"tempfile",
]
[[package]]
name = "regex"
version = "1.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "rustix"
version = "0.38.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
dependencies = [
"bitflags 2.5.0",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "seahash"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "subtle"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "syn"
version = "2.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tempfile"
version = "3.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
dependencies = [
"cfg-if",
"fastrand",
"rustix",
"windows-sys",
]
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]]
name = "termion"
version = "2.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4648c7def6f2043b2568617b9f9b75eae88ca185dbc1f1fda30e95a85d49d7d"
dependencies = [
"libc",
"libredox 0.0.2",
"numtoa",
"redox_termios",
]
[[package]]
name = "time"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
dependencies = [
"libc",
"wasi 0.10.0+wasi-snapshot-preview1",
"winapi",
]
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "users"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032"
dependencies = [
"libc",
"log",
]
[[package]]
name = "uuid"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
dependencies = [
"getrandom",
]
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
dependencies = [
"windows-sys",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]]
name = "windows_i686_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]]
name = "windows_i686_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]]
name = "zerocopy"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "854e949ac82d619ee9a14c66a1b674ac730422372ccb759ce0c39cabcf2bf8e6"
dependencies = [
"byteorder",
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "125139de3f6b9d625c39e2efdd73d41bdac468ccd556556440e322be0e1bbd91"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[package]
name = "redoxfs-fuzz"
version = "0.0.0"
publish = false
edition = "2021"
[features]
default = []
log = []
[package.metadata]
cargo-fuzz = true
[dependencies]
anyhow = "1.0.86"
arbitrary = { version = "1.3.2", features = ["derive"] }
fuser = { version = "0.12.0" }
libfuzzer-sys = "0.4"
nix = { version = "0.29.0", features = ["fs"] }
tempfile = "3.10.1"
[dependencies.redoxfs]
path = ".."
[[bin]]
name = "fuse_fuzz_target"
path = "fuzz_targets/fuse_fuzz_target.rs"
test = false
doc = false
bench = false
//! Fuzzer that exercises random file system operations against a FUSE-mounted redoxfs.
#![no_main]
use anyhow::{ensure, Result};
use fuser;
use libfuzzer_sys::{arbitrary::Arbitrary, fuzz_target, Corpus};
use nix::sys::statvfs::statvfs;
use std::{
fs::{self, File, FileTimes, OpenOptions},
io::{Read, Seek, SeekFrom, Write},
os::unix::fs::{self as unix_fs, PermissionsExt},
path::{Path, PathBuf},
thread,
time::{Duration, SystemTime, UNIX_EPOCH},
};
use tempfile;
use redoxfs::{mount::fuse::Fuse, DiskSparse, FileSystem};
/// Maximum size for files and buffers. Chosen arbitrarily with fuzzing performance in mind.
const MAX_SIZE: u64 = 10_000_000;
/// Limit on the number of remounts in a single test case. Chosen arbitrarily with fuzzing
/// performance in mind: remounts are costly.
const MAX_MOUNT_SEQUENCES: usize = 3;
/// An operation to be performed by the fuzzer.
#[derive(Arbitrary, Clone, Debug)]
enum Operation {
Chown {
path: PathBuf,
uid: Option<u32>,
gid: Option<u32>,
},
CreateDir {
path: PathBuf,
},
HardLink {
original: PathBuf,
link: PathBuf,
},
Metadata {
path: PathBuf,
},
Read {
path: PathBuf,
},
ReadDir {
path: PathBuf,
},
ReadLink {
path: PathBuf,
},
RemoveDir {
path: PathBuf,
},
RemoveFile {
path: PathBuf,
},
Rename {
from: PathBuf,
to: PathBuf,
},
SeekRead {
path: PathBuf,
seek_pos: u64,
buf_size: usize,
},
SeekWrite {
path: PathBuf,
seek_pos: u64,
buf_size: usize,
},
SetLen {
path: PathBuf,
size: u64,
},
SetPermissions {
path: PathBuf,
readonly: Option<bool>,
mode: Option<u32>,
},
SetTimes {
path: PathBuf,
accessed_since_epoch: Option<Duration>,
modified_since_epoch: Option<Duration>,
},
Statvfs {},
SymLink {
original: PathBuf,
link: PathBuf,
},
Write {
path: PathBuf,
buf_size: usize,
},
}
/// Parameters for mounting the file system and operations to be performed afterwards.
#[derive(Arbitrary, Clone, Debug)]
struct MountSequence {
squash: bool,
operations: Vec<Operation>,
}
/// The whole input to a single fuzzer invocation.
#[derive(Arbitrary, Clone, Debug)]
struct TestCase {
disk_size: u64,
reserved_size: u64,
mount_sequences: Vec<MountSequence>,
}
/// Creates the disk for backing the Redoxfs.
fn create_disk(temp_path: &Path, disk_size: u64) -> DiskSparse {
let disk_path = temp_path.join("disk.img");
DiskSparse::create(disk_path, disk_size).unwrap()
}
/// Creates an empty Redoxfs.
fn create_redoxfs(disk: DiskSparse, reserved_size: u64) -> bool {
let password = None;
let reserved = vec![0; reserved_size as usize];
let ctime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
FileSystem::create_reserved(
disk,
password,
&reserved,
ctime.as_secs(),
ctime.subsec_nanos(),
)
.is_ok()
}
/// Mounts an existing Redoxfs, runs the callback and performs the unmount.
fn with_redoxfs_mount<F>(temp_path: &Path, disk: DiskSparse, squash: bool, callback: F)
where
F: FnOnce(&Path) + Send + 'static,
{
let password = None;
let block = None;
let mut fs = FileSystem::open(disk, password, block, squash).unwrap();
let mount_path = temp_path.join("mount");
fs::create_dir_all(&mount_path).unwrap();
let mut session = fuser::Session::new(Fuse { fs: &mut fs }, &mount_path, &[]).unwrap();
let mut unmounter = session.unmount_callable();
let join_handle = thread::spawn(move || {
callback(&mount_path);
unmounter.unmount().unwrap();
});
session.run().unwrap();
join_handle.join().unwrap();
}
fn get_path_within_fs(fs_path: &Path, path_to_add: &Path) -> Result<PathBuf> {
ensure!(path_to_add.is_relative());
ensure!(path_to_add
.components()
.all(|c| c != std::path::Component::ParentDir));
Ok(fs_path.join(path_to_add))
}
fn do_operation(fs_path: &Path, op: &Operation) -> Result<()> {
match op {
Operation::Chown { path, uid, gid } => {
let path = get_path_within_fs(fs_path, path)?;
unix_fs::chown(path, *uid, *gid)?;
}
Operation::CreateDir { path } => {
let path = get_path_within_fs(fs_path, path)?;
fs::create_dir(path)?;
}
Operation::HardLink { original, link } => {
let original = get_path_within_fs(fs_path, original)?;
let link = get_path_within_fs(fs_path, link)?;
fs::hard_link(original, link)?;
}
Operation::Metadata { path } => {
let path = get_path_within_fs(fs_path, path)?;
fs::metadata(path)?;
}
Operation::Read { path } => {
let path = get_path_within_fs(fs_path, path)?;
fs::read(path)?;
}
Operation::ReadDir { path } => {
let path = get_path_within_fs(fs_path, path)?;
let _ = fs::read_dir(path)?.count();
}
Operation::ReadLink { path } => {
let path = get_path_within_fs(fs_path, path)?;
fs::read_link(path)?;
}
Operation::RemoveDir { path } => {
let path = get_path_within_fs(fs_path, path)?;
fs::remove_dir(path)?;
}
Operation::RemoveFile { path } => {
let path = get_path_within_fs(fs_path, path)?;
fs::remove_file(path)?;
}
Operation::Rename { from, to } => {
let from = get_path_within_fs(fs_path, from)?;
let to = get_path_within_fs(fs_path, to)?;
fs::rename(from, to)?;
}
Operation::SeekRead {
path,
seek_pos,
buf_size,
} => {
ensure!(*buf_size as u64 <= MAX_SIZE);
let path = get_path_within_fs(fs_path, path)?;
let mut file = File::open(path)?;
file.seek(SeekFrom::Start(*seek_pos))?;
let mut buf = vec![0; *buf_size];
file.read(&mut buf)?;
}
Operation::SeekWrite {
path,
seek_pos,
buf_size,
} => {
ensure!(*seek_pos <= MAX_SIZE);
ensure!(*buf_size as u64 <= MAX_SIZE);
let path = get_path_within_fs(fs_path, path)?;
let mut file = OpenOptions::new().write(true).open(path)?;
file.seek(SeekFrom::Start(*seek_pos))?;
let buf = vec![0; *buf_size];
file.write(&buf)?;
}
Operation::SetLen { path, size } => {
let path = get_path_within_fs(fs_path, path)?;
let file = OpenOptions::new().write(true).open(path)?;
file.set_len(*size)?;
}
Operation::SetPermissions {
path,
readonly,
mode,
} => {
let path = get_path_within_fs(fs_path, path)?;
let metadata = fs::metadata(&path)?;
let mut perms = metadata.permissions();
if let Some(readonly) = readonly {
perms.set_readonly(*readonly);
}
if let Some(mode) = mode {
perms.set_mode(*mode);
}
fs::set_permissions(path, perms)?;
}
Operation::SetTimes {
path,
accessed_since_epoch,
modified_since_epoch,
} => {
let path = get_path_within_fs(fs_path, path)?;
let file = File::options().write(true).open(path)?;
let mut times = FileTimes::new();
if let Some(accessed_since_epoch) = accessed_since_epoch {
if let Some(accessed) = UNIX_EPOCH.checked_add(*accessed_since_epoch) {
times = times.set_accessed(accessed);
}
}
if let Some(modified_since_epoch) = modified_since_epoch {
if let Some(modified) = UNIX_EPOCH.checked_add(*modified_since_epoch) {
times = times.set_modified(modified);
}
}
file.set_times(times)?;
}
Operation::Statvfs {} => {
statvfs(fs_path)?;
}
Operation::SymLink { original, link } => {
let original = get_path_within_fs(fs_path, original)?;
let link = get_path_within_fs(fs_path, link)?;
unix_fs::symlink(original, link)?;
}
Operation::Write { path, buf_size } => {
ensure!(*buf_size as u64 <= MAX_SIZE);
let path = get_path_within_fs(fs_path, path)?;
let buf = vec![0; *buf_size];
fs::write(path, &buf)?;
}
}
Ok(())
}
fuzz_target!(|test_case: TestCase| -> Corpus {
if test_case.disk_size > MAX_SIZE
|| test_case.reserved_size > MAX_SIZE
|| test_case.mount_sequences.len() > MAX_MOUNT_SEQUENCES
{
return Corpus::Reject;
}
let temp_dir = tempfile::Builder::new()
.prefix("fuse_fuzz_target")
.tempdir()
.unwrap();
#[cfg(feature = "log")]
eprintln!("create fs");
let disk = create_disk(temp_dir.path(), test_case.disk_size);
if !create_redoxfs(disk, test_case.reserved_size) {
// File system creation failed (e.g., due to insufficient space) so we bail out, still
// exercising this code path is useful.
return Corpus::Keep;
}
for mount_seq in test_case.mount_sequences.iter() {
#[cfg(feature = "log")]
eprintln!("mount fs");
let disk = create_disk(temp_dir.path(), test_case.disk_size);
let operations = mount_seq.operations.clone();
with_redoxfs_mount(temp_dir.path(), disk, mount_seq.squash, move |fs_path| {
for operation in operations.iter() {
#[cfg(feature = "log")]
eprintln!("do operation {operation:?}");
let _result = do_operation(fs_path, operation);
#[cfg(feature = "log")]
eprintln!("operation result {:?}", _result.err());
}
});
#[cfg(feature = "log")]
eprintln!("unmounted fs");
}
Corpus::Keep
});
...@@ -7,8 +7,31 @@ use crate::{BlockAddr, BlockLevel, BlockPtr, BlockTrait, BLOCK_SIZE}; ...@@ -7,8 +7,31 @@ use crate::{BlockAddr, BlockLevel, BlockPtr, BlockTrait, BLOCK_SIZE};
pub const ALLOC_LIST_ENTRIES: usize = pub const ALLOC_LIST_ENTRIES: usize =
(BLOCK_SIZE as usize - mem::size_of::<BlockPtr<AllocList>>()) / mem::size_of::<AllocEntry>(); (BLOCK_SIZE as usize - mem::size_of::<BlockPtr<AllocList>>()) / mem::size_of::<AllocEntry>();
/// The RedoxFS block allocator. This struct manages all "data" blocks in RedoxFS
/// (i.e, all blocks that aren't reserved or part of the header chain).
///
/// [`Allocator`] can allocate blocks of many "levels"---that is, it can
/// allocate multiple consecutive [`BLOCK_SIZE`] blocks in one operation.
///
/// This reduces the amount of memory that the [`Allocator`] uses:
/// Instead of storing the index of each free [`BLOCK_SIZE`] block,
/// the `levels` array can keep track of higher-level blocks, splitting
/// them when a smaller block is requested.
///
/// Higher-level blocks also allow us to more efficiently allocate memory
/// for large files.
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct Allocator { pub struct Allocator {
/// This array keeps track of all free blocks of each level,
/// and is initialized using the AllocList chain when we open the filesystem.
///
/// Every element of the outer array represents a block level:
/// - item 0: free level 0 blocks (with size [`BLOCK_SIZE`])
/// - item 1: free level 1 blocks (with size 2*[`BLOCK_SIZE`])
/// - item 2: free level 2 blocks (with size 4*[`BLOCK_SIZE`])
/// ...and so on.
///
/// Each inner array contains a list of free block indices,
levels: Vec<Vec<u64>>, levels: Vec<Vec<u64>>,
} }
...@@ -17,6 +40,7 @@ impl Allocator { ...@@ -17,6 +40,7 @@ impl Allocator {
&self.levels &self.levels
} }
/// Count the number of free [`BLOCK_SIZE`] available to this [`Allocator`].
pub fn free(&self) -> u64 { pub fn free(&self) -> u64 {
let mut free = 0; let mut free = 0;
for level in 0..self.levels.len() { for level in 0..self.levels.len() {
...@@ -26,10 +50,13 @@ impl Allocator { ...@@ -26,10 +50,13 @@ impl Allocator {
free free
} }
/// Find a free block of the given level, mark it as "used", and return its address.
/// Returns [`None`] if there are no free blocks with this level.
pub fn allocate(&mut self, block_level: BlockLevel) -> Option<BlockAddr> { pub fn allocate(&mut self, block_level: BlockLevel) -> Option<BlockAddr> {
// First, find the lowest level with a free block // First, find the lowest level with a free block
let mut index_opt = None; let mut index_opt = None;
let mut level = block_level.0; let mut level = block_level.0;
// Start searching at the level we want. Smaller levels are too small!
while level < self.levels.len() { while level < self.levels.len() {
if !self.levels[level].is_empty() { if !self.levels[level].is_empty() {
index_opt = self.levels[level].pop(); index_opt = self.levels[level].pop();
...@@ -38,7 +65,8 @@ impl Allocator { ...@@ -38,7 +65,8 @@ impl Allocator {
level += 1; level += 1;
} }
// Next, if a free block was found, split it up until you have a usable block of the right level // If a free block was found, split it until we find a usable block of the right level.
// The left side of the split block is kept free, and the right side is allocated.
let index = index_opt?; let index = index_opt?;
while level > block_level.0 { while level > block_level.0 {
level -= 1; level -= 1;
...@@ -49,6 +77,10 @@ impl Allocator { ...@@ -49,6 +77,10 @@ impl Allocator {
Some(unsafe { BlockAddr::new(index, block_level) }) Some(unsafe { BlockAddr::new(index, block_level) })
} }
/// Try to allocate the exact block specified, making all necessary splits.
/// Returns [`None`] if this some (or all) of this block is already allocated.
///
/// Note that [`BlockAddr`] encodes the blocks location _and_ level.
pub fn allocate_exact(&mut self, exact_addr: BlockAddr) -> Option<BlockAddr> { pub fn allocate_exact(&mut self, exact_addr: BlockAddr) -> Option<BlockAddr> {
// This function only supports level 0 right now // This function only supports level 0 right now
assert_eq!(exact_addr.level().0, 0); assert_eq!(exact_addr.level().0, 0);
...@@ -83,9 +115,12 @@ impl Allocator { ...@@ -83,9 +115,12 @@ impl Allocator {
Some(unsafe { BlockAddr::new(index_opt?, exact_addr.level()) }) Some(unsafe { BlockAddr::new(index_opt?, exact_addr.level()) })
} }
/// Deallocate the given block, marking it "free" so that it can be re-used later.
pub fn deallocate(&mut self, addr: BlockAddr) { pub fn deallocate(&mut self, addr: BlockAddr) {
// See if block matches with a sibling - if so, join them into a larger block, and populate // When we deallocate, we check if block we're deallocating has a free sibling.
// this all the way to the top level // If it does, we join the two to create one free block in the next (higher) level.
//
// We repeat this until we no longer have a sibling to join.
let mut index = addr.index(); let mut index = addr.index();
let mut level = addr.level().0; let mut level = addr.level().0;
loop { loop {
...@@ -98,34 +133,51 @@ impl Allocator { ...@@ -98,34 +133,51 @@ impl Allocator {
let mut found = false; let mut found = false;
let mut i = 0; let mut i = 0;
// look at all free blocks in the current level...
while i < self.levels[level].len() { while i < self.levels[level].len() {
// index of the second block we're looking at
let level_index = self.levels[level][i]; let level_index = self.levels[level][i];
// - the block we just freed aligns with the next largest block, and
// - the second block we're looking at is the right sibling of this block
if index % next_size == 0 && index + level_size == level_index { if index % next_size == 0 && index + level_size == level_index {
// "alloc" the next highest block, repeat deallocation process.
self.levels[level].remove(i); self.levels[level].remove(i);
found = true; found = true;
break; break;
// - the index of this block doesn't align with the next largest block, and
// - the block we're looking at is the left neighbor of this block
} else if level_index % next_size == 0 && level_index + level_size == index { } else if level_index % next_size == 0 && level_index + level_size == index {
// "alloc" the next highest block, repeat deallocation process.
self.levels[level].remove(i); self.levels[level].remove(i);
index = level_index; index = level_index; // index moves to left block
found = true; found = true;
break; break;
} }
i += 1; i += 1;
} }
// We couldn't find a higher block,
// deallocate this one and finish
if !found { if !found {
self.levels[level].push(index); self.levels[level].push(index);
return; return;
} }
// repeat deallocation process on the
// higher-level block we just created.
level += 1; level += 1;
} }
} }
} }
#[repr(packed)] #[repr(C, packed)]
pub struct AllocEntry { pub struct AllocEntry {
/// The index of the first block this [`AllocEntry`] refers to
index: Le<u64>, index: Le<u64>,
/// The number of blocks after (and including) `index` that are are free or used.
/// If negative, they are used; if positive, they are free.
count: Le<i64>, count: Le<i64>,
} }
...@@ -186,10 +238,14 @@ impl fmt::Debug for AllocEntry { ...@@ -186,10 +238,14 @@ impl fmt::Debug for AllocEntry {
} }
} }
/// Alloc log node /// A node in the allocation chain.
#[repr(packed)] #[repr(C, packed)]
pub struct AllocList { pub struct AllocList {
/// A pointer to the previous AllocList.
/// If this is the null pointer, this is the first element of the chain.
pub prev: BlockPtr<AllocList>, pub prev: BlockPtr<AllocList>,
/// Allocation entries.
pub entries: [AllocEntry; ALLOC_LIST_ENTRIES], pub entries: [AllocEntry; ALLOC_LIST_ENTRIES],
} }
......
extern crate libc; extern crate libc;
extern crate redoxfs;
#[cfg(target_os = "redox")] #[cfg(target_os = "redox")]
extern crate syscall; extern crate syscall;
extern crate redoxfs;
extern crate uuid; extern crate uuid;
use std::env; use std::env;
...@@ -75,7 +73,6 @@ fn capability_mode() { ...@@ -75,7 +73,6 @@ fn capability_mode() {
#[cfg(target_os = "redox")] #[cfg(target_os = "redox")]
fn bootloader_password() -> Option<Vec<u8>> { fn bootloader_password() -> Option<Vec<u8>> {
use libredox::call::MmapArgs; use libredox::call::MmapArgs;
use syscall::MapFlags;
let addr_env = env::var_os("REDOXFS_PASSWORD_ADDR")?; let addr_env = env::var_os("REDOXFS_PASSWORD_ADDR")?;
let size_env = env::var_os("REDOXFS_PASSWORD_SIZE")?; let size_env = env::var_os("REDOXFS_PASSWORD_SIZE")?;
...@@ -103,10 +100,12 @@ fn bootloader_password() -> Option<Vec<u8>> { ...@@ -103,10 +100,12 @@ fn bootloader_password() -> Option<Vec<u8>> {
addr: core::ptr::null_mut(), addr: core::ptr::null_mut(),
length: aligned_size, length: aligned_size,
prot: libredox::flag::PROT_READ, prot: libredox::flag::PROT_READ,
flags: libredox::flag::MAP_SHARED, flags: libredox::flag::MAP_SHARED,
fd: fd.raw(), fd: fd.raw(),
offset: addr as u64, offset: addr as u64,
}).expect("failed to map REDOXFS_PASSWORD").cast::<u8>(); })
.expect("failed to map REDOXFS_PASSWORD")
.cast::<u8>();
for i in 0..size { for i in 0..size {
password.push(password_map.add(i).read()); password.push(password_map.add(i).read());
...@@ -117,8 +116,19 @@ fn bootloader_password() -> Option<Vec<u8>> { ...@@ -117,8 +116,19 @@ fn bootloader_password() -> Option<Vec<u8>> {
Some(password) Some(password)
} }
fn print_err_exit(err: impl AsRef<str>) -> ! {
eprintln!("{}", err.as_ref());
usage();
process::exit(1)
}
fn print_usage_exit() -> ! {
usage();
process::exit(1)
}
fn usage() { fn usage() {
println!("redoxfs [--uuid] [disk or uuid] [mountpoint] [block in hex]"); println!("redoxfs --no-daemon [-d] [--uuid] [disk or uuid] [mountpoint] [block in hex]");
} }
enum DiskId { enum DiskId {
...@@ -264,7 +274,12 @@ fn filesystem_by_uuid( ...@@ -264,7 +274,12 @@ fn filesystem_by_uuid(
None None
} }
fn daemon(disk_id: &DiskId, mountpoint: &str, block_opt: Option<u64>, mut write: File) -> ! { fn daemon(
disk_id: &DiskId,
mountpoint: &str,
block_opt: Option<u64>,
mut write: Option<File>,
) -> ! {
setsig(); setsig();
let filesystem_opt = match *disk_id { let filesystem_opt = match *disk_id {
...@@ -281,7 +296,10 @@ fn daemon(disk_id: &DiskId, mountpoint: &str, block_opt: Option<u64>, mut write: ...@@ -281,7 +296,10 @@ fn daemon(disk_id: &DiskId, mountpoint: &str, block_opt: Option<u64>, mut write:
path, path,
mounted_path.display() mounted_path.display()
); );
let _ = write.write(&[0]);
if let Some(ref mut write) = write {
let _ = write.write(&[0]);
}
}) { }) {
Ok(()) => { Ok(()) => {
process::exit(0); process::exit(0);
...@@ -304,7 +322,10 @@ fn daemon(disk_id: &DiskId, mountpoint: &str, block_opt: Option<u64>, mut write: ...@@ -304,7 +322,10 @@ fn daemon(disk_id: &DiskId, mountpoint: &str, block_opt: Option<u64>, mut write:
} }
} }
let _ = write.write(&[1]); if let Some(ref mut write) = write {
let _ = write.write(&[1]);
}
process::exit(1); process::exit(1);
} }
...@@ -313,79 +334,74 @@ fn main() { ...@@ -313,79 +334,74 @@ fn main() {
let mut args = env::args().skip(1); let mut args = env::args().skip(1);
let disk_id = match args.next() { let mut daemonise = true;
Some(arg) => { let mut disk_id: Option<DiskId> = None;
if arg == "--uuid" { let mut mountpoint: Option<String> = None;
let uuid = match args.next() { let mut block_opt: Option<u64> = None;
Some(arg) => match Uuid::parse_str(&arg) {
Ok(uuid) => uuid, while let Some(arg) = args.next() {
Err(err) => { match arg.as_str() {
println!("redoxfs: invalid uuid '{}': {}", arg, err); "--no-daemon" | "-d" => daemonise = false,
usage();
process::exit(1); "--uuid" if disk_id.is_none() => {
disk_id = Some(DiskId::Uuid(
match args.next().as_deref().map(Uuid::parse_str) {
Some(Ok(uuid)) => uuid,
Some(Err(err)) => {
print_err_exit(format!("redoxfs: invalid uuid '{}': {}", arg, err))
} }
None => print_err_exit("redoxfs: no uuid provided"),
}, },
None => { ));
println!("redoxfs: no uuid provided");
usage();
process::exit(1);
}
};
DiskId::Uuid(uuid)
} else {
DiskId::Path(arg)
} }
}
None => {
println!("redoxfs: no disk provided");
usage();
process::exit(1);
}
};
let mountpoint = match args.next() { disk if disk_id.is_none() => disk_id = Some(DiskId::Path(disk.to_owned())),
Some(arg) => arg,
None => { mnt if disk_id.is_some() && mountpoint.is_none() => mountpoint = Some(mnt.to_owned()),
println!("redoxfs: no mountpoint provided");
usage(); opts if mountpoint.is_some() => match u64::from_str_radix(opts, 16) {
process::exit(1); Ok(block) => block_opt = Some(block),
Err(err) => print_err_exit(format!("redoxfs: invalid block '{}': {}", opts, err)),
},
_ => print_usage_exit(),
} }
}
let Some(disk_id) = disk_id else {
print_err_exit("redoxfs: no disk provided");
}; };
let block_opt = match args.next() { let Some(mountpoint) = mountpoint else {
Some(arg) => match u64::from_str_radix(&arg, 16) { print_err_exit("redoxfs: no mountpoint provided");
Ok(block) => Some(block),
Err(err) => {
println!("redoxfs: invalid block '{}': {}", arg, err);
usage();
process::exit(1);
}
},
None => None,
}; };
let mut pipes = [0; 2]; if daemonise {
if pipe(&mut pipes) == 0 { let mut pipes = [0; 2];
let mut read = unsafe { File::from_raw_fd(pipes[0] as RawFd) }; if pipe(&mut pipes) == 0 {
let write = unsafe { File::from_raw_fd(pipes[1] as RawFd) }; let mut read = unsafe { File::from_raw_fd(pipes[0] as RawFd) };
let write = unsafe { File::from_raw_fd(pipes[1] as RawFd) };
let pid = fork(); let pid = fork();
if pid == 0 { if pid == 0 {
drop(read); drop(read);
daemon(&disk_id, &mountpoint, block_opt, write); daemon(&disk_id, &mountpoint, block_opt, Some(write));
} else if pid > 0 { } else if pid > 0 {
drop(write); drop(write);
let mut res = [0]; let mut res = [0];
read.read_exact(&mut res).unwrap(); read.read_exact(&mut res).unwrap();
process::exit(res[0] as i32); process::exit(res[0] as i32);
} else {
panic!("redoxfs: failed to fork");
}
} else { } else {
panic!("redoxfs: failed to fork"); panic!("redoxfs: failed to create pipe");
} }
} else { } else {
panic!("redoxfs: failed to create pipe"); println!("redoxfs: running in foreground");
daemon(&disk_id, &mountpoint, block_opt, None);
} }
} }
...@@ -5,6 +5,11 @@ use crate::BLOCK_SIZE; ...@@ -5,6 +5,11 @@ use crate::BLOCK_SIZE;
const BLOCK_LIST_ENTRIES: usize = BLOCK_SIZE as usize / mem::size_of::<BlockPtr<BlockRaw>>(); const BLOCK_LIST_ENTRIES: usize = BLOCK_SIZE as usize / mem::size_of::<BlockPtr<BlockRaw>>();
/// An address of a data block.
///
/// This encodes a block's position _and_ [`BlockLevel`]:
/// the first four bits of this `u64` encode the block's level,
/// the rest encode its index.
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct BlockAddr(u64); pub struct BlockAddr(u64);
...@@ -43,34 +48,50 @@ impl BlockAddr { ...@@ -43,34 +48,50 @@ impl BlockAddr {
} }
} }
/// The size of a block.
///
/// Level 0 blocks are blocks of [`BLOCK_SIZE`] bytes.
/// A level 1 block consists of two consecutive level 0 blocks.
/// A level n block consists of two consecutive level n-1 blocks.
///
/// See [`crate::Allocator`] docs for more details.
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct BlockLevel(pub(crate) usize); pub struct BlockLevel(pub(crate) usize);
impl BlockLevel { impl BlockLevel {
/// Returns the smallest block level that can contain
/// the given number of bytes.
pub(crate) fn for_bytes(bytes: u64) -> Self { pub(crate) fn for_bytes(bytes: u64) -> Self {
//TODO: optimize if bytes == 0 {
let mut level = BlockLevel(0); return BlockLevel(0);
while level.bytes() < bytes {
level.0 += 1;
} }
level let level = bytes
.div_ceil(BLOCK_SIZE)
.next_power_of_two()
.trailing_zeros() as usize;
BlockLevel(level)
} }
/// The number of [`BLOCK_SIZE`] blocks (i.e, level 0 blocks)
/// in a block of this level
pub fn blocks(self) -> i64 { pub fn blocks(self) -> i64 {
1 << self.0 1 << self.0
} }
/// The number of bytes in a block of this level
pub fn bytes(self) -> u64 { pub fn bytes(self) -> u64 {
BLOCK_SIZE << self.0 BLOCK_SIZE << self.0
} }
} }
pub unsafe trait BlockTrait { pub unsafe trait BlockTrait {
/// Create an empty block of this type.
fn empty(level: BlockLevel) -> Option<Self> fn empty(level: BlockLevel) -> Option<Self>
where where
Self: Sized; Self: Sized;
} }
/// A [`BlockAddr`] and the data it points to.
#[derive(Clone, Copy, Debug, Default)] #[derive(Clone, Copy, Debug, Default)]
pub struct BlockData<T> { pub struct BlockData<T> {
addr: BlockAddr, addr: BlockAddr,
...@@ -86,15 +107,6 @@ impl<T> BlockData<T> { ...@@ -86,15 +107,6 @@ impl<T> BlockData<T> {
self.addr self.addr
} }
#[must_use = "don't forget to de-allocate old block address"]
pub fn swap_addr(&mut self, addr: BlockAddr) -> BlockAddr {
// Address levels must match
assert_eq!(self.addr.level(), addr.level());
let old = self.addr;
self.addr = addr;
old
}
pub fn data(&self) -> &T { pub fn data(&self) -> &T {
&self.data &self.data
} }
...@@ -106,6 +118,19 @@ impl<T> BlockData<T> { ...@@ -106,6 +118,19 @@ impl<T> BlockData<T> {
pub(crate) unsafe fn into_parts(self) -> (BlockAddr, T) { pub(crate) unsafe fn into_parts(self) -> (BlockAddr, T) {
(self.addr, self.data) (self.addr, self.data)
} }
/// Set the address of this [`BlockData`] to `addr`, returning this
/// block's old address. This method does not update block data.
///
/// `addr` must point to a block with the same level as this block.
#[must_use = "don't forget to de-allocate old block address"]
pub fn swap_addr(&mut self, addr: BlockAddr) -> BlockAddr {
// Address levels must match
assert_eq!(self.addr.level(), addr.level());
let old = self.addr;
self.addr = addr;
old
}
} }
impl<T: BlockTrait> BlockData<T> { impl<T: BlockTrait> BlockData<T> {
...@@ -125,7 +150,7 @@ impl<T: ops::Deref<Target = [u8]>> BlockData<T> { ...@@ -125,7 +150,7 @@ impl<T: ops::Deref<Target = [u8]>> BlockData<T> {
} }
} }
#[repr(packed)] #[repr(C, packed)]
pub struct BlockList<T> { pub struct BlockList<T> {
pub ptrs: [BlockPtr<T>; BLOCK_LIST_ENTRIES], pub ptrs: [BlockPtr<T>; BLOCK_LIST_ENTRIES],
} }
...@@ -176,7 +201,14 @@ impl<T> ops::DerefMut for BlockList<T> { ...@@ -176,7 +201,14 @@ impl<T> ops::DerefMut for BlockList<T> {
} }
} }
#[repr(packed)] /// An address of a data block, along with a checksum of its data.
///
/// This encodes a block's position _and_ [`BlockLevel`].
/// the first four bits of `addr` encode the block's level,
/// the rest encode its index.
///
/// Also see [`BlockAddr`].
#[repr(C, packed)]
pub struct BlockPtr<T> { pub struct BlockPtr<T> {
addr: Le<u64>, addr: Le<u64>,
hash: Le<u64>, hash: Le<u64>,
...@@ -253,7 +285,7 @@ impl<T> fmt::Debug for BlockPtr<T> { ...@@ -253,7 +285,7 @@ impl<T> fmt::Debug for BlockPtr<T> {
} }
} }
#[repr(packed)] #[repr(C, packed)]
pub struct BlockRaw([u8; BLOCK_SIZE as usize]); pub struct BlockRaw([u8; BLOCK_SIZE as usize]);
unsafe impl BlockTrait for BlockRaw { unsafe impl BlockTrait for BlockRaw {
......
use alloc::{boxed::Box, vec}; use alloc::{boxed::Box, vec};
use core::{mem, ops, slice, str}; use core::{mem, ops, slice, str};
use crate::{BlockLevel, BlockTrait, Node, TreePtr, RECORD_LEVEL, DIR_ENTRY_MAX_LENGTH}; use crate::{BlockLevel, BlockTrait, Node, TreePtr, DIR_ENTRY_MAX_LENGTH, RECORD_LEVEL};
#[repr(packed)] #[repr(C, packed)]
pub struct DirEntry { pub struct DirEntry {
node_ptr: TreePtr<Node>, node_ptr: TreePtr<Node>,
name: [u8; DIR_ENTRY_MAX_LENGTH], name: [u8; DIR_ENTRY_MAX_LENGTH],
......
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
use std::io::{Read, Seek, SeekFrom, Write}; use std::io::{Seek, SeekFrom};
use std::os::unix::fs::FileExt;
use std::path::Path; use std::path::Path;
use syscall::error::{Error, Result, EIO}; use syscall::error::{Error, Result, EIO};
use crate::disk::Disk; use crate::disk::Disk;
use crate::BLOCK_SIZE; use crate::BLOCK_SIZE;
macro_rules! try_disk { pub struct DiskFile {
($expr:expr) => { pub file: File,
match $expr { }
Ok(val) => val,
trait ResultExt {
type T;
fn or_eio(self) -> Result<Self::T>;
}
impl<T> ResultExt for Result<T> {
type T = T;
fn or_eio(self) -> Result<Self::T> {
match self {
Ok(t) => Ok(t),
Err(err) => { Err(err) => {
eprintln!("Disk I/O Error: {}", err); eprintln!("RedoxFS: IO ERROR: {err}");
return Err(Error::new(EIO)); Err(Error::new(EIO))
} }
} }
}; }
} }
impl<T> ResultExt for std::io::Result<T> {
pub struct DiskFile { type T = T;
pub file: File, fn or_eio(self) -> Result<Self::T> {
match self {
Ok(t) => Ok(t),
Err(err) => {
eprintln!("RedoxFS: IO ERROR: {err}");
Err(Error::new(EIO))
}
}
}
} }
impl DiskFile { impl DiskFile {
pub fn open<P: AsRef<Path>>(path: P) -> Result<DiskFile> { pub fn open(path: impl AsRef<Path>) -> Result<DiskFile> {
let file = try_disk!(OpenOptions::new().read(true).write(true).open(path)); let file = OpenOptions::new()
.read(true)
.write(true)
.open(path)
.or_eio()?;
Ok(DiskFile { file }) Ok(DiskFile { file })
} }
pub fn create<P: AsRef<Path>>(path: P, size: u64) -> Result<DiskFile> { pub fn create(path: impl AsRef<Path>, size: u64) -> Result<DiskFile> {
let file = try_disk!(OpenOptions::new() let file = OpenOptions::new()
.read(true) .read(true)
.write(true) .write(true)
.create(true) .create(true)
.open(path)); .open(path)
try_disk!(file.set_len(size)); .or_eio()?;
file.set_len(size).or_eio()?;
Ok(DiskFile { file }) Ok(DiskFile { file })
} }
} }
impl Disk for DiskFile { impl Disk for DiskFile {
unsafe fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> { unsafe fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> {
try_disk!(self.file.seek(SeekFrom::Start(block * BLOCK_SIZE))); self.file.read_at(buffer, block * BLOCK_SIZE).or_eio()
let count = try_disk!(self.file.read(buffer));
Ok(count)
} }
unsafe fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize> { unsafe fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize> {
try_disk!(self.file.seek(SeekFrom::Start(block * BLOCK_SIZE))); self.file.write_at(buffer, block * BLOCK_SIZE).or_eio()
let count = try_disk!(self.file.write(buffer));
Ok(count)
} }
fn size(&mut self) -> Result<u64> { fn size(&mut self) -> Result<u64> {
let size = try_disk!(self.file.seek(SeekFrom::End(0))); self.file.seek(SeekFrom::End(0)).or_eio()
Ok(size)
} }
} }
use aes::{Aes128, BlockDecrypt, BlockEncrypt}; use aes::{Aes128, BlockDecrypt, BlockEncrypt};
use alloc::{collections::VecDeque, vec::Vec}; use alloc::{collections::VecDeque, vec::Vec};
use core::mem; use syscall::error::{Error, Result, EKEYREJECTED, ENOENT, ENOKEY};
use syscall::error::{Error, Result, EIO, EKEYREJECTED, ENOENT, ENOKEY, ENOSPC};
use crate::{ #[cfg(feature = "std")]
AllocEntry, AllocList, Allocator, BlockAddr, BlockData, BlockLevel, BlockTrait, Disk, Header, use crate::{AllocEntry, AllocList, BlockData, BlockTrait, Key, KeySlot, Node, Salt, TreeList};
Key, KeySlot, Node, Salt, Transaction, TreeList, BLOCK_SIZE, HEADER_RING, use crate::{Allocator, BlockAddr, BlockLevel, Disk, Header, Transaction, BLOCK_SIZE, HEADER_RING};
};
/// A file system /// A file system
pub struct FileSystem<D: Disk> { pub struct FileSystem<D: Disk> {
...@@ -122,94 +120,96 @@ impl<D: Disk> FileSystem<D> { ...@@ -122,94 +120,96 @@ impl<D: Disk> FileSystem<D> {
let size = disk.size()?; let size = disk.size()?;
let block_offset = (reserved.len() as u64 + BLOCK_SIZE - 1) / BLOCK_SIZE; let block_offset = (reserved.len() as u64 + BLOCK_SIZE - 1) / BLOCK_SIZE;
if size >= (block_offset + HEADER_RING + 4) * BLOCK_SIZE { if size < (block_offset + HEADER_RING + 4) * BLOCK_SIZE {
for block in 0..block_offset as usize { return Err(Error::new(syscall::error::ENOSPC));
let mut data = [0; BLOCK_SIZE as usize]; }
let mut i = 0; // Fill reserved data, pad with zeroes
while i < data.len() && block * BLOCK_SIZE as usize + i < reserved.len() { for block in 0..block_offset as usize {
data[i] = reserved[block * BLOCK_SIZE as usize + i]; let mut data = [0; BLOCK_SIZE as usize];
i += 1;
}
unsafe { let mut i = 0;
disk.write_at(block as u64, &data)?; while i < data.len() && block * BLOCK_SIZE as usize + i < reserved.len() {
} data[i] = reserved[block * BLOCK_SIZE as usize + i];
i += 1;
} }
let mut header = Header::new(size); unsafe {
disk.write_at(block as u64, &data)?;
let aes_opt = match password_opt { }
Some(password) => { }
//TODO: handle errors
header.key_slots[0] =
KeySlot::new(password, Salt::new().unwrap(), Key::new().unwrap()).unwrap();
Some(header.key_slots[0].key(password).unwrap().into_aes())
}
None => None,
};
let mut fs = FileSystem { let mut header = Header::new(size);
disk,
block: block_offset,
header,
allocator: Allocator::default(),
aes_opt,
aes_blocks: Vec::with_capacity(BLOCK_SIZE as usize / aes::BLOCK_SIZE),
};
// Write header generation zero let aes_opt = match password_opt {
let count = unsafe { fs.disk.write_at(fs.block, &fs.header)? }; Some(password) => {
if count != mem::size_of_val(&fs.header) { //TODO: handle errors
// Wrote wrong number of bytes header.key_slots[0] =
#[cfg(feature = "log")] KeySlot::new(password, Salt::new().unwrap(), Key::new().unwrap()).unwrap();
log::error!("CREATE: WRONG NUMBER OF BYTES"); Some(header.key_slots[0].key(password).unwrap().into_aes())
return Err(Error::new(EIO));
} }
None => None,
};
let mut fs = FileSystem {
disk,
block: block_offset,
header,
allocator: Allocator::default(),
aes_opt,
aes_blocks: Vec::with_capacity(BLOCK_SIZE as usize / aes::BLOCK_SIZE),
};
// Write header generation zero
let count = unsafe { fs.disk.write_at(fs.block, &fs.header)? };
if count != core::mem::size_of_val(&fs.header) {
// Wrote wrong number of bytes
#[cfg(feature = "log")]
log::error!("CREATE: WRONG NUMBER OF BYTES");
return Err(Error::new(syscall::error::EIO));
}
// Set tree and alloc pointers and write header generation one // Set tree and alloc pointers and write header generation one
fs.tx(|tx| unsafe { fs.tx(|tx| unsafe {
let tree = BlockData::new( let tree = BlockData::new(
BlockAddr::new(HEADER_RING + 1, BlockLevel::default()), BlockAddr::new(HEADER_RING + 1, BlockLevel::default()),
TreeList::empty(BlockLevel::default()).unwrap(), TreeList::empty(BlockLevel::default()).unwrap(),
); );
let mut alloc = BlockData::new( let mut alloc = BlockData::new(
BlockAddr::new(HEADER_RING + 2, BlockLevel::default()), BlockAddr::new(HEADER_RING + 2, BlockLevel::default()),
AllocList::empty(BlockLevel::default()).unwrap(), AllocList::empty(BlockLevel::default()).unwrap(),
); );
let alloc_free = size / BLOCK_SIZE - (block_offset + HEADER_RING + 4);
alloc.data_mut().entries[0] = AllocEntry::new(HEADER_RING + 4, alloc_free as i64);
tx.header.tree = tx.write_block(tree)?; let alloc_free = size / BLOCK_SIZE - (block_offset + HEADER_RING + 4);
tx.header.alloc = tx.write_block(alloc)?; alloc.data_mut().entries[0] = AllocEntry::new(HEADER_RING + 4, alloc_free as i64);
tx.header_changed = true;
Ok(()) tx.header.tree = tx.write_block(tree)?;
})?; tx.header.alloc = tx.write_block(alloc)?;
tx.header_changed = true;
unsafe { Ok(())
fs.reset_allocator()?; })?;
}
fs.tx(|tx| unsafe { unsafe {
let mut root = BlockData::new( fs.reset_allocator()?;
BlockAddr::new(HEADER_RING + 3, BlockLevel::default()),
Node::new(Node::MODE_DIR | 0o755, 0, 0, ctime, ctime_nsec),
);
root.data_mut().set_links(1);
let root_ptr = tx.write_block(root)?;
assert_eq!(tx.insert_tree(root_ptr)?.id(), 1);
Ok(())
})?;
// Make sure everything is synced and squash allocations
Transaction::new(&mut fs).commit(true)?;
Ok(fs)
} else {
Err(Error::new(ENOSPC))
} }
fs.tx(|tx| unsafe {
let mut root = BlockData::new(
BlockAddr::new(HEADER_RING + 3, BlockLevel::default()),
Node::new(Node::MODE_DIR | 0o755, 0, 0, ctime, ctime_nsec),
);
root.data_mut().set_links(1);
let root_ptr = tx.write_block(root)?;
assert_eq!(tx.insert_tree(root_ptr)?.id(), 1);
Ok(())
})?;
// Make sure everything is synced and squash allocations
Transaction::new(&mut fs).commit(true)?;
Ok(fs)
} }
/// start a filesystem transaction, required for making any changes /// start a filesystem transaction, required for making any changes
...@@ -227,7 +227,7 @@ impl<D: Disk> FileSystem<D> { ...@@ -227,7 +227,7 @@ impl<D: Disk> FileSystem<D> {
/// Reset allocator to state stored on disk /// Reset allocator to state stored on disk
/// ///
/// # Safety /// # Safety
/// Unsafe, it must only be called when openning the filesystem /// Unsafe, it must only be called when opening the filesystem
unsafe fn reset_allocator(&mut self) -> Result<()> { unsafe fn reset_allocator(&mut self) -> Result<()> {
self.allocator = Allocator::default(); self.allocator = Allocator::default();
...@@ -268,52 +268,58 @@ impl<D: Disk> FileSystem<D> { ...@@ -268,52 +268,58 @@ impl<D: Disk> FileSystem<D> {
} }
pub(crate) fn decrypt(&mut self, data: &mut [u8]) -> bool { pub(crate) fn decrypt(&mut self, data: &mut [u8]) -> bool {
if let Some(ref aes) = self.aes_opt { let aes = if let Some(ref aes) = self.aes_opt {
assert_eq!(data.len() % aes::BLOCK_SIZE, 0); aes
} else {
self.aes_blocks.clear(); // Do nothing if encryption is disabled
for i in 0..data.len() / aes::BLOCK_SIZE { return false;
self.aes_blocks.push(aes::Block::clone_from_slice( };
&data[i * aes::BLOCK_SIZE..(i + 1) * aes::BLOCK_SIZE],
));
}
aes.decrypt_blocks(&mut self.aes_blocks); assert_eq!(data.len() % aes::BLOCK_SIZE, 0);
for i in 0..data.len() / aes::BLOCK_SIZE { self.aes_blocks.clear();
data[i * aes::BLOCK_SIZE..(i + 1) * aes::BLOCK_SIZE] for i in 0..data.len() / aes::BLOCK_SIZE {
.copy_from_slice(&self.aes_blocks[i]); self.aes_blocks.push(aes::Block::clone_from_slice(
} &data[i * aes::BLOCK_SIZE..(i + 1) * aes::BLOCK_SIZE],
self.aes_blocks.clear(); ));
}
true aes.decrypt_blocks(&mut self.aes_blocks);
} else {
false for i in 0..data.len() / aes::BLOCK_SIZE {
data[i * aes::BLOCK_SIZE..(i + 1) * aes::BLOCK_SIZE]
.copy_from_slice(&self.aes_blocks[i]);
} }
self.aes_blocks.clear();
true
} }
pub(crate) fn encrypt(&mut self, data: &mut [u8]) -> bool { pub(crate) fn encrypt(&mut self, data: &mut [u8]) -> bool {
if let Some(ref aes) = self.aes_opt { let aes = if let Some(ref aes) = self.aes_opt {
assert_eq!(data.len() % aes::BLOCK_SIZE, 0); aes
} else {
self.aes_blocks.clear(); // Do nothing if encryption is disabled
for i in 0..data.len() / aes::BLOCK_SIZE { return false;
self.aes_blocks.push(aes::Block::clone_from_slice( };
&data[i * aes::BLOCK_SIZE..(i + 1) * aes::BLOCK_SIZE],
));
}
aes.encrypt_blocks(&mut self.aes_blocks); assert_eq!(data.len() % aes::BLOCK_SIZE, 0);
for i in 0..data.len() / aes::BLOCK_SIZE { self.aes_blocks.clear();
data[i * aes::BLOCK_SIZE..(i + 1) * aes::BLOCK_SIZE] for i in 0..data.len() / aes::BLOCK_SIZE {
.copy_from_slice(&self.aes_blocks[i]); self.aes_blocks.push(aes::Block::clone_from_slice(
} &data[i * aes::BLOCK_SIZE..(i + 1) * aes::BLOCK_SIZE],
self.aes_blocks.clear(); ));
}
true aes.encrypt_blocks(&mut self.aes_blocks);
} else {
false for i in 0..data.len() / aes::BLOCK_SIZE {
data[i * aes::BLOCK_SIZE..(i + 1) * aes::BLOCK_SIZE]
.copy_from_slice(&self.aes_blocks[i]);
} }
self.aes_blocks.clear();
true
} }
} }
...@@ -3,7 +3,6 @@ use core::{fmt, mem, slice}; ...@@ -3,7 +3,6 @@ use core::{fmt, mem, slice};
use endian_num::Le; use endian_num::Le;
use aes::{Aes128, BlockDecrypt, BlockEncrypt}; use aes::{Aes128, BlockDecrypt, BlockEncrypt};
use uuid::Uuid;
use crate::{AllocList, BlockPtr, KeySlot, Tree, BLOCK_SIZE, SIGNATURE, VERSION}; use crate::{AllocList, BlockPtr, KeySlot, Tree, BLOCK_SIZE, SIGNATURE, VERSION};
...@@ -11,7 +10,7 @@ pub const HEADER_RING: u64 = 256; ...@@ -11,7 +10,7 @@ pub const HEADER_RING: u64 = 256;
/// The header of the filesystem /// The header of the filesystem
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
#[repr(packed)] #[repr(C, packed)]
pub struct Header { pub struct Header {
/// Signature, should be SIGNATURE /// Signature, should be SIGNATURE
pub signature: [u8; 8], pub signature: [u8; 8],
...@@ -40,7 +39,7 @@ pub struct Header { ...@@ -40,7 +39,7 @@ pub struct Header {
impl Header { impl Header {
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub fn new(size: u64) -> Header { pub fn new(size: u64) -> Header {
let uuid = Uuid::new_v4(); let uuid = uuid::Uuid::new_v4();
let mut header = Header { let mut header = Header {
signature: *SIGNATURE, signature: *SIGNATURE,
version: VERSION.into(), version: VERSION.into(),
......
...@@ -40,7 +40,7 @@ impl Salt { ...@@ -40,7 +40,7 @@ impl Salt {
/// The key slot, containing the salt and encrypted key that are used with one password /// The key slot, containing the salt and encrypted key that are used with one password
#[derive(Clone, Copy, Default)] #[derive(Clone, Copy, Default)]
#[repr(packed)] #[repr(C, packed)]
pub struct KeySlot { pub struct KeySlot {
salt: Salt, salt: Salt,
encrypted_key: EncryptedKey, encrypted_key: EncryptedKey,
......
...@@ -3,11 +3,14 @@ ...@@ -3,11 +3,14 @@
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
// Used often in generating redox_syscall errors // Used often in generating redox_syscall errors
#![allow(clippy::or_fun_call)] #![allow(clippy::or_fun_call)]
#![allow(unexpected_cfgs)]
extern crate alloc; extern crate alloc;
use core::sync::atomic::AtomicUsize; use core::sync::atomic::AtomicUsize;
// The alloc log grows by 1 block about every 21 generations
pub const ALLOC_GC_THRESHOLD: u64 = 1024;
pub const BLOCK_SIZE: u64 = 4096; pub const BLOCK_SIZE: u64 = 4096;
// A record is 4KiB << 5 = 128KiB // A record is 4KiB << 5 = 128KiB
pub const RECORD_LEVEL: usize = 5; pub const RECORD_LEVEL: usize = 5;
...@@ -47,8 +50,10 @@ mod disk; ...@@ -47,8 +50,10 @@ mod disk;
mod filesystem; mod filesystem;
mod header; mod header;
mod key; mod key;
#[cfg(feature = "std")] #[cfg(all(feature = "std", not(fuzzing)))]
mod mount; mod mount;
#[cfg(all(feature = "std", fuzzing))]
pub mod mount;
mod node; mod node;
mod record; mod record;
mod transaction; mod transaction;
......
...@@ -27,12 +27,12 @@ const NULL_TIME: Duration = Duration::new(0, 0); ...@@ -27,12 +27,12 @@ const NULL_TIME: Duration = Duration::new(0, 0);
pub fn mount<D, P, T, F>( pub fn mount<D, P, T, F>(
mut filesystem: filesystem::FileSystem<D>, mut filesystem: filesystem::FileSystem<D>,
mountpoint: P, mountpoint: P,
mut callback: F, callback: F,
) -> io::Result<T> ) -> io::Result<T>
where where
D: Disk, D: Disk,
P: AsRef<Path>, P: AsRef<Path>,
F: FnMut(&Path) -> T, F: FnOnce(&Path) -> T,
{ {
let mountpoint = mountpoint.as_ref(); let mountpoint = mountpoint.as_ref();
...@@ -374,7 +374,7 @@ impl<'f, D: Disk> Filesystem for Fuse<'f, D> { ...@@ -374,7 +374,7 @@ impl<'f, D: Disk> Filesystem for Fuse<'f, D> {
name: &OsStr, name: &OsStr,
mode: u32, mode: u32,
_umask: u32, _umask: u32,
flags: i32, _flags: i32,
reply: ReplyCreate, reply: ReplyCreate,
) { ) {
let parent_ptr = TreePtr::<Node>::new(parent_id as u32); let parent_ptr = TreePtr::<Node>::new(parent_id as u32);
...@@ -390,7 +390,7 @@ impl<'f, D: Disk> Filesystem for Fuse<'f, D> { ...@@ -390,7 +390,7 @@ impl<'f, D: Disk> Filesystem for Fuse<'f, D> {
}) { }) {
Ok(node) => { Ok(node) => {
// println!("Create {:?}:{:o}:{:o}", node.1.name(), node.1.mode, mode); // println!("Create {:?}:{:o}:{:o}", node.1.name(), node.1.mode, mode);
reply.created(&TTL, &node_attr(&node), 0, 0, flags as u32); reply.created(&TTL, &node_attr(&node), 0, 0, 0);
} }
Err(error) => { Err(error) => {
reply.error(error.errno); reply.error(error.errno);
......
#[cfg(not(target_os = "redox"))] #[cfg(all(not(target_os = "redox"), not(fuzzing)))]
mod fuse; mod fuse;
#[cfg(all(not(target_os = "redox"), fuzzing))]
pub mod fuse;
#[cfg(not(target_os = "redox"))] #[cfg(not(target_os = "redox"))]
pub use self::fuse::mount; pub use self::fuse::mount;
......
use std::fs::File; use redox_scheme::{RequestKind, SignalBehavior, Socket, V2};
use std::io::{self, Read, Write}; use std::io;
use std::path::Path; use std::path::Path;
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
use syscall::{Packet, SchemeMut, KSMSG_CANCEL};
use crate::{Disk, FileSystem, Transaction, IS_UMT}; use crate::{Disk, FileSystem, Transaction, IS_UMT};
...@@ -15,39 +14,33 @@ pub fn mount<D, P, T, F>(filesystem: FileSystem<D>, mountpoint: P, mut callback: ...@@ -15,39 +14,33 @@ pub fn mount<D, P, T, F>(filesystem: FileSystem<D>, mountpoint: P, mut callback:
where where
D: Disk, D: Disk,
P: AsRef<Path>, P: AsRef<Path>,
F: FnMut(&Path) -> T, F: FnOnce(&Path) -> T,
{ {
let mountpoint = mountpoint.as_ref(); let mountpoint = mountpoint.as_ref();
let socket_path = format!(":{}", mountpoint.display()); let socket = Socket::<V2>::create(&format!("{}", mountpoint.display()))?;
let mut socket = File::create(&socket_path)?;
let mounted_path = format!("{}:", mountpoint.display()); let mounted_path = format!("{}:", mountpoint.display());
let res = callback(Path::new(&mounted_path)); let res = callback(Path::new(&mounted_path));
let mut scheme = FileScheme::new(format!("{}", mountpoint.display()), filesystem); let mut scheme = FileScheme::new(format!("{}", mountpoint.display()), filesystem);
while IS_UMT.load(Ordering::SeqCst) == 0 { while IS_UMT.load(Ordering::SeqCst) == 0 {
let mut packet = Packet::default(); let req = match socket.next_request(SignalBehavior::Restart)? {
match socket.read(&mut packet) { None => break,
Ok(0) => break, Some(req) => {
Ok(_ok) => (), if let RequestKind::Call(r) = req.kind() {
Err(err) => { r
if err.kind() == io::ErrorKind::Interrupted {
continue;
} else { } else {
return Err(err); // TODO: Redoxfs does not yet support asynchronous file IO. It might still make
// sense to implement cancellation for huge buffers, e.g. dd bs=1G
continue;
} }
} }
} };
let response = req.handle_scheme_mut(&mut scheme);
// TODO: Redoxfs does not yet support asynchronous file IO. It might still make sense to if !socket.write_response(response, SignalBehavior::Restart)? {
// implement cancellation for huge buffers, e.g. dd bs=1G break;
if packet.a == KSMSG_CANCEL {
continue;
} }
scheme.handle(&mut packet);
socket.write(&packet)?;
} }
// Squash allocations and sync on unmount // Squash allocations and sync on unmount
......
use std::cmp::{max, min};
use std::slice; use std::slice;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
...@@ -6,11 +5,11 @@ use alloc::collections::BTreeMap; ...@@ -6,11 +5,11 @@ use alloc::collections::BTreeMap;
use libredox::call::MmapArgs; use libredox::call::MmapArgs;
use range_tree::RangeTree; use range_tree::RangeTree;
use syscall::data::{Map, Stat, TimeSpec}; use syscall::data::{Stat, TimeSpec};
use syscall::error::{Error, Result, EBADF, EINVAL, EISDIR, EPERM}; use syscall::error::{Error, Result, EBADF, EINVAL, EISDIR, EPERM};
use syscall::flag::{ use syscall::flag::{
MapFlags, F_GETFL, F_SETFL, MODE_PERM, O_ACCMODE, O_APPEND, O_RDONLY, O_RDWR, O_WRONLY, MapFlags, F_GETFL, F_SETFL, MODE_PERM, O_ACCMODE, O_APPEND, O_RDONLY, O_RDWR, O_WRONLY,
PROT_READ, PROT_WRITE, SEEK_CUR, SEEK_END, SEEK_SET, PROT_READ, PROT_WRITE,
}; };
use syscall::{EBADFD, PAGE_SIZE}; use syscall::{EBADFD, PAGE_SIZE};
...@@ -29,11 +28,11 @@ pub trait Resource<D: Disk> { ...@@ -29,11 +28,11 @@ pub trait Resource<D: Disk> {
fn set_path(&mut self, path: &str); fn set_path(&mut self, path: &str);
fn read(&mut self, buf: &mut [u8], tx: &mut Transaction<D>) -> Result<usize>; fn read(&mut self, buf: &mut [u8], offset: u64, tx: &mut Transaction<D>) -> Result<usize>;
fn write(&mut self, buf: &[u8], tx: &mut Transaction<D>) -> Result<usize>; fn write(&mut self, buf: &[u8], offset: u64, tx: &mut Transaction<D>) -> Result<usize>;
fn seek(&mut self, offset: isize, whence: usize, tx: &mut Transaction<D>) -> Result<isize>; fn fsize(&mut self, tx: &mut Transaction<D>) -> Result<u64>;
fn fmap( fn fmap(
&mut self, &mut self,
...@@ -143,7 +142,6 @@ pub struct DirResource { ...@@ -143,7 +142,6 @@ pub struct DirResource {
parent_ptr_opt: Option<TreePtr<Node>>, parent_ptr_opt: Option<TreePtr<Node>>,
node_ptr: TreePtr<Node>, node_ptr: TreePtr<Node>,
data: Option<Vec<u8>>, data: Option<Vec<u8>>,
seek: isize,
uid: u32, uid: u32,
} }
...@@ -160,7 +158,6 @@ impl DirResource { ...@@ -160,7 +158,6 @@ impl DirResource {
parent_ptr_opt, parent_ptr_opt,
node_ptr, node_ptr,
data, data,
seek: 0,
uid, uid,
} }
} }
...@@ -185,7 +182,6 @@ impl<D: Disk> Resource<D> for DirResource { ...@@ -185,7 +182,6 @@ impl<D: Disk> Resource<D> for DirResource {
parent_ptr_opt: self.parent_ptr_opt, parent_ptr_opt: self.parent_ptr_opt,
node_ptr: self.node_ptr, node_ptr: self.node_ptr,
data: self.data.clone(), data: self.data.clone(),
seek: self.seek,
uid: self.uid, uid: self.uid,
})) }))
} }
...@@ -194,32 +190,24 @@ impl<D: Disk> Resource<D> for DirResource { ...@@ -194,32 +190,24 @@ impl<D: Disk> Resource<D> for DirResource {
self.path = path.to_string(); self.path = path.to_string();
} }
fn read(&mut self, buf: &mut [u8], _tx: &mut Transaction<D>) -> Result<usize> { fn read(&mut self, buf: &mut [u8], offset: u64, _tx: &mut Transaction<D>) -> Result<usize> {
let data = self.data.as_ref().ok_or(Error::new(EISDIR))?; let data = self.data.as_ref().ok_or(Error::new(EISDIR))?;
let size = data.len() as isize; let src = usize::try_from(offset)
let mut i = 0; .ok()
while i < buf.len() && self.seek < size { .and_then(|o| data.get(o..))
buf[i] = data[self.seek as usize]; .unwrap_or(&[]);
i += 1;
self.seek += 1; let byte_count = core::cmp::min(src.len(), buf.len());
} buf[..byte_count].copy_from_slice(&src[..byte_count]);
Ok(i) Ok(byte_count)
} }
fn write(&mut self, _buf: &[u8], _tx: &mut Transaction<D>) -> Result<usize> { fn write(&mut self, _buf: &[u8], _offset: u64, _tx: &mut Transaction<D>) -> Result<usize> {
Err(Error::new(EBADF)) Err(Error::new(EBADF))
} }
fn seek(&mut self, offset: isize, whence: usize, _tx: &mut Transaction<D>) -> Result<isize> { fn fsize(&mut self, _tx: &mut Transaction<D>) -> Result<u64> {
let data = self.data.as_ref().ok_or(Error::new(EBADF))?; Ok(self.data.as_ref().ok_or(Error::new(EBADF))?.len() as u64)
let size = data.len() as isize;
self.seek = match whence {
SEEK_SET => max(0, min(size, offset)),
SEEK_CUR => max(0, min(size, self.seek + offset)),
SEEK_END => max(0, min(size, size + offset)),
_ => return Err(Error::new(EINVAL)),
};
Ok(self.seek)
} }
fn fmap( fn fmap(
...@@ -336,7 +324,6 @@ pub struct FileResource { ...@@ -336,7 +324,6 @@ pub struct FileResource {
parent_ptr_opt: Option<TreePtr<Node>>, parent_ptr_opt: Option<TreePtr<Node>>,
node_ptr: TreePtr<Node>, node_ptr: TreePtr<Node>,
flags: usize, flags: usize,
seek: isize,
uid: u32, uid: u32,
} }
#[derive(Debug)] #[derive(Debug)]
...@@ -370,7 +357,6 @@ impl FileResource { ...@@ -370,7 +357,6 @@ impl FileResource {
parent_ptr_opt, parent_ptr_opt,
node_ptr, node_ptr,
flags, flags,
seek: 0,
uid, uid,
} }
} }
...@@ -395,7 +381,6 @@ impl<D: Disk> Resource<D> for FileResource { ...@@ -395,7 +381,6 @@ impl<D: Disk> Resource<D> for FileResource {
parent_ptr_opt: self.parent_ptr_opt, parent_ptr_opt: self.parent_ptr_opt,
node_ptr: self.node_ptr, node_ptr: self.node_ptr,
flags: self.flags, flags: self.flags,
seek: self.seek,
uid: self.uid, uid: self.uid,
})) }))
} }
...@@ -404,55 +389,43 @@ impl<D: Disk> Resource<D> for FileResource { ...@@ -404,55 +389,43 @@ impl<D: Disk> Resource<D> for FileResource {
self.path = path.to_string(); self.path = path.to_string();
} }
fn read(&mut self, buf: &mut [u8], tx: &mut Transaction<D>) -> Result<usize> { fn read(&mut self, buf: &mut [u8], offset: u64, tx: &mut Transaction<D>) -> Result<usize> {
if self.flags & O_ACCMODE == O_RDWR || self.flags & O_ACCMODE == O_RDONLY { if self.flags & O_ACCMODE != O_RDWR && self.flags & O_ACCMODE != O_RDONLY {
let atime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); return Err(Error::new(EBADF));
let count = tx.read_node(
self.node_ptr,
self.seek as u64,
buf,
atime.as_secs(),
atime.subsec_nanos(),
)?;
self.seek += count as isize;
Ok(count)
} else {
Err(Error::new(EBADF))
} }
let atime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
tx.read_node(
self.node_ptr,
offset,
buf,
atime.as_secs(),
atime.subsec_nanos(),
)
} }
fn write(&mut self, buf: &[u8], tx: &mut Transaction<D>) -> Result<usize> { fn write(&mut self, buf: &[u8], offset: u64, tx: &mut Transaction<D>) -> Result<usize> {
if self.flags & O_ACCMODE == O_RDWR || self.flags & O_ACCMODE == O_WRONLY { if self.flags & O_ACCMODE != O_RDWR && self.flags & O_ACCMODE != O_WRONLY {
if self.flags & O_APPEND == O_APPEND { return Err(Error::new(EBADF));
let node = tx.read_tree(self.node_ptr)?;
self.seek = node.data().size() as isize;
}
let mtime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let count = tx.write_node(
self.node_ptr,
self.seek as u64,
buf,
mtime.as_secs(),
mtime.subsec_nanos(),
)?;
self.seek += count as isize;
Ok(count)
} else {
Err(Error::new(EBADF))
} }
let effective_offset = if self.flags & O_APPEND == O_APPEND {
let node = tx.read_tree(self.node_ptr)?;
node.data().size()
} else {
offset
};
let mtime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
tx.write_node(
self.node_ptr,
effective_offset,
buf,
mtime.as_secs(),
mtime.subsec_nanos(),
)
} }
fn seek(&mut self, offset: isize, whence: usize, tx: &mut Transaction<D>) -> Result<isize> { fn fsize(&mut self, tx: &mut Transaction<D>) -> Result<u64> {
self.seek = match whence { let node = tx.read_tree(self.node_ptr)?;
SEEK_SET => max(0, offset), Ok(node.data().size())
SEEK_CUR => max(0, self.seek + offset),
SEEK_END => {
let node = tx.read_tree(self.node_ptr)?;
max(0, node.data().size() as isize + offset)
}
_ => return Err(Error::new(EINVAL)),
};
Ok(self.seek)
} }
fn fmap( fn fmap(
...@@ -492,15 +465,13 @@ impl<D: Disk> Resource<D> for FileResource { ...@@ -492,15 +465,13 @@ impl<D: Disk> Resource<D> for FileResource {
length: new_size, length: new_size,
// PRIVATE/SHARED doesn't matter once the pages are passed in the fmap // PRIVATE/SHARED doesn't matter once the pages are passed in the fmap
// handler. // handler.
prot: libredox::flag::PROT_READ prot: libredox::flag::PROT_READ | libredox::flag::PROT_WRITE,
| libredox::flag::PROT_WRITE,
flags: libredox::flag::MAP_PRIVATE, flags: libredox::flag::MAP_PRIVATE,
offset: 0, offset: 0,
fd: !0, fd: !0,
addr: core::ptr::null_mut(), addr: core::ptr::null_mut(),
} })? as *mut u8
)? as *mut u8
} }
} else { } else {
unsafe { unsafe {
......