Sat Jul 25 11:45:58 2009 UTC ()
When installing via a temporary file, base the name of the temporary
file on the name of the target file, not just the target directory, to
ensure uniqueness when multiple concurrent invocations of install(1)
simultaneously install files in the same directory.  Fixes bin/41512.


(gson)
diff -r1.111 -r1.112 src/usr.bin/xinstall/xinstall.c

cvs diff -r1.111 -r1.112 src/usr.bin/xinstall/xinstall.c (expand / switch to unified diff)

--- src/usr.bin/xinstall/xinstall.c 2009/06/08 21:58:44 1.111
+++ src/usr.bin/xinstall/xinstall.c 2009/07/25 11:45:58 1.112
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: xinstall.c,v 1.111 2009/06/08 21:58:44 yamt Exp $ */ 1/* $NetBSD: xinstall.c,v 1.112 2009/07/25 11:45:58 gson Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1987, 1993 4 * Copyright (c) 1987, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -36,27 +36,27 @@ @@ -36,27 +36,27 @@
36#define HAVE_STRUCT_STAT_ST_FLAGS 1 36#define HAVE_STRUCT_STAT_ST_FLAGS 1
37#endif 37#endif
38 38
39#include <sys/cdefs.h> 39#include <sys/cdefs.h>
40#if defined(__COPYRIGHT) && !defined(lint) 40#if defined(__COPYRIGHT) && !defined(lint)
41__COPYRIGHT("@(#) Copyright (c) 1987, 1993\ 41__COPYRIGHT("@(#) Copyright (c) 1987, 1993\
42 The Regents of the University of California. All rights reserved."); 42 The Regents of the University of California. All rights reserved.");
43#endif /* not lint */ 43#endif /* not lint */
44 44
45#if defined(__RCSID) && !defined(lint) 45#if defined(__RCSID) && !defined(lint)
46#if 0 46#if 0
47static char sccsid[] = "@(#)xinstall.c 8.1 (Berkeley) 7/21/93"; 47static char sccsid[] = "@(#)xinstall.c 8.1 (Berkeley) 7/21/93";
48#else 48#else
49__RCSID("$NetBSD: xinstall.c,v 1.111 2009/06/08 21:58:44 yamt Exp $"); 49__RCSID("$NetBSD: xinstall.c,v 1.112 2009/07/25 11:45:58 gson Exp $");
50#endif 50#endif
51#endif /* not lint */ 51#endif /* not lint */
52 52
53#define __MKTEMP_OK__ /* All uses of mktemp have been checked */ 53#define __MKTEMP_OK__ /* All uses of mktemp have been checked */
54#include <sys/param.h> 54#include <sys/param.h>
55#include <sys/mman.h> 55#include <sys/mman.h>
56#include <sys/stat.h> 56#include <sys/stat.h>
57#include <sys/wait.h> 57#include <sys/wait.h>
58#include <sys/time.h> 58#include <sys/time.h>
59 59
60#include <ctype.h> 60#include <ctype.h>
61#include <err.h> 61#include <err.h>
62#include <errno.h> 62#include <errno.h>
@@ -408,28 +408,27 @@ parseid(char *name, id_t *id) @@ -408,28 +408,27 @@ parseid(char *name, id_t *id)
408 408
409/* 409/*
410 * do_link -- 410 * do_link --
411 * make a hard link, obeying dorename if set 411 * make a hard link, obeying dorename if set
412 * return -1 on failure 412 * return -1 on failure
413 */ 413 */
414int 414int
415do_link(char *from_name, char *to_name) 415do_link(char *from_name, char *to_name)
416{ 416{
417 char tmpl[MAXPATHLEN]; 417 char tmpl[MAXPATHLEN];
418 int ret; 418 int ret;
419 419
420 if (dorename) { 420 if (dorename) {
421 (void)snprintf(tmpl, sizeof(tmpl), "%s/inst.XXXXXX", 421 (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name);
422 xdirname(to_name)); 
423 /* This usage is safe. */ 422 /* This usage is safe. */
424 if (mktemp(tmpl) == NULL) 423 if (mktemp(tmpl) == NULL)
425 err(1, "%s: mktemp", tmpl); 424 err(1, "%s: mktemp", tmpl);
426 ret = link(from_name, tmpl); 425 ret = link(from_name, tmpl);
427 if (ret == 0) { 426 if (ret == 0) {
428 ret = rename(tmpl, to_name); 427 ret = rename(tmpl, to_name);
429 /* If rename has posix semantics, then the temporary 428 /* If rename has posix semantics, then the temporary
430 * file may still exist when from_name and to_name point 429 * file may still exist when from_name and to_name point
431 * to the same file, so unlink it unconditionally. 430 * to the same file, so unlink it unconditionally.
432 */ 431 */
433 (void)unlink(tmpl); 432 (void)unlink(tmpl);
434 } 433 }
435 return (ret); 434 return (ret);
@@ -438,28 +437,27 @@ do_link(char *from_name, char *to_name) @@ -438,28 +437,27 @@ do_link(char *from_name, char *to_name)
438} 437}
439 438
440/* 439/*
441 * do_symlink -- 440 * do_symlink --
442 * make a symbolic link, obeying dorename if set 441 * make a symbolic link, obeying dorename if set
443 * exit on failure 442 * exit on failure
444 */ 443 */
445void 444void
446do_symlink(char *from_name, char *to_name) 445do_symlink(char *from_name, char *to_name)
447{ 446{
448 char tmpl[MAXPATHLEN]; 447 char tmpl[MAXPATHLEN];
449 448
450 if (dorename) { 449 if (dorename) {
451 (void)snprintf(tmpl, sizeof(tmpl), "%s/inst.XXXXXX", 450 (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name);
452 xdirname(to_name)); 
453 /* This usage is safe. */ 451 /* This usage is safe. */
454 if (mktemp(tmpl) == NULL) 452 if (mktemp(tmpl) == NULL)
455 err(1, "%s: mktemp", tmpl); 453 err(1, "%s: mktemp", tmpl);
456 454
457 if (symlink(from_name, tmpl) == -1) 455 if (symlink(from_name, tmpl) == -1)
458 err(1, "symlink %s -> %s", from_name, tmpl); 456 err(1, "symlink %s -> %s", from_name, tmpl);
459 if (rename(tmpl, to_name) == -1) { 457 if (rename(tmpl, to_name) == -1) {
460 /* remove temporary link before exiting */ 458 /* remove temporary link before exiting */
461 (void)unlink(tmpl); 459 (void)unlink(tmpl);
462 err(1, "%s: rename", to_name); 460 err(1, "%s: rename", to_name);
463 } 461 }
464 } else { 462 } else {
465 if (symlink(from_name, to_name) == -1) 463 if (symlink(from_name, to_name) == -1)
@@ -658,28 +656,27 @@ install(char *from_name, char *to_name,  @@ -658,28 +656,27 @@ install(char *from_name, char *to_name,
658 } 656 }
659 657
660 /* 658 /*
661 * Unlink now... avoid ETXTBSY errors later. Try and turn 659 * Unlink now... avoid ETXTBSY errors later. Try and turn
662 * off the append/immutable bits -- if we fail, go ahead, 660 * off the append/immutable bits -- if we fail, go ahead,
663 * it might work. 661 * it might work.
664 */ 662 */
665#if ! HAVE_NBTOOL_CONFIG_H 663#if ! HAVE_NBTOOL_CONFIG_H
666 if (stat(to_name, &to_sb) == 0 && 664 if (stat(to_name, &to_sb) == 0 &&
667 to_sb.st_flags & (NOCHANGEBITS)) 665 to_sb.st_flags & (NOCHANGEBITS))
668 (void)chflags(to_name, to_sb.st_flags & ~(NOCHANGEBITS)); 666 (void)chflags(to_name, to_sb.st_flags & ~(NOCHANGEBITS));
669#endif 667#endif
670 if (dorename) { 668 if (dorename) {
671 (void)snprintf(tmpl, sizeof(tmpl), "%s/inst.XXXXXX", 669 (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name);
672 xdirname(to_name)); 
673 oto_name = to_name; 670 oto_name = to_name;
674 to_name = tmpl; 671 to_name = tmpl;
675 } else { 672 } else {
676 oto_name = NULL; /* pacify gcc */ 673 oto_name = NULL; /* pacify gcc */
677 if (dobackup) 674 if (dobackup)
678 backup(to_name); 675 backup(to_name);
679 else 676 else
680 (void)unlink(to_name); 677 (void)unlink(to_name);
681 } 678 }
682 679
683 if (dolink) { 680 if (dolink) {
684 makelink(from_name, dorename ? oto_name : to_name); 681 makelink(from_name, dorename ? oto_name : to_name);
685 return; 682 return;