From 5f644ea699ae17dcb50a82122a2172154247f267 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Sat, 23 Feb 2002 21:46:03 +0000
Subject: [PATCH] Add fstat / S_ISDIR checks to make sure we're not trying to
 use a directory for COPY TO/FROM.

Brent Verner
---
 src/backend/commands/copy.c | 18 ++++++++++++++++--
 src/bin/psql/copy.c         | 15 +++++++++++++--
 2 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index f42b865687..59b94d4d33 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.145 2002/02/12 21:25:41 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.146 2002/02/23 21:46:02 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -326,12 +326,20 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
 		}
 		else
 		{
+      struct stat st;
 			fp = AllocateFile(filename, PG_BINARY_R);
-			if (fp == NULL)
+			
+      if (fp == NULL)
 				elog(ERROR, "COPY command, running in backend with "
 					 "effective uid %d, could not open file '%s' for "
 					 "reading.  Errno = %s (%d).",
 					 (int) geteuid(), filename, strerror(errno), errno);
+      
+      fstat(fileno(fp),&st);
+      if( S_ISDIR(st.st_mode) ){
+        fclose(fp);
+        elog(ERROR,"COPY: %s is a directory.",filename);
+      }
 		}
 		CopyFrom(rel, binary, oids, fp, delim, null_print);
 	}
@@ -360,6 +368,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
 		else
 		{
 			mode_t		oumask; /* Pre-existing umask value */
+      struct stat st;
 
 			/*
 			 * Prevent write to relative path ... too easy to shoot
@@ -378,6 +387,11 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
 					 "effective uid %d, could not open file '%s' for "
 					 "writing.  Errno = %s (%d).",
 					 (int) geteuid(), filename, strerror(errno), errno);
+      fstat(fileno(fp),&st);
+      if( S_ISDIR(st.st_mode) ){
+        fclose(fp);
+        elog(ERROR,"COPY: %s is a directory.",filename);
+      }
 		}
 		CopyTo(rel, binary, oids, fp, delim, null_print);
 	}
diff --git a/src/bin/psql/copy.c b/src/bin/psql/copy.c
index 0f5cb1e8d8..e374e698eb 100644
--- a/src/bin/psql/copy.c
+++ b/src/bin/psql/copy.c
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/copy.c,v 1.19 2001/06/02 18:25:18 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/copy.c,v 1.20 2002/02/23 21:46:03 momjian Exp $
  */
 #include "postgres_fe.h"
 #include "copy.h"
@@ -11,6 +11,7 @@
 #include <errno.h>
 #include <assert.h>
 #include <signal.h>
+#include <sys/stat.h>
 #ifndef WIN32
 #include <unistd.h>				/* for isatty */
 #else
@@ -233,6 +234,7 @@ do_copy(const char *args)
 	struct copy_options *options;
 	PGresult   *result;
 	bool		success;
+  struct stat st;
 
 	/* parse options */
 	options = parse_slash_copy(args);
@@ -292,7 +294,16 @@ do_copy(const char *args)
 		free_copy_options(options);
 		return false;
 	}
-
+  /* make sure the specified file is not a directory */
+  fstat(fileno(copystream),&st);
+  if( S_ISDIR(st.st_mode) ){
+    fclose(copystream);
+		psql_error("%s: cannot COPY TO/FROM a directory\n",
+				   options->file);
+		free_copy_options(options);
+		return false;
+  }
+  
 	result = PSQLexec(query);
 
 	switch (PQresultStatus(result))
-- 
2.24.1