Index: contrib/texinfo/util/texindex.c
===================================================================
RCS file: /home/ncvs/src/contrib/texinfo/util/texindex.c,v
retrieving revision 1.1.1.8
diff -u -p -I__FBSDID -r1.1.1.8 texindex.c
--- util/texindex.c 23 May 2005 10:46:22 -0000 1.1.1.8
+++ util/texindex.c 8 Jan 2006 23:31:32 -0000
@@ -384,17 +384,33 @@ For more information about these matters
usage (1);
}
+static char **tv;
+static int tv_alloc;
+static int tv_used;
+
+static int
+findtempname (char *tempname)
+{
+ int i;
+
+ for (i = 0; i < tv_used; i++)
+ if (strcmp (tv[i], tempname) == 0)
+ return (1);
+ return (0);
+}
+
/* Return a name for temporary file COUNT. */
static char *
maketempname (int count)
{
static char *tempbase = NULL;
+ char *tempname;
char tempsuffix[10];
+ int fd;
if (!tempbase)
{
- int fd;
tempbase = concat (tempdir, "txidxXXXXXX");
fd = mkstemp (tempbase);
@@ -403,7 +419,52 @@ maketempname (int count)
}
sprintf (tempsuffix, ".%d", count);
- return concat (tempbase, tempsuffix);
+ tempname = concat (tempbase, tempsuffix);
+ /*
+ * The open logic becomes a bit convoluted. If open(2) fails due to EEXIST,
+ * it's likely because somebody attempted to race us, or because we have
+ * already created this file.
+ */
+ fd = open (tempname, O_CREAT|O_EXCL|O_WRONLY, 0600);
+ if (fd == -1)
+ {
+ /*
+ * If errno is not EEXIST, then open failed for some other reason, so
+ * we should terminate. If errno == EEXIST AND we didn't create this
+ * file, terminate. Otherwise, it's safe to say that errno == EEXIST
+ * because we already created it, in this event, we can just return.
+ */
+ if (errno != EEXIST ||
+ (errno == EEXIST && findtempname (tempname) == 0))
+ pfatal_with_name (tempname);
+ return (tempname);
+ }
+ else if (fd > 0)
+ {
+ close (fd);
+ }
+ if (tv == NULL)
+ {
+ tv_alloc = 16;
+ tv = calloc (tv_alloc, sizeof (char *));
+ if (tv == NULL)
+ {
+ fprintf (stderr, "calloc failed\n");
+ exit (1);
+ }
+ }
+ else if (tv_used == tv_alloc)
+ {
+ tv_alloc += 4;
+ tv = realloc (tv, tv_alloc * sizeof (char *));
+ if (tv == NULL)
+ {
+ fprintf (stderr, "realloc failed");
+ exit (1);
+ }
+ }
+ tv[tv_used++] = strdup (tempname);
+ return tempname;
}