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 (88)
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
version = 4
[[package]]
name = "aes"
......@@ -31,47 +16,70 @@ dependencies = [
[[package]]
name = "aho-corasick"
version = "0.7.20"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "argon2"
version = "0.3.4"
name = "anstream"
version = "0.6.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25df3c03f1040d0069fcd3907e24e36d59f9b6fa07ba49be0eb25a794f036ba7"
checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338"
dependencies = [
"base64ct",
"blake2",
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "atty"
version = "0.2.14"
name = "anstyle"
version = "1.0.9"
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 = [
"hermit-abi",
"libc",
"winapi",
"utf8parse",
]
[[package]]
name = "backtrace"
version = "0.3.67"
name = "anstyle-query"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
......@@ -82,9 +90,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "bitflags"
version = "1.3.2"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "blake2"
......@@ -106,15 +114,9 @@ dependencies = [
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
version = "1.0.79"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cfg-if"
......@@ -131,11 +133,17 @@ dependencies = [
"generic-array",
]
[[package]]
name = "colorchoice"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "cpufeatures"
version = "0.2.6"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181"
checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
dependencies = [
"libc",
]
......@@ -150,11 +158,20 @@ dependencies = [
"typenum",
]
[[package]]
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
]
[[package]]
name = "digest"
version = "0.10.6"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
......@@ -162,51 +179,39 @@ dependencies = [
]
[[package]]
name = "env_logger"
version = "0.9.3"
name = "endian-num"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
checksum = "f8f59926911ef34d1efb9ea1ee8ca78385df62ce700ccf2bcb149011bd226888"
[[package]]
name = "failure"
version = "0.1.8"
name = "env_filter"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab"
dependencies = [
"backtrace",
"failure_derive",
"log",
"regex",
]
[[package]]
name = "failure_derive"
version = "0.1.8"
name = "env_logger"
version = "0.11.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
"anstream",
"anstyle",
"env_filter",
"humantime",
"log",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "fuser"
version = "0.12.0"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5910691a0ececcc6eba8bb14029025c2d123e96a53db1533f6a4602861a5aaf7"
checksum = "2e697f6f62c20b6fad1ba0f84ae909f25971cf16e735273524e3977c94604cf8"
dependencies = [
"libc",
"log",
......@@ -214,7 +219,6 @@ dependencies = [
"page_size",
"pkg-config",
"smallvec",
"users",
"zerocopy",
]
......@@ -230,28 +234,13 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.9"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
name = "gimli"
version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
"wasi",
]
[[package]]
......@@ -260,62 +249,64 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "libc"
version = "0.2.141"
version = "0.2.161"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
[[package]]
name = "log"
version = "0.4.17"
name = "libredox"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"cfg-if",
"bitflags",
"libc",
"redox_syscall",
]
[[package]]
name = "memchr"
version = "2.5.0"
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "miniz_oxide"
version = "0.6.2"
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [
"adler",
]
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "numtoa"
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "object"
version = "0.30.3"
name = "numtoa"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
dependencies = [
"memchr",
]
checksum = "6aa2c4e539b869820a2b82e1aef6ff40aa85e65decdd5185e83fb4b1249cd00f"
[[package]]
name = "opaque-debug"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "page_size"
version = "0.4.2"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eebde548fbbf1ea81a99b128872779c437752fb99f217c45245e1a61dcd9edcd"
checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da"
dependencies = [
"libc",
"winapi",
......@@ -323,113 +314,88 @@ dependencies = [
[[package]]
name = "pkg-config"
version = "0.3.26"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "proc-macro2"
version = "1.0.56"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.26"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.3.23"
name = "range-tree"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
dependencies = [
"libc",
"rand 0.4.6",
]
checksum = "384c2842d4e069d5ccacf5fe1dca4ef8d07a5444329715f0fc3c61813502d4d1"
[[package]]
name = "rand"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
dependencies = [
"fuchsia-cprng",
"libc",
"rand_core 0.3.1",
"rdrand",
"winapi",
]
[[package]]
name = "rand_core"
name = "redox-path"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
checksum = "436d45c2b6a5b159d43da708e62b25be3a4a3d5550d654b72216ade4c4bfd717"
[[package]]
name = "rdrand"
version = "0.4.0"
name = "redox-scheme"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
checksum = "6143c4d307e1c99ac14f60b5b07b2dccaf9d17137f7cee4e4e29977dd8014a1b"
dependencies = [
"rand_core 0.3.1",
"libredox",
"redox_syscall",
]
[[package]]
name = "redox_simple_endian"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "175b27da3d5db1502bd20ae0917ba132d256a2b169f1686681304ebb86504eab"
[[package]]
name = "redox_syscall"
version = "0.2.16"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
dependencies = [
"bitflags",
]
[[package]]
name = "redox_termios"
version = "0.1.2"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f"
dependencies = [
"redox_syscall",
]
checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb"
[[package]]
name = "redoxfs"
version = "0.5.7"
version = "0.6.9"
dependencies = [
"aes",
"argon2",
"base64ct",
"endian-num",
"env_logger",
"failure",
"fuser",
"getrandom",
"libc",
"libredox",
"log",
"redox_simple_endian",
"range-tree",
"redox-path",
"redox-scheme",
"redox_syscall",
"seahash",
"termion",
......@@ -439,26 +405,32 @@ dependencies = [
[[package]]
name = "regex"
version = "1.7.3"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.29"
name = "regex-automata"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "rustc-demangle"
version = "0.1.22"
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4a36c42d1873f9a77c53bde094f9664d9891bc604a45b4798fd2c389ed12e5b"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "seahash"
......@@ -467,120 +439,111 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]]
name = "smallvec"
version = "1.10.0"
name = "serde"
version = "1.0.214"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "subtle"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
"serde_derive",
]
[[package]]
name = "synstructure"
version = "0.12.6"
name = "serde_derive"
version = "1.0.214"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
dependencies = [
"proc-macro2",
"quote",
"syn",
"unicode-xid",
]
[[package]]
name = "termcolor"
version = "1.2.0"
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "subtle"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56"
dependencies = [
"winapi-util",
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "termion"
version = "1.5.6"
version = "4.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e"
checksum = "7eaa98560e51a2cf4f0bb884d8b2098a9ea11ecf3b7078e9c68242c74cc923a7"
dependencies = [
"libc",
"libredox",
"numtoa",
"redox_syscall",
"redox_termios",
]
[[package]]
name = "time"
version = "0.1.45"
version = "0.3.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [
"libc",
"wasi 0.10.0+wasi-snapshot-preview1",
"winapi",
"deranged",
"num-conv",
"powerfmt",
"serde",
"time-core",
]
[[package]]
name = "typenum"
version = "1.16.0"
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "unicode-ident"
version = "1.0.8"
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-xid"
version = "0.2.4"
name = "unicode-ident"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "users"
version = "0.11.0"
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032"
dependencies = [
"libc",
"log",
]
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "0.5.1"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc7e3b898aa6f6c08e5295b6c89258d1331e9ac578cc992fb818759951bdc22"
checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a"
dependencies = [
"rand 0.3.23",
"getrandom",
]
[[package]]
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"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasi"
......@@ -605,25 +568,89 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"winapi",
"windows-targets",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
name = "windows-targets"
version = "0.52.6"
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]]
name = "zerocopy"
version = "0.6.1"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"byteorder",
"zerocopy-derive",
......@@ -631,9 +658,9 @@ dependencies = [
[[package]]
name = "zerocopy-derive"
version = "0.3.2"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6505e6815af7de1746a08f69c69606bb45695a17149517680f3b2149713b19a3"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
......
......@@ -2,11 +2,11 @@
name = "redoxfs"
description = "The Redox Filesystem"
repository = "https://gitlab.redox-os.org/redox-os/redoxfs"
version = "0.5.7"
version = "0.6.9"
license-file = "LICENSE"
readme = "README.md"
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
edition = "2018"
edition = "2021"
[lib]
name = "redoxfs"
......@@ -32,29 +32,24 @@ required-features = ["std"]
[dependencies]
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 }
env_logger = { version = "0.9.0", optional = true }
failure = "0.1.8"
env_logger = { version = "0.11", optional = true }
endian-num = "0.1"
getrandom = { version = "0.2.5", optional = true }
libc = "0.2"
log = { version = "0.4.14", default-features = false, optional = true}
redox_syscall = "0.2.12"
redox_syscall = { version = "0.5" }
range-tree = { version = "0.1", optional = true }
seahash = { version = "4.1.0", default-features = false }
termion = { version = "1.5.6", optional = true }
uuid = { version = "0.5", default-features = false }
# https://github.com/rexlunae/simple-endian-rs/pull/5
[dependencies.redox_simple_endian]
version = "0.3.0"
default-features = false
features = [
"bitwise", "comparisons", "format", "math_ops", "neg_ops", "shift_ops",
"both_endian", "float_impls", "integer_impls", "byte_impls"
]
termion = { version = "4", optional = true }
uuid = { version = "1.4", default-features = false }
redox-path = "0.3.0"
libredox = { version = "0.1.3", optional = true }
redox-scheme = { version = "0.2.1", optional = true }
[features]
default = ["std"]
default = ["std", "log"]
force-soft = [
"aes/force-soft"
]
......@@ -63,12 +58,19 @@ std = [
"fuser",
"getrandom",
"libc",
"libredox",
"range-tree",
"termion",
"time",
"uuid/v4"
"uuid/v4",
"redox_syscall/std",
"redox-scheme"
]
[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 }
time = { version = "0.1", optional = true }
time = { version = "0.3", optional = true }
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(fuzzing)'] }
......@@ -14,8 +14,8 @@ else
endif
image.bin:
dd if=/dev/zero of=image.bin bs=1048576 count=1024
cargo build --release --bin redoxfs-mkfs
dd if=/dev/zero of=image.bin bs=1048576 count=1024
target/release/redoxfs-mkfs image.bin
mount: image.bin FORCE
......
# redoxfs
The Redox Filesystem. Compatible with Redox and Linux.
# RedoxFS
This is the default filesystem of Redox OS inspired by [ZFS](https://docs.freebsd.org/en/books/handbook/zfs/) and adapted to a microkernel architecture.
(It's a replacement for [TFS](https://gitlab.redox-os.org/redox-os/tfs))
Current features:
- Compatible with Redox and Linux (FUSE)
- Copy-on-write
- Data/metadata checksums
- Transparent encryption
- Standard Unix file attributes
- File/directory size limit up to 193TiB (212TB)
- File/directory quantity limit up to 4 billion per 193TiB (2^32 - 1 = 4294967295)
- MIT licensed
- Disk encryption fully supported by the Redox bootloader, letting it load the kernel off an encrypted partition.
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
```
[![Travis Build Status](https://travis-ci.org/redox-os/redoxfs.svg?branch=master)](https://travis-ci.org/redox-os/redoxfs)
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
[![crates.io](http://meritbadge.herokuapp.com/redoxfs)](https://crates.io/crates/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
});
use alloc::vec::Vec;
use core::{fmt, mem, ops, slice};
use simple_endian::*;
use crate::BlockPtr;
pub const ALLOC_LIST_ENTRIES: usize = 255;
use endian_num::Le;
use crate::{BlockAddr, BlockLevel, BlockPtr, BlockTrait, BLOCK_SIZE};
pub const ALLOC_LIST_ENTRIES: usize =
(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)]
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>>,
}
......@@ -16,6 +40,7 @@ impl Allocator {
&self.levels
}
/// Count the number of free [`BLOCK_SIZE`] available to this [`Allocator`].
pub fn free(&self) -> u64 {
let mut free = 0;
for level in 0..self.levels.len() {
......@@ -25,63 +50,79 @@ impl Allocator {
free
}
pub fn allocate(&mut self) -> Option<u64> {
/// 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> {
// First, find the lowest level with a free block
let mut addr_opt = None;
let mut level = 0;
let mut index_opt = None;
let mut level = block_level.0;
// Start searching at the level we want. Smaller levels are too small!
while level < self.levels.len() {
if !self.levels[level].is_empty() {
addr_opt = self.levels[level].pop();
index_opt = self.levels[level].pop();
break;
}
level += 1;
}
// Next, if a free block was found, split it up until you have a usable level 0 block
let addr = addr_opt?;
while level > 0 {
// 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?;
while level > block_level.0 {
level -= 1;
let level_size = 1 << level;
self.levels[level].push(addr + level_size);
self.levels[level].push(index + level_size);
}
Some(addr)
Some(unsafe { BlockAddr::new(index, block_level) })
}
pub fn allocate_exact(&mut self, exact_addr: u64) -> Option<u64> {
let mut addr_opt = None;
/// 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> {
// This function only supports level 0 right now
assert_eq!(exact_addr.level().0, 0);
let exact_index = exact_addr.index();
let mut index_opt = None;
// Go from the highest to the lowest level
for level in (0..self.levels.len()).rev() {
let level_size = 1 << level;
// Split higher block if found
if let Some(addr) = addr_opt.take() {
self.levels[level].push(addr);
self.levels[level].push(addr + level_size);
if let Some(index) = index_opt.take() {
self.levels[level].push(index);
self.levels[level].push(index + level_size);
}
// Look for matching block and remove it
for i in 0..self.levels[level].len() {
let start = self.levels[level][i];
if start <= exact_addr {
if start <= exact_index {
let end = start + level_size;
if end > exact_addr {
if end > exact_index {
self.levels[level].remove(i);
addr_opt = Some(start);
index_opt = Some(start);
break;
}
}
}
}
addr_opt
Some(unsafe { BlockAddr::new(index_opt?, exact_addr.level()) })
}
pub fn deallocate(&mut self, mut addr: u64) {
// See if block matches with a sibling - if so, join them into a larger block, and populate
// this all the way to the top level
let mut level = 0;
/// Deallocate the given block, marking it "free" so that it can be re-used later.
pub fn deallocate(&mut self, addr: BlockAddr) {
// When we deallocate, we check if block we're deallocating has a free sibling.
// 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 level = addr.level().0;
loop {
while level >= self.levels.len() {
self.levels.push(Vec::new());
......@@ -92,51 +133,76 @@ impl Allocator {
let mut found = false;
let mut i = 0;
// look at all free blocks in the current level...
while i < self.levels[level].len() {
let level_addr = self.levels[level][i];
if addr % next_size == 0 && addr + level_size == level_addr {
// index of the second block we're looking at
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 {
// "alloc" the next highest block, repeat deallocation process.
self.levels[level].remove(i);
found = true;
break;
} else if level_addr % next_size == 0 && level_addr + level_size == addr {
// - 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 {
// "alloc" the next highest block, repeat deallocation process.
self.levels[level].remove(i);
addr = level_addr;
index = level_index; // index moves to left block
found = true;
break;
}
i += 1;
}
// We couldn't find a higher block,
// deallocate this one and finish
if !found {
self.levels[level].push(addr);
self.levels[level].push(index);
return;
}
// repeat deallocation process on the
// higher-level block we just created.
level += 1;
}
}
}
#[repr(packed)]
#[repr(C, packed)]
pub struct AllocEntry {
addr: u64le,
count: i64le,
/// The index of the first block this [`AllocEntry`] refers to
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>,
}
impl AllocEntry {
pub fn new(addr: u64, count: i64) -> Self {
pub fn new(index: u64, count: i64) -> Self {
Self {
addr: addr.into(),
index: index.into(),
count: count.into(),
}
}
pub fn addr(&self) -> u64 {
{ self.addr }.to_native()
pub fn allocate(addr: BlockAddr) -> Self {
Self::new(addr.index(), -addr.level().blocks())
}
pub fn deallocate(addr: BlockAddr) -> Self {
Self::new(addr.index(), addr.level().blocks())
}
pub fn index(&self) -> u64 {
self.index.to_ne()
}
pub fn count(&self) -> i64 {
{ self.count }.to_native()
self.count.to_ne()
}
pub fn is_null(&self) -> bool {
......@@ -146,10 +212,7 @@ impl AllocEntry {
impl Clone for AllocEntry {
fn clone(&self) -> Self {
Self {
addr: self.addr,
count: self.count,
}
*self
}
}
......@@ -158,7 +221,7 @@ impl Copy for AllocEntry {}
impl Default for AllocEntry {
fn default() -> Self {
Self {
addr: 0.into(),
index: 0.into(),
count: 0.into(),
}
}
......@@ -166,27 +229,35 @@ impl Default for AllocEntry {
impl fmt::Debug for AllocEntry {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let addr = self.addr();
let index = self.index();
let count = self.count();
f.debug_struct("AllocEntry")
.field("addr", &addr)
.field("index", &index)
.field("count", &count)
.finish()
}
}
/// Alloc log node
#[repr(packed)]
/// A node in the allocation chain.
#[repr(C, packed)]
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>,
/// Allocation entries.
pub entries: [AllocEntry; ALLOC_LIST_ENTRIES],
}
impl Default for AllocList {
fn default() -> Self {
Self {
prev: BlockPtr::default(),
entries: [AllocEntry::default(); ALLOC_LIST_ENTRIES],
unsafe impl BlockTrait for AllocList {
fn empty(level: BlockLevel) -> Option<Self> {
if level.0 == 0 {
Some(Self {
prev: BlockPtr::default(),
entries: [AllocEntry::default(); ALLOC_LIST_ENTRIES],
})
} else {
None
}
}
}
......@@ -238,14 +309,17 @@ fn alloc_node_size_test() {
fn allocator_test() {
let mut alloc = Allocator::default();
assert_eq!(alloc.allocate(), None);
assert_eq!(alloc.allocate(BlockLevel::default()), None);
alloc.deallocate(1);
assert_eq!(alloc.allocate(), Some(1));
assert_eq!(alloc.allocate(), None);
alloc.deallocate(unsafe { BlockAddr::new(1, BlockLevel::default()) });
assert_eq!(
alloc.allocate(BlockLevel::default()),
Some(unsafe { BlockAddr::new(1, BlockLevel::default()) })
);
assert_eq!(alloc.allocate(BlockLevel::default()), None);
for addr in 1023..2048 {
alloc.deallocate(addr);
alloc.deallocate(unsafe { BlockAddr::new(addr, BlockLevel::default()) });
}
assert_eq!(alloc.levels.len(), 11);
......@@ -260,9 +334,12 @@ fn allocator_test() {
}
for addr in 1023..2048 {
assert_eq!(alloc.allocate(), Some(addr));
assert_eq!(
alloc.allocate(BlockLevel::default()),
Some(unsafe { BlockAddr::new(addr, BlockLevel::default()) })
);
}
assert_eq!(alloc.allocate(), None);
assert_eq!(alloc.allocate(BlockLevel::default()), None);
assert_eq!(alloc.levels.len(), 11);
for level in 0..alloc.levels.len() {
......
......@@ -88,7 +88,7 @@ fn main() {
process::exit(1);
}
let uuid = Uuid::from_bytes(&fs.header.uuid()).unwrap();
let uuid = Uuid::from_bytes(fs.header.uuid());
println!(
"redoxfs-ar: created filesystem on {}, reserved {} blocks, size {} MB, uuid {}",
disk_path,
......
......@@ -76,7 +76,7 @@ fn main() {
let password = io::stdin()
.read_passwd(&mut io::stderr())
.unwrap()
.unwrap_or(String::new());
.unwrap_or_default();
eprintln!();
......@@ -101,7 +101,7 @@ fn main() {
ctime.subsec_nanos(),
) {
Ok(filesystem) => {
let uuid = Uuid::from_bytes(&filesystem.header.uuid()).unwrap();
let uuid = Uuid::from_bytes(filesystem.header.uuid());
eprintln!(
"redoxfs-mkfs: created filesystem on {}, reserved {} blocks, size {} MB, uuid {}",
disk_path,
......
#[cfg(not(target_os = "redox"))]
extern crate libc;
extern crate redoxfs;
#[cfg(target_os = "redox")]
extern crate syscall;
extern crate redoxfs;
extern crate uuid;
use std::env;
......@@ -13,13 +10,15 @@ use std::io::{self, Read, Write};
use std::os::unix::io::{FromRawFd, RawFd};
use std::process;
#[cfg(target_os = "redox")]
use std::{mem::MaybeUninit, ptr::addr_of_mut, sync::atomic::Ordering};
use redoxfs::{mount, DiskCache, DiskFile, FileSystem};
use termion::input::TermRead;
use uuid::Uuid;
#[cfg(target_os = "redox")]
extern "C" fn unmount_handler(_s: usize) {
use std::sync::atomic::Ordering;
redoxfs::IS_UMT.store(1, Ordering::SeqCst);
}
......@@ -28,27 +27,32 @@ extern "C" fn unmount_handler(_s: usize) {
//for, so I put 2. I don't think 0,0 is a valid sa_mask. I don't know what i'm doing here. When u
//send it a sigkill, it shuts off the filesystem
fn setsig() {
use syscall::{sigaction, SigAction, SigActionFlags, SIGTERM};
let sig_action = SigAction {
sa_handler: Some(unmount_handler),
sa_mask: [0, 0],
sa_flags: SigActionFlags::empty(),
};
sigaction(SIGTERM, Some(&sig_action), None).unwrap();
// TODO: High-level wrapper like the nix crate?
unsafe {
let mut action = MaybeUninit::<libc::sigaction>::uninit();
assert_eq!(
libc::sigemptyset(addr_of_mut!((*action.as_mut_ptr()).sa_mask)),
0
);
addr_of_mut!((*action.as_mut_ptr()).sa_flags).write(0);
addr_of_mut!((*action.as_mut_ptr()).sa_sigaction).write(unmount_handler as usize);
assert_eq!(
libc::sigaction(libc::SIGTERM, action.as_ptr(), core::ptr::null_mut()),
0
);
}
}
#[cfg(not(target_os = "redox"))]
// on linux, this is implemented properly, so no need for this unscrupulous nonsense!
fn setsig() {}
#[cfg(not(target_os = "redox"))]
fn fork() -> isize {
unsafe { libc::fork() as isize }
}
#[cfg(not(target_os = "redox"))]
fn pipe(pipes: &mut [i32; 2]) -> isize {
unsafe { libc::pipe(pipes.as_mut_ptr()) as isize }
}
......@@ -61,23 +65,15 @@ fn bootloader_password() -> Option<Vec<u8>> {
None
}
#[cfg(target_os = "redox")]
fn fork() -> isize {
unsafe { libc::fork() as isize }
}
#[cfg(target_os = "redox")]
fn pipe(pipes: &mut [usize; 2]) -> isize {
syscall::Error::mux(syscall::pipe2(pipes, 0)) as isize
}
#[cfg(target_os = "redox")]
fn capability_mode() {
syscall::setrens(0, 0).expect("redoxfs: failed to enter null namespace");
libredox::call::setrens(0, 0).expect("redoxfs: failed to enter null namespace");
}
#[cfg(target_os = "redox")]
fn bootloader_password() -> Option<Vec<u8>> {
use libredox::call::MmapArgs;
let addr_env = env::var_os("REDOXFS_PASSWORD_ADDR")?;
let size_env = env::var_os("REDOXFS_PASSWORD_SIZE")?;
......@@ -95,20 +91,44 @@ fn bootloader_password() -> Option<Vec<u8>> {
let mut password = Vec::with_capacity(size);
unsafe {
let password_map = syscall::physmap(addr, size, syscall::PhysmapFlags::empty())
.expect("failed to map REDOXFS_PASSWORD");
let aligned_size = size.next_multiple_of(syscall::PAGE_SIZE);
let fd = libredox::Fd::open("memory:physical", libredox::flag::O_CLOEXEC, 0)
.expect("failed to open physical memory file");
let password_map = libredox::call::mmap(MmapArgs {
addr: core::ptr::null_mut(),
length: aligned_size,
prot: libredox::flag::PROT_READ,
flags: libredox::flag::MAP_SHARED,
fd: fd.raw(),
offset: addr as u64,
})
.expect("failed to map REDOXFS_PASSWORD")
.cast::<u8>();
for i in 0..size {
password.push(*((password_map + i) as *const u8));
password.push(password_map.add(i).read());
}
let _ = syscall::physunmap(password_map);
let _ = libredox::call::munmap(password_map.cast(), aligned_size);
}
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() {
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 {
......@@ -129,7 +149,7 @@ fn filesystem_by_path(
let password = io::stdin()
.read_passwd(&mut io::stderr())
.unwrap()
.unwrap_or(String::new());
.unwrap_or_default();
eprintln!();
......@@ -145,36 +165,31 @@ fn filesystem_by_path(
bootloader_password()
};
match DiskFile::open(&path).map(|image| DiskCache::new(image)) {
Ok(disk) => match redoxfs::FileSystem::open(
disk,
password_opt.as_ref().map(|x| x.as_slice()),
block_opt,
true,
) {
Ok(filesystem) => {
println!(
"redoxfs: opened filesystem on {} with uuid {}",
path,
Uuid::from_bytes(&filesystem.header.uuid())
.unwrap()
.hyphenated()
);
return Some((path.to_string(), filesystem));
}
Err(err) => match err.errno {
syscall::ENOKEY => {
if password_opt.is_some() {
println!("redoxfs: incorrect password ({}/{})", attempt, attempts);
}
}
_ => {
println!("redoxfs: failed to open filesystem {}: {}", path, err);
break;
match DiskFile::open(path).map(DiskCache::new) {
Ok(disk) => {
match redoxfs::FileSystem::open(disk, password_opt.as_deref(), block_opt, true) {
Ok(filesystem) => {
println!(
"redoxfs: opened filesystem on {} with uuid {}",
path,
Uuid::from_bytes(filesystem.header.uuid()).hyphenated()
);
return Some((path.to_string(), filesystem));
}
},
},
Err(err) => match err.errno {
syscall::ENOKEY => {
if password_opt.is_some() {
println!("redoxfs: incorrect password ({}/{})", attempt, attempts);
}
}
_ => {
println!("redoxfs: failed to open filesystem {}: {}", path, err);
break;
}
},
}
}
Err(err) => {
println!("redoxfs: failed to open image {}: {}", path, err);
break;
......@@ -199,15 +214,19 @@ fn filesystem_by_uuid(
) -> Option<(String, FileSystem<DiskCache<DiskFile>>)> {
use std::fs;
match fs::read_dir(":") {
use redox_path::RedoxPath;
match fs::read_dir("/scheme") {
Ok(entries) => {
for entry_res in entries {
if let Ok(entry) = entry_res {
if let Ok(path) = entry.path().into_os_string().into_string() {
let scheme = path.trim_start_matches(':').trim_matches('/');
if scheme.starts_with("disk") {
println!("redoxfs: found scheme {}", scheme);
match fs::read_dir(&format!("{}:", scheme)) {
if let Some(disk) = entry.path().to_str() {
if RedoxPath::from_absolute(disk)
.unwrap_or(RedoxPath::from_absolute("/")?)
.is_scheme_category("disk")
{
println!("redoxfs: found scheme {}", disk);
match fs::read_dir(disk) {
Ok(entries) => {
for entry_res in entries {
if let Ok(entry) = entry_res {
......@@ -239,7 +258,7 @@ fn filesystem_by_uuid(
}
}
Err(err) => {
println!("redoxfs: failed to list '{}': {}", scheme, err);
println!("redoxfs: failed to list '{}': {}", disk, err);
}
}
}
......@@ -255,7 +274,12 @@ fn filesystem_by_uuid(
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();
let filesystem_opt = match *disk_id {
......@@ -264,7 +288,7 @@ fn daemon(disk_id: &DiskId, mountpoint: &str, block_opt: Option<u64>, mut write:
};
if let Some((path, filesystem)) = filesystem_opt {
match mount(filesystem, &mountpoint, |mounted_path| {
match mount(filesystem, mountpoint, |mounted_path| {
capability_mode();
println!(
......@@ -272,7 +296,10 @@ fn daemon(disk_id: &DiskId, mountpoint: &str, block_opt: Option<u64>, mut write:
path,
mounted_path.display()
);
let _ = write.write(&[0]);
if let Some(ref mut write) = write {
let _ = write.write(&[0]);
}
}) {
Ok(()) => {
process::exit(0);
......@@ -295,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);
}
......@@ -304,79 +334,74 @@ fn main() {
let mut args = env::args().skip(1);
let disk_id = match args.next() {
Some(arg) => {
if arg == "--uuid" {
let uuid = match args.next() {
Some(arg) => match Uuid::parse_str(&arg) {
Ok(uuid) => uuid,
Err(err) => {
println!("redoxfs: invalid uuid '{}': {}", arg, err);
usage();
process::exit(1);
let mut daemonise = true;
let mut disk_id: Option<DiskId> = None;
let mut mountpoint: Option<String> = None;
let mut block_opt: Option<u64> = None;
while let Some(arg) = args.next() {
match arg.as_str() {
"--no-daemon" | "-d" => daemonise = false,
"--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() {
Some(arg) => arg,
None => {
println!("redoxfs: no mountpoint provided");
usage();
process::exit(1);
disk if disk_id.is_none() => disk_id = Some(DiskId::Path(disk.to_owned())),
mnt if disk_id.is_some() && mountpoint.is_none() => mountpoint = Some(mnt.to_owned()),
opts if mountpoint.is_some() => match u64::from_str_radix(opts, 16) {
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() {
Some(arg) => match u64::from_str_radix(&arg, 16) {
Ok(block) => Some(block),
Err(err) => {
println!("redoxfs: invalid block '{}': {}", arg, err);
usage();
process::exit(1);
}
},
None => None,
let Some(mountpoint) = mountpoint else {
print_err_exit("redoxfs: no mountpoint provided");
};
let mut pipes = [0; 2];
if pipe(&mut pipes) == 0 {
let mut read = unsafe { File::from_raw_fd(pipes[0] as RawFd) };
let write = unsafe { File::from_raw_fd(pipes[1] as RawFd) };
if daemonise {
let mut pipes = [0; 2];
if pipe(&mut pipes) == 0 {
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();
if pid == 0 {
drop(read);
let pid = fork();
if pid == 0 {
drop(read);
daemon(&disk_id, &mountpoint, block_opt, write);
} else if pid > 0 {
drop(write);
daemon(&disk_id, &mountpoint, block_opt, Some(write));
} else if pid > 0 {
drop(write);
let mut res = [0];
read.read_exact(&mut res).unwrap();
let mut res = [0];
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 {
panic!("redoxfs: failed to fork");
panic!("redoxfs: failed to create pipe");
}
} else {
panic!("redoxfs: failed to create pipe");
println!("redoxfs: running in foreground");
daemon(&disk_id, &mountpoint, block_opt, None);
}
}
use core::{fmt, marker::PhantomData, mem, ops, slice};
use simple_endian::*;
use endian_num::Le;
use crate::BLOCK_SIZE;
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)]
pub struct BlockAddr(u64);
impl BlockAddr {
// Unsafe because this can create invalid blocks
pub(crate) unsafe fn new(index: u64, level: BlockLevel) -> Self {
// Level must only use the lowest four bits
if level.0 > 0xF {
panic!("block level used more than four bits");
}
// Index must not use the highest four bits
let inner = index
.checked_shl(4)
.expect("block index used highest four bits")
| (level.0 as u64);
Self(inner)
}
pub fn null(level: BlockLevel) -> Self {
unsafe { Self::new(0, level) }
}
pub fn index(&self) -> u64 {
// The first four bits store the level
self.0 >> 4
}
pub fn level(&self) -> BlockLevel {
// The first four bits store the level
BlockLevel((self.0 & 0xF) as usize)
}
pub fn is_null(&self) -> bool {
self.index() == 0
}
}
/// 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)]
pub struct BlockLevel(pub(crate) usize);
impl BlockLevel {
/// Returns the smallest block level that can contain
/// the given number of bytes.
pub(crate) fn for_bytes(bytes: u64) -> Self {
if bytes == 0 {
return BlockLevel(0);
}
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 {
1 << self.0
}
/// The number of bytes in a block of this level
pub fn bytes(self) -> u64 {
BLOCK_SIZE << self.0
}
}
pub unsafe trait BlockTrait {
/// Create an empty block of this type.
fn empty(level: BlockLevel) -> Option<Self>
where
Self: Sized;
}
/// A [`BlockAddr`] and the data it points to.
#[derive(Clone, Copy, Debug, Default)]
pub struct BlockData<T> {
addr: u64,
addr: BlockAddr,
data: T,
}
impl<T> BlockData<T> {
pub fn new(addr: u64, data: T) -> Self {
pub fn new(addr: BlockAddr, data: T) -> Self {
Self { addr, data }
}
pub fn addr(&self) -> u64 {
pub fn addr(&self) -> BlockAddr {
self.addr
}
#[must_use = "don't forget to de-allocate old block address"]
pub fn swap_addr(&mut self, addr: u64) -> u64 {
let old = self.addr;
self.addr = addr;
old
}
pub fn data(&self) -> &T {
&self.data
}
......@@ -33,24 +115,56 @@ impl<T> BlockData<T> {
&mut self.data
}
pub fn into_data(self) -> T {
self.data
pub(crate) unsafe fn into_parts(self) -> (BlockAddr, T) {
(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> {
pub fn empty(addr: BlockAddr) -> Option<Self> {
let empty = T::empty(addr.level())?;
Some(Self::new(addr, empty))
}
}
impl<T: ops::Deref<Target = [u8]>> BlockData<T> {
pub fn create_ptr(&self) -> BlockPtr<T> {
BlockPtr {
addr: self.addr.into(),
addr: self.addr.0.into(),
hash: seahash::hash(self.data.deref()).into(),
phantom: PhantomData,
}
}
}
#[repr(packed)]
#[repr(C, packed)]
pub struct BlockList<T> {
pub ptrs: [BlockPtr<T>; 256],
pub ptrs: [BlockPtr<T>; BLOCK_LIST_ENTRIES],
}
unsafe impl<T> BlockTrait for BlockList<T> {
fn empty(level: BlockLevel) -> Option<Self> {
if level.0 == 0 {
Some(Self {
ptrs: [BlockPtr::default(); BLOCK_LIST_ENTRIES],
})
} else {
None
}
}
}
impl<T> BlockList<T> {
......@@ -64,14 +178,6 @@ impl<T> BlockList<T> {
}
}
impl<T> Default for BlockList<T> {
fn default() -> Self {
Self {
ptrs: [BlockPtr::default(); 256],
}
}
}
impl<T> ops::Deref for BlockList<T> {
type Target = [u8];
fn deref(&self) -> &[u8] {
......@@ -95,24 +201,39 @@ 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> {
addr: u64le,
hash: u64le,
addr: Le<u64>,
hash: Le<u64>,
phantom: PhantomData<T>,
}
impl<T> BlockPtr<T> {
pub fn addr(&self) -> u64 {
{ self.addr }.to_native()
pub fn null(level: BlockLevel) -> Self {
Self {
addr: BlockAddr::null(level).0.into(),
hash: 0.into(),
phantom: PhantomData,
}
}
pub fn addr(&self) -> BlockAddr {
BlockAddr(self.addr.to_ne())
}
pub fn hash(&self) -> u64 {
{ self.hash }.to_native()
self.hash.to_ne()
}
pub fn is_null(&self) -> bool {
self.addr() == 0
self.addr().is_null()
}
/// Cast BlockPtr to another type
......@@ -137,11 +258,7 @@ impl<T> BlockPtr<T> {
impl<T> Clone for BlockPtr<T> {
fn clone(&self) -> Self {
Self {
addr: self.addr,
hash: self.hash,
phantom: PhantomData,
}
*self
}
}
......@@ -168,18 +285,22 @@ impl<T> fmt::Debug for BlockPtr<T> {
}
}
#[repr(packed)]
#[repr(C, packed)]
pub struct BlockRaw([u8; BLOCK_SIZE as usize]);
impl Clone for BlockRaw {
fn clone(&self) -> Self {
Self(self.0)
unsafe impl BlockTrait for BlockRaw {
fn empty(level: BlockLevel) -> Option<Self> {
if level.0 == 0 {
Some(Self([0; BLOCK_SIZE as usize]))
} else {
None
}
}
}
impl Default for BlockRaw {
fn default() -> Self {
Self([0; BLOCK_SIZE as usize])
impl Clone for BlockRaw {
fn clone(&self) -> Self {
Self(self.0)
}
}
......
use alloc::{boxed::Box, vec};
use core::{mem, ops, slice, str};
use crate::{Node, TreePtr};
use crate::{BlockLevel, BlockTrait, Node, TreePtr, DIR_ENTRY_MAX_LENGTH, RECORD_LEVEL};
#[repr(packed)]
#[repr(C, packed)]
pub struct DirEntry {
node_ptr: TreePtr<Node>,
name: [u8; 252],
name: [u8; DIR_ENTRY_MAX_LENGTH],
}
impl DirEntry {
pub fn new(node_ptr: TreePtr<Node>, name: &str) -> Option<DirEntry> {
pub fn new(node_ptr: TreePtr<Node>, name: &str) -> DirEntry {
let mut entry = DirEntry {
node_ptr,
..Default::default()
};
if name.len() > entry.name.len() {
return None;
}
entry.name[..name.len()].copy_from_slice(name.as_bytes());
Some(entry)
entry
}
pub fn node_ptr(&self) -> TreePtr<Node> {
......@@ -43,10 +40,7 @@ impl DirEntry {
impl Clone for DirEntry {
fn clone(&self) -> Self {
Self {
node_ptr: self.node_ptr,
name: self.name,
}
*self
}
}
......@@ -56,14 +50,27 @@ impl Default for DirEntry {
fn default() -> Self {
Self {
node_ptr: TreePtr::default(),
name: [0; 252],
name: [0; DIR_ENTRY_MAX_LENGTH],
}
}
}
#[repr(packed)]
//TODO: this is a box to prevent stack overflows
pub struct DirList {
pub entries: [DirEntry; 16],
pub entries: Box<[DirEntry]>,
}
unsafe impl BlockTrait for DirList {
fn empty(level: BlockLevel) -> Option<Self> {
if level.0 <= RECORD_LEVEL {
let entries = level.bytes() as usize / mem::size_of::<DirEntry>();
Some(Self {
entries: vec![DirEntry::default(); entries].into_boxed_slice(),
})
} else {
None
}
}
}
impl DirList {
......@@ -77,21 +84,13 @@ impl DirList {
}
}
impl Default for DirList {
fn default() -> Self {
Self {
entries: [DirEntry::default(); 16],
}
}
}
impl ops::Deref for DirList {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self as *const DirList as *const u8,
mem::size_of::<DirList>(),
self.entries.as_ptr() as *const u8,
self.entries.len() * mem::size_of::<DirEntry>(),
) as &[u8]
}
}
......@@ -100,13 +99,22 @@ impl ops::Deref for DirList {
impl ops::DerefMut for DirList {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut DirList as *mut u8, mem::size_of::<DirList>())
as &mut [u8]
slice::from_raw_parts_mut(
self.entries.as_mut_ptr() as *mut u8,
self.entries.len() * mem::size_of::<DirEntry>(),
) as &mut [u8]
}
}
}
#[test]
fn dir_list_size_test() {
assert_eq!(mem::size_of::<DirList>(), crate::BLOCK_SIZE as usize);
use core::ops::Deref;
for level_i in 0..RECORD_LEVEL {
let level = BlockLevel(level_i);
assert_eq!(
DirList::empty(level).unwrap().deref().len(),
level.bytes() as usize
);
}
}
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 syscall::error::{Error, Result, EIO};
use crate::disk::Disk;
use crate::BLOCK_SIZE;
macro_rules! try_disk {
($expr:expr) => {
match $expr {
Ok(val) => val,
pub struct DiskFile {
pub file: File,
}
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) => {
eprintln!("Disk I/O Error: {}", err);
return Err(Error::new(EIO));
eprintln!("RedoxFS: IO ERROR: {err}");
Err(Error::new(EIO))
}
}
};
}
}
pub struct DiskFile {
pub file: File,
impl<T> ResultExt for std::io::Result<T> {
type T = T;
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 {
pub fn open<P: AsRef<Path>>(path: P) -> Result<DiskFile> {
let file = try_disk!(OpenOptions::new().read(true).write(true).open(path));
pub fn open(path: impl AsRef<Path>) -> Result<DiskFile> {
let file = OpenOptions::new()
.read(true)
.write(true)
.open(path)
.or_eio()?;
Ok(DiskFile { file })
}
pub fn create<P: AsRef<Path>>(path: P, size: u64) -> Result<DiskFile> {
let file = try_disk!(OpenOptions::new()
pub fn create(path: impl AsRef<Path>, size: u64) -> Result<DiskFile> {
let file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(path));
try_disk!(file.set_len(size));
.open(path)
.or_eio()?;
file.set_len(size).or_eio()?;
Ok(DiskFile { file })
}
}
impl Disk for DiskFile {
unsafe fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> {
try_disk!(self.file.seek(SeekFrom::Start(block * BLOCK_SIZE)));
let count = try_disk!(self.file.read(buffer));
Ok(count)
self.file.read_at(buffer, block * BLOCK_SIZE).or_eio()
}
unsafe fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize> {
try_disk!(self.file.seek(SeekFrom::Start(block * BLOCK_SIZE)));
let count = try_disk!(self.file.write(buffer));
Ok(count)
self.file.write_at(buffer, block * BLOCK_SIZE).or_eio()
}
fn size(&mut self) -> Result<u64> {
let size = try_disk!(self.file.seek(SeekFrom::End(0)));
Ok(size)
self.file.seek(SeekFrom::End(0)).or_eio()
}
}
use core::cmp::min;
use BLOCK_SIZE;
pub struct BlockIter {
block: u64,
length: u64,
i: u64,
}
impl Iterator for BlockIter {
type Item = (u64, u64);
fn next(&mut self) -> Option<Self::Item> {
if self.i < (self.length + BLOCK_SIZE - 1) / BLOCK_SIZE {
let ret = Some((
self.block + self.i,
min(BLOCK_SIZE, self.length - self.i * BLOCK_SIZE),
));
self.i += 1;
ret
} else {
None
}
}
}
/// A disk extent, [wikipedia](https://en.wikipedia.org/wiki/Extent_(file_systems))
#[derive(Copy, Clone, Debug, Default)]
#[repr(packed)]
pub struct Extent {
pub block: u64,
pub length: u64,
}
impl Extent {
pub fn default() -> Extent {
Extent {
block: 0,
length: 0,
}
}
pub fn new(block: u64, length: u64) -> Extent {
Extent {
block: block,
length: length,
}
}
pub fn blocks(&self) -> BlockIter {
BlockIter {
block: self.block,
length: self.length,
i: 0,
}
}
}
use aes::{Aes128, BlockDecrypt, BlockEncrypt};
use alloc::{collections::VecDeque, vec::Vec};
use core::mem;
use syscall::error::{Error, Result, EKEYREJECTED, EIO, ENOENT, ENOKEY, ENOSPC};
use syscall::error::{Error, Result, EKEYREJECTED, ENOENT, ENOKEY};
use crate::{
AllocEntry, AllocList, Allocator, BlockData, Disk, Header, Key, KeySlot, Node, Salt,
Transaction, TreeList, BLOCK_SIZE, HEADER_RING,
};
#[cfg(feature = "std")]
use crate::{AllocEntry, AllocList, BlockData, BlockTrait, Key, KeySlot, Node, Salt, TreeList};
use crate::{Allocator, BlockAddr, BlockLevel, Disk, Header, Transaction, BLOCK_SIZE, HEADER_RING};
/// A file system
pub struct FileSystem<D: Disk> {
......@@ -122,93 +120,99 @@ impl<D: Disk> FileSystem<D> {
let size = disk.size()?;
let block_offset = (reserved.len() as u64 + BLOCK_SIZE - 1) / BLOCK_SIZE;
if size >= (block_offset + HEADER_RING + 4) * BLOCK_SIZE {
for block in 0..block_offset as usize {
let mut data = [0; BLOCK_SIZE as usize];
if size < (block_offset + HEADER_RING + 4) * BLOCK_SIZE {
return Err(Error::new(syscall::error::ENOSPC));
}
let mut i = 0;
while i < data.len() && block * BLOCK_SIZE as usize + i < reserved.len() {
data[i] = reserved[block * BLOCK_SIZE as usize + i];
i += 1;
}
// Fill reserved data, pad with zeroes
for block in 0..block_offset as usize {
let mut data = [0; BLOCK_SIZE as usize];
unsafe {
disk.write_at(block as u64, &data)?;
}
let mut i = 0;
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);
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,
};
unsafe {
disk.write_at(block as u64, &data)?;
}
}
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),
};
let mut header = Header::new(size);
// Write header generation zero
let count = unsafe {
fs.disk.write_at(fs.block, &fs.header)?
};
if count != 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(EIO));
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 {
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
fs.tx(|tx| unsafe {
let tree = BlockData::new(HEADER_RING + 1, TreeList::default());
// Set tree and alloc pointers and write header generation one
fs.tx(|tx| unsafe {
let tree = BlockData::new(
BlockAddr::new(HEADER_RING + 1, BlockLevel::default()),
TreeList::empty(BlockLevel::default()).unwrap(),
);
let mut alloc = BlockData::new(HEADER_RING + 2, AllocList::default());
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);
let mut alloc = BlockData::new(
BlockAddr::new(HEADER_RING + 2, BlockLevel::default()),
AllocList::empty(BlockLevel::default()).unwrap(),
);
tx.header.tree = tx.write_block(tree)?;
tx.header.alloc = tx.write_block(alloc)?;
tx.header_changed = true;
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);
Ok(())
})?;
tx.header.tree = tx.write_block(tree)?;
tx.header.alloc = tx.write_block(alloc)?;
tx.header_changed = true;
unsafe {
fs.reset_allocator()?;
}
Ok(())
})?;
fs.tx(|tx| unsafe {
let mut root = BlockData::new(
HEADER_RING + 3,
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))
unsafe {
fs.reset_allocator()?;
}
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
pub fn tx<F: FnOnce(&mut Transaction<D>) -> Result<T>, T>(&mut self, f: F) -> Result<T> {
let mut tx = Transaction::new(self);
let t = f(&mut tx)?;
......@@ -223,7 +227,7 @@ impl<D: Disk> FileSystem<D> {
/// Reset allocator to state stored on disk
///
/// # 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<()> {
self.allocator = Allocator::default();
......@@ -243,19 +247,18 @@ impl<D: Disk> FileSystem<D> {
for alloc in allocs {
for entry in alloc.data().entries.iter() {
let addr = entry.addr();
let index = entry.index();
let count = entry.count();
if count < 0 {
for i in 0..-count {
//TODO: replace assert with error?
assert_eq!(
self.allocator.allocate_exact(addr + i as u64),
Some(addr + i as u64)
);
let addr = BlockAddr::new(index + i as u64, BlockLevel::default());
assert_eq!(self.allocator.allocate_exact(addr), Some(addr));
}
} else {
for i in 0..count {
self.allocator.deallocate(addr + i as u64);
let addr = BlockAddr::new(index + i as u64, BlockLevel::default());
self.allocator.deallocate(addr);
}
}
}
......@@ -265,52 +268,58 @@ impl<D: Disk> FileSystem<D> {
}
pub(crate) fn decrypt(&mut self, data: &mut [u8]) -> bool {
if let Some(ref aes) = self.aes_opt {
assert_eq!(data.len() % aes::BLOCK_SIZE, 0);
self.aes_blocks.clear();
for i in 0..data.len() / aes::BLOCK_SIZE {
self.aes_blocks.push(aes::Block::clone_from_slice(
&data[i * aes::BLOCK_SIZE..(i + 1) * aes::BLOCK_SIZE],
));
}
let aes = if let Some(ref aes) = self.aes_opt {
aes
} else {
// Do nothing if encryption is disabled
return false;
};
aes.decrypt_blocks(&mut self.aes_blocks);
assert_eq!(data.len() % aes::BLOCK_SIZE, 0);
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();
self.aes_blocks.clear();
for i in 0..data.len() / aes::BLOCK_SIZE {
self.aes_blocks.push(aes::Block::clone_from_slice(
&data[i * aes::BLOCK_SIZE..(i + 1) * aes::BLOCK_SIZE],
));
}
true
} else {
false
aes.decrypt_blocks(&mut self.aes_blocks);
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 {
if let Some(ref aes) = self.aes_opt {
assert_eq!(data.len() % aes::BLOCK_SIZE, 0);
self.aes_blocks.clear();
for i in 0..data.len() / aes::BLOCK_SIZE {
self.aes_blocks.push(aes::Block::clone_from_slice(
&data[i * aes::BLOCK_SIZE..(i + 1) * aes::BLOCK_SIZE],
));
}
let aes = if let Some(ref aes) = self.aes_opt {
aes
} else {
// Do nothing if encryption is disabled
return false;
};
aes.encrypt_blocks(&mut self.aes_blocks);
assert_eq!(data.len() % aes::BLOCK_SIZE, 0);
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();
self.aes_blocks.clear();
for i in 0..data.len() / aes::BLOCK_SIZE {
self.aes_blocks.push(aes::Block::clone_from_slice(
&data[i * aes::BLOCK_SIZE..(i + 1) * aes::BLOCK_SIZE],
));
}
true
} else {
false
aes.encrypt_blocks(&mut self.aes_blocks);
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
}
}
use core::ops::{Deref, DerefMut};
use core::{fmt, mem, slice};
use simple_endian::*;
use endian_num::Le;
use aes::{Aes128, BlockDecrypt, BlockEncrypt};
use uuid::Uuid;
use crate::{AllocList, BlockPtr, KeySlot, Tree, BLOCK_SIZE, SIGNATURE, VERSION};
......@@ -11,18 +10,18 @@ pub const HEADER_RING: u64 = 256;
/// The header of the filesystem
#[derive(Clone, Copy)]
#[repr(packed)]
#[repr(C, packed)]
pub struct Header {
/// Signature, should be SIGNATURE
pub signature: [u8; 8],
/// Version, should be VERSION
pub version: u64le,
pub version: Le<u64>,
/// Disk ID, a 128-bit unique identifier
pub uuid: [u8; 16],
/// Disk size, in number of BLOCK_SIZE sectors
pub size: u64le,
pub size: Le<u64>,
/// Generation of header
pub generation: u64le,
pub generation: Le<u64>,
/// Block of first tree node
pub tree: BlockPtr<Tree>,
/// Block of last alloc node
......@@ -34,13 +33,13 @@ pub struct Header {
/// encrypted hash of header data without hash, set to hash and padded if disk is not encrypted
pub encrypted_hash: [u8; 16],
/// hash of header data without hash
pub hash: u64le,
pub hash: Le<u64>,
}
impl Header {
#[cfg(feature = "std")]
pub fn new(size: u64) -> Header {
let uuid = Uuid::new_v4();
let uuid = uuid::Uuid::new_v4();
let mut header = Header {
signature: *SIGNATURE,
version: VERSION.into(),
......@@ -58,12 +57,12 @@ impl Header {
return false;
}
if { self.version }.to_native() != VERSION {
if self.version.to_ne() != VERSION {
// Version does not match
return false;
}
if { self.hash }.to_native() != self.create_hash() {
if self.hash.to_ne() != self.create_hash() {
// Hash does not match
return false;
}
......@@ -77,11 +76,11 @@ impl Header {
}
pub fn size(&self) -> u64 {
{ self.size }.to_native()
self.size.to_ne()
}
pub fn generation(&self) -> u64 {
{ self.generation }.to_native()
self.generation.to_ne()
}
fn create_hash(&self) -> u64 {
......@@ -94,7 +93,7 @@ impl Header {
fn create_encrypted_hash(&self, aes_opt: Option<&Aes128>) -> [u8; 16] {
let mut encrypted_hash = [0; 16];
for (i, b) in { self.hash }.to_native().to_le_bytes().iter().enumerate() {
for (i, b) in self.hash.to_le_bytes().iter().enumerate() {
encrypted_hash[i] = *b;
}
if let Some(aes) = aes_opt {
......@@ -212,7 +211,7 @@ fn header_hash_test() {
let mut header = Header::default();
assert_eq!(header.create_hash(), 0xe81ffcb86026ff96);
header.update_hash(None);
assert_eq!({ header.hash }.to_native(), 0xe81ffcb86026ff96);
assert_eq!(header.hash.to_ne(), 0xe81ffcb86026ff96);
assert_eq!(
header.encrypted_hash,
[0x96, 0xff, 0x26, 0x60, 0xb8, 0xfc, 0x1f, 0xe8, 0, 0, 0, 0, 0, 0, 0, 0]
......
......@@ -40,7 +40,7 @@ impl Salt {
/// The key slot, containing the salt and encrypted key that are used with one password
#[derive(Clone, Copy, Default)]
#[repr(packed)]
#[repr(C, packed)]
pub struct KeySlot {
salt: Salt,
encrypted_key: EncryptedKey,
......
......@@ -3,20 +3,30 @@
#![cfg_attr(not(feature = "std"), no_std)]
// Used often in generating redox_syscall errors
#![allow(clippy::or_fun_call)]
#![allow(unexpected_cfgs)]
extern crate alloc;
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;
// A record is 4KiB << 5 = 128KiB
pub const RECORD_LEVEL: usize = 5;
pub const RECORD_SIZE: u64 = BLOCK_SIZE << RECORD_LEVEL;
pub const SIGNATURE: &[u8; 8] = b"RedoxFS\0";
pub const VERSION: u64 = 5;
pub const VERSION: u64 = 6;
pub const DIR_ENTRY_MAX_LENGTH: usize = 252;
pub static IS_UMT: AtomicUsize = AtomicUsize::new(0);
pub use self::allocator::{AllocEntry, AllocList, Allocator, ALLOC_LIST_ENTRIES};
#[cfg(feature = "std")]
pub use self::archive::{archive, archive_at};
pub use self::block::{BlockData, BlockList, BlockPtr, BlockRaw};
pub use self::block::{
BlockAddr, BlockData, BlockLevel, BlockList, BlockPtr, BlockRaw, BlockTrait,
};
pub use self::dir::{DirEntry, DirList};
pub use self::disk::*;
pub use self::filesystem::FileSystem;
......@@ -25,8 +35,10 @@ pub use self::key::{Key, KeySlot, Salt};
#[cfg(feature = "std")]
pub use self::mount::mount;
pub use self::node::{Node, NodeLevel};
pub use self::record::RecordRaw;
pub use self::transaction::Transaction;
pub use self::tree::{Tree, TreeData, TreeList, TreePtr};
#[cfg(feature = "std")]
pub use self::unmount::unmount_path;
mod allocator;
......@@ -38,9 +50,12 @@ mod disk;
mod filesystem;
mod header;
mod key;
#[cfg(feature = "std")]
#[cfg(all(feature = "std", not(fuzzing)))]
mod mount;
#[cfg(all(feature = "std", fuzzing))]
pub mod mount;
mod node;
mod record;
mod transaction;
mod tree;
#[cfg(feature = "std")]
......