Bruce Momjian wrote:

Andrew Dunstan wrote:


I wanted to keep a solution that was as native to the OS as possible,
but because we can't do that on Win32 and few people like the unix
system call to 'rm', it is time to clean it up.

One question --- why is there a sleep loop needed for unlink in your
patch?






We will just be calling the existing pgunlink() (which has a sleep) in the Windows cases, so this question becomes moot.



Great. Thanks. Sorry I delayed addressing this for so long.



Please check the enclosed patch to see if it does what you want.

Should we look at replacing cp/copy in 7.6?




probably. Put it as a possible TODO maybe.

cheers

andrew


Index: src/Makefile.global.in
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/Makefile.global.in,v
retrieving revision 1.189
diff -c -r1.189 Makefile.global.in
*** src/Makefile.global.in	2 Jun 2004 21:05:52 -0000	1.189
--- src/Makefile.global.in	28 Jul 2004 17:29:31 -0000
***************
*** 340,346 ****
  #
  # substitute implementations of the C library
  
! LIBOBJS = @LIBOBJS@ exec.o noblock.o path.o pipe.o pgsleep.o pgstrcasecmp.o sprompt.o thread.o
  
  ifneq (,$(LIBOBJS))
  LIBS := -lpgport $(LIBS)
--- 340,346 ----
  #
  # substitute implementations of the C library
  
! LIBOBJS = @LIBOBJS@ dirmod.o exec.o noblock.o path.o pipe.o pgsleep.o pgstrcasecmp.o sprompt.o thread.o
  
  ifneq (,$(LIBOBJS))
  LIBS := -lpgport $(LIBS)
Index: src/backend/commands/dbcommands.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/commands/dbcommands.c,v
retrieving revision 1.137
diff -c -r1.137 dbcommands.c
*** src/backend/commands/dbcommands.c	25 Jun 2004 21:55:53 -0000	1.137
--- src/backend/commands/dbcommands.c	28 Jul 2004 17:29:32 -0000
***************
*** 915,921 ****
  	Relation rel;
  	HeapScanDesc scan;
  	HeapTuple tuple;
- 	char buf[MAXPGPATH + 100];
  
  	rel = heap_openr(TableSpaceRelationName, AccessShareLock);
  	scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
--- 915,920 ----
***************
*** 938,954 ****
  			continue;
  		}
  
! #ifndef WIN32
! 		snprintf(buf, sizeof(buf), "rm -rf '%s'", dstpath);
! #else
! 		snprintf(buf, sizeof(buf), "rmdir /s /q \"%s\"", dstpath);
! #endif
! 		if (system(buf) != 0)
  		{
  			ereport(WARNING,
  				(errmsg("could not remove database directory \"%s\"",
  						dstpath),
- 				 errdetail("Failing system command was: %s", buf),
  				 errhint("Look in the postmaster's stderr log for more information.")));
  		}
  
--- 937,947 ----
  			continue;
  		}
  
! 		if (! rmtree(dstpath,true) )
  		{
  			ereport(WARNING,
  				(errmsg("could not remove database directory \"%s\"",
  						dstpath),
  				 errhint("Look in the postmaster's stderr log for more information.")));
  		}
  
Index: src/bin/initdb/Makefile
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/initdb/Makefile,v
retrieving revision 1.41
diff -c -r1.41 Makefile
*** src/bin/initdb/Makefile	24 May 2004 01:01:37 -0000	1.41
--- src/bin/initdb/Makefile	28 Jul 2004 17:29:32 -0000
***************
*** 15,21 ****
  
  override CPPFLAGS := -DFRONTEND -I$(libpq_srcdir) $(CPPFLAGS)
  
! OBJS=	initdb.o exec.o
  
  all: submake-libpq submake-libpgport initdb
  
--- 15,21 ----
  
  override CPPFLAGS := -DFRONTEND -I$(libpq_srcdir) $(CPPFLAGS)
  
! OBJS=	initdb.o exec.o dirmod.o
  
  all: submake-libpq submake-libpgport initdb
  
