summaryrefslogtreecommitdiff
path: root/sftp-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'sftp-server.c')
-rw-r--r--sftp-server.c47
1 files changed, 30 insertions, 17 deletions
diff --git a/sftp-server.c b/sftp-server.c
index 84264693d..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"
25RCSID("$OpenBSD: sftp-server.c,v 1.38 2002/09/11 22:41:50 djm Exp $"); 25RCSID("$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"
@@ -158,7 +158,7 @@ handle_new(int use, char *name, int fd, DIR *dirp)
158 handles[i].use = use; 158 handles[i].use = use;
159 handles[i].dirp = dirp; 159 handles[i].dirp = dirp;
160 handles[i].fd = fd; 160 handles[i].fd = fd;
161 handles[i].name = name; 161 handles[i].name = xstrdup(name);
162 return i; 162 return i;
163 } 163 }
164 } 164 }
@@ -230,9 +230,11 @@ handle_close(int handle)
230 if (handle_is_ok(handle, HANDLE_FILE)) { 230 if (handle_is_ok(handle, HANDLE_FILE)) {
231 ret = close(handles[handle].fd); 231 ret = close(handles[handle].fd);
232 handles[handle].use = HANDLE_UNUSED; 232 handles[handle].use = HANDLE_UNUSED;
233 xfree(handles[handle].name);
233 } else if (handle_is_ok(handle, HANDLE_DIR)) { 234 } else if (handle_is_ok(handle, HANDLE_DIR)) {
234 ret = closedir(handles[handle].dirp); 235 ret = closedir(handles[handle].dirp);
235 handles[handle].use = HANDLE_UNUSED; 236 handles[handle].use = HANDLE_UNUSED;
237 xfree(handles[handle].name);
236 } else { 238 } else {
237 errno = ENOENT; 239 errno = ENOENT;
238 } 240 }
@@ -396,7 +398,7 @@ process_open(void)
396 if (fd < 0) { 398 if (fd < 0) {
397 status = errno_to_portable(errno); 399 status = errno_to_portable(errno);
398 } else { 400 } else {
399 handle = handle_new(HANDLE_FILE, xstrdup(name), fd, NULL); 401 handle = handle_new(HANDLE_FILE, name, fd, NULL);
400 if (handle < 0) { 402 if (handle < 0) {
401 close(fd); 403 close(fd);
402 } else { 404 } else {
@@ -681,7 +683,7 @@ process_opendir(void)
681 if (dirp == NULL) { 683 if (dirp == NULL) {
682 status = errno_to_portable(errno); 684 status = errno_to_portable(errno);
683 } else { 685 } else {
684 handle = handle_new(HANDLE_DIR, xstrdup(path), 0, dirp); 686 handle = handle_new(HANDLE_DIR, path, 0, dirp);
685 if (handle < 0) { 687 if (handle < 0) {
686 closedir(dirp); 688 closedir(dirp);
687 } else { 689 } else {
@@ -832,18 +834,32 @@ static void
832process_rename(void) 834process_rename(void)
833{ 835{
834 u_int32_t id; 836 u_int32_t id;
835 struct stat st;
836 char *oldpath, *newpath; 837 char *oldpath, *newpath;
837 int ret, status = SSH2_FX_FAILURE; 838 int status;
839 struct stat sb;
838 840
839 id = get_int(); 841 id = get_int();
840 oldpath = get_string(NULL); 842 oldpath = get_string(NULL);
841 newpath = get_string(NULL); 843 newpath = get_string(NULL);
842 TRACE("rename id %u old %s new %s", id, oldpath, newpath); 844 TRACE("rename id %u old %s new %s", id, oldpath, newpath);
843 /* fail if 'newpath' exists */ 845 status = SSH2_FX_FAILURE;
844 if (stat(newpath, &st) == -1) { 846 if (lstat(oldpath, &sb) == -1)
845 ret = rename(oldpath, newpath); 847 status = errno_to_portable(errno);
846 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 848 else if (S_ISREG(sb.st_mode)) {
849 /* Race-free rename of regular files */
850 if (link(oldpath, newpath) == -1)
851 status = errno_to_portable(errno);
852 else if (unlink(oldpath) == -1) {
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;
847 } 863 }
848 send_status(id, status); 864 send_status(id, status);
849 xfree(oldpath); 865 xfree(oldpath);
@@ -878,19 +894,16 @@ static void
878process_symlink(void) 894process_symlink(void)
879{ 895{
880 u_int32_t id; 896 u_int32_t id;
881 struct stat st;
882 char *oldpath, *newpath; 897 char *oldpath, *newpath;
883 int ret, status = SSH2_FX_FAILURE; 898 int ret, status;
884 899
885 id = get_int(); 900 id = get_int();
886 oldpath = get_string(NULL); 901 oldpath = get_string(NULL);
887 newpath = get_string(NULL); 902 newpath = get_string(NULL);
888 TRACE("symlink id %u old %s new %s", id, oldpath, newpath); 903 TRACE("symlink id %u old %s new %s", id, oldpath, newpath);
889 /* fail if 'newpath' exists */ 904 /* this will fail if 'newpath' exists */
890 if (stat(newpath, &st) == -1) { 905 ret = symlink(oldpath, newpath);
891 ret = symlink(oldpath, newpath); 906 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
892 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
893 }
894 send_status(id, status); 907 send_status(id, status);
895 xfree(oldpath); 908 xfree(oldpath);
896 xfree(newpath); 909 xfree(newpath);