refactor sfgets() and sfread() to both allow NULL filenames and guess from /proc if needed and possible

This commit is contained in:
Axel Kohlmeyer
2019-10-18 17:55:28 +02:00
parent fe20490891
commit e2988c5c20
3 changed files with 34 additions and 19 deletions

View File

@ -606,7 +606,7 @@ void PairLJ96Cut::read_restart(FILE *fp)
int me = comm->me; int me = comm->me;
for (i = 1; i <= atom->ntypes; i++) for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) { 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); MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) { if (setflag[i][j]) {
if (me == 0) { if (me == 0) {

View File

@ -107,14 +107,43 @@ int utils::cfvarg(std::string mode, const char *arg, char *&cfv_id)
return rv; 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 */ /* like fgets() but aborts with an error or EOF is encountered */
void utils::sfgets(const char *srcname, int srcline, char *s, int size, void utils::sfgets(const char *srcname, int srcline, char *s, int size,
FILE *fp, const char *filename, Error *error) FILE *fp, const char *filename, Error *error)
{ {
char *rv = fgets(s,size,fp); char *rv = fgets(s,size,fp);
if (rv == NULL) { // something went wrong if (rv == NULL) { // something went wrong
char buf[MAXPATHLENBUF];
std::string errmsg; std::string errmsg;
// try to figure out the file name from the file pointer
if (!filename)
filename = guesspath(buf,MAXPATHLENBUF,fp);
if (feof(fp)) { if (feof(fp)) {
errmsg = "Unexpected end of file while reading file '"; errmsg = "Unexpected end of file while reading file '";
} else if (ferror(fp)) { } else if (ferror(fp)) {
@ -131,32 +160,18 @@ void utils::sfgets(const char *srcname, int srcline, char *s, int size,
return; return;
} }
#define MAXFILEBUF 1024
/* like fread() but aborts with an error or EOF is encountered */ /* like fread() but aborts with an error or EOF is encountered */
void utils::sfread(const char *srcname, int srcline, void *s, size_t size, void utils::sfread(const char *srcname, int srcline, void *s, size_t size,
size_t num, FILE *fp, const char *filename, Error *error) size_t num, FILE *fp, const char *filename, Error *error)
{ {
char inferred_name[MAXFILEBUF];
size_t rv = fread(s,size,num,fp); size_t rv = fread(s,size,num,fp);
if (rv != num) { // something went wrong if (rv != num) { // something went wrong
char buf[MAXPATHLENBUF];
std::string errmsg; std::string errmsg;
// try to figure out the file name from the file pointer // try to figure out the file name from the file pointer
if (!filename) { if (!filename)
// on Linux we can infer the name of the open file from /proc filename = guesspath(buf,MAXPATHLENBUF,fp);
// 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 (feof(fp)) { if (feof(fp)) {
errmsg = "Unexpected end of file while reading file '"; errmsg = "Unexpected end of file while reading file '";

View File

@ -63,7 +63,7 @@ namespace LAMMPS_NS {
* \param s buffer for storing the result of fgets() * \param s buffer for storing the result of fgets()
* \param size size of buffer s (max number of bytes read by fgets()) * \param size size of buffer s (max number of bytes read by fgets())
* \param fp file pointer used 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) * \param error pointer to Error class instance (for abort)
*/ */
void sfgets(const char *srcname, int srcline, char *s, int size, void sfgets(const char *srcname, int srcline, char *s, int size,