Commits

Jed Brown committed 099d3e5 Merge with conflicts

Merge branch 'jed/avoid-getpwuid' into maint

The file path routines were broken because the current directory was
placed in front of the given path before checking for leading ~ or
~user. This is now fixed, along with the removal of getpwuid (a
liability on BG/Q and Cray). We still attempt to use getpwnam when
encountering ~user.

* jed/avoid-getpwuid:
Sys ex13: avoid non-portable realpath(1) in verification test
cleanup includes that are no longer needed. Also remove check for _fullpath() as the corresponding code is removed.
Sys: fix PetscGetFullPath expansion of ~ and ~user, ensure NULL termination
Sys: avoid getpwuid in file path routines
Sys: add failing test expanding ~/file-name and ~user/file-name

Conflicts:
config/PETSc/Configure.py

Comments (0)

Files changed (7)

config/PETSc/Configure.py

                                             'sys/systeminfo', 'sys/times', 'sys/utsname','string', 'stdlib','memory',
                                             'sys/socket','sys/wait','netinet/in','netdb','Direct','time','Ws2tcpip','sys/types',
                                             'WindowsX', 'cxxabi','float','ieeefp','stdint','sched','pthread','mathimf'])
-    functions = ['access', '_access', 'clock', 'drand48', 'getcwd', '_getcwd', 'getdomainname', 'gethostname', 'getpwuid',
+    functions = ['access', '_access', 'clock', 'drand48', 'getcwd', '_getcwd', 'getdomainname', 'gethostname',
                  'gettimeofday', 'getwd', 'memalign', 'memmove', 'mkstemp', 'popen', 'PXFGETARG', 'rand', 'getpagesize',
                  'readlink', 'realpath',  'sigaction', 'signal', 'sigset', 'usleep', 'sleep', '_sleep', 'socket',
-                 'times', 'gethostbyname', 'uname','snprintf','_snprintf','_fullpath','lseek','_lseek','time','fork','stricmp',
+                 'times', 'gethostbyname', 'uname','snprintf','_snprintf','lseek','_lseek','time','fork','stricmp',
                  'strcasecmp', 'bzero', 'dlopen', 'dlsym', 'dlclose', 'dlerror','get_nprocs','sysctlbyname',
                  '_intel_fast_memcpy','_intel_fast_memset']
     libraries1 = [(['socket', 'nsl'], 'socket'), (['fpe'], 'handle_sigfpes')]

src/sys/examples/tests/ex13.c

+static char help[] = "Demonstrates PETSc path routines.\n";
+
+#include <petscsys.h>
+
+#undef __FUNCT__
+#define __FUNCT__ "RealpathPhonyFile"
+/* realpath(3) requires the path to exist, but GNU coreutils' realpath(1) only needs the containing directory to exist.
+ * So split path into (dir, base) and only use realpath(3) on dir.
+ *
+ */
+static PetscErrorCode RealpathPhonyFile(const char *path,char *buf,size_t len)
+{
+  char dir[PETSC_MAX_PATH_LEN],rpath[PETSC_MAX_PATH_LEN],*last;
+  const char *base;
+  size_t dlen;
+  PetscErrorCode ierr;
+
+  PetscFunctionBegin;
+  ierr = PetscStrncpy(dir,path,sizeof dir);CHKERRQ(ierr);
+  dir[sizeof dir-1] = 0;
+  ierr = PetscStrlen(dir,&dlen);CHKERRQ(ierr);
+  last = dir + dlen - 1;
+  while (last > dir && *last == '/') *last-- = 0; /* drop trailing slashes */
+  while (last > dir && *last != '/') last--;      /* seek backward to next slash */
+  if (last > dir) {
+    *last = 0;
+    base = last + 1;
+  } else {                      /* Current directory */
+    dir[0] = '.';
+    dir[1] = '\0';
+    base = path;
+  }
+#if defined(PETSC_HAVE_REALPATH)
+  if (!realpath(dir,rpath)) {
+    perror("ex13: realpath");
+    SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"realpath()");
+  }
+#else
+  ierr = PetscStrncpy(rpath,dir,sizeof rpath);CHKERRQ(ierr);
+  rpath[sizeof rpath-1] = 0;
+#endif
+  ierr = PetscStrlen(rpath,&dlen);CHKERRQ(ierr);
+  ierr = PetscMemcpy(buf,rpath,PetscMin(dlen,len-1));CHKERRQ(ierr);
+  buf[PetscMin(dlen,len-1)] = '/';
+  ierr = PetscStrncpy(buf+PetscMin(dlen+1,len-1),base,PetscMax(len-dlen-1,0));CHKERRQ(ierr);
+  buf[len-1] = 0;
+  PetscFunctionReturn(0);
+}
+
+
+#undef __FUNCT__
+#define __FUNCT__ "CheckLen"
+static PetscErrorCode CheckLen(const char *path,size_t len,size_t *used)
+{
+  char           *buf,cmd[4096],spath[PETSC_MAX_PATH_LEN],rpath[PETSC_MAX_PATH_LEN];
+  PetscErrorCode ierr;
+  FILE           *fp;
+  PetscBool      match;
+
+  PetscFunctionBegin;
+  /* dynamically allocate so valgrind and PETSc can check for overflow */
+  ierr = PetscMalloc(len,&buf);CHKERRQ(ierr);
+  ierr = PetscGetFullPath(path,buf,len);CHKERRQ(ierr);
+  ierr = PetscSNPrintf(cmd,sizeof cmd,"printf %%s %s",path);CHKERRQ(ierr);
+  ierr = PetscPOpen(PETSC_COMM_SELF,NULL,cmd,"r",&fp);CHKERRQ(ierr);
+  if (!fgets(spath,sizeof spath,fp)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in shell command: %s",cmd);
+  ierr = PetscPClose(PETSC_COMM_SELF,fp,NULL);CHKERRQ(ierr);
+  ierr = RealpathPhonyFile(spath,rpath,len);CHKERRQ(ierr);
+  ierr = PetscStrcmp(rpath,buf,&match);CHKERRQ(ierr);
+  if (!match) {
+    ierr = PetscPrintf(PETSC_COMM_SELF,"$(realpath %s | head -c %d) %s != %s\n",path,(int)len-1,rpath,buf);CHKERRQ(ierr);
+  }
+  if (used) {ierr = PetscStrlen(buf,used);CHKERRQ(ierr);}
+  ierr = PetscFree(buf);CHKERRQ(ierr);
+  PetscFunctionReturn(0);
+}
+
+#undef __FUNCT__
+#define __FUNCT__ "Check"
+static PetscErrorCode Check(const char *path)
+{
+  PetscErrorCode ierr;
+  size_t         used;
+
+  PetscFunctionBegin;
+  ierr = CheckLen(path,PETSC_MAX_PATH_LEN,&used);CHKERRQ(ierr);
+  ierr = CheckLen(path,used-1,NULL);CHKERRQ(ierr);
+  PetscFunctionReturn(0);
+}
+
+#undef __FUNCT__
+#define __FUNCT__ "main"
+int main(int argc,char **argv)
+{
+  PetscErrorCode ierr;
+  char           user[256],buf[512];
+
+  PetscInitialize(&argc,&argv,(char*)0,help);
+  ierr = Check("~/file-name");CHKERRQ(ierr);
+  ierr = PetscGetUserName(user,256);CHKERRQ(ierr);
+  ierr = PetscSNPrintf(buf,sizeof buf,"~%s/file-name",user);CHKERRQ(ierr);
+  ierr = Check(buf);CHKERRQ(ierr);
+  ierr = Check("/dev/null");CHKERRQ(ierr);
+  ierr = Check("./this-dir");CHKERRQ(ierr);
+  ierr = Check("also-this-dir");CHKERRQ(ierr);
+  ierr = PetscFinalize();
+  return 0;
+}
+

src/sys/examples/tests/makefile

 FPPFLAGS        =
 LOCDIR          = src/sys/examples/tests/
 EXAMPLESC       = ex1.c ex2.c ex3.c ex7.c ex9.c ex10.c ex11.c ex12.c \
-                ex14.c ex15.c ex16.c ex18.c ex19.c ex20.c ex21.c \
+                ex13.c ex14.c ex15.c ex16.c ex18.c ex19.c ex20.c ex21.c \
                 ex22.c ex23.c ex24.c
 EXAMPLESF       = ex1f.F ex5f.F ex6f.F ex17f.F
 MANSEC          = Sys
 	-${CLINKER} -o ex12 ex12.o  ${PETSC_SYS_LIB}
 	${RM} -f ex12.o
 
+ex13: ex13.o chkopts
+	-${CLINKER} -o ex13 ex13.o  ${PETSC_SYS_LIB}
+	${RM} -f ex13.o
+
 ex14: ex14.o chkopts
 	-${CLINKER} -o ex14 ex14.o  ${PETSC_SYS_LIB}
 	${RM} -f ex14.o
 	   else echo "Error in PetscMemmove."; fi; \
 	   ${RM} -f ex10_1.tmp ex10_1.tmp
 
+runex13:
+	-@${MPIEXEC} -n 1 ./ex13 > ex13_1.tmp 2>&1;\
+	   ${DIFF} output/ex13_1.out ex13_1.tmp || printf "${PWD}\nPossible problem with with ex13_1, diffs above \n========================================="; \
+	   ${RM} ex13_1.tmp
+
 runex19:
 	-@${MPIEXEC} -n 1 ./ex19 > ex19_1.tmp 2>&1;   \
 	   if (${DIFF} output/ex19_1.out ex19_1.tmp) then true; \
 	   ${RM} -f ex23.tmp
 
 
-TESTEXAMPLES_C		       = ex19.PETSc runex19 ex19.rm \
+TESTEXAMPLES_C		       = ex13.PETSc runex13 ex13.rm ex19.PETSc runex19 ex19.rm \
                                  ex20.PETSc runex20 runex20_2 runex20_3 ex20.rm  ex21.PETSc ex21.rm \
                                  ex22.PETSc runex22 ex22.rm ex24.PETSc ex24.rm
 TESTEXAMPLES_C_X	       = ex1.PETSc runex1 ex1.rm ex2.PETSc runex2 ex2.rm ex3.PETSc runex3 ex3.rm

src/sys/examples/tests/output/ex13_1.out

-rank =   0
-rank =   0

src/sys/fileio/fpath.c

 #if defined(PETSC_HAVE_PWD_H)
 #include <pwd.h>
 #endif
-#include <ctype.h>
-#include <sys/stat.h>
-#if defined(PETSC_HAVE_UNISTD_H)
-#include <unistd.h>
-#endif
-#if defined(PETSC_HAVE_SYS_UTSNAME_H)
-#include <sys/utsname.h>
-#endif
-#include <fcntl.h>
-#if defined(PETSC_HAVE_SYS_SYSTEMINFO_H)
-#include <sys/systeminfo.h>
-#endif
-
-#if defined(PETSC_HAVE_PWD_H)
 
 #undef __FUNCT__
 #define __FUNCT__ "PetscGetFullPath"
 @*/
 PetscErrorCode  PetscGetFullPath(const char path[],char fullpath[],size_t flen)
 {
-  struct passwd  *pwde;
   PetscErrorCode ierr;
   size_t         ln;
   PetscBool      flg;
     ierr = PetscStrncmp("/tmp_mnt/",path,9,&flg);CHKERRQ(ierr);
     if (flg) {ierr = PetscStrncpy(fullpath,path + 8,flen);CHKERRQ(ierr);}
     else     {ierr = PetscStrncpy(fullpath,path,flen);CHKERRQ(ierr);}
+    fullpath[flen-1] = 0;
     PetscFunctionReturn(0);
   }
-  ierr = PetscGetWorkingDirectory(fullpath,flen);CHKERRQ(ierr);
-  ierr = PetscStrlen(fullpath,&ln);CHKERRQ(ierr);
-  ierr = PetscStrncat(fullpath,"/",flen - ln);CHKERRQ(ierr);
-  if (path[0] == '.' && path[1] == '/') {
-    ierr = PetscStrlen(fullpath,&ln);CHKERRQ(ierr);
-    ierr = PetscStrncat(fullpath,path+2,flen - ln - 1);CHKERRQ(ierr);
-  } else {
-    ierr = PetscStrlen(fullpath,&ln);CHKERRQ(ierr);
-    ierr = PetscStrncat(fullpath,path,flen - ln - 1);CHKERRQ(ierr);
-  }
 
+  ierr = PetscStrncpy(fullpath,path,flen);CHKERRQ(ierr);
+  fullpath[flen-1] = 0;
   /* Remove the various "special" forms (~username/ and ~/) */
   if (fullpath[0] == '~') {
-    char tmppath[PETSC_MAX_PATH_LEN];
+    char tmppath[PETSC_MAX_PATH_LEN],*rest;
     if (fullpath[1] == '/') {
-#if defined(PETSC_HAVE_GETPWUID)
-      pwde = getpwuid(geteuid());
-      if (!pwde) PetscFunctionReturn(0);
-      ierr = PetscStrcpy(tmppath,pwde->pw_dir);CHKERRQ(ierr);
-      ierr = PetscStrlen(tmppath,&ln);CHKERRQ(ierr);
-      if (tmppath[ln-1] != '/') {ierr = PetscStrcat(tmppath+ln-1,"/");CHKERRQ(ierr);}
-      ierr = PetscStrcat(tmppath,fullpath + 2);CHKERRQ(ierr);
-      ierr = PetscStrncpy(fullpath,tmppath,flen);CHKERRQ(ierr);
-#else
-      PetscFunctionReturn(0);
-#endif
+      ierr = PetscGetHomeDirectory(tmppath,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
+      rest = fullpath + 2;
     } else {
+#if defined(PETSC_HAVE_PWD_H)
+      struct passwd  *pwde;
       char *p,*name;
 
       /* Find username */
       name = fullpath + 1;
       p    = name;
       while (*p && *p != '/') p++;
-      *p   = 0; p++;
+      *p   = 0;
+      rest = p + 1;
       pwde = getpwnam(name);
       if (!pwde) PetscFunctionReturn(0);
 
       ierr = PetscStrcpy(tmppath,pwde->pw_dir);CHKERRQ(ierr);
-      ierr = PetscStrlen(tmppath,&ln);CHKERRQ(ierr);
-      if (tmppath[ln-1] != '/') {ierr = PetscStrcat(tmppath+ln-1,"/");CHKERRQ(ierr);}
-      ierr = PetscStrcat(tmppath,p);CHKERRQ(ierr);
-      ierr = PetscStrncpy(fullpath,tmppath,flen);CHKERRQ(ierr);
+#else
+      PetscFunctionReturn(0);
+#endif
     }
+    ierr = PetscStrlen(tmppath,&ln);CHKERRQ(ierr);
+    if (tmppath[ln-1] != '/') {ierr = PetscStrcat(tmppath+ln-1,"/");CHKERRQ(ierr);}
+    ierr = PetscStrcat(tmppath,rest);CHKERRQ(ierr);
+    ierr = PetscStrncpy(fullpath,tmppath,flen);CHKERRQ(ierr);
+    fullpath[flen-1] = 0;
+  } else {
+    ierr = PetscGetWorkingDirectory(fullpath,flen);CHKERRQ(ierr);
+    ierr = PetscStrlen(fullpath,&ln);CHKERRQ(ierr);
+    ierr = PetscStrncpy(fullpath+ln,"/",flen - ln);CHKERRQ(ierr);
+    fullpath[flen-1] = 0;
+    ierr = PetscStrlen(fullpath,&ln);CHKERRQ(ierr);
+    if (path[0] == '.' && path[1] == '/') {
+      ierr = PetscStrncat(fullpath,path+2,flen - ln - 1);CHKERRQ(ierr);
+    } else {
+      ierr = PetscStrncat(fullpath,path,flen - ln - 1);CHKERRQ(ierr);
+    }
+    fullpath[flen-1] = 0;
   }
+
   /* Remove the automounter part of the path */
   ierr = PetscStrncmp(fullpath,"/tmp_mnt/",9,&flg);CHKERRQ(ierr);
   if (flg) {
   /* We could try to handle things like the removal of .. etc */
   PetscFunctionReturn(0);
 }
-#elif defined(PETSC_HAVE__FULLPATH)
-#undef __FUNCT__
-#define __FUNCT__ "PetscGetFullPath"
-PetscErrorCode  PetscGetFullPath(const char path[],char fullpath[],size_t flen)
-{
-  PetscFunctionBegin;
-  _fullpath(fullpath,path,flen);
-  PetscFunctionReturn(0);
-}
-#else
-#undef __FUNCT__
-#define __FUNCT__ "PetscGetFullPath"
-PetscErrorCode  PetscGetFullPath(const char path[],char fullpath[],size_t flen)
-{
-  PetscErrorCode ierr;
-
-  PetscFunctionBegin;
-  ierr = PetscStrcpy(fullpath,path);CHKERRQ(ierr);
-  PetscFunctionReturn(0);
-}
-#endif

src/sys/fileio/ghome.c

       Code for manipulating files.
 */
 #include <petscsys.h>
-#if defined(PETSC_HAVE_PWD_H)
-#include <pwd.h>
-#endif
-#include <ctype.h>
-#include <sys/stat.h>
-#if defined(PETSC_HAVE_UNISTD_H)
-#include <unistd.h>
-#endif
-#if defined(PETSC_HAVE_SYS_UTSNAME_H)
-#include <sys/utsname.h>
-#endif
-#if defined(PETSC_HAVE_SYS_SYSTEMINFO_H)
-#include <sys/systeminfo.h>
-#endif
 
 #undef __FUNCT__
 #define __FUNCT__ "PetscGetHomeDirectory"
 PetscErrorCode  PetscGetHomeDirectory(char dir[],size_t maxlen)
 {
   PetscErrorCode ierr;
-  char           *d1 = 0;
-#if defined(PETSC_HAVE_GETPWUID)
-  struct passwd *pw = 0;
-#endif
+  const char     *d1;
 
   PetscFunctionBegin;
-#if defined(PETSC_HAVE_GETPWUID)
-  pw = getpwuid(getuid());
-  if (pw) d1 = pw->pw_dir;
-#else
   d1 = getenv("HOME");
-#endif
   if (d1) {
     ierr = PetscStrncpy(dir,d1,maxlen);CHKERRQ(ierr);
   } else if (maxlen > 0) dir[0] = 0;

src/sys/utils/fuser.c

       Code for manipulating files.
 */
 #include <petscsys.h>
-#if defined(PETSC_HAVE_PWD_H)
-#include <pwd.h>
-#endif
-#include <ctype.h>
-#include <sys/stat.h>
-#if defined(PETSC_HAVE_SYS_UTSNAME_H)
-#include <sys/utsname.h>
-#endif
 #if defined(PETSC_HAVE_WINDOWS_H)
 #include <windows.h>
 #endif
-#if defined(PETSC_HAVE_SYS_SYSTEMINFO_H)
-#include <sys/systeminfo.h>
-#endif
-#if defined(PETSC_HAVE_UNISTD_H)
-#include <unistd.h>
-#endif
-
 
 #if defined(PETSC_HAVE_GET_USER_NAME)
 #undef __FUNCT__
   PetscFunctionReturn(0);
 }
 
-#elif defined(PETSC_HAVE_PWD_H)
+#else
 #undef __FUNCT__
 #define __FUNCT__ "PetscGetUserName"
 /*@C
 @*/
 PetscErrorCode  PetscGetUserName(char name[],size_t nlen)
 {
-  struct passwd  *pw=0;
-  PetscErrorCode ierr;
-
-  PetscFunctionBegin;
-#if defined(PETSC_HAVE_GETPWUID)
-  pw = getpwuid(getuid());
-#endif
-  if (!pw) {ierr = PetscStrncpy(name,"Unknown",nlen);CHKERRQ(ierr);}
-  else     {ierr = PetscStrncpy(name,pw->pw_name,nlen);CHKERRQ(ierr);}
-  PetscFunctionReturn(0);
-}
-
-#else
-
-#undef __FUNCT__
-#define __FUNCT__ "PetscGetUserName"
-PetscErrorCode  PetscGetUserName(char *name,size_t nlen)
-{
+  const char     *user;
   PetscErrorCode ierr;
 
   PetscFunctionBegin;
-  ierr = PetscStrncpy(name,"Unknown",nlen);CHKERRQ(ierr);
+  user = getenv("USER");
+  if (!user) user = "Unknown";
+  ierr = PetscStrncpy(name,user,nlen);CHKERRQ(ierr);
   PetscFunctionReturn(0);
 }
-#endif /* !PETSC_HAVE_PWD_H */
-
+#endif