>From 341ac1c69df18eac9a5ebf0cfc5553fa62bff3bd Mon Sep 17 00:00:00 2001 From: Christian Kellermann Date: Wed, 28 Sep 2011 17:23:57 +0200 Subject: [PATCH] Replace ##sys#file-info with ##sys#file-exists This also introduces a simpler runtime function that calls access to test for file accessability. This fixes bug #706 reported by Sven Hartrumpf. The old version returned false whenever fstat failed. In Sven's case the size parameter overflowed, and file-exists? returns #f. Thanks to Thomas Chust for the suggestion. --- chicken.h | 3 ++- library.scm | 3 ++- runtime.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/chicken.h b/chicken.h index 8c6eff3..47b12f7 100644 --- a/chicken.h +++ b/chicken.h @@ -572,7 +572,7 @@ static inline int isinf_ld (long double x) #define C_CIRCULAR_DATA_ERROR 36 #define C_BAD_ARGUMENT_TYPE_NO_BOOLEAN_ERROR 37 #define C_BAD_ARGUMENT_TYPE_NO_LOCATIVE_ERROR 38 - +#define C_SYSCALL_ERROR 39 /* Platform information */ #if defined(C_BIG_ENDIAN) @@ -1674,6 +1674,7 @@ C_fctexport void C_ccall C_make_tagged_pointer(C_word c, C_word closure, C_word C_fctexport void C_ccall C_ensure_heap_reserve(C_word c, C_word closure, C_word k, C_word n) C_noret; C_fctexport void C_ccall C_return_to_host(C_word c, C_word closure, C_word k) C_noret; C_fctexport void C_ccall C_file_info(C_word c, C_word closure, C_word k, C_word port) C_noret; +C_fctexport void C_ccall C_file_exists(C_word c, C_word closure, C_word k, C_word port) C_noret; C_fctexport void C_ccall C_get_environment_variable(C_word c, C_word closure, C_word k, C_word name) C_noret; C_fctexport void C_ccall C_get_symbol_table_info(C_word c, C_word closure, C_word k) C_noret; C_fctexport void C_ccall C_get_memory_info(C_word c, C_word closure, C_word k) C_noret; diff --git a/library.scm b/library.scm index e07e9c4..5fef68e 100644 --- a/library.scm +++ b/library.scm @@ -191,6 +191,7 @@ EOF (define ##sys#call-host (##core#primitive "C_return_to_host")) (define return-to-host ##sys#call-host) (define ##sys#file-info (##core#primitive "C_file_info")) +(define ##sys#file-exists (##core#primitive "C_file_exists")) (define ##sys#symbol-table-info (##core#primitive "C_get_symbol_table_info")) (define ##sys#memory-info (##core#primitive "C_get_memory_info")) (define (current-milliseconds) (##core#inline_allocate ("C_a_i_current_milliseconds" 4) #f)) @@ -1979,7 +1980,7 @@ EOF (##sys#pathname-resolution name (lambda (name) - (and (##sys#file-info (##sys#platform-fixup-pathname name)) name) ) + (and (##sys#file-exists (##sys#platform-fixup-pathname name)) name) ) #:exists?) ) (define (directory-exists? name) diff --git a/runtime.c b/runtime.c index c0c91bc..32804cf 100644 --- a/runtime.c +++ b/runtime.c @@ -737,6 +737,7 @@ static C_PTABLE_ENTRY *create_initial_ptable() C_pte(C_ensure_heap_reserve); C_pte(C_return_to_host); C_pte(C_file_info); + C_pte(C_file_exists); C_pte(C_get_symbol_table_info); C_pte(C_get_memory_info); C_pte(C_decode_seconds); @@ -1616,6 +1617,11 @@ void barf(int code, char *loc, ...) c = 0; break; + case C_SYSCALL_ERROR: + msg = C_text("Underlying syscall error"); + c = 1; + break; + default: panic(C_text("illegal internal error code")); } @@ -7776,6 +7782,31 @@ void C_ccall C_file_info(C_word c, C_word closure, C_word k, C_word name) file_info_2(NULL); } +void C_ccall C_file_exists(C_word c, C_word closure, C_word k, C_word name) +{ + C_word v = C_SCHEME_FALSE; + int call_res = 0; + + int len = C_header_size(name); + char *buffer2; + int res = 0; + + buffer2 = buffer; + if(len >= sizeof(buffer)) { + if((buffer2 = (char *)C_malloc(len + 1)) == NULL) + barf(C_OUT_OF_MEMORY_ERROR, "stat"); + } + C_strncpy(buffer2, C_c_string(name), len); + buffer2[ len ] = '\0'; + call_res=access(buffer2, F_OK); + if (call_res == 0) { + v = C_SCHEME_TRUE; + } else if (errno != ENOENT) { + barf(C_SYSCALL_ERROR, "access"); + } + + C_kontinue(k, v); +} void file_info_2(void *dummy) { -- 1.7.4.1