WIP: Windows support #925
8 changed files with 166 additions and 31 deletions
|
@ -101,7 +101,7 @@
|
|||
"original": {
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "162ab0edc2936508470199b2e8e6c444a2535019",
|
||||
"rev": "19b70f147b9c67a759e35824b241f1ed92e46694",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
let
|
||||
{
|
||||
system ? builtins.currentSystem,
|
||||
}: let
|
||||
lock = builtins.fromJSON (builtins.readFile ../flake.lock);
|
||||
|
||||
inherit (lock.nodes.flake-compat.locked) owner repo rev narHash;
|
||||
|
@ -8,7 +10,7 @@ let
|
|||
sha256 = narHash;
|
||||
};
|
||||
|
||||
flake = (import flake-compat { system = builtins.currentSystem; src = ../.; });
|
||||
flake = (import flake-compat { inherit system; src = ../.; });
|
||||
in
|
||||
rec {
|
||||
pkgsSrc = flake.defaultNix.inputs.nixpkgs;
|
||||
|
|
|
@ -4,6 +4,52 @@
|
|||
let
|
||||
log = v: builtins.trace v v;
|
||||
|
||||
targetIsWindows = target == "x86_64-w64-mingw32";
|
||||
|
||||
pkgsNative = import pkgsSrc { inherit system; };
|
||||
|
||||
# HACK: work around https://github.com/NixOS/nixpkgs/issues/177129
|
||||
# Though this is an issue between Clang and GCC,
|
||||
# so it may not get fixed anytime soon...
|
||||
empty-libgcc_eh = pkgsNative.stdenv.mkDerivation {
|
||||
pname = "empty-libgcc_eh";
|
||||
version = "0";
|
||||
dontUnpack = true;
|
||||
installPhase = ''
|
||||
mkdir -p "$out"/lib
|
||||
"${pkgsNative.binutils}"/bin/ar r "$out"/lib/libgcc_eh.a
|
||||
'';
|
||||
};
|
||||
|
||||
# HACK: winapi contains a bunch of statically linked libraries embedded in the
|
||||
# repo. Its build.rs would normally correctly find these files, but I guess
|
||||
# cargo2nix gets in the way somehow. We download the repo manually so we can
|
||||
# link into it.
|
||||
#
|
||||
# Btw... where did these static library files come from? We just trust them?
|
||||
winapi-rs = pkgsNative.fetchFromGitHub {
|
||||
owner = "retep998";
|
||||
repo = "winapi-rs";
|
||||
rev = "0.3.9"; # Must match the version found in Cargo.lock
|
||||
hash = "sha256-/Qoz8kNsjnDEqkH/vciuzGAT1dpL7d94nbQnQh5sGQw=";
|
||||
};
|
||||
|
||||
# HACK: see winapi-rs comment, same applies here but for the windows crate.
|
||||
windows-rs-0-48-5 = pkgsNative.fetchFromGitHub {
|
||||
owner = "microsoft";
|
||||
repo = "windows-rs";
|
||||
rev = "0.48.5"; # Must match the version found in Cargo.lock
|
||||
hash = "sha256-24c1TBaNu742eZUlzo0ChVlln2tJALc8KUs+fbqP9po=";
|
||||
};
|
||||
|
||||
# HACK: see winapi-rs comment, same applies here but for the windows crate.
|
||||
windows-rs-0-52-0 = pkgsNative.fetchFromGitHub {
|
||||
owner = "microsoft";
|
||||
repo = "windows-rs";
|
||||
rev = "0.52.0"; # Must match the version found in Cargo.lock
|
||||
hash = "sha256-ZhsIAtiVPuBeNlkYnPEMrZh4FZJKnQyynXws5zv+8KI=";
|
||||
};
|
||||
|
||||
pkgs = if target != null then
|
||||
import pkgsSrc {
|
||||
inherit system;
|
||||
|
@ -62,13 +108,35 @@ let
|
|||
# [1]
|
||||
hardeningDisable = [ "pie" ];
|
||||
};
|
||||
|
||||
overrideArgs = old:
|
||||
if targetIsWindows then {
|
||||
rustcLinkFlags = old.rustcLinkFlags or [] ++ [
|
||||
"-L${pkgs.windows.pthreads}/lib"
|
||||
"-L${empty-libgcc_eh}/lib"
|
||||
"-L${winapi-rs}/x86_64/lib"
|
||||
"-L${windows-rs-0-48-5}/crates/targets/x86_64_gnu/lib"
|
||||
"-L${windows-rs-0-52-0}/crates/targets/x86_64_gnu/lib"
|
||||
];
|
||||
} else {};
|
||||
})
|
||||
|
||||
(pkgs.rustBuilder.rustLib.makeOverride {
|
||||
name = "libsodium-sys";
|
||||
|
||||
overrideArgs = old: {
|
||||
features = [ ]; # [3]
|
||||
};
|
||||
|
||||
# libsodium-sys doesn't consider windows-gnu to be a "supported" build
|
||||
# target, even though libsodium itself releases official mingw builds.
|
||||
# Use nix's own libsodium, via a special envvar, instead.
|
||||
overrideAttrs = drv: if targetIsWindows then {
|
||||
setBuildEnv = ''
|
||||
${drv.setBuildEnv}
|
||||
export SODIUM_LIB_DIR=${pkgs.libsodium}/lib
|
||||
'';
|
||||
} else {};
|
||||
})
|
||||
|
||||
(pkgs.rustBuilder.rustLib.makeOverride {
|
||||
|
@ -77,6 +145,17 @@ let
|
|||
features = [ ]; # [3]
|
||||
};
|
||||
})
|
||||
|
||||
(pkgs.rustBuilder.rustLib.makeOverride {
|
||||
name = "timeago";
|
||||
overrideArgs = old:
|
||||
if targetIsWindows then {
|
||||
rustcLinkFlags = old.rustcLinkFlags or [] ++ [
|
||||
"-L${pkgs.windows.pthreads}/lib"
|
||||
"-L${empty-libgcc_eh}/lib"
|
||||
];
|
||||
} else {};
|
||||
})
|
||||
];
|
||||
|
||||
/* We ship some parts of the code disabled by default by putting them behind a flag.
|
||||
|
@ -123,11 +202,18 @@ let
|
|||
]; # segfault with static-pie
|
||||
"x86_64-unknown-linux-musl" =
|
||||
[ "target-feature=+crt-static" "link-arg=-static-pie" ];
|
||||
"x86_64-pc-windows-gnu" = [
|
||||
"target-feature=+crt-static"
|
||||
"link-arg=-static-pie"
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
# NixOS and Rust/Cargo triples do not match for ARM, fix it here.
|
||||
rustTarget = if target == "armv6l-unknown-linux-musleabihf" then
|
||||
"arm-unknown-linux-musleabihf"
|
||||
else if targetIsWindows then
|
||||
"x86_64-pc-windows-gnu"
|
||||
else
|
||||
target;
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
use std::convert::Infallible;
|
||||
use std::fs::{self, Permissions};
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
|
@ -18,7 +16,7 @@ use hyper::{HeaderMap, StatusCode};
|
|||
use hyper_util::rt::TokioIo;
|
||||
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tokio::net::{TcpListener, TcpStream, UnixListener, UnixStream};
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
use tokio::sync::watch;
|
||||
use tokio::time::{sleep_until, Instant};
|
||||
|
||||
|
@ -119,7 +117,13 @@ impl<A: ApiHandler> ApiServer<A> {
|
|||
let handler = move |request, socketaddr| self.clone().handler(request, socketaddr);
|
||||
server_loop(server_name, listener, handler, must_exit).await
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
UnixOrTCPSocketAddress::UnixSocket(ref path) => {
|
||||
use std::fs::{self, Permissions};
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
use tokio::net::UnixListener;
|
||||
|
||||
if path.exists() {
|
||||
fs::remove_file(path)?
|
||||
}
|
||||
|
@ -135,6 +139,11 @@ impl<A: ApiHandler> ApiServer<A> {
|
|||
let handler = move |request, socketaddr| self.clone().handler(request, socketaddr);
|
||||
server_loop(server_name, listener, handler, must_exit).await
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
UnixOrTCPSocketAddress::UnixSocket(ref _path) => {
|
||||
panic!("Unix domain sockets are not supported on windows yet: https://github.com/tokio-rs/tokio/issues/2201");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -264,11 +273,13 @@ impl Accept for TcpListener {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct UnixListenerOn(pub UnixListener, pub String);
|
||||
#[cfg(not(windows))]
|
||||
pub struct UnixListenerOn(pub tokio::net::UnixListener, pub String);
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[async_trait]
|
||||
impl Accept for UnixListenerOn {
|
||||
type Stream = UnixStream;
|
||||
type Stream = tokio::net::UnixStream;
|
||||
async fn accept(&self) -> std::io::Result<(Self::Stream, String)> {
|
||||
self.0
|
||||
.accept()
|
||||
|
|
|
@ -792,11 +792,7 @@ impl BlockManagerLocked {
|
|||
// Now, we do an fsync on the containing directory, to ensure that the rename
|
||||
// is persisted properly. See:
|
||||
// http://thedjbway.b0llix.net/qmail/syncdir.html
|
||||
let dir = fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.mode(0)
|
||||
.open(directory)
|
||||
.await?;
|
||||
let dir = fs::OpenOptions::new().read(true).open(directory).await?;
|
||||
dir.sync_all().await?;
|
||||
drop(dir);
|
||||
}
|
||||
|
|
|
@ -52,10 +52,14 @@ pub struct Secrets {
|
|||
/// from config or CLI param or env variable or read from a file specified in config or CLI
|
||||
/// param or env variable)
|
||||
pub fn fill_secrets(mut config: Config, secrets: Secrets) -> Result<Config, Error> {
|
||||
#[cfg(unix)]
|
||||
let allow_world_readable = secrets
|
||||
.allow_world_readable_secrets
|
||||
.unwrap_or(config.allow_world_readable_secrets);
|
||||
|
||||
#[cfg(not(unix))]
|
||||
let allow_world_readable = config.allow_world_readable_secrets;
|
||||
|
||||
fill_secret(
|
||||
&mut config.rpc_secret,
|
||||
&config.rpc_secret_file,
|
||||
|
|
|
@ -219,11 +219,21 @@ pub fn gen_node_key(metadata_dir: &Path) -> Result<NodeKey, Error> {
|
|||
let (pubkey, key) = ed25519::gen_keypair();
|
||||
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
let mut f = std::fs::File::create(key_file.as_path())?;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
let mut perm = f.metadata()?.permissions();
|
||||
perm.set_mode(0o600);
|
||||
std::fs::set_permissions(key_file.as_path(), perm)?;
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
// TODO(mediocregopher): set permissions on windows
|
||||
}
|
||||
|
||||
f.write_all(&key[..])?;
|
||||
}
|
||||
|
||||
|
@ -805,6 +815,7 @@ impl NodeStatus {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn update_disk_usage(&mut self, meta_dir: &Path, data_dir: &DataDirEnum) {
|
||||
use nix::sys::statvfs::statvfs;
|
||||
|
||||
|
@ -866,11 +877,25 @@ impl NodeStatus {
|
|||
})(),
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn update_disk_usage(&mut self, _meta_dir: &Path, _data_dir: &DataDirEnum) {
|
||||
// TODO(mediocregopher): update disk usage on windows, only used for metrics
|
||||
}
|
||||
}
|
||||
|
||||
/// Obtain the list of currently available IP addresses on all non-loopback
|
||||
/// interfaces, optionally filtering them to be inside a given IpNet.
|
||||
fn get_default_ip(filter_ipnet: Option<ipnet::IpNet>) -> Option<IpAddr> {
|
||||
// pnet creates a dependency on winpcap, which is a giant pain to get working with
|
||||
// cross-compilation.
|
||||
#[cfg(windows)]
|
||||
{
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
pnet_datalink::interfaces()
|
||||
.into_iter()
|
||||
// filter down and loopback interfaces
|
||||
|
@ -882,6 +907,7 @@ fn get_default_ip(filter_ipnet: Option<ipnet::IpNet>) -> Option<IpAddr> {
|
|||
filter_ipnet.is_some_and(|ipnet| ipnet.contains(&ipn.ip())) || filter_ipnet.is_none()
|
||||
})
|
||||
.map(|ipn| ipn.ip())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_rpc_public_addr(config: &Config) -> Option<SocketAddr> {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
use std::fs::{self, Permissions};
|
||||
use std::os::unix::prelude::PermissionsExt;
|
||||
use std::{convert::Infallible, sync::Arc};
|
||||
|
||||
use tokio::net::{TcpListener, UnixListener};
|
||||
use tokio::net::TcpListener;
|
||||
use tokio::sync::watch;
|
||||
|
||||
use hyper::{
|
||||
|
@ -20,7 +18,7 @@ use opentelemetry::{
|
|||
|
||||
use crate::error::*;
|
||||
|
||||
use garage_api::generic_server::{server_loop, UnixListenerOn};
|
||||
use garage_api::generic_server::server_loop;
|
||||
use garage_api::helpers::*;
|
||||
use garage_api::s3::cors::{add_cors_headers, find_matching_cors_rule, handle_options_for_bucket};
|
||||
use garage_api::s3::error::{
|
||||
|
@ -96,7 +94,14 @@ impl WebServer {
|
|||
move |stream, socketaddr| self.clone().handle_request(stream, socketaddr);
|
||||
server_loop(server_name, listener, handler, must_exit).await
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
UnixOrTCPSocketAddress::UnixSocket(ref path) => {
|
||||
use std::fs::{self, Permissions};
|
||||
use std::os::unix::prelude::PermissionsExt;
|
||||
use tokio::net::UnixListener;
|
||||
use garage_api::generic_server::UnixListenerOn;
|
||||
|
||||
if path.exists() {
|
||||
fs::remove_file(path)?
|
||||
}
|
||||
|
@ -110,6 +115,11 @@ impl WebServer {
|
|||
move |stream, socketaddr| self.clone().handle_request(stream, socketaddr);
|
||||
server_loop(server_name, listener, handler, must_exit).await
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
UnixOrTCPSocketAddress::UnixSocket(ref _path) => {
|
||||
panic!("Unix domain sockets are not supported on windows yet: https://github.com/tokio-rs/tokio/issues/2201");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue