$NetBSD: patch-bd,v 1.5 2010/07/13 10:59:43 sbd Exp $

Incorporate str3510.patch from
http://www.cups.org/str.php?L3510
"cups overwrites files as root in a directory with non-root write permission"

--- cups/file.c.orig	2009-05-14 21:18:35.000000000 +0000
+++ cups/file.c
@@ -59,6 +59,7 @@
  */
 
 #include "file-private.h"
+#include <sys/stat.h>
 
 
 /*
@@ -69,6 +70,7 @@
 static ssize_t	cups_compress(cups_file_t *fp, const char *buf, size_t bytes);
 #endif /* HAVE_LIBZ */
 static ssize_t	cups_fill(cups_file_t *fp);
+static int cups_open(const char *filename, int mode);
 static ssize_t	cups_read(cups_file_t *fp, char *buf, size_t bytes);
 static ssize_t	cups_write(cups_file_t *fp, const char *buf, size_t bytes);
 
@@ -827,7 +829,8 @@ cupsFileOpen(const char *filename,	/* I 
   switch (*mode)
   {
     case 'a' : /* Append file */
-        fd = open(filename, O_RDWR | O_CREAT | O_APPEND | O_LARGEFILE | O_BINARY, 0666);
+        fd = cups_open(filename,
+	O_RDWR | O_CREAT | O_APPEND | O_LARGEFILE | O_BINARY);
         break;
 
     case 'r' : /* Read file */
@@ -835,7 +838,17 @@ cupsFileOpen(const char *filename,	/* I 
 	break;
 
     case 'w' : /* Write file */
-        fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT | O_LARGEFILE | O_BINARY, 0666);
+        fd = cups_open(filename, O_WRONLY | O_LARGEFILE | O_BINARY);
+ if (fd < 0 && errno == ENOENT)
+ {
+   fd = cups_open(filename,
+		  O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE | O_BINARY);
+   if (fd < 0 && errno == EEXIST)
+     fd = cups_open(filename, O_WRONLY | O_LARGEFILE | O_BINARY);
+ }
+
+ if (fd >= 0)
+   ftruncate(fd, 0);
         break;
 
     case 's' : /* Read/write socket */
@@ -2207,6 +2220,88 @@ cups_fill(cups_file_t *fp)		/* I - CUPS 
   return (bytes);
 }
 
+/*
+ * 'cups_open()' - Safely open a file for writing.
+ *
+ * We don't allow appending to directories or files that are hard-linked or
+ * symlinked.
+ */
+
+static int /* O - File descriptor or -1 otherwise */
+cups_open(const char *filename, /* I - Filename */
+   int        mode) /* I - Open mode */
+{
+  int fd; /* File descriptor */
+  struct stat fileinfo; /* File information */
+#ifndef WIN32
+  struct stat linkinfo; /* Link information */
+#endif /* !WIN32 */
+
+
+ /*
+  * Open the file...
+  */
+
+  if ((fd = open(filename, mode, 0666)) < 0)
+    return (-1);
+
+ /*
+  * Then verify that the file descriptor doesn't point to a directory or hard-
+  * linked file.
+  */
+
+  if (fstat(fd, &fileinfo))
+  {
+    close(fd);
+    return (-1);
+  }
+
+  if (fileinfo.st_nlink != 1)
+  {
+    close(fd);
+    errno = EPERM;
+    return (-1);
+  }
+
+  if (S_ISDIR(fileinfo.st_mode))
+  {
+    close(fd);
+    errno = EISDIR;
+    return (-1);
+  }
+
+#ifndef WIN32
+ /*
+  * Then use lstat to determine whether the filename is a symlink...
+  */
+
+  if (lstat(filename, &linkinfo))
+  {
+    close(fd);
+    return (-1);
+  }
+
+  if (S_ISLNK(linkinfo.st_mode) ||
+      fileinfo.st_dev != linkinfo.st_dev ||
+      fileinfo.st_ino != linkinfo.st_ino ||
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__DragonFly__)
+      fileinfo.st_gen != linkinfo.st_gen ||
+#endif
+      fileinfo.st_nlink != linkinfo.st_nlink ||
+      fileinfo.st_mode != linkinfo.st_mode)
+  {
+   /*
+    * Yes, don't allow!
+    */
+
+    close(fd);
+    errno = EPERM;
+    return (-1);
+  }
+#endif /* !WIN32 */
+
+  return (fd);
+}
 
 /*
  * 'cups_read()' - Read from a file descriptor.
