From e2988c5c20be066cc886a9031f25e6aabb2ab8bf Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 18 Oct 2019 17:55:28 +0200 Subject: [PATCH] refactor sfgets() and sfread() to both allow NULL filenames and guess from /proc if needed and possible --- src/pair_lj96_cut.cpp | 2 +- src/utils.cpp | 49 ++++++++++++++++++++++++++++--------------- src/utils.h | 2 +- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/pair_lj96_cut.cpp b/src/pair_lj96_cut.cpp index d0e625fad4..f554872965 100644 --- a/src/pair_lj96_cut.cpp +++ b/src/pair_lj96_cut.cpp @@ -606,7 +606,7 @@ void PairLJ96Cut::read_restart(FILE *fp) int me = comm->me; for (i = 1; i <= atom->ntypes; i++) for (j = i; j <= atom->ntypes; j++) { - if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp); + if (me == 0) utils::sfread(FLERR,&setflag[i][j],sizeof(int),1,fp,NULL,error); MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world); if (setflag[i][j]) { if (me == 0) { diff --git a/src/utils.cpp b/src/utils.cpp index 8f1dadad0b..f6556a3ac8 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -107,14 +107,43 @@ int utils::cfvarg(std::string mode, const char *arg, char *&cfv_id) return rv; } +/** \brief try to detect pathname from FILE pointer. Currently only supported on Linux, otherwise will report "(unknown)". + * + * \param buf storage buffer for pathname. output will be truncated if not large enough + * \param len size of storage buffer. output will be truncated to this length - 1 + * \param fp FILE pointer structe from STDIO library for which we want to detect the name + * \return pointer to the storage buffer, i.e. buf + */ +static const char *guesspath(char *buf, int len, FILE *fp) +{ + memset(buf,0,len); + +#if defined(__linux) + char procpath[32]; + int fd = fileno(fp); + snprintf(procpath,32,"/proc/self/fd/%d",fd); + // get pathname from /proc or copy (unknown) + if (readlink(procpath,buf,len-1) <= 0) strcpy(buf,"(unknown)"); +#else + strcpy(buf,"(unknown)"); +#endif + return buf; +} + +#define MAXPATHLENBUF 1024 /* like fgets() but aborts with an error or EOF is encountered */ void utils::sfgets(const char *srcname, int srcline, char *s, int size, FILE *fp, const char *filename, Error *error) { char *rv = fgets(s,size,fp); if (rv == NULL) { // something went wrong + char buf[MAXPATHLENBUF]; std::string errmsg; + // try to figure out the file name from the file pointer + if (!filename) + filename = guesspath(buf,MAXPATHLENBUF,fp); + if (feof(fp)) { errmsg = "Unexpected end of file while reading file '"; } else if (ferror(fp)) { @@ -131,32 +160,18 @@ void utils::sfgets(const char *srcname, int srcline, char *s, int size, return; } -#define MAXFILEBUF 1024 /* like fread() but aborts with an error or EOF is encountered */ void utils::sfread(const char *srcname, int srcline, void *s, size_t size, size_t num, FILE *fp, const char *filename, Error *error) { - char inferred_name[MAXFILEBUF]; size_t rv = fread(s,size,num,fp); if (rv != num) { // something went wrong + char buf[MAXPATHLENBUF]; std::string errmsg; // try to figure out the file name from the file pointer - if (!filename) { - // on Linux we can infer the name of the open file from /proc - // otherwise we set it to "(unknown)" -#if defined(__linux) - char procpath[32]; - int fd = fileno(fp); - snprintf(procpath,32,"/proc/self/fd/%d",fd); - memset(inferred_name,0,MAXFILEBUF); - if (readlink(procpath,inferred_name,MAXFILEBUF) <= 0) - strcpy(inferred_name,"(unknown)"); -#else - strcpy(inferred_name,"(unknown)"); -#endif - filename = inferred_name; - } + if (!filename) + filename = guesspath(buf,MAXPATHLENBUF,fp); if (feof(fp)) { errmsg = "Unexpected end of file while reading file '"; diff --git a/src/utils.h b/src/utils.h index 8b18f95c77..e87aa4bb91 100644 --- a/src/utils.h +++ b/src/utils.h @@ -63,7 +63,7 @@ namespace LAMMPS_NS { * \param s buffer for storing the result of fgets() * \param size size of buffer s (max number of bytes read by fgets()) * \param fp file pointer used by fgets() - * \param filename file name associated with fp (for error message) + * \param filename file name associated with fp (may be NULL; then LAMMPS will try to detect) * \param error pointer to Error class instance (for abort) */ void sfgets(const char *srcname, int srcline, char *s, int size,