***************
*** 25,30 ****
--- 25,33 ----
  exec.c: % : $(top_srcdir)/src/port/%
  	rm -f $@ && $(LN_S) $< .
  
+ dirmod.c: % : $(top_srcdir)/src/port/%
+ 	rm -f $@ && $(LN_S) $< .
+ 
  install: all installdirs
  	$(INSTALL_PROGRAM) initdb$(X) $(DESTDIR)$(bindir)/initdb$(X)
  
Index: src/bin/initdb/initdb.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/initdb/initdb.c,v
retrieving revision 1.44
diff -c -r1.44 initdb.c
*** src/bin/initdb/initdb.c	19 Jul 2004 02:47:12 -0000	1.44
--- src/bin/initdb/initdb.c	28 Jul 2004 17:29:32 -0000
***************
*** 135,141 ****
  
  static void *xmalloc(size_t size);
  static char *xstrdup(const char *s);
- static bool rmtree(char *path, bool rmtopdir);
  static char **replace_token(char **lines, char *token, char *replacement);
  static char **readfile(char *path);
  static void writefile(char *path, char **lines);
--- 135,140 ----
***************
*** 241,270 ****
  }
  
  /*
-  * delete a directory tree recursively
-  * assumes path points to a valid directory
-  * deletes everything under path
-  * if rmtopdir is true deletes the directory too
-  */
- static bool
- rmtree(char *path, bool rmtopdir)
- {
- 	char		buf[MAXPGPATH + 64];
- 
- #ifndef WIN32
- 	/* doesn't handle .* files, but we don't make any... */
- 	snprintf(buf, sizeof(buf), "rm -rf \"%s\"%s", path,
- 			 rmtopdir ? "" : "/*");
- #else
- 	snprintf(buf, sizeof(buf), "%s /s /q \"%s\"",
- 			 rmtopdir ? "rmdir" : "del", path);
- #endif
- 
- 	return !system(buf);
- }
- 
- 
- /*
   * make a copy of the array of lines, with token replaced by replacement
   * the first time it occurs on each line.
   *
--- 240,245 ----
Index: src/include/port.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/port.h,v
retrieving revision 1.45
diff -c -r1.45 port.h
*** src/include/port.h	23 Jul 2004 01:58:36 -0000	1.45
--- src/include/port.h	28 Jul 2004 17:29:32 -0000
***************
*** 148,153 ****
--- 148,155 ----
  #define unlink(path)		pgunlink(path)
  #endif
  
+ extern bool rmtree(char *path, bool rmtopdir);
+ 
  #ifdef WIN32
  
  /* open() replacement to allow delete of held files */
Index: src/port/dirmod.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/port/dirmod.c,v
retrieving revision 1.12
diff -c -r1.12 dirmod.c
*** src/port/dirmod.c	26 Feb 2004 02:59:26 -0000	1.12
--- src/port/dirmod.c	28 Jul 2004 17:29:32 -0000
***************
*** 15,30 ****
   *-------------------------------------------------------------------------
   */
  
- #ifndef TEST_VERSION
- 
- #if defined(WIN32) || defined(__CYGWIN__)
- 
- 
  #ifndef FRONTEND
  #include "postgres.h"
  #else
  #include "postgres_fe.h"
  #endif
  #include "miscadmin.h"
  
  #undef rename
--- 15,37 ----
   *-------------------------------------------------------------------------
   */
  
  #ifndef FRONTEND
  #include "postgres.h"
  #else
  #include "postgres_fe.h"
  #endif
+ 
+ #include <unistd.h>
+ #include <dirent.h>
+ #include <sys/stat.h>
+ 
+ #define _(x) gettext((x))
+ 
+ #ifndef TEST_VERSION
+ 
+ #if defined(WIN32) || defined(__CYGWIN__)
+ 
+ 
  #include "miscadmin.h"
  
  #undef rename
***************
*** 105,110 ****
--- 112,277 ----
  
  #endif
  
