diff options
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | sftp-server.c | 29 |
2 files changed, 29 insertions, 11 deletions
@@ -1,9 +1,16 @@ | |||
1 | 20030326 | ||
2 | - (djm) OpenBSD CVS Sync | ||
3 | - deraadt@cvs.openbsd.org 2003/03/26 04:02:51 | ||
4 | [sftp-server.c] | ||
5 | one last fix to the tree: race fix broke stuff; pr 3169; | ||
6 | srp@srparish.net, help from djm | ||
7 | - Release 3.6p1 | ||
8 | |||
1 | 20030324 | 9 | 20030324 |
2 | - (djm) OpenBSD CVS Sync | 10 | - (djm) OpenBSD CVS Sync |
3 | - markus@cvs.openbsd.org 2003/03/23 19:02:00 | 11 | - markus@cvs.openbsd.org 2003/03/23 19:02:00 |
4 | [monitor.c] | 12 | [monitor.c] |
5 | unbreak rekeying for privsep; ok millert@ | 13 | unbreak rekeying for privsep; ok millert@ |
6 | - Release 3.6p1 | ||
7 | 14 | ||
8 | 20030320 | 15 | 20030320 |
9 | - (djm) OpenBSD CVS Sync | 16 | - (djm) OpenBSD CVS Sync |
@@ -1247,4 +1254,4 @@ | |||
1247 | save auth method before monitor_reset_key_state(); bugzilla bug #284; | 1254 | save auth method before monitor_reset_key_state(); bugzilla bug #284; |
1248 | ok provos@ | 1255 | ok provos@ |
1249 | 1256 | ||
1250 | $Id: ChangeLog,v 1.2633.2.6 2003/03/23 22:12:50 djm Exp $ | 1257 | $Id: ChangeLog,v 1.2633.2.7 2003/03/26 04:59:47 djm Exp $ |
diff --git a/sftp-server.c b/sftp-server.c index 0c00003f8..9a66b4de7 100644 --- a/sftp-server.c +++ b/sftp-server.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 22 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
23 | */ | 23 | */ |
24 | #include "includes.h" | 24 | #include "includes.h" |
25 | RCSID("$OpenBSD: sftp-server.c,v 1.40 2003/03/05 22:33:43 markus Exp $"); | 25 | RCSID("$OpenBSD: sftp-server.c,v 1.41 2003/03/26 04:02:51 deraadt Exp $"); |
26 | 26 | ||
27 | #include "buffer.h" | 27 | #include "buffer.h" |
28 | #include "bufaux.h" | 28 | #include "bufaux.h" |
@@ -836,20 +836,31 @@ process_rename(void) | |||
836 | u_int32_t id; | 836 | u_int32_t id; |
837 | char *oldpath, *newpath; | 837 | char *oldpath, *newpath; |
838 | int status; | 838 | int status; |
839 | struct stat sb; | ||
839 | 840 | ||
840 | id = get_int(); | 841 | id = get_int(); |
841 | oldpath = get_string(NULL); | 842 | oldpath = get_string(NULL); |
842 | newpath = get_string(NULL); | 843 | newpath = get_string(NULL); |
843 | TRACE("rename id %u old %s new %s", id, oldpath, newpath); | 844 | TRACE("rename id %u old %s new %s", id, oldpath, newpath); |
844 | /* fail if 'newpath' exists */ | 845 | status = SSH2_FX_FAILURE; |
845 | if (link(oldpath, newpath) == -1) | 846 | if (lstat(oldpath, &sb) == -1) |
846 | status = errno_to_portable(errno); | 847 | status = errno_to_portable(errno); |
847 | else if (unlink(oldpath) == -1) { | 848 | else if (S_ISREG(sb.st_mode)) { |
848 | status = errno_to_portable(errno); | 849 | /* Race-free rename of regular files */ |
849 | /* clean spare link */ | 850 | if (link(oldpath, newpath) == -1) |
850 | unlink(newpath); | 851 | status = errno_to_portable(errno); |
851 | } else | 852 | else if (unlink(oldpath) == -1) { |
852 | status = SSH2_FX_OK; | 853 | status = errno_to_portable(errno); |
854 | /* clean spare link */ | ||
855 | unlink(newpath); | ||
856 | } else | ||
857 | status = SSH2_FX_OK; | ||
858 | } else if (stat(newpath, &sb) == -1) { | ||
859 | if (rename(oldpath, newpath) == -1) | ||
860 | status = errno_to_portable(errno); | ||
861 | else | ||
862 | status = SSH2_FX_OK; | ||
863 | } | ||
853 | send_status(id, status); | 864 | send_status(id, status); |
854 | xfree(oldpath); | 865 | xfree(oldpath); |
855 | xfree(newpath); | 866 | xfree(newpath); |