Index: src/backend/postmaster/pgstat.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/postmaster/pgstat.c,v
retrieving revision 1.187
diff -c -r1.187 pgstat.c
*** src/backend/postmaster/pgstat.c	1 Jan 2009 17:23:46 -0000	1.187
--- src/backend/postmaster/pgstat.c	21 Apr 2009 06:32:54 -0000
***************
*** 111,116 ****
--- 111,117 ----
  bool		pgstat_track_counts = false;
  int			pgstat_track_functions = TRACK_FUNC_OFF;
  int			pgstat_track_activity_query_size = 1024;
+ char	   *pgstat_temp_directory;
  
  /* ----------
   * Built from GUC parameter
***************
*** 2953,2958 ****
--- 2954,2964 ----
  	const char *statfile = permanent?PGSTAT_STAT_PERMANENT_FILENAME:pgstat_stat_filename;
  
  	/*
+ 	 * Create temporary statistics directory if not present; ignore errors
+ 	 */
+ 	CreateDir(pgstat_temp_directory, 0700);
+ 
+ 	/*
  	 * Open the statistics temp file to write out the current values.
  	 */
  	fpout = AllocateFile(tmpfile, PG_BINARY_W);
Index: src/backend/storage/file/fd.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/storage/file/fd.c,v
retrieving revision 1.148
diff -c -r1.148 fd.c
*** src/backend/storage/file/fd.c	4 Mar 2009 09:12:49 -0000	1.148
--- src/backend/storage/file/fd.c	21 Apr 2009 06:32:54 -0000
***************
*** 1875,1877 ****
--- 1875,2084 ----
  
  	FreeDir(temp_dir);
  }
