diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | sftp-server.c | 29 |
2 files changed, 28 insertions, 10 deletions
@@ -1,3 +1,10 @@ | |||
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 | |||
1 | 20030325 | 8 | 20030325 |
2 | - (djm) Fix getpeerid support for 64 bit BE systems. From | 9 | - (djm) Fix getpeerid support for 64 bit BE systems. From |
3 | Arnd Bergmann <arndb@de.ibm.com> | 10 | Arnd Bergmann <arndb@de.ibm.com> |
@@ -1252,4 +1259,4 @@ | |||
1252 | save auth method before monitor_reset_key_state(); bugzilla bug #284; | 1259 | save auth method before monitor_reset_key_state(); bugzilla bug #284; |
1253 | ok provos@ | 1260 | ok provos@ |
1254 | 1261 | ||
1255 | $Id: ChangeLog,v 1.2641 2003/03/24 22:07:52 djm Exp $ | 1262 | $Id: ChangeLog,v 1.2642 2003/03/26 05:01:11 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); |