summaryrefslogtreecommitdiffstats
path: root/vendor/dunce
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/dunce')
-rw-r--r--vendor/dunce/.cargo-checksum.json1
-rw-r--r--vendor/dunce/Cargo.toml42
-rw-r--r--vendor/dunce/LICENSE121
-rw-r--r--vendor/dunce/README.md17
-rw-r--r--vendor/dunce/src/lib.rs324
5 files changed, 505 insertions, 0 deletions
diff --git a/vendor/dunce/.cargo-checksum.json b/vendor/dunce/.cargo-checksum.json
new file mode 100644
index 000000000..3bb53b2b9
--- /dev/null
+++ b/vendor/dunce/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"97bcc4c25e6528ec52bf3df5202dc0e9eacdd3e7ff93c51f5d89c41b88e63b5f","LICENSE":"a2010f343487d3f7618affe54f789f5487602331c0a8d03f49e9a7c547cf0499","README.md":"890653901012199b8780375755a8a0b5b6eafcded2c3bccace87099bdfba9274","src/lib.rs":"ed0d70d8b377aed2d43d574acdcc54a4bc33a73241c4c7058838197543f48156"},"package":"0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c"} \ No newline at end of file
diff --git a/vendor/dunce/Cargo.toml b/vendor/dunce/Cargo.toml
new file mode 100644
index 000000000..f414baec2
--- /dev/null
+++ b/vendor/dunce/Cargo.toml
@@ -0,0 +1,42 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "dunce"
+version = "1.0.3"
+authors = ["Kornel <kornel@geekhood.net>"]
+description = "Normalize Windows paths to the most compatible format, avoiding UNC where possible"
+homepage = "https://lib.rs/crates/dunce"
+documentation = "https://docs.rs/dunce"
+readme = "README.md"
+keywords = [
+ "realpath",
+ "unc",
+ "canonicalize",
+ "windows",
+ "deunc",
+]
+categories = ["filesystem"]
+license = "CC0-1.0 OR MIT-0"
+repository = "https://gitlab.com/kornelski/dunce"
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[badges.appveyor]
+repository = "pornel/dunce"
+
+[badges.gitlab]
+repository = "kornelski/dunce"
+
+[badges.maintenance]
+status = "passively-maintained"
diff --git a/vendor/dunce/LICENSE b/vendor/dunce/LICENSE
new file mode 100644
index 000000000..0e259d42c
--- /dev/null
+++ b/vendor/dunce/LICENSE
@@ -0,0 +1,121 @@
+Creative Commons Legal Code
+
+CC0 1.0 Universal
+
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+ HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+ i. the right to reproduce, adapt, distribute, perform, display,
+ communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+ likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+ subject to the limitations in paragraph 4(a), below;
+ v. rights protecting the extraction, dissemination, use and reuse of data
+ in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+ European Parliament and of the Council of 11 March 1996 on the legal
+ protection of databases, and under any national implementation
+ thereof, including any amended or successor version of such
+ directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+ world based on applicable law or treaty, and any national
+ implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+ surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+ warranties of any kind concerning the Work, express, implied,
+ statutory or otherwise, including without limitation warranties of
+ title, merchantability, fitness for a particular purpose, non
+ infringement, or the absence of latent or other defects, accuracy, or
+ the present or absence of errors, whether or not discoverable, all to
+ the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+ that may apply to the Work or any use thereof, including without
+ limitation any person's Copyright and Related Rights in the Work.
+ Further, Affirmer disclaims responsibility for obtaining any necessary
+ consents, permissions or other rights required for any use of the
+ Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+ party to this document and has no duty or obligation with respect to
+ this CC0 or use of the Work.
diff --git a/vendor/dunce/README.md b/vendor/dunce/README.md
new file mode 100644
index 000000000..40a9c1032
--- /dev/null
+++ b/vendor/dunce/README.md
@@ -0,0 +1,17 @@
+# Dunce (de-UNC)
+
+In Windows the regular paths (`C:\foo`) are supported by all programs,
+but have lots of bizarre restrictions for backwards compatibility with MS-DOS.
+There are also Windows NT UNC paths (`\\?\C:\foo`), which are more robust and with fewer gotchas,
+but are rarely supported by Windows programs. Even Microsoft's own!
+
+This crate converts Windows UNC paths to the MS-DOS-compatible format whenever possible,
+but leaves UNC paths as-is when they can't be unambiguously expressed in a simpler way.
+This allows legacy programs to access all paths they can possibly access,
+and doesn't break any paths for UNC-aware programs.
+
+In Rust the worst UNC offender is the `fs::canonicalize()` function. This crate provides
+a drop-in replacement for it that returns paths you'd expect.
+
+On non-Windows platforms these functions leave paths unmodified, so it's safe to use them
+unconditionally for all platforms.
diff --git a/vendor/dunce/src/lib.rs b/vendor/dunce/src/lib.rs
new file mode 100644
index 000000000..8f11ec0e2
--- /dev/null
+++ b/vendor/dunce/src/lib.rs
@@ -0,0 +1,324 @@
+//! Filesystem paths in Windows are a total mess. This crate normalizes paths to the most
+//! compatible (but still correct) format, so that you don't have to worry about the mess.
+//!
+//! In Windows the regular/legacy paths (`C:\foo`) are supported by all programs, but have
+//! lots of bizarre restrictions for backwards compatibility with MS-DOS.
+//!
+//! And there are Windows NT UNC paths (`\\?\C:\foo`), which are more robust and with fewer
+//! gotchas, but are rarely supported by Windows programs. Even Microsoft's own!
+//!
+//! This crate converts paths to legacy format whenever possible, but leaves UNC paths as-is
+//! when they can't be unambiguously expressed in a simpler way. This allows legacy programs
+//! to access all paths they can possibly access, and UNC-aware programs to access all paths.
+//!
+//! On non-Windows platforms these functions leave paths unmodified, so it's safe to use them
+//! unconditionally for all platforms.
+//!
+//! Parsing is based on https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
+//!
+//! [Project homepage](https://crates.rs/crates/dunce).
+#![doc(html_logo_url = "https://assets.gitlab-static.net/uploads/-/system/project/avatar/4717715/dyc.png")]
+
+#[cfg(any(windows, test))]
+use std::ffi::OsStr;
+use std::fs;
+use std::io;
+#[cfg(windows)]
+use std::os::windows::ffi::OsStrExt;
+#[cfg(windows)]
+use std::path::{Component, Prefix};
+use std::path::{Path, PathBuf};
+
+/// Takes any path, and when possible, converts Windows UNC paths to regular paths.
+///
+/// On non-Windows this is no-op.
+///
+/// `\\?\C:\Windows` will be converted to `C:\Windows`,
+/// but `\\?\C:\COM` will be left as-is (due to a reserved filename).
+///
+/// Use this to pass arbitrary paths to programs that may not be UNC-aware.
+/// It's generally safe to pass UNC paths to legacy programs, because
+/// the paths contain a reserved character, so will gracefully fail
+/// if used with wrong APIs.
+///
+/// This function does not perform any I/O.
+///
+/// Currently paths with unpaired surrogates aren't converted even if they
+/// can be due to limitations of Rust's `OsStr` API.
+#[inline]
+pub fn simplified(path: &Path) -> &Path {
+ if is_safe_to_strip_unc(path) {
+ // unfortunately we can't safely strip prefix from a non-Unicode path
+ path.to_str().and_then(|s| s.get(4..)).map(Path::new).unwrap_or(path)
+ } else {
+ path
+ }
+}
+
+/// Like `std::fs::canonicalize()`, but on Windows it outputs the most
+/// compatible form of a path instead of UNC.
+#[inline(always)]
+pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
+ let path = path.as_ref();
+
+ #[cfg(not(windows))]
+ {
+ fs::canonicalize(path)
+ }
+ #[cfg(windows)]
+ {
+ canonicalize_win(path)
+ }
+}
+
+#[cfg(windows)]
+fn canonicalize_win(path: &Path) -> io::Result<PathBuf> {
+ let real_path = fs::canonicalize(path)?;
+ Ok(if is_safe_to_strip_unc(&real_path) {
+ real_path.to_str().and_then(|s| s.get(4..)).map(PathBuf::from).unwrap_or(real_path)
+ } else {
+ real_path
+ })
+}
+
+pub use self::canonicalize as realpath;
+
+#[cfg(any(windows,test))]
+fn windows_char_len(s: &OsStr) -> usize {
+ #[cfg(not(windows))]
+ let len = s.to_string_lossy().chars().map(|c| if c as u32 <= 0xFFFF {1} else {2}).sum();
+ #[cfg(windows)]
+ let len = s.encode_wide().count();
+ len
+}
+
+#[cfg(any(windows,test))]
+fn is_valid_filename(file_name: &OsStr) -> bool {
+ let file_name = file_name.as_ref();
+ if windows_char_len(file_name) > 255 {
+ return false;
+ }
+
+ // Non-unicode is safe, but Rust can't reasonably losslessly operate on such strings
+ let file_name = if let Some(s) = file_name.to_str() {
+ s
+ } else {
+ return false;
+ };
+ if file_name.is_empty() {
+ return false;
+ }
+ // Only ASCII subset is checked, and UTF-8 is safe for that
+ let byte_str = file_name.as_bytes();
+ for &c in byte_str {
+ match c {
+ 0..=31 |
+ b'<' | b'>' | b':' | b'"' |
+ b'/' | b'\\' | b'|' | b'?' | b'*' => return false,
+ _ => {},
+ }
+ }
+
+ // Filename can't end with . or space (except before extension, but this checks the whole name)
+ let last_char = byte_str[byte_str.len()-1];
+ if last_char == b' ' || last_char == b'.' {
+ return false;
+ }
+ true
+}
+
+#[cfg(any(windows, test))]
+const RESERVED_NAMES: [&'static str; 22] = [
+ "AUX", "NUL", "PRN", "CON", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8",
+ "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
+];
+
+#[cfg(any(windows, test))]
+fn is_reserved<P: AsRef<OsStr>>(file_name: P) -> bool {
+ // con.txt is reserved too
+ if let Some(stem) = Path::new(&file_name).file_stem() {
+ // all reserved DOS names have ASCII-compatible stem
+ if let Some(name) = stem.to_str() {
+ // "con.. .txt" is "CON" for DOS
+ let trimmed = right_trim(name);
+ if trimmed.len() <= 4 {
+ for name in &RESERVED_NAMES {
+ if name.eq_ignore_ascii_case(trimmed) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ false
+}
+
+#[cfg(not(windows))]
+#[inline]
+fn is_safe_to_strip_unc(_path: &Path) -> bool {
+ false
+}
+
+#[cfg(windows)]
+fn is_safe_to_strip_unc(path: &Path) -> bool {
+ let mut components = path.components();
+ match components.next() {
+ Some(Component::Prefix(p)) => match p.kind() {
+ Prefix::VerbatimDisk(..) => {},
+ _ => return false, // Other kinds of UNC paths
+ },
+ _ => return false, // relative or empty
+ }
+
+ for component in components {
+ match component {
+ Component::RootDir => {},
+ Component::Normal(file_name) => {
+ // it doesn't allocate in most cases,
+ // and checks are interested only in the ASCII subset, so lossy is fine
+ if !is_valid_filename(file_name) || is_reserved(file_name) {
+ return false;
+ }
+ }
+ _ => return false, // UNC paths take things like ".." literally
+ };
+ }
+
+ if windows_char_len(path.as_os_str()) > 260 { // However, if the path is going to be used as a directory it's 248
+ return false;
+ }
+ true
+}
+
+/// Trim '.' and ' '
+#[cfg(any(windows, test))]
+fn right_trim(mut s: &str) -> &str {
+ while s.len() > 0 {
+ let last = s.len()-1;
+ unsafe {
+ if s.as_bytes()[last] == b'.' || s.as_bytes()[last] == b' ' {
+ s = s.get_unchecked(0..last) // trim of ASCII byte can't break UTF-8
+ } else {
+ break;
+ }
+ }
+ }
+ s
+}
+
+#[test]
+fn trim_test() {
+ assert_eq!("a", right_trim("a."));
+ assert_eq!("ą", right_trim("ą."));
+ assert_eq!("a", right_trim("a "));
+ assert_eq!("ąą", right_trim("ąą "));
+ assert_eq!("a", right_trim("a. . . .... "));
+ assert_eq!("a. . . ..ź", right_trim("a. . . ..ź.. "));
+ assert_eq!(" b", right_trim(" b"));
+ assert_eq!(" べ", right_trim(" べ"));
+ assert_eq!("c. c", right_trim("c. c."));
+ assert_eq!("。", right_trim("。"));
+ assert_eq!("", right_trim(""));
+}
+
+#[test]
+fn reserved() {
+ assert!(is_reserved("CON"));
+ assert!(is_reserved("con"));
+ assert!(is_reserved("con.con"));
+ assert!(is_reserved("COM4"));
+ assert!(is_reserved("COM4.txt"));
+ assert!(is_reserved("COM4 .txt"));
+ assert!(is_reserved("con."));
+ assert!(is_reserved("con ."));
+ assert!(is_reserved("con "));
+ assert!(is_reserved("con . "));
+ assert!(is_reserved("con . .txt"));
+ assert!(is_reserved("con.....txt"));
+ assert!(is_reserved("PrN....."));
+
+ assert!(!is_reserved(" PrN....."));
+ assert!(!is_reserved(" CON"));
+ assert!(!is_reserved("COM0"));
+ assert!(!is_reserved("COM77"));
+ assert!(!is_reserved(" CON "));
+ assert!(!is_reserved(".CON"));
+ assert!(!is_reserved("@CON"));
+ assert!(!is_reserved("not.CON"));
+ assert!(!is_reserved("CON。"));
+}
+
+#[test]
+fn len() {
+ assert_eq!(1, windows_char_len(OsStr::new("a")));
+ assert_eq!(1, windows_char_len(OsStr::new("€")));
+ assert_eq!(1, windows_char_len(OsStr::new("本")));
+ assert_eq!(2, windows_char_len(OsStr::new("🧐")));
+ assert_eq!(2, windows_char_len(OsStr::new("®®")));
+}
+
+#[test]
+fn valid() {
+ assert!(!is_valid_filename("..".as_ref()));
+ assert!(!is_valid_filename(".".as_ref()));
+ assert!(!is_valid_filename("aaaaaaaaaa:".as_ref()));
+ assert!(!is_valid_filename("ą:ą".as_ref()));
+ assert!(!is_valid_filename("".as_ref()));
+ assert!(!is_valid_filename("a ".as_ref()));
+ assert!(!is_valid_filename(" a. ".as_ref()));
+ assert!(!is_valid_filename("a/".as_ref()));
+ assert!(!is_valid_filename("/a".as_ref()));
+ assert!(!is_valid_filename("/".as_ref()));
+ assert!(!is_valid_filename("\\".as_ref()));
+ assert!(!is_valid_filename("\\a".as_ref()));
+ assert!(!is_valid_filename("<x>".as_ref()));
+ assert!(!is_valid_filename("a*".as_ref()));
+ assert!(!is_valid_filename("?x".as_ref()));
+ assert!(!is_valid_filename("a\0a".as_ref()));
+ assert!(!is_valid_filename("\x1f".as_ref()));
+ assert!(!is_valid_filename(::std::iter::repeat("a").take(257).collect::<String>().as_ref()));
+
+ assert!(is_valid_filename(::std::iter::repeat("®").take(254).collect::<String>().as_ref()));
+ assert!(is_valid_filename("ファイル".as_ref()));
+ assert!(is_valid_filename("a".as_ref()));
+ assert!(is_valid_filename("a.aaaaaaaa".as_ref()));
+ assert!(is_valid_filename("a........a".as_ref()));
+ assert!(is_valid_filename(" b".as_ref()));
+}
+
+#[test]
+#[cfg(windows)]
+fn realpath_test() {
+ assert_eq!(r"C:\WINDOWS", canonicalize(r"C:\Windows").unwrap().to_str().unwrap().to_uppercase());
+ assert_ne!(r".", canonicalize(r".").unwrap().to_str().unwrap());
+}
+
+#[test]
+#[cfg(windows)]
+fn strip() {
+ assert_eq!(Path::new(r"C:\foo\😀"), simplified(Path::new(r"\\?\C:\foo\😀")));
+ assert_eq!(Path::new(r"\\?\serv\"), simplified(Path::new(r"\\?\serv\")));
+ assert_eq!(Path::new(r"\\.\C:\notdisk"), simplified(Path::new(r"\\.\C:\notdisk")));
+ assert_eq!(Path::new(r"\\?\GLOBALROOT\Device\ImDisk0\path\to\file.txt"), simplified(Path::new(r"\\?\GLOBALROOT\Device\ImDisk0\path\to\file.txt")));
+}
+
+#[test]
+#[cfg(windows)]
+fn safe() {
+ assert!(is_safe_to_strip_unc(Path::new(r"\\?\C:\foo\bar")));
+ assert!(is_safe_to_strip_unc(Path::new(r"\\?\Z:\foo\bar\")));
+ assert!(is_safe_to_strip_unc(Path::new(r"\\?\Z:\😀\🎃\")));
+ assert!(is_safe_to_strip_unc(Path::new(r"\\?\c:\foo")));
+
+ let long = ::std::iter::repeat("®").take(160).collect::<String>();
+ assert!(is_safe_to_strip_unc(Path::new(&format!(r"\\?\c:\{}", long))));
+ assert!(!is_safe_to_strip_unc(Path::new(&format!(r"\\?\c:\{}\{}", long, long))));
+
+ assert!(!is_safe_to_strip_unc(Path::new(r"\\?\C:\foo\.\bar")));
+ assert!(!is_safe_to_strip_unc(Path::new(r"\\?\C:\foo\..\bar")));
+ assert!(!is_safe_to_strip_unc(Path::new(r"\\?\c\foo")));
+ assert!(!is_safe_to_strip_unc(Path::new(r"\\?\c\foo/bar")));
+ assert!(!is_safe_to_strip_unc(Path::new(r"\\?\c:foo")));
+ assert!(!is_safe_to_strip_unc(Path::new(r"\\?\cc:foo")));
+ assert!(!is_safe_to_strip_unc(Path::new(r"\\?\c:foo\bar")));
+}