+ 
+ /* source stolen from FreeBSD /src/bin/mkdir/mkdir.c and adapted */
+ 
+ /*
+  * this tries to build all the elements of a path to a directory a la mkdir -p
+  * we assume the path is in canonical form, i.e. uses / as the separator
+  * we also assume it isn't null.
+  *
+  * note that on failure, the path arg has been modified to show the particular
+  * directory level we had problems with.
+  */
+ static int
+ mkdir_p(char *path, mode_t omode)
+ {
+ 	struct stat sb;
+ 	mode_t		numask,
+ 				oumask;
+ 	int			first,
+ 				last,
+ 				retval;
+ 	char	   *p;
+ 
+ 	p = path;
+ 	oumask = 0;
+ 	retval = 0;
+ 
+ #ifdef WIN32
+ 	/* skip network and drive specifiers for win32 */
+ 	if (strlen(p) >= 2)
+ 	{
+ 		if (p[0] == '/' && p[1] == '/')
+ 		{
+ 			/* network drive */
+ 			p = strstr(p + 2, "/");
+ 			if (p == NULL)
+ 				return 1;
+ 		}
+ 		else if (p[1] == ':' &&
+ 				 ((p[0] >= 'a' && p[0] <= 'z') ||
+ 				  (p[0] >= 'A' && p[0] <= 'Z')))
+ 		{
+ 			/* local drive */
+ 			p += 2;
+ 		}
+ 	}
+ #endif
+ 
+ 	if (p[0] == '/')			/* Skip leading '/'. */
+ 		++p;
+ 	for (first = 1, last = 0; !last; ++p)
+ 	{
+ 		if (p[0] == '\0')
+ 			last = 1;
+ 		else if (p[0] != '/')
+ 			continue;
+ 		*p = '\0';
+ 		if (!last && p[1] == '\0')
+ 			last = 1;
+ 		if (first)
+ 		{
+ 			/*
+ 			 * POSIX 1003.2: For each dir operand that does not name an
+ 			 * existing directory, effects equivalent to those caused by the
+ 			 * following command shall occcur:
+ 			 *
+ 			 * mkdir -p -m $(umask -S),u+wx $(dirname dir) && mkdir [-m mode]
+ 			 * dir
+ 			 *
+ 			 * We change the user's umask and then restore it, instead of
+ 			 * doing chmod's.
+ 			 */
+ 			oumask = umask(0);
+ 			numask = oumask & ~(S_IWUSR | S_IXUSR);
+ 			(void) umask(numask);
+ 			first = 0;
+ 		}
+ 		if (last)
+ 			(void) umask(oumask);
+ 
+ 		/* check for pre-existing directory; ok if it's a parent */
+ 		if (stat(path, &sb) == 0)
+ 		{
+ 			if (!S_ISDIR(sb.st_mode))
+ 			{
+ 				if (last)
+ 					errno = EEXIST;
+ 				else
+ 					errno = ENOTDIR;
+ 				retval = 1;
+ 				break;
+ 			}
+ 		}
+ 		else if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0)
+ 		{
+ 			retval = 1;
+ 			break;
+ 		}
+ 		if (!last)
+ 			*p = '/';
+ 	}
+ 	if (!first && !last)
+ 		(void) umask(oumask);
+ 	return retval;
+ }
+ 
+ /* Create the specified directory if not present; ignore errors */
+ void
+ CreateDir(char *pathname, mode_t mode)
+ {
+ 	struct stat st;
+ 	char		path[MAXPGPATH];
+ 	char		orig_wd[MAXPGPATH];
+ 	char		lnk_buf[MAXPGPATH];
+ 
+ 	/* Create the specified directory if not present */
+ 	if (lstat(pathname, &st) < 0)
+ 	{
+ 		mkdir_p(pathname, mode);
+ 		return;
+ 	}
+ 
+ 	/* Do nothing if the specified directory is present */
+ 	if (S_ISDIR(st.st_mode))
+ 		return;
+ 
+ 	/*
+ 	 * If the specified 'pathname' indicates the symlink, we pursue
+ 	 * the chain of it and create the referenced directory.
+ 	 */
+ #ifdef HAVE_READLINK
+ 	StrNCpy(path, pathname, MAXPGPATH);
+ 
+ 	/*
+ 	 * To resolve a symlink properly, we have to chdir into its directory and
+ 	 * then chdir to where the symlink points; otherwise we may fail to
+ 	 * resolve relative links correctly (consider cases involving mount
+ 	 * points, for example).  After following the final symlink, we use
+ 	 * getcwd() to figure out where the heck we're at.
+ 	 *
+ 	 * One might think we could skip all this if path doesn't point to a
+ 	 * symlink to start with, but that's wrong.  We also want to get rid of
+ 	 * any directory symlinks that are present in the given path. We expect
+ 	 * getcwd() to give us an accurate, symlink-free path.
+ 	 */
+ 	if (!getcwd(orig_wd, MAXPGPATH))
+ 	{
+ 		ereport(LOG,
+ 				(errmsg("could not identify current directory: %m")));
+ 		return;
+ 	}
+ 
+ 	for (;;)
+ 	{
+ 		char	   *lsep;
+ 		char	   *fname;
+ 		int			rllen;
+ 
+ 		/*
+ 		 * Create the referenced directory when the chain of symlinks
+ 		 * can not be pursued any longer.
+ 		 */
+ 		if (lstat(path, &st) < 0 || !S_ISLNK(st.st_mode))
+ 		{
+ 			mkdir_p(path, mode);
+ 			break;
+ 		}
+ 
+ 		lsep = last_dir_separator(path);
+ 		if (lsep)
+ 		{
+ 			*lsep = '\0';
+ 
+ 			if (chdir(path) == -1)
+ 			{
+ 				ereport(LOG,
+ 						(errmsg("could not change directory to \"%s\": %m",
+ 								path)));
+ 				break;
+ 			}
+ 
+ 			fname = lsep + 1;
+ 		}
+ 		else
+ 			fname = path;
+ 
+ 		rllen = readlink(fname, lnk_buf, MAXPGPATH);
+ 		if (rllen < 0 || rllen >= MAXPGPATH)
+ 		{
+ 			ereport(LOG,
+ 					(errmsg("could not read symbolic link \"%s\": %m",
+ 							fname)));
+ 			break;
+ 		}
+ 		
+ 		lnk_buf[rllen] = '\0';
+ 		StrNCpy(path, lnk_buf, MAXPGPATH);
+ 	}
+ 
+ 	if (chdir(orig_wd) == -1)
+ 	{
+ 		ereport(LOG,
+ 				(errmsg("could not change directory to \"%s\": %m"),
+ 				 orig_wd));
+ 		return;
+ 	}
+ #endif   /* HAVE_READLINK */
+ }
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/misc/guc.c,v
retrieving revision 1.502
diff -c -r1.502 guc.c
*** src/backend/utils/misc/guc.c	7 Apr 2009 23:27:34 -0000	1.502
--- src/backend/utils/misc/guc.c	21 Apr 2009 06:32:55 -0000
***************
*** 375,382 ****
  char	   *IdentFileName;
  char	   *external_pid_file;
  
- char	   *pgstat_temp_directory;
- 
  int			tcp_keepalives_idle;
  int			tcp_keepalives_interval;
  int			tcp_keepalives_count;
--- 375,380 ----
Index: src/include/pgstat.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/pgstat.h,v
retrieving revision 1.82
diff -c -r1.82 pgstat.h
*** src/include/pgstat.h	4 Jan 2009 22:19:59 -0000	1.82
--- src/include/pgstat.h	21 Apr 2009 06:32:55 -0000
***************
*** 593,598 ****
--- 593,599 ----
  extern bool pgstat_track_counts;
  extern int	pgstat_track_functions;
  extern PGDLLIMPORT int	pgstat_track_activity_query_size;
+ extern PGDLLIMPORT char *pgstat_temp_directory;
  extern char *pgstat_stat_tmpname;
  extern char *pgstat_stat_filename;
  
Index: src/include/storage/fd.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/storage/fd.h,v
retrieving revision 1.64
diff -c -r1.64 fd.h
*** src/include/storage/fd.h	12 Jan 2009 05:10:45 -0000	1.64
--- src/include/storage/fd.h	21 Apr 2009 06:32:55 -0000
***************
*** 98,103 ****
--- 98,105 ----
  extern int	pg_fsync_writethrough(int fd);
  extern int	pg_fdatasync(int fd);
  
+ extern void CreateDir(char *pathname, mode_t mode);
+ 
  /* Filename components for OpenTemporaryFile */
  #define PG_TEMP_FILES_DIR "pgsql_tmp"
  #define PG_TEMP_FILE_PREFIX "pgsql_tmp"