+ #if defined(WIN32) || defined(__CYGWIN__)
+ #define rmt_unlink(path) pgunlink(path)
+ #else
+ #define rmt_unlink(path) unlink(path)
+ #endif
+ 
+ #ifdef FRONTEND
+ 
+ static void *
+ xmalloc(size_t size)
+ {
+     void       *result;
+ 
+     result = malloc(size);
+     if (!result)
+     {
+         fprintf(stderr, _("out of memory\n"));
+         exit(1);
+     }
+     return result;
+ }
+ 
+ static char *
+ xstrdup(const char *s)
+ {
+     char       *result;
+ 
+     result = strdup(s);
+     if (!result)
+     {
+         fprintf(stderr, _("out of memory\n"));
+         exit(1);
+     }
+     return result;
+ }
+ 
+ #define xfree(n) free(n)
+ 
+ #else
+ 
+ /* on the backend, use palloc and friends */
+ 
+ #define xmalloc(n) palloc(n)
+ #define xstrdup(n) pstrdup (n)
+ #define xfree(n) pfree(n)
+ 
+ #endif
+ 
+ /*
+  * deallocate memory used for filenames
+  */
+ 
+ static void
+ rmt_cleanup(char ** filenames)
+ {
+ 	char ** fn;
+ 
+ 	for (fn = filenames; *fn; fn++)
+ 		xfree(*fn);
+ 
+ 	xfree(filenames);
+ }
+ 
+ 
+ 
+ /*
+  * delete a directory tree recursively
+  * assumes path points to a valid directory
+  * deletes everything under path
+  * if rmtopdir is true deletes the directory too
+  *
+  */
+ 
+ bool
+ rmtree(char *path, bool rmtopdir)
+ {
+ 	char		filepath[MAXPGPATH];
+ 	DIR		   *dir;
+ 	struct dirent *file;
+ 	char	  **filenames;
+ 	char	  **filename;
+ 	int			numnames = 0;
+ 	struct stat statbuf;
+ 
+ 	/*
+ 	 * we copy all the names out of the directory before we start
+ 	 * modifying it.
+ 	 *
+ 	 */
+ 
+ 	dir = opendir(path);
+ 	if (dir == NULL)
+ 		return false;
+ 
+ 	while ((file = readdir(dir)) != NULL)
+ 	{
+ 		if (strcmp(file->d_name, ".") != 0 && strcmp(file->d_name, "..") != 0)
+ 			numnames++;
+ 	}
+ 
+ 	rewinddir(dir);
+ 
+ 	filenames = xmalloc((numnames + 2) * sizeof(char *));
+ 	numnames = 0;
+ 
+ 	while ((file = readdir(dir)) != NULL)
+ 	{
+ 		if (strcmp(file->d_name, ".") != 0 && strcmp(file->d_name, "..") != 0)
+ 			filenames[numnames++] = xstrdup(file->d_name);
+ 	}
+ 
+ 	filenames[numnames] = NULL;
+ 
+ 	closedir(dir);
+ 
+ 	/* now we have the names we can start removing things */
+ 
+ 	for (filename = filenames; *filename; filename++)
+ 	{
+ 		snprintf(filepath, MAXPGPATH, "%s/%s", path, *filename);
+ 
+ 		if (stat(filepath, &statbuf) != 0)
+ 		{
+ 			rmt_cleanup(filenames);
+ 			return false;
+ 		}
+ 
+ 		if (S_ISDIR(statbuf.st_mode))
+ 		{
+ 			/* call ourselves recursively for a directory */
+ 			if (!rmtree(filepath, true))
+ 			{
+ 				rmt_cleanup(filenames);
+ 				return false;
+ 			}
+ 		}
+ 		else
+ 		{
+ 			if (rmt_unlink(filepath) != 0)
+ 			{
+ 				rmt_cleanup(filenames);
+ 				return false;
+ 			}
+ 		}
+ 	}
+ 
+ 	if (rmtopdir)
+ 	{
+ 		if (rmdir(path) != 0)
+ 		{
+ 			rmt_cleanup(filenames);
+ 			return false;
+ 		}
+ 	}
+ 
+ 	rmt_cleanup(filenames);
+ 	return true;
+ }
+ 
+ 
  #else
  
  
---------------------------(end of broadcast)---------------------------
TIP 8: explain analyze is your friend

Reply via email to