Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 9 Aug 2013 17:24:23 +0000 (UTC)
From:      Jilles Tjoelker <jilles@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r254151 - in head: include lib/libc/stdio tools/regression/lib/libc/stdio
Message-ID:  <201308091724.r79HONBh039632@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jilles
Date: Fri Aug  9 17:24:23 2013
New Revision: 254151
URL: http://svnweb.freebsd.org/changeset/base/254151

Log:
  Add mkostemp() and mkostemps().
  
  These are like mkstemp() and mkstemps() but allow passing open(2) flags like
  O_CLOEXEC.

Added:
  head/tools/regression/lib/libc/stdio/test-mkostemp.c   (contents, props changed)
Modified:
  head/include/stdlib.h
  head/lib/libc/stdio/Makefile.inc
  head/lib/libc/stdio/Symbol.map
  head/lib/libc/stdio/mktemp.3
  head/lib/libc/stdio/mktemp.c
  head/tools/regression/lib/libc/stdio/Makefile

Modified: head/include/stdlib.h
==============================================================================
--- head/include/stdlib.h	Fri Aug  9 16:43:50 2013	(r254150)
+++ head/include/stdlib.h	Fri Aug  9 17:24:23 2013	(r254151)
@@ -282,6 +282,8 @@ const char *
 int	 heapsort(void *, size_t, size_t, int (*)(const void *, const void *));
 int	 l64a_r(long, char *, int);
 int	 mergesort(void *, size_t, size_t, int (*)(const void *, const void *));
