summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/launcher.rs8
-rw-r--r--src/launcher/runner.rs18
-rw-r--r--src/util.rs53
3 files changed, 66 insertions, 13 deletions
diff --git a/src/launcher.rs b/src/launcher.rs
index 348639d..40d9742 100644
--- a/src/launcher.rs
+++ b/src/launcher.rs
@@ -16,7 +16,7 @@ use std::ffi::{OsStr, OsString};
use std::fmt::{Display, Formatter};
use std::io::ErrorKind;
use std::io::ErrorKind::AlreadyExists;
-use std::path::{Component, Path, PathBuf};
+use std::path::{Component, Path, PathBuf, Prefix};
use std::{env, process};
use std::env::JoinPathsError;
use std::time::{Instant, SystemTime, UNIX_EPOCH};
@@ -36,7 +36,7 @@ use version::{VersionList, VersionResolveError, VersionResult};
use crate::version::{Logging, Library, OSRestriction, OperatingSystem, DownloadType, DownloadInfo, LibraryExtractRule, CompleteVersion, FeatureMatcher};
use assets::{AssetError, AssetRepository};
-use crate::util::{self, FileVerifyError, IntegrityError};
+use crate::util::{self, AsJavaPath, FileVerifyError, IntegrityError};
pub use settings::*;
pub use runner::run_the_game;
@@ -551,8 +551,8 @@ impl Launcher {
info!("Building classpath");
let classpath = env::join_paths(downloads.iter()
- .map(|job| job.get_path())
- .chain(client_jar_path.iter().map(|p| p.as_path())))
+ .map(|job| job.get_path().as_java_path())
+ .chain(client_jar_path.iter().map(|p| p.as_path().as_java_path())))
.map_err(|e| LaunchError::LibraryClasspathError(e))?
.into_string()
.unwrap_or_else(|os| {
diff --git a/src/launcher/runner.rs b/src/launcher/runner.rs
index 0f65b49..41b3ed1 100644
--- a/src/launcher/runner.rs
+++ b/src/launcher/runner.rs
@@ -2,6 +2,7 @@ use std::borrow::Cow;
use std::ffi::{OsStr, OsString};
use std::iter;
use std::process::Command;
+use crate::util::AsJavaPath;
use crate::version::{CompleteVersion, FeatureMatcher, OperatingSystem};
use super::rules::CompatCheck;
use super::strsub::{self, SubFunc};
@@ -14,7 +15,7 @@ impl<'rep, 'l, F: FeatureMatcher> SubFunc<'rep> for LaunchArgSub<'rep, 'l, F> {
fn substitute(&self, key: &str) -> Option<Cow<'rep, str>> {
match key {
"assets_index_name" => self.0.asset_index_name.as_ref().map(|s| Cow::Borrowed(s.as_str())),
- "assets_root" => Some(self.0.launcher.assets.get_home().to_string_lossy()),
+ "assets_root" => Some(self.0.launcher.assets.get_home().as_java_path().to_string_lossy()),
"auth_access_token" => Some(Cow::Borrowed("-")), // TODO
"auth_player_name" => Some(Cow::Borrowed("Player")), // TODO
"auth_session" => Some(Cow::Borrowed("-")), // TODO
@@ -22,14 +23,15 @@ impl<'rep, 'l, F: FeatureMatcher> SubFunc<'rep> for LaunchArgSub<'rep, 'l, F> {
"auth_xuid" => Some(Cow::Borrowed("00000000-0000-0000-0000-000000000000")), // TODO
"classpath" => Some(Cow::Borrowed(self.0.classpath.as_str())), // TODO
"classpath_separator" => None, // FIXME
- "game_assets" => self.0.virtual_assets_path.as_ref().map(|s| s.to_string_lossy()),
- "game_directory" => Some(self.0.instance_home.to_string_lossy()),
+ "game_assets" => self.0.virtual_assets_path.as_ref()
+ .map(|s| s.as_path().as_java_path().to_string_lossy()),
+ "game_directory" => Some(self.0.instance_home.as_java_path().to_string_lossy()),
"language" => Some(Cow::Borrowed("en-us")), // ???
"launcher_name" => Some(Cow::Borrowed("ozone (olauncher 3)")), // TODO
"launcher_version" => Some(Cow::Borrowed("yeah")), // TODO
- "library_directory" => Some(self.0.launcher.libraries.home.to_string_lossy()),
- "natives_directory" => Some(self.0.natives_path.to_string_lossy()),
- "primary_jar" => self.0.client_jar.as_ref().map(|p| p.to_string_lossy()),
+ "library_directory" => Some(self.0.launcher.libraries.home.as_java_path().to_string_lossy()),
+ "natives_directory" => Some(self.0.natives_path.as_java_path().to_string_lossy()),
+ "primary_jar" => self.0.client_jar.as_ref().map(|p| p.as_path().as_java_path().to_string_lossy()),
"quickPlayMultiplayer" => None, // TODO
"quickPlayPath" => None, // TODO
"quickPlayRealms" => None, // TODO
@@ -45,7 +47,7 @@ impl<'rep, 'l, F: FeatureMatcher> SubFunc<'rep> for LaunchArgSub<'rep, 'l, F> {
if let Some(asset_key) = key.strip_prefix("asset=") {
return self.0.asset_index.as_ref()
.map_or(None, |idx| idx.objects.get(asset_key))
- .map(|obj| Cow::Owned(self.0.launcher.assets.get_object_path(obj).to_string_lossy().into_owned()))
+ .map(|obj| Cow::Owned(self.0.launcher.assets.get_object_path(obj).as_java_path().to_string_lossy().into_owned()))
}
None
@@ -116,7 +118,7 @@ pub fn run_the_game(launch: &Launch) -> Result<(), Box<dyn std::error::Error>> {
.map(|o| o.as_os_str())
.chain(iter::once(OsStr::new(launch.main_class.as_str())))
.chain(launch.game_args.iter().map(|o| o.as_os_str())))
- .current_dir(launch.instance_path.as_path()).spawn()?.wait()?;
+ .current_dir(launch.instance_path.as_path().as_java_path()).spawn()?.wait()?;
Ok(())
}
diff --git a/src/util.rs b/src/util.rs
index a7c2d5e..7927620 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -1,11 +1,13 @@
use std::error::Error;
+use std::ffi::OsStr;
use std::fmt::{Display, Formatter};
use std::io::ErrorKind;
-use std::path::{Component, Path, PathBuf};
+use std::path::{Component, Path, PathBuf, Prefix};
use log::debug;
use sha1_smol::{Digest, Sha1};
use tokio::fs::File;
use tokio::io::AsyncReadExt;
+use crate::util;
#[derive(Debug)]
pub enum IntegrityError {
@@ -128,3 +130,52 @@ pub fn check_path(name: &str) -> Result<&Path, &'static str> {
Ok(entry_path)
}
+
+#[cfg(windows)]
+pub fn strip_verbatim(path: &Path) -> &Path {
+ let Some(Component::Prefix(p)) = path.components().next() else {
+ return path;
+ };
+
+ match p.kind() {
+ Prefix::VerbatimDisk(_) =>
+ Path::new(unsafe { OsStr::from_encoded_bytes_unchecked(&path.as_os_str().as_encoded_bytes()[4..]) }),
+ _ => path
+ }
+}
+
+#[cfg(not(windows))]
+pub fn strip_verbatim(path: &Path) -> &Path {
+ path
+}
+
+pub trait AsJavaPath {
+ fn as_java_path(&self) -> &Path;
+}
+
+impl AsJavaPath for Path {
+ fn as_java_path(&self) -> &Path {
+ strip_verbatim(self)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ #[cfg(windows)]
+ fn test_strip_verbatim() {
+ let path = Path::new(r"\\?\C:\Some\Verbatim\Path");
+ match path.components().next().unwrap() {
+ Component::Prefix(p) => assert!(matches!(p.kind(), Prefix::VerbatimDisk(_)), "(TEST BUG) path does not start with verbatim disk"),
+ _ => panic!("(TEST BUG) path does not start with prefix")
+ }
+
+ let path2 = path.as_java_path();
+ match path2.components().next().unwrap() {
+ Component::Prefix(p) => assert!(matches!(p.kind(), Prefix::Disk(_))),
+ _ => panic!("path does not begin with prefix")
+ }
+ }
+}