diff options
author | Damien Miller <djm@mindrot.org> | 2003-03-26 15:59:47 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2003-03-26 15:59:47 +1100 |
commit | 63e2615c137bde9587954d7947b5319c3b4d5f31 (patch) | |
tree | 1febae6e72650930491a582e8e4212a5a2ae6f7c /sftp-server.c | |
parent | a62e554c2495d5845a2add7f1f35aed31c385e0c (diff) |
- (djm) OpenBSD CVS Sync
- deraadt@cvs.openbsd.org 2003/03/26 04:02:51
[sftp-server.c]
one last fix to the tree: race fix broke stuff; pr 3169;
srp@srparish.net, help from djm
- Release 3.6p1
Diffstat (limited to 'sftp-server.c')
-rw-r--r-- | sftp-server.c | 29 |
1 files changed, 20 insertions, 9 deletions
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); |