Alvaro Herrera wrote:

> > In addition to that, it might be a good idea to do what the comment in the
> > code suggests, namely do more than zero checking on each file name to try
> > to make sure it looks like a stats temp file name that we'd generate
> > before we delete it.  The ownership/permissions test wouldn't be enough
> > to prevent you from pointing at, say, ~postgres and thereby losing some
> > files you'd rather not.
> 
> This seems pretty simple to do; see second attachment.  (It would delete
> files named, "db_1234.tmpfoobar", that is, valid names with suffixes,
> but I can't see that being a problem).  (I haven't really tested this
> part at all.)

Here's the second attachment.

-- 
Álvaro Herrera                http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
*** a/src/backend/postmaster/pgstat.c
--- b/src/backend/postmaster/pgstat.c
***************
*** 562,576 **** pgstat_reset_remove_files(const char *directory)
  	struct dirent *entry;
  	char		fname[MAXPGPATH];
  
! 	dir = AllocateDir(pgstat_stat_directory);
! 	while ((entry = ReadDir(dir, pgstat_stat_directory)) != NULL)
  	{
  		if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
  			continue;
  
! 		/* XXX should we try to ignore files other than the ones we write? */
  
! 		snprintf(fname, MAXPGPATH, "%s/%s", pgstat_stat_directory,
  				 entry->d_name);
  		unlink(fname);
  	}
--- 562,589 ----
  	struct dirent *entry;
  	char		fname[MAXPGPATH];
  
! 	dir = AllocateDir(directory);
! 	while ((entry = ReadDir(dir, directory)) != NULL)
  	{
+ 		Oid		tmp_oid;
+ 		char	tmp_type[5];
+ 		int		nitems;
+ 
  		if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
  			continue;
  
! 		/*
! 		 * Skip directory entries that don't match the file names we write.
! 		 * See get_dbstat_filename for the pattern.
! 		 */
! 		nitems = sscanf(fname, "db_%u.%4s", &tmp_oid, tmp_type);
! 		if (nitems != 2)
! 			continue;
! 		if (strncmp(tmp_type, "tmp", 4) != 0 &&
! 			strncmp(tmp_type, "stat", 4) != 0)
! 			continue;
  
! 		snprintf(fname, MAXPGPATH, "%s/%s", directory,
  				 entry->d_name);
  		unlink(fname);
  	}
***************
*** 3627,3632 **** get_dbstat_filename(bool permanent, bool tempname, Oid databaseid,
--- 3640,3646 ----
  {
  	int			printed;
  
+ 	/* NB -- pgstat_reset_remove_files knows about the pattern this uses */
  	printed = snprintf(filename, len, "%s/db_%u.%s",
  					   permanent ? PGSTAT_STAT_PERMANENT_DIRECTORY :
  					   pgstat_stat_directory,
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to