+int	 mkostemp(char *, int);
+int	 mkostemps(char *, int, int);
 void	 qsort_r(void *, size_t, size_t, void *,
 	    int (*)(void *, const void *, const void *));
 int	 radixsort(const unsigned char **, int, const unsigned char *,

Modified: head/lib/libc/stdio/Makefile.inc
==============================================================================
--- head/lib/libc/stdio/Makefile.inc	Fri Aug  9 16:43:50 2013	(r254150)
+++ head/lib/libc/stdio/Makefile.inc	Fri Aug  9 17:24:23 2013	(r254151)
@@ -60,7 +60,8 @@ MLINKS+=getc.3 fgetc.3 getc.3 getc_unloc
 	getc.3 getchar_unlocked.3 getc.3 getw.3
 MLINKS+=getline.3 getdelim.3
 MLINKS+=getwc.3 fgetwc.3 getwc.3 getwchar.3
-MLINKS+=mktemp.3 mkdtemp.3 mktemp.3 mkstemp.3 mktemp.3 mkstemps.3
+MLINKS+=mktemp.3 mkdtemp.3 mktemp.3 mkstemp.3 mktemp.3 mkstemps.3 \
+	mktemp.3 mkostemp.3 mktemp.3 mkostemps.3
 MLINKS+=open_memstream.3 open_wmemstream.3
 MLINKS+=printf.3 asprintf.3 printf.3 dprintf.3 printf.3 fprintf.3 \
 	printf.3 snprintf.3 printf.3 sprintf.3 \

Modified: head/lib/libc/stdio/Symbol.map
==============================================================================
--- head/lib/libc/stdio/Symbol.map	Fri Aug  9 16:43:50 2013	(r254150)
+++ head/lib/libc/stdio/Symbol.map	Fri Aug  9 17:24:23 2013	(r254151)
@@ -158,6 +158,8 @@ FBSD_1.3 {
 	fmemopen;
 	open_memstream;
 	open_wmemstream;
+	mkostemp;
+	mkostemps;
 };
 
 FBSDprivate_1.0 {

Modified: head/lib/libc/stdio/mktemp.3
==============================================================================
--- head/lib/libc/stdio/mktemp.3	Fri Aug  9 16:43:50 2013	(r254150)
+++ head/lib/libc/stdio/mktemp.3	Fri Aug  9 17:24:23 2013	(r254151)
@@ -28,7 +28,7 @@
 .\"     @(#)mktemp.3	8.1 (Berkeley) 6/4/93
 .\" $FreeBSD$
 .\"
-.Dd July 5, 2013
+.Dd August 8, 2013
 .Dt MKTEMP 3
 .Os
 .Sh NAME
@@ -42,6 +42,10 @@
 .Fn mktemp "char *template"
 .Ft int
 .Fn mkstemp "char *template"
+.Ft int
+.Fn mkostemp "char *template" "int oflags"
+.Ft int
+.Fn mkostemps "char *template" "int suffixlen" "int oflags"
 .Ft char *
 .Fn mkdtemp "char *template"
 .In unistd.h
@@ -85,16 +89,41 @@ This avoids the race between testing for
 for use.
 .Pp
 The
+.Fn mkostemp
+function
+is like
+.Fn mkstemp
+but allows specifying additional
+.Xr open 2
+flags (defined in
+.In fcntl.h ) .
+The permitted flags are
+.Dv O_APPEND ,
+.Dv O_DIRECT ,
+.Dv O_SHLOCK ,
+.Dv O_EXLOCK ,
+.Dv O_SYNC
+and
+.Dv O_CLOEXEC .
+.Pp
+The
 .Fn mkstemps
-function acts the same as
-.Fn mkstemp ,
-except it permits a suffix to exist in the template.
+and
+.Fn mkostemps
+functions act the same as
+.Fn mkstemp
+and
+.Fn mkostemp
+respectively,
+except they permit a suffix to exist in the template.
 The template should be of the form
 .Pa /tmp/tmpXXXXXXsuffix .
 The
 .Fn mkstemps
+and
+.Fn mkostemps
 function
-is told the length of the suffix string.
+are told the length of the suffix string.
 .Pp
 The
 .Fn mkdtemp
@@ -110,9 +139,11 @@ functions return a pointer to the templa
 .Dv NULL
 on failure.
 The
-.Fn mkstemp
-and
+.Fn mkstemp ,
+.Fn mkostemp
 .Fn mkstemps
+and
+.Fn mkostemps
 functions
 return \-1 if no suitable file could be created.
 If either call fails an error code is placed in the global variable
@@ -120,7 +151,9 @@ If either call fails an error code is pl
 .Sh ERRORS
 The
 .Fn mkstemp ,
-.Fn mkstemps
+.Fn mkostemp ,
+.Fn mkstemps ,
+.Fn mkostemps
 and
 .Fn mkdtemp
 functions
@@ -133,8 +166,25 @@ The pathname portion of the template is 
 .El
 .Pp
 The
+.Fn mkostemp
+and
+.Fn mkostemps
+functions
+may also set
+.Va errno
+to the following value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa oflags
+argument is invalid.
+.El
+.Pp
+The
 .Fn mkstemp ,
-.Fn mkstemps
+.Fn mkostemp ,
+.Fn mkstemps ,
+.Fn mkostemps
 and
 .Fn mkdtemp
 functions
@@ -145,9 +195,11 @@ to any value specified by the
 function.
 .Pp
 The
-.Fn mkstemp
-and
+.Fn mkstemp ,
+.Fn mkostemp ,
 .Fn mkstemps
+and
+.Fn mkostemps
 functions
 may also set
 .Va errno
@@ -209,8 +261,11 @@ function is expected to conform to
 and is not specified by
 .St -p1003.1-2008 .
 The
+.Fn mkostemp ,
 .Fn mkstemps
-function does not conform to any standard.
+and
+.Fn mkostemps
+functions do not conform to any standard.
 .Sh HISTORY
 A
 .Fn mktemp
@@ -232,6 +287,12 @@ function first appeared in
 .Ox 2.4 ,
 and later in
 .Fx 3.4 .
+The
+.Fn mkostemp
+and
+.Fn mkostemps
+functions appeared in
+.Fx 10.0 .
 .Sh BUGS
 This family of functions produces filenames which can be guessed,
 though the risk is minimized when large numbers of
@@ -248,6 +309,8 @@ and opening it for use
 particularly dangerous from a security perspective.
 Whenever it is possible,
 .Fn mkstemp
+or
+.Fn mkostemp
 should be used instead, since it does not have the race condition.
 If
 .Fn mkstemp

Modified: head/lib/libc/stdio/mktemp.c
==============================================================================
--- head/lib/libc/stdio/mktemp.c	Fri Aug  9 16:43:50 2013	(r254150)
+++ head/lib/libc/stdio/mktemp.c	Fri Aug  9 17:24:23 2013	(r254151)
@@ -47,17 +47,33 @@ __FBSDID("$FreeBSD$");
 
 char *_mktemp(char *);
 
-static int _gettemp(char *, int *, int, int);
+static int _gettemp(char *, int *, int, int, int);
 
 static const unsigned char padchar[] =
 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 
 int
+mkostemps(char *path, int slen, int oflags)
+{
+	int fd;
+
+	return (_gettemp(path, &fd, 0, slen, oflags) ? fd : -1);
+}
+
+int
 mkstemps(char *path, int slen)
 {
 	int fd;
 
-	return (_gettemp(path, &fd, 0, slen) ? fd : -1);
+	return (_gettemp(path, &fd, 0, slen, 0) ? fd : -1);
+}
+
+int
+mkostemp(char *path, int oflags)
+{
+	int fd;
+
+	return (_gettemp(path, &fd, 0, 0, oflags) ? fd : -1);
 }
 
 int
@@ -65,19 +81,19 @@ mkstemp(char *path)
 {
 	int fd;
 
-	return (_gettemp(path, &fd, 0, 0) ? fd : -1);
+	return (_gettemp(path, &fd, 0, 0, 0) ? fd : -1);
 }
 
 char *
 mkdtemp(char *path)
 {
-	return (_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL);
+	return (_gettemp(path, (int *)NULL, 1, 0, 0) ? path : (char *)NULL);
 }
 
 char *
 _mktemp(char *path)
 {
-	return (_gettemp(path, (int *)NULL, 0, 0) ? path : (char *)NULL);
+	return (_gettemp(path, (int *)NULL, 0, 0, 0) ? path : (char *)NULL);
 }
 
 __warn_references(mktemp,
@@ -90,7 +106,7 @@ mktemp(char *path)
 }
 
 static int
-_gettemp(char *path, int *doopen, int domkdir, int slen)
+_gettemp(char *path, int *doopen, int domkdir, int slen, int oflags)
 {
 	char *start, *trv, *suffp, *carryp;
 	char *pad;
@@ -99,7 +115,9 @@ _gettemp(char *path, int *doopen, int do
 	uint32_t rand;
 	char carrybuf[MAXPATHLEN];
 
-	if ((doopen != NULL && domkdir) || slen < 0) {
+	if ((doopen != NULL && domkdir) || slen < 0 ||
+	    (oflags & ~(O_APPEND | O_DIRECT | O_SHLOCK | O_EXLOCK | O_SYNC |
+	    O_CLOEXEC)) != 0) {
 		errno = EINVAL;
 		return (0);
 	}
@@ -151,7 +169,8 @@ _gettemp(char *path, int *doopen, int do
 	for (;;) {
 		if (doopen) {
 			if ((*doopen =
-			    _open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
+			    _open(path, O_CREAT|O_EXCL|O_RDWR|oflags, 0600)) >=
+			    0)
 				return (1);
 			if (errno != EEXIST)
 				return (0);

Modified: head/tools/regression/lib/libc/stdio/Makefile
==============================================================================
--- head/tools/regression/lib/libc/stdio/Makefile	Fri Aug  9 16:43:50 2013	(r254150)
+++ head/tools/regression/lib/libc/stdio/Makefile	Fri Aug  9 17:24:23 2013	(r254151)
@@ -1,8 +1,8 @@
 # $FreeBSD$
 
-TESTS=	test-fmemopen test-getdelim test-open_memstream test-open_wmemstream \
-	test-perror test-print-positional test-printbasic test-printfloat \
-	test-scanfloat 
+TESTS=	test-fmemopen test-getdelim test-mkostemp test-open_memstream \
+	test-open_wmemstream test-perror test-print-positional test-printbasic \
+	test-printfloat test-scanfloat 
 CFLAGS+= -lm
 
 .PHONY: tests

Added: head/tools/regression/lib/libc/stdio/test-mkostemp.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/lib/libc/stdio/test-mkostemp.c	Fri Aug  9 17:24:23 2013	(r254151)
@@ -0,0 +1,164 @@
+/*-
+ * Copyright (c) 2013 Jilles Tjoelker
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test program for mkostemp().
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static const char template[] = _PATH_TMP "mkostemp.XXXXXXXX";
+static int testnum;
+
+#define MISCFLAGS (O_APPEND | O_DIRECT | O_SHLOCK | O_EXLOCK | O_SYNC)
+
+static void
+test_one(int oflags)
+{
+	char tmpf[sizeof(template)];
+	struct stat st1, st2;
+	int fd;
+
+	memcpy(tmpf, template, sizeof(tmpf));
+	fd = mkostemp(tmpf, oflags);
+	if (fd < 0) {
+		printf("not ok %d - oflags=%#x "
+		    "mkostemp() reported failure: %s\n",
+		    testnum++, oflags, strerror(errno));
+		return;
+	}
+	if (memcmp(tmpf, template, sizeof(tmpf) - 8 - 1) != 0) {
+		printf("not ok %d - oflags=%#x "
+		    "returned pathname does not match template: %s\n",
+		    testnum++, oflags, tmpf);
+		return;
+	}
+	do {
+		if (fcntl(fd, F_GETFD) !=
+		    (oflags & O_CLOEXEC ? FD_CLOEXEC : 0)) {
+			printf("not ok %d - oflags=%#x "
+			    "close-on-exec flag incorrect\n",
+			    testnum++, oflags);
+			break;
+		}
+		if ((fcntl(fd, F_GETFL) & MISCFLAGS) != (oflags & MISCFLAGS)) {
+			printf("not ok %d - oflags=%#x "
+			    "open flags incorrect\n",
+			    testnum++, oflags);
+			break;
+		}
+		if (stat(tmpf, &st1) == -1) {
+			printf("not ok %d - oflags=%#x "
+			    "cannot stat returned pathname %s: %s\n",
+			    testnum++, oflags, tmpf, strerror(errno));
+			break;
+		}
+		if (fstat(fd, &st2) == -1) {
+			printf("not ok %d - oflags=%#x "
+			    "cannot fstat returned fd %d: %s\n",
+			    testnum++, oflags, fd, strerror(errno));
+			break;
+		}
+		if (!S_ISREG(st1.st_mode) || (st1.st_mode & 0777) != 0600 ||
+		    st1.st_nlink != 1 || st1.st_size != 0) {
+			printf("not ok %d - oflags=%#x "
+			    "named file attributes incorrect\n",
+			    testnum++, oflags);
+			break;
+		}
+		if (!S_ISREG(st2.st_mode) || (st2.st_mode & 0777) != 0600 ||
+		    st2.st_nlink != 1 || st2.st_size != 0) {
+			printf("not ok %d - oflags=%#x "
+			    "opened file attributes incorrect\n",
+			    testnum++, oflags);
+			break;
+		}
+		if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) {
+			printf("not ok %d - oflags=%#x "
+			    "named and opened file do not match\n",
+			    testnum++, oflags);
+			break;
+		}
+		(void)unlink(tmpf);
+		if (fstat(fd, &st2) == -1)
+			printf("not ok %d - oflags=%#x "
+			    "cannot fstat returned fd %d again: %s\n",
+			    testnum++, oflags, fd, strerror(errno));
+		else if (st2.st_nlink != 0)
+			printf("not ok %d - oflags=%#x "
+			    "st_nlink is not 0 after unlink\n",
+			    testnum++, oflags);
+		else
+			printf("ok %d - oflags=%#x\n", testnum++, oflags);
+		(void)close(fd);
+		return;
+	} while (0);
+	(void)close(fd);
+	(void)unlink(tmpf);
+}
+
+static void
+test_badflags(void)
+{
+	char tmpf[sizeof(template)];
+
+	memcpy(tmpf, template, sizeof(tmpf));
+	if (mkostemp(tmpf, O_CREAT) == -1)
+		printf("ok %d - mkostemp(O_CREAT) correctly failed\n",
+		    testnum++);
+	else
+		printf("not ok %d - mkostemp(O_CREAT) wrongly succeeded\n",
+		    testnum++);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int i;
+	const char *e;
+
+	printf("1..5\n");
+	testnum = 1;
+
+	test_one(0);
+	test_one(O_CLOEXEC);
+	test_one(O_APPEND);
+	test_one(O_APPEND | O_CLOEXEC);
+	test_badflags();
+
+	return (0);
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201308091724.r79HONBh039632>