diff --git a/.gitignore b/.gitignore index 3a8cabc..561170a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target .idea +/auth/ diff --git a/Cargo.lock b/Cargo.lock index 8acf70b..d9e0cfe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,6 +70,24 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" + [[package]] name = "bimap" version = "0.6.3" @@ -141,14 +159,15 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.33" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" +checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", + "serde", "wasm-bindgen", "windows-targets 0.52.0", ] @@ -178,6 +197,36 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "const_format" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.6" @@ -218,6 +267,51 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.48", +] + +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + [[package]] name = "digest" version = "0.10.7" @@ -246,7 +340,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -261,6 +355,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "either" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" + [[package]] name = "enum-ordinalize" version = "3.1.15" @@ -286,6 +386,15 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding 2.3.1", +] + [[package]] name = "fuser" version = "0.14.0" @@ -297,7 +406,6 @@ dependencies = [ "memchr", "page_size", "pkg-config", - "serde", "smallvec", "zerocopy", ] @@ -396,11 +504,14 @@ name = "gdriver-backend" version = "0.1.0" dependencies = [ "chrono", - "fuser", + "const_format", "futures", "gdriver-common", + "google-drive3", + "lazy_static", "serde", "tarpc", + "thiserror", "tokio", "tracing", ] @@ -437,6 +548,8 @@ dependencies = [ "tarpc", "thiserror", "tokio", + "tracing", + "tracing-subscriber", ] [[package]] @@ -466,6 +579,66 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "google-apis-common" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78672323eaeeb181cadd4d07333f1bcc8c2840a55b58afa8ab052664cd4a54ad" +dependencies = [ + "base64 0.13.1", + "chrono", + "http", + "hyper", + "itertools 0.10.5", + "mime", + "serde", + "serde_json", + "serde_with", + "tokio", + "tower-service", + "url 1.7.2", + "yup-oauth2", +] + +[[package]] +name = "google-drive3" +version = "5.0.4+20240227" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479d55d400d8714e341586b7972d2577043995fa1ca2f782668b915aced56d16" +dependencies = [ + "anyhow", + "google-apis-common", + "http", + "hyper", + "hyper-rustls 0.24.2", + "itertools 0.10.5", + "mime", + "serde", + "serde_json", + "tokio", + "tower-service", + "url 1.7.2", +] + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 2.1.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -493,12 +666,109 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + [[package]] name = "humantime" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http", + "hyper", + "log", + "rustls 0.21.10", + "rustls-native-certs 0.6.3", + "tokio", + "tokio-rustls 0.24.1", +] + +[[package]] +name = "hyper-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "399c78f9338483cb7e630c8474b07268983c6bd5acee012e4211f9f7bb21b070" +dependencies = [ + "futures-util", + "http", + "hyper", + "log", + "rustls 0.22.3", + "rustls-native-certs 0.7.0", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.25.0", +] + [[package]] name = "iana-time-zone" version = "0.1.59" @@ -522,6 +792,33 @@ dependencies = [ "cc", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -530,6 +827,7 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", + "serde", ] [[package]] @@ -542,6 +840,24 @@ dependencies = [ "hashbrown 0.14.3", ] +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.10" @@ -597,12 +913,24 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + [[package]] name = "memchr" version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -620,7 +948,17 @@ checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "wasi", - "windows-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", ] [[package]] @@ -634,6 +972,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" version = "0.1.45" @@ -663,6 +1007,15 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "object" version = "0.32.2" @@ -678,6 +1031,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + [[package]] name = "opentelemetry" version = "0.18.0" @@ -716,7 +1075,7 @@ dependencies = [ "futures-util", "once_cell", "opentelemetry_api", - "percent-encoding", + "percent-encoding 2.3.1", "rand", "thiserror", ] @@ -727,6 +1086,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "page_size" version = "0.6.0" @@ -737,6 +1102,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" + [[package]] name = "percent-encoding" version = "2.3.1" @@ -826,6 +1197,12 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -900,18 +1277,178 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "rustc-demangle" version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustls" +version = "0.21.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", +] + +[[package]] +name = "rustls" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99008d7ad0bbbea527ec27bddbc0e432c5b87d8175178cee68d2eec9c4a1813c" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.2", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile 1.0.4", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.1.2", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +dependencies = [ + "base64 0.22.0", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "ryu" version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + +[[package]] +name = "security-framework" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "serde" version = "1.0.195" @@ -934,15 +1471,43 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", "serde", ] +[[package]] +name = "serde_with" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" +dependencies = [ + "base64 0.13.1", + "chrono", + "hex", + "indexmap 1.9.3", + "serde", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "serde_yaml" version = "0.9.30" @@ -976,6 +1541,15 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + [[package]] name = "slab" version = "0.4.9" @@ -998,15 +1572,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + [[package]] name = "syn" version = "1.0.109" @@ -1092,6 +1684,54 @@ dependencies = [ "once_cell", ] +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "libc", + "num-conv", + "num_threads", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.35.1" @@ -1099,14 +1739,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ "backtrace", + "bytes", "libc", "mio", "num_cpus", "pin-project-lite", + "signal-hook-registry", "socket2", "tokio-macros", "tracing", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1120,6 +1762,27 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.10", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls 0.22.3", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-serde" version = "0.8.0" @@ -1160,6 +1823,12 @@ dependencies = [ "serde", ] +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + [[package]] name = "tracing" version = "0.1.40" @@ -1193,6 +1862,17 @@ dependencies = [ "valuable", ] +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + [[package]] name = "tracing-opentelemetry" version = "0.18.0" @@ -1212,11 +1892,20 @@ version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ + "nu-ansi-term", "sharded-slab", + "smallvec", "thread_local", "tracing-core", + "tracing-log", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "typenum" version = "1.17.0" @@ -1229,24 +1918,73 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-segmentation" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + [[package]] name = "unsafe-libyaml" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +dependencies = [ + "idna 0.1.5", + "matches", + "percent-encoding 1.0.1", +] + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna 0.5.0", + "percent-encoding 2.3.1", +] + [[package]] name = "valuable" version = "0.1.0" @@ -1259,6 +1997,15 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -1359,6 +2106,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -1473,6 +2229,33 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +[[package]] +name = "yup-oauth2" +version = "8.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45b7ff561fdc7809a2adad8bce73e157d01129074098e6405d0d7dfa2d087782" +dependencies = [ + "anyhow", + "async-trait", + "base64 0.21.7", + "futures", + "http", + "hyper", + "hyper-rustls 0.25.0", + "itertools 0.12.1", + "log", + "percent-encoding 2.3.1", + "rustls 0.22.3", + "rustls-pemfile 1.0.4", + "seahash", + "serde", + "serde_json", + "time", + "tokio", + "tower-service", + "url 2.5.0", +] + [[package]] name = "zerocopy" version = "0.7.32" @@ -1493,3 +2276,9 @@ dependencies = [ "quote", "syn 2.0.48", ] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/Cargo.toml b/Cargo.toml index 5361674..49cd6e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,20 +1,20 @@ [workspace] members = [ - "gdriver-common", - "gdriver-backend", - "gdriver-client", + "gdriver-common", + "gdriver-backend", + "gdriver-client", ] -resolver="2" +resolver = "2" [workspace.dependencies] -tracing="0.1" -tokio={ version = "1.35", features = ["rt-multi-thread", "tracing", "fs", "macros"] } -serde={ version = "1.0", features = ["serde_derive"] } +tracing = "0.1" +tokio = { version = "1.35", features = ["rt-multi-thread", "tracing", "fs", "macros", "signal"] } +serde = { version = "1.0", features = ["serde_derive"] } tarpc = { version = "0.34", features = ["full"] } -futures="0.3" -lazy_static="1.4" -chrono="0.4" +futures = "0.3" +lazy_static = "1.4" +chrono = "0.4" [patch.crates-io] #tarpc = {path = "../../Documents/git/OMGeeky/tarpc/tarpc/"} -tarpc = {git = "https://github.com/google/tarpc.git"} +tarpc = { git = "https://github.com/google/tarpc.git" } diff --git a/gdriver-backend/src/drive.rs b/gdriver-backend/src/drive.rs index f74cbfd..4eff0db 100644 --- a/gdriver-backend/src/drive.rs +++ b/gdriver-backend/src/drive.rs @@ -1,18 +1,26 @@ use std::collections::HashMap; +use crate::drive::google_drive::GoogleDrive; +use crate::path_resolver::PathResolver; use chrono::{DateTime, Utc}; use crate::prelude::*; - +mod google_drive; pub struct Drive { tracked_files: HashMap>, + pub path_resolver: PathResolver, + google_drive: GoogleDrive, } impl Drive { - pub fn new() -> Self { - Self { + #[instrument()] + pub async fn new() -> Result { + Ok(Self { tracked_files: HashMap::new(), - } + path_resolver: PathResolver::new(), + google_drive: GoogleDrive::new().await?, + }) } + #[instrument(skip(self))] pub fn get_file_tracking_state(&self, id: &DriveId) -> TrackingState { let file = self.tracked_files.get(id); match file { @@ -20,6 +28,24 @@ impl Drive { None => TrackingState::Untracked, } } + #[instrument(skip(self))] + pub async fn update(&mut self) -> Result<()> { + let changes = self.google_drive.get_changes().await?; + if changes.is_empty() { + info!("No changes"); + return Ok(()); + } + for change in changes { + dbg!(change); + } + Err("Not implemented".into()) + + // Ok(()) //TODO: implement this + } + #[instrument(skip(self))] + pub async fn ping(&self) -> Result<()> { + self.google_drive.ping().await + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum TrackingState { diff --git a/gdriver-backend/src/drive/google_drive.rs b/gdriver-backend/src/drive/google_drive.rs new file mode 100644 index 0000000..a8a0ce7 --- /dev/null +++ b/gdriver-backend/src/drive/google_drive.rs @@ -0,0 +1,164 @@ +use crate::prelude::*; +use const_format::formatcp; +use gdriver_common::ipc::gdriver_service::SETTINGS; +use gdriver_common::prelude::*; +use google_drive3::api::{Change, File, Scope, StartPageToken}; +use google_drive3::hyper::client::HttpConnector; +use google_drive3::hyper::{Body, Client, Response}; +use google_drive3::hyper_rustls::HttpsConnector; +use google_drive3::DriveHub; +use google_drive3::{hyper_rustls, oauth2}; +use std::any::type_name; +use std::fmt::{Debug, Display, Formatter}; +use tokio::fs; + +const FIELDS_FILE: &'static str = "id, name, size, mimeType, kind, md5Checksum, parents, trashed, createdTime, modifiedTime, viewedByMeTime"; +const FIELDS_CHANGE: &str = formatcp!("changes(removed, fileId, changeType, file({FIELDS_FILE}))"); +#[derive(Clone)] +pub struct GoogleDrive { + hub: DriveHub>, + changes_start_page_token: Option, +} + +impl GoogleDrive { + #[instrument] + pub(crate) async fn new() -> Result { + trace!("Initializing GoogleDrive client."); + let auth = oauth2::read_application_secret("auth/client_secret.json").await?; + + let auth = oauth2::InstalledFlowAuthenticator::builder( + auth, + oauth2::InstalledFlowReturnMethod::HTTPRedirect, + ) + .persist_tokens_to_disk("auth/tokens.json") + .build() + .await?; + let http_client = Client::builder().build( + hyper_rustls::HttpsConnectorBuilder::new() + .with_native_roots() + .https_or_http() + .enable_http1() + // .enable_http2() + .build(), + ); + let hub = DriveHub::new(http_client, auth); + + let drive = GoogleDrive { + hub, + changes_start_page_token: None, + }; + trace!("Successfully initialized {}", drive); + Ok(drive) + } + #[instrument] + pub(crate) async fn ping(&self) -> Result<()> { + let (response, body) = self + .hub + .about() + .get() + .param("fields", "user(emailAddress)") + .add_scope(Scope::Readonly) + .doit() + .await?; + let status_code = response.status(); + let email = body + .user + .unwrap_or_default() + .email_address + .unwrap_or_default(); + trace!("response status: {}, email: '{}'", status_code, email); + if status_code.is_success() { + return Ok(()); + } + error!( + "Did not get expected result on ping: {} {:?}", + status_code, response + ); + + Err("Did not get expected result on ping".into()) + } + //region changes + #[instrument] + pub async fn get_changes(&mut self) -> Result> { + let mut page_token = Some(self.change_start_token().await?); + let mut changes = Vec::new(); + while let Some(current_page_token) = page_token { + info!("Getting changes with page token: {}", current_page_token); + let (response, body) = self + .hub + .changes() + .list(current_page_token.as_str()) + .param("fields", FIELDS_CHANGE) + .page_size(2) //TODO: Change this to a more reasonable value + .include_corpus_removals(true) //TODO3: Check if this is useful + .supports_all_drives(false) + .restrict_to_my_drive(true) + .include_removed(true) + .include_items_from_all_drives(false) + .doit() + .await?; + self.changes_start_page_token = body.new_start_page_token; + if response.status().is_success() { + changes.extend(body.changes.unwrap_or_default()); + page_token = body.next_page_token; + } else { + error!("Could not get changes: {:?}", response); + return Err("Could not get changes".into()); + } + } + trace!("Got {} changes", changes.len()); + Ok(changes) + } + + async fn change_start_token(&mut self) -> Result { + Ok(match &self.changes_start_page_token { + None => { + // + let token = fs::read_to_string(SETTINGS.get_changes_file_path()) + .await + .unwrap_or_default(); + self.changes_start_page_token = if !token.is_empty() { + Some(token) + } else { + Some(self.get_changes_start_token_from_api().await?) + }; + self.changes_start_page_token + .clone() + .expect("We just set it") + } + Some(start_token) => start_token.clone(), + }) + } + async fn get_changes_start_token_from_api(&self) -> Result { + let (response, body) = self + .hub + .changes() + .get_start_page_token() + .supports_all_drives(false) + .doit() + .await?; + if response.status().is_success() { + let start_page_token = body.start_page_token.unwrap_or_default(); + Ok(start_page_token) + } else { + Err("Could not get start page token".into()) + } + } + //endregion +} + +//region debug & display traits +impl Debug for GoogleDrive { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct(type_name::()) + .field("changes_start_page_token", &self.changes_start_page_token) + .finish() + } +} + +impl Display for GoogleDrive { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", type_name::()) + } +} +//endregion diff --git a/gdriver-backend/src/main.rs b/gdriver-backend/src/main.rs index fb7b352..7eacb01 100644 --- a/gdriver-backend/src/main.rs +++ b/gdriver-backend/src/main.rs @@ -8,6 +8,7 @@ use tarpc::{ }; mod drive; +mod path_resolver; mod prelude; mod sample; mod service; diff --git a/gdriver-backend/src/path_resolver.rs b/gdriver-backend/src/path_resolver.rs new file mode 100644 index 0000000..fadbaaa --- /dev/null +++ b/gdriver-backend/src/path_resolver.rs @@ -0,0 +1,61 @@ +use crate::drive::Drive; +use crate::prelude::*; +use gdriver_common::ipc::gdriver_service::ReadDirResult; +use gdriver_common::prelude::*; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use std::path::Path; + +#[derive(Eq, PartialEq, Debug, Clone)] +pub struct PathResolver { + parents: HashMap>, + children: HashMap>, +} + +impl PathResolver { + pub fn new() -> Self { + Self { + parents: HashMap::new(), + children: HashMap::new(), + } + } + pub async fn get_id_from_path(&mut self, path: &Path, drive: &Drive) -> Result { + let segments: Vec<_> = path + .to_str() + .ok_or(PathResolveError::InvalidPath)? + .split('/') + .collect(); + let mut current = ROOT_ID.clone(); + self.update_from_drive(drive).await?; + for segment in segments { + current = self + .get_id_from_parent_and_name(segment, ¤t) + .ok_or("path-segment not found")?; + } + return Ok(current); + } + pub fn get_id_from_parent_and_name(&self, name: &str, parent: &DriveId) -> Option { + if let Some(children) = self.children.get(parent) { + if let Some(x) = children.into_iter().find(|x| x.name.eq(name)) { + return Some(x.id.clone()); + } + } + None + } + + async fn update_from_drive(&mut self, drive: &Drive) -> Result<()> { + todo!() + } + pub(crate) fn add_relationship(&mut self, parent: DriveId, entry: ReadDirResult) { + todo!() + } + pub(crate) fn remove_relationship(&mut self, parent: DriveId, entry: ReadDirResult) { + todo!() + } +} + +#[derive(Debug, Serialize, Deserialize, thiserror::Error)] +pub enum PathResolveError { + #[error("The path provided was invalid")] + InvalidPath, +} diff --git a/gdriver-backend/src/service.rs b/gdriver-backend/src/service.rs index b83380e..78bfc7b 100644 --- a/gdriver-backend/src/service.rs +++ b/gdriver-backend/src/service.rs @@ -20,8 +20,21 @@ impl GDriverService for GdriverServer { // todo!() // } - async fn get_file_by_name(self, context: Context, name: OsString, parent: DriveId) -> StdResult { - todo!() + async fn get_file_by_name( + self, + context: Context, + name: OsString, + parent: DriveId, + ) -> StdResult { + let mut drive_lock = self.drive.lock().await; + let x = drive_lock.path_resolver.get_id_from_parent_and_name( + name.to_str().ok_or(GetFileByPathError::InvalidName)?, + &parent, + ); + match x { + None => Err(GetFileByPathError::NotFound), + Some(id) => Ok(id), + } } async fn get_file_by_path( @@ -29,7 +42,7 @@ impl GDriverService for GdriverServer { context: Context, path: PathBuf, ) -> StdResult { - todo!() + Err(GetFileByPathError::Other) } async fn write_local_change( @@ -37,7 +50,7 @@ impl GDriverService for GdriverServer { context: Context, id: DriveId, ) -> StdResult<(), WriteLocalChangeError> { - todo!() + Err(WriteLocalChangeError::Other) } async fn get_metadata_for_file( @@ -45,7 +58,7 @@ impl GDriverService for GdriverServer { context: Context, id: DriveId, ) -> StdResult<(), GetMetadataError> { - todo!() + Err(GetMetadataError::Other) } async fn download_content_for_file( @@ -53,7 +66,7 @@ impl GDriverService for GdriverServer { context: Context, id: DriveId, ) -> StdResult<(), GetContentError> { - todo!() + Err(GetContentError::Other) } async fn list_files_in_directory( @@ -78,7 +91,7 @@ impl GDriverService for GdriverServer { context: Context, id: DriveId, ) -> StdResult<(), MarkFileAsDeletedError> { - todo!() + Err(MarkFileAsDeletedError::Other) } async fn mark_file_for_keeping_local( @@ -86,7 +99,7 @@ impl GDriverService for GdriverServer { context: Context, id: DriveId, ) -> StdResult<(), MarkFileForKeepingLocalError> { - todo!() + Err(MarkFileForKeepingLocalError::Other) } async fn unmark_file_for_keeping_local( @@ -94,7 +107,7 @@ impl GDriverService for GdriverServer { context: Context, id: DriveId, ) -> StdResult<(), UnmarkFileForKeepingLocalError> { - todo!() + Err(UnmarkFileForKeepingLocalError::Other) } #[doc = " Returns true if the file was had remote changes and was updadet"] @@ -103,7 +116,7 @@ impl GDriverService for GdriverServer { context: Context, id: DriveId, ) -> StdResult { - todo!() + Err(UpdateChangesError::Other) } async fn update_changes(self, context: Context) -> StdResult<(), UpdateChangesError> { @@ -174,7 +187,16 @@ pub async fn start() -> Result<()> { let config = &CONFIGURATION; info!("Config: {:?}", **config); - let drive = Drive::new(); + let drive = Drive::new().await?; + match drive.ping().await { + Ok(_) => { + info!("Can reach google drive api."); + } + Err(e) => { + error!("Cannot reach google drive api."); + return Err(e); + } + } let m = Arc::new(Mutex::new(drive)); let server_addr = (config.ip, config.port); diff --git a/gdriver-client/src/filesystem.rs b/gdriver-client/src/filesystem.rs index 19f7a14..df24060 100644 --- a/gdriver-client/src/filesystem.rs +++ b/gdriver-client/src/filesystem.rs @@ -1,24 +1,22 @@ +use crate::filesystem::attributes::{read_inode_attributes_from_meta_file, ConvertFileType}; +use crate::filesystem::errors::FilesystemError; +use crate::prelude::macros::*; +use crate::prelude::*; +use anyhow::anyhow; +use bimap::BiMap; +use fuser::{KernelConfig, ReplyAttr, ReplyDirectory, ReplyEntry, Request}; +use gdriver_common::drive_structure::drive_id::DriveId; +use gdriver_common::drive_structure::drive_id::ROOT_ID; +use gdriver_common::ipc::gdriver_service::errors::GDriverServiceError; +use gdriver_common::ipc::gdriver_service::GDriverServiceClient; +use gdriver_common::ipc::gdriver_service::SETTINGS; +use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::ffi::{OsStr, OsString}; use std::os::raw::c_int; use std::time::Duration; - -use anyhow::anyhow; -use bimap::BiMap; -use fuser::{KernelConfig, ReplyEntry, Request}; -use tracing::*; - -use gdriver_common::drive_structure::drive_id::{DriveId, ROOT_ID}; -use gdriver_common::drive_structure::meta::read_metadata_file; -use gdriver_common::ipc::gdriver_service::{ - errors::GDriverServiceError, GDriverServiceClient, GDriverSettings, -}; - -use crate::filesystem::attributes::read_inode_attributes_from_meta_file; -use crate::filesystem::errors::FilesystemError; -use crate::prelude::macros::*; -use crate::prelude::*; use tarpc::context::current as current_context; +use tokio::sync::mpsc::Receiver; mod macros; @@ -32,26 +30,33 @@ struct FileIdentifier { parent: Inode, name: OsString, } - +#[derive(Debug, Copy, Clone, Serialize, Deserialize, Hash, Ord, PartialOrd, Eq, PartialEq)] +pub enum ShutdownRequest { + Gracefully, + Force, +} pub struct Filesystem { gdriver_client: GDriverServiceClient, entry_ids: BiMap, ino_to_file_handles: HashMap>, next_ino: u64, - gdriver_settings: GDriverSettings, entry_name_parent_to_ino: BiMap, + shutdown_signal_receiver: Receiver, } impl Filesystem { - pub fn new(gdriver_client: GDriverServiceClient) -> Self { + pub fn new( + gdriver_client: GDriverServiceClient, + shutdown_signal_receiver: Receiver, + ) -> Self { Self { gdriver_client, entry_ids: BiMap::new(), ino_to_file_handles: HashMap::new(), next_ino: 222, - gdriver_settings: GDriverSettings::default(), entry_name_parent_to_ino: BiMap::new(), + shutdown_signal_receiver, } } fn generate_ino(&mut self) -> Inode { @@ -93,23 +98,26 @@ mod attributes; impl fuser::Filesystem for Filesystem { //region init + #[instrument(skip(self, _req, _config))] fn init(&mut self, _req: &Request<'_>, _config: &mut KernelConfig) -> StdResult<(), c_int> { self.entry_ids.insert(1, ROOT_ID.clone()); - self.gdriver_settings = send_request!(self.gdriver_client.get_settings(current_context())) + + send_request!(self.gdriver_client.update_changes(current_context())) .map_err(|e| { - error!("Got a connection error while fetching settings: {e}"); - libc::ECONNREFUSED + error!("Got a connection error while updating changes for on init. "); + dbg!(e); + libc::ECANCELED })? .map_err(|e| { - error!("Got an error while fetching settings: {e}"); - trace!("details: {e:?}"); - libc::EBADMSG + error!("Error while updating changes on init"); + dbg!(e); + libc::EIO })?; - Ok(()) } //endregion //region lookup + #[instrument(skip(self, _req, reply))] fn lookup(&mut self, _req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEntry) { let metadata = utils::lookup::lookup(self, parent, name.to_os_string()); match metadata { @@ -133,6 +141,67 @@ impl fuser::Filesystem for Filesystem { } } //endregion + #[instrument(skip(self, _req, reply))] + fn getattr(&mut self, _req: &Request<'_>, ino: u64, reply: ReplyAttr) { + let id = self.get_id_from_ino(ino); + info!("Reading dir: {id:?}/{ino}"); + match id { + None => {} + Some(id) => { + let result = utils::get_attributes(self, id, ino); + match result { + Ok(attr) => { + reply.attr(&TTL, &attr.into()); + } + Err(e) => { + error!("Got an error during readdir: {}", e); + dbg!(e); + reply.error(libc::EIO); + } + } + } + } + } + #[instrument(skip(self, _req, reply))] + fn readdir( + &mut self, + _req: &Request<'_>, + ino: u64, + _fh: u64, + offset: i64, + mut reply: ReplyDirectory, + ) { + let id = self.get_id_from_ino(ino); + info!("Reading dir: {id:?}/{ino}"); + match id { + None => {} + Some(id) => { + let result = utils::readdir::readdir(self, id.clone(), offset as u64); + match result { + Ok(entries) => { + let mut counter = 0; + for entry in entries { + let ino = self.get_ino_from_id(entry.id); + counter += 1; + let buffer_full = + reply.add(ino, counter, entry.kind.into_ft(), entry.name); + if buffer_full { + debug!("Buffer full after {counter}"); + break; + } + } + debug!("sending ok"); + reply.ok(); + } + Err(e) => { + error!("Got an error during readdir: {}", e); + dbg!(e); + reply.error(libc::EIO); + } + } + } + } + } } mod errors { use gdriver_common::ipc::gdriver_service::errors::GDriverServiceError; @@ -155,6 +224,7 @@ mod errors { } mod utils { use super::*; + use crate::filesystem::attributes::InodeAttributes; pub mod lookup { use super::*; use crate::filesystem::attributes::InodeAttributes; @@ -205,16 +275,39 @@ mod utils { .clone(); } } - let open_file_handles = - fs.ino_to_file_handles.get(&ino).map(Vec::len).unwrap_or(0) as u64; - send_request!(fs - .gdriver_client - .get_metadata_for_file(current_context(), id.clone()))? + get_attributes(fs, &id, ino) + } + } + pub(crate) fn get_attributes( + fs: &Filesystem, + id: &DriveId, + ino: Inode, + ) -> StdResult { + let open_file_handles = fs.ino_to_file_handles.get(&ino).map(Vec::len).unwrap_or(0) as u64; + send_request!(fs + .gdriver_client + .get_metadata_for_file(current_context(), id.clone()))? + .map_err(GDriverServiceError::from)?; + let meta_path = SETTINGS.get_metadata_file_path(&id); + let metadata = read_inode_attributes_from_meta_file(&meta_path, ino, open_file_handles) + .map_err(FilesystemError::IO)?; + Ok(metadata) + } + pub mod readdir { + use super::*; + pub fn readdir( + fs: &mut Filesystem, + id: DriveId, + offset: u64, + ) -> StdResult, FilesystemError> + { + let res = send_request!(fs.gdriver_client.list_files_in_directory_with_offset( + current_context(), + id, + offset as u64 + ))? .map_err(GDriverServiceError::from)?; - let meta_path = fs.gdriver_settings.get_metadata_file_path(&id); - let metadata = read_inode_attributes_from_meta_file(&meta_path, ino, open_file_handles) - .map_err(FilesystemError::IO)?; - Ok(metadata) + Ok(res) } } } diff --git a/gdriver-client/src/main.rs b/gdriver-client/src/main.rs index d8d9d9f..b22259e 100644 --- a/gdriver-client/src/main.rs +++ b/gdriver-client/src/main.rs @@ -1,13 +1,27 @@ +use fuser::{MountOption, Session, SessionUnmounter}; use std::{error::Error, net::IpAddr, result::Result as StdResult}; +use tokio::sync::mpsc::{channel, Sender}; +use crate::filesystem::{Filesystem, ShutdownRequest}; use gdriver_common::{ipc::sample::*, prelude::*}; use tarpc::{client, tokio_serde::formats::Json}; +use tokio::task::JoinHandle; type Result = StdResult>; #[tokio::main] async fn main() -> Result<()> { - service::start().await?; + gdriver_common::tracing_setup::init_tracing(); + // service::start().await?; + let mount_options = &[MountOption::RW]; + let (tx, rx) = channel(1); + let f = Filesystem::new( + service::create_client(CONFIGURATION.ip, CONFIGURATION.port).await?, + rx, + ); + mount(f, &"/var/tmp/gdriver2_mount", mount_options, tx) + .await? + .await?; Ok(()) } pub mod prelude; @@ -15,3 +29,40 @@ mod sample; mod filesystem; mod service; + +async fn mount( + fs: Filesystem, + mountpoint: &str, + options: &[MountOption], + sender: Sender, +) -> Result> { + let mut session = Session::new(fs, mountpoint.as_ref(), options)?; + let session_ender = session.unmount_callable(); + let end_program_signal_handle = tokio::spawn(async move { + let _ = end_program_signal_awaiter(sender, session_ender).await; + }); + debug!("Mounting fuse filesystem"); + let _ = session.run(); + debug!("Stopped with mounting"); + // Ok(session_ender) + Ok(end_program_signal_handle) +} + +async fn end_program_signal_awaiter( + sender: Sender, + mut session_unmounter: SessionUnmounter, +) -> Result<()> { + info!("Waiting for Ctrl-C"); + println!("Waiting for Ctrl-C"); + tokio::signal::ctrl_c() + .await + .expect("failed to listen for ctrl_c event"); + println!(); //to not have ^C on the same line as the next log if it is directly in a console + info!("got signal to end program"); + sender.send(ShutdownRequest::Gracefully).await?; + info!("sent stop command to file uploader"); + info!("unmounting..."); + session_unmounter.unmount()?; + info!("unmounted"); + Ok(()) +} diff --git a/gdriver-common/Cargo.toml b/gdriver-common/Cargo.toml index 7718525..0775de5 100644 --- a/gdriver-common/Cargo.toml +++ b/gdriver-common/Cargo.toml @@ -7,14 +7,16 @@ edition = "2021" [dependencies] serde.workspace = true +tracing.workspace = true tarpc.workspace = true tokio.workspace = true futures.workspace = true lazy_static.workspace = true -confique={ version = "0.2" } +confique = { version = "0.2" } thiserror = "1.0" -anyhow = "1.0.79" +anyhow = "1.0" directories = "5.0" -serde_json = "1.0.111" +serde_json = "1.0" +tracing-subscriber = "0.3" #[patch.crates-io] #confique = {path="~/Documents/git/OMGeeky/confique "}