diff -ur openssh-5.3p1/Makefile.in openssh-5.3p1_atomic/Makefile.in --- openssh-5.3p1/Makefile.in 2009-08-27 20:47:38.000000000 -0400 +++ openssh-5.3p1_atomic/Makefile.in 2009-11-20 09:31:03.000000000 -0500 @@ -141,8 +141,8 @@ sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) -scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o - $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) +scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o entropy.o + $(LD) -o $@ scp.o progressmeter.o bufaux.o entropy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) @@ -159,8 +159,8 @@ ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) -sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o - $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) +sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o entropy.o + $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o entropy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o $(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT) diff -ur openssh-5.3p1/scp.c openssh-5.3p1_atomic/scp.c --- openssh-5.3p1/scp.c 2008-11-03 03:23:45.000000000 -0500 +++ openssh-5.3p1_atomic/scp.c 2009-11-20 09:31:03.000000000 -0500 @@ -143,6 +143,9 @@ /* This is used to store the pid of ssh_program */ pid_t do_cmd_pid = -1; +/* temporary folder where the files will be storred before being moved to their actual location */ +char *tmpdir; + static void killchild(int signo) { @@ -395,6 +398,9 @@ if (!isatty(STDOUT_FILENO)) showprogress = 0; + + tmpdir=getenv("TMP"); + if(!tmpdir)tmpdir="/tmp"; remin = STDIN_FILENO; remout = STDOUT_FILENO; @@ -868,7 +874,7 @@ mode_t mode, omode, mask; off_t size, statbytes; int setimes, targisdir, wrerrno = 0; - char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; + char ch, *cp, *np, *targ, *why, *vect[1], buf[2048],*origname; struct timeval tv[2]; #define atime tv[0] @@ -1024,6 +1030,12 @@ } omode = mode; mode |= S_IWRITE; + + origname=np; + np=calloc(1,strlen(origname)+20); + sprintf(np,"%s.tmpscpparts.XXXXXX",origname); + mkstemp(np); + if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { bad: run_err("%s: %s", np, strerror(errno)); continue; @@ -1083,6 +1095,7 @@ run_err("%s: truncate: %s", np, strerror(errno)); wrerr = DISPLAYED; } + if (pflag) { if (exists || omode != mode) #ifdef HAVE_FCHMOD @@ -1109,6 +1122,16 @@ if (close(ofd) == -1) { wrerr = YES; wrerrno = errno; + }else{ + if(rename(np,origname)){ + wrerr = YES; + wrerrno = errno; + }else{ + xfree(np); + np=origname; + origname=0; + } + } (void) response(); if (setimes && wrerr == NO) { @@ -1129,6 +1152,10 @@ case DISPLAYED: break; } + if(origname){ + xfree(np); + np=origname; + } } screwup: run_err("protocol error: %s", why); diff -ur openssh-5.3p1/sftp-server.c openssh-5.3p1_atomic/sftp-server.c --- openssh-5.3p1/sftp-server.c 2009-08-27 20:43:13.000000000 -0400 +++ openssh-5.3p1_atomic/sftp-server.c 2009-11-20 09:31:03.000000000 -0500 @@ -62,6 +62,8 @@ /* Our client */ struct passwd *pw = NULL; char *client_addr = NULL; +char *origname = NULL; +char *tmpdir = NULL; /* input and output queue */ Buffer iqueue; @@ -551,8 +553,18 @@ a = get_attrib(); flags = flags_from_portable(pflags); mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666; + origname=NULL; + if (pflags & SSH2_FXF_WRITE || pflags & SSH2_FXF_CREAT){ + origname=name; + name=calloc(1,11+strlen(tmpdir)+1); + sprintf(name,"%s/sftp_XXXXXX",tmpdir); + mkstemp(name); + logit("created tmp file for \"%s\": \"%s\"",origname,name); + } + logit("open \"%s\" flags %s mode 0%o", name, string_from_portable(pflags), mode); + fd = open(name, flags, mode); if (fd < 0) { status = errno_to_portable(errno); @@ -575,13 +587,26 @@ { u_int32_t id; int handle, ret, status = SSH2_FX_FAILURE; - + char *name; + int namel; id = get_int(); handle = get_handle(); debug3("request %u: close handle %u", id, handle); handle_log_close(handle, NULL); + name=handle_to_name(handle); + namel=strlen(name); + name=calloc(1,namel+1); + memcpy(name,handle_to_name(handle),namel); ret = handle_close(handle); status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; + if(origname!=NULL && status==SSH2_FX_OK){ + if(rename(name,origname)){ + logit("error moving file %s: %s",name,strerror(errno)); + status = SSH2_FX_FAILURE; + } + xfree(origname); + } + xfree(name); send_status(id, status); } @@ -1341,7 +1366,7 @@ __progname = ssh_get_progname(argv[0]); log_init(__progname, log_level, log_facility, log_stderr); - while (!skipargs && (ch = getopt(argc, argv, "f:l:che")) != -1) { + while (!skipargs && (ch = getopt(argc, argv, "f:l:t:che")) != -1) { switch (ch) { case 'c': /* @@ -1363,6 +1388,10 @@ if (log_facility == SYSLOG_FACILITY_NOT_SET) error("Invalid log facility \"%s\"", optarg); break; + case 't': + tmpdir=calloc(1,strlen(optarg)+1); + memcpy(tmpdir,optarg,strlen(optarg)); + break; case 'h': default: sftp_server_usage(); @@ -1370,6 +1399,12 @@ } log_init(__progname, log_level, log_facility, log_stderr); + + if(tmpdir==NULL){ + tmpdir=calloc(1,6), + strcpy(tmpdir,"/tmp/"); + } + debug2("tmp dir: \"%s\"",tmpdir); if ((cp = getenv("SSH_CONNECTION")) != NULL) { client_addr = xstrdup(cp);