From fefc01b46b55155c93b1bd07435fc6134ec1814b Mon Sep 17 00:00:00 2001 From: Anthony Scemama Date: Tue, 3 Jan 2023 18:29:21 +0100 Subject: [PATCH] Added trexio_cp --- configure.ac | 7 +- src/templates_front/templator_front.org | 138 +++++++++++++++++++++++- tests/io_all.c | 24 +++-- 3 files changed, 157 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index 0a6f6b8..ef4376b 100644 --- a/configure.ac +++ b/configure.ac @@ -104,7 +104,7 @@ esac ## --------- # Checks for basic header files. -AC_CHECK_HEADERS([fcntl.h inttypes.h stdint.h stdbool.h stdlib.h string.h unistd.h]) +AC_CHECK_HEADERS([fcntl.h inttypes.h stdint.h stdbool.h stdlib.h string.h unistd.h sys/types.h sys/wait.h ]) ### HDF5 @@ -130,11 +130,12 @@ if test "x${with_hdf5}" = xno; then recommended to build efficient TREXIO. ------------------------------------------]) else - AC_HAVE_LIBRARY([hdf5_hl], [], AC_MSG_ERROR([ + AC_CHECK_LIB([hdf5_hl],[main],[],[AC_MSG_ERROR( ----------------------------------- Error: hdf5_hl library is required ----------------------------------- -]), []) +)],[])ac_cv_lib_hdf5_hl=ac_cv_lib_hdf5_hl_main + fi CFLAGS="${HDF5_CFLAGS} ${CFLAGS}" diff --git a/src/templates_front/templator_front.org b/src/templates_front/templator_front.org index 76c8b72..d979303 100644 --- a/src/templates_front/templator_front.org +++ b/src/templates_front/templator_front.org @@ -44,6 +44,9 @@ typedef int32_t trexio_exit_code; #include #include #include +#include +#include + #include "trexio.h" #include "trexio_private.h" @@ -1585,6 +1588,139 @@ def _inquire(file_name: str) -> bool: raise Error(rc) #+end_src +** File copy + + ~trexio_cp~ copies a TREXIO file using =/bin/cp=. + + **Input parameters:** + 1) ~source_file_name~ - string containing the name of the source file + 2) ~destination_file_name~ - string containing the name of the new file + + **Output:** + - ~trexio_exit_code~ + +*** C + + #+begin_src c :tangle prefix_front.h :exports none +trexio_exit_code trexio_cp(const char* source_file_name, const char* dest_file_name); + #+end_src + + #+begin_src c :tangle prefix_front.c + +trexio_exit_code +trexio_cp(const char* source, const char* dest) +{ + + if (source == NULL || source[0] == '\0') { + return TREXIO_INVALID_ARG_1; + } + + if (dest == NULL || dest[0] == '\0') { + return TREXIO_INVALID_ARG_2; + } + + + back_end_t back_end_local = TREXIO_AUTO; + /* Try to determine the applicable backend if the back_end argument is TREXIO_AUTO */ +#ifdef HAVE_HDF5 + /* Check if the TREXIO file exists and if it is a directory */ + trexio_exit_code rc_text = trexio_text_inquire(source); + if (rc_text == TREXIO_SUCCESS) { + back_end_local = TREXIO_TEXT; + } else { + /* If not, check if it is an HDF5 file */ + trexio_exit_code rc_hdf5 = trexio_hdf5_inquire(source); + if (rc_hdf5 == TREXIO_SUCCESS) { + back_end_local = TREXIO_HDF5; + } else { + /* File is neither a directory nor an HDF5 file -> return an error */ + return TREXIO_FILE_ERROR; + } +#else + /* In the current implementation if HDF5 back end is not available - then there is only back end left */ + back_end_local = TREXIO_TEXT; +#endif + } + assert (back_end_local != TREXIO_AUTO); + + if (trexio_inquire(dest) == TREXIO_SUCCESS) { + /* Destination file already exists */ + return TREXIO_FILE_ERROR; + }; + + /* Call cp */ + + pid_t pid = fork(); + if (pid == 0) { + switch (back_end_local) { + case TREXIO_TEXT: + execl("/bin/cp", "/bin/cp", "-r", "-n", source, dest, (char *)0); + case TREXIO_HDF5: +#ifdef HAVE_HDF5 + execl("/bin/cp", "/bin/cp", "-n", source, dest, (char *)0); +#else + return TREXIO_FILE_ERROR; +#endif +/* + case TREXIO_JSON: + execl("/bin/cp", "/bin/cp", source, dest, (char *)0); +,*/ + default: + return TREXIO_FILE_ERROR; + } + } else if (pid < 0) { + return TREXIO_FILE_ERROR; + } else { + int wstatus; + pid_t ws = waitpid( pid, &wstatus, 0); + if (ws != pid || !WIFEXITED(wstatus) ) + return TREXIO_FILE_ERROR; + } + + return TREXIO_SUCCESS; +} + #+end_src + +*** Fortran + + #+begin_src f90 :tangle prefix_fortran.f90 +interface + integer(trexio_exit_code) function trexio_cp (source, destination) bind(C, name="trexio_cp") + use, intrinsic :: iso_c_binding + import + character(kind=c_char), dimension(*) :: source, destination + end function trexio_cp +end interface + #+end_src + +*** Python + + #+begin_src python :tangle basic_python.py +def _cp(source: str, destination: str): + """Copies a TREXIO file + + Parameters: + + source: str + Name of the source file + + destination: str + Name of the destination file + + Examples: + >>> from trexio import cp as tr_cp + >>> tr_cp("example.h5", "new.h5") + """ + + from shutil import copytree, copyfile + + f = File(filename=source, mode='r', back_end=TREXIO_AUTO) + if f.back_end == TREXIO_TEXT: + copytree(source, destination) + elif f.back_end == TREXIO_HDF5: + copyfile(source, destination) + #+end_src + ** File state **Note:** the use of the functions below is discouraged as of version 2.3.0. @@ -1676,7 +1812,7 @@ end interface *** Python See TREXIO File Python class. - + ** Tasks to be done before closing #+begin_src c :tangle trexio_private.h :exports none diff --git a/tests/io_all.c b/tests/io_all.c index 9096d29..42dc94e 100644 --- a/tests/io_all.c +++ b/tests/io_all.c @@ -18,19 +18,25 @@ int main() { bool have_hdf5 = trexio_has_backend(TREXIO_HDF5); if(have_hdf5) { - rc = system("rm -f -- test_all.h5"); + rc = system("rm -f -- test_all.h5 test_all2.h5"); assert (rc == 0); - test_write("test_all.h5", TREXIO_HDF5); - test_read ("test_all.h5", TREXIO_HDF5); - rc = system("rm -f -- test_all.h5"); + test_write("test_all.h5" , TREXIO_HDF5); + rc = trexio_cp ("test_all.h5", "test_all2.h5"); + assert (rc == TREXIO_SUCCESS); + test_read ("test_all2.h5", TREXIO_HDF5); + rc = system("rm -f -- test_all.h5 test_all2.h5"); assert (rc == 0); } - rc = system("rm -f -- test_all.dir/*.txt test_all.dir/*.txt.size test_all.dir/.lock && rm -fd -- test_all.dir"); + rc = system("rm -f -- test_all.dir/*.txt test_all.dir/*.txt.size test_all.dir/.lock && rm -fd -- test_all.dir && \ + rm -f -- test_all2.dir/*.txt test_all2.dir/*.txt.size test_all2.dir/.lock && rm -fd -- test_all2.dir"); assert (rc == 0); - test_write("test_all.dir", TREXIO_TEXT); - test_read ("test_all.dir", TREXIO_TEXT); - rc = system("rm -f -- test_all.dir/*.txt test_all.dir/*.txt.size test_all.dir/.lock && rm -fd -- test_all.dir"); + test_write("test_all.dir" , TREXIO_TEXT); + rc = trexio_cp ("test_all.dir" , "test_all2.dir"); + assert (rc == TREXIO_SUCCESS); + test_read ("test_all2.dir", TREXIO_TEXT); + rc = system("rm -f -- test_all.dir/*.txt test_all.dir/*.txt.size test_all.dir/.lock && rm -fd -- test_all.dir && \ + rm -f -- test_all2.dir/*.txt test_all2.dir/*.txt.size test_all2.dir/.lock && rm -fd -- test_all2.dir"); assert (rc == 0); return 0; @@ -138,6 +144,7 @@ int test_write(const char* file_name, const back_end_t backend) { // open file again in 'write' mode file = trexio_open(file_name, 'w', backend, &rc); assert (file != NULL); + assert (rc == TREXIO_SUCCESS); // write some missing blocks (e.g. if forgot last time) rc = trexio_write_nucleus_charge(file,charge); @@ -169,6 +176,7 @@ int test_read(const char* file_name, const back_end_t backend) { // open existing file on 'read' mode [created by test_write] file = trexio_open(file_name, 'r', TREXIO_AUTO, &rc); assert (file != NULL); + assert (rc == TREXIO_SUCCESS); // read nucleus_num rc = trexio_read_nucleus_num(file,&num);