From 0f4667d94200f609023769a1138d7a7984715842 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Wed, 15 Jul 2020 20:24:26 +0200 Subject: [PATCH] ADDED: path_canonical/2, obtaining the canonical absolute path. This addresses a remaining aspect of #511. --- src/clause_types.rs | 3 +++ src/lib/files.pl | 30 +++++++++++++++++++++++++++++- src/machine/system_calls.rs | 25 +++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index 89e4d00d..c4546623 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -178,6 +178,7 @@ pub enum SystemClauseType { MakeDirectory, DeleteFile, WorkingDirectory, + PathCanonical, DeleteAttribute, DeleteHeadAttribute, DynamicModuleResolution(usize), @@ -345,6 +346,7 @@ impl SystemClauseType { &SystemClauseType::MakeDirectory => clause_name!("$make_directory"), &SystemClauseType::DeleteFile => clause_name!("$delete_file"), &SystemClauseType::WorkingDirectory => clause_name!("$working_directory"), + &SystemClauseType::PathCanonical => clause_name!("$path_canonical"), &SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"), &SystemClauseType::REPL(REPLCodePtr::UseModule) => clause_name!("$use_module"), &SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule) => { @@ -681,6 +683,7 @@ impl SystemClauseType { ("$make_directory", 1) => Some(SystemClauseType::MakeDirectory), ("$delete_file", 1) => Some(SystemClauseType::DeleteFile), ("$working_directory", 2) => Some(SystemClauseType::WorkingDirectory), + ("$path_canonical", 2) => Some(SystemClauseType::PathCanonical), ("$use_module", 1) => Some(SystemClauseType::REPL(REPLCodePtr::UseModule)), ("$use_module_from_file", 1) => Some(SystemClauseType::REPL(REPLCodePtr::UseModuleFromFile)), diff --git a/src/lib/files.pl b/src/lib/files.pl index 9e54bf33..69847b29 100644 --- a/src/lib/files.pl +++ b/src/lib/files.pl @@ -52,7 +52,8 @@ directory_exists/1, delete_file/1, make_directory/1, - working_directory/2]). + working_directory/2, + path_canonical/2]). :- use_module(library(error)). :- use_module(library(lists)). @@ -87,7 +88,34 @@ delete_file(File) :- list_of_chars(File), '$delete_file'(File). +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + Dir0 is the current working directory, and the working directory + is changed to Dir. + + Use working_directory(Ds, Ds) to determine the current working directory, + and leave it as is. +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + working_directory(Dir0, Dir) :- can_be(list, Dir0), can_be(list, Dir), '$working_directory'(Dir0, Dir). + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + True iff Cs is the canonical, absolute path of Ps. + + All intermediate components are normalized, and all symbolic links + are resolved. + + The predicate fails in the following situations, though not + necessarily *only* in these cases: + + 1. Ps is a path that does not exist. + 2. A non-final component in Ps is not a directory. +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +path_canonical(Ps, Cs) :- + must_be(list, Ps), + maplist(must_be(character), Ps), + can_be(list, Cs), + '$path_canonical'(Ps, Cs). diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 77ef1366..2f357873 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -918,6 +918,31 @@ impl MachineState { return Ok(()); } } + &SystemClauseType::PathCanonical => { + let path = self.heap_pstr_iter(self[temp_v!(1)]).to_string(); + + match fs::canonicalize(path) { + Ok(canonical) => { + let cs = + match canonical.to_str() { + Some(s) => { s } + _ => { + let stub = MachineError::functor_stub(clause_name!("path_canonical"), 2); + let err = MachineError::representation_error(RepFlag::Character); + let err = self.error_form(err, stub); + + return Err(err); + } + }; + let chars = self.heap.put_complete_string(cs); + self.unify(self[temp_v!(2)], chars); + } + _ => { + self.fail = true; + return Ok(()); + } + } + } &SystemClauseType::AtEndOfExpansion => { if self.cp == LocalCodePtr::TopLevel(0, 0) { self.at_end_of_expansion = true; -- 2.54.0