sfree(act.name);
sfree(act.buf);
static void sink(char *targ, char *src){    char *destfname;    int targisdir = 0;    int exists;    DWORD attr;    HANDLE f;    unsigned long received;    int wrerror = 0;    unsigned long stat_bytes;    time_t stat_starttime, stat_lasttime;    char *stat_name;    attr = GetFileAttributes(targ);    if (attr != (DWORD) - 1 && (attr & FILE_ATTRIBUTE_DIRECTORY) != 0)	targisdir = 1;    if (targetshouldbedirectory && !targisdir)	bump("%s: Not a directory", targ);    scp_sink_init();    while (1) {	struct scp_sink_action act;	if (scp_get_sink_action(&act))	    return;	if (act.action == SCP_SINK_ENDDIR)	    return;	if (act.action == SCP_SINK_RETRY)	    continue;	if (targisdir) {	    /*	     * Prevent the remote side from maliciously writing to	     * files outside the target area by sending a filename	     * containing `../'. In fact, it shouldn't be sending	     * filenames with any slashes or colons in at all; so	     * we'll find the last slash, backslash or colon in the	     * filename and use only the part after that. (And	     * warn!)	     * 	     * In addition, we also ensure here that if we're	     * copying a single file and the target is a directory	     * (common usage: `pscp host:filename .') the remote	     * can't send us a _different_ file name. We can	     * distinguish this case because `src' will be non-NULL	     * and the last component of that will fail to match	     * (the last component of) the name sent.	     * 	     * Well, not always; if `src' is a wildcard, we do	     * expect to get back filenames that don't correspond	     * exactly to it. Ideally in this case, we would like	     * to ensure that the returned filename actually	     * matches the wildcard pattern - but one of SCP's	     * protocol infelicities is that wildcard matching is	     * done at the server end _by the server's rules_ and	     * so in general this is infeasible. Hence, we only	     * accept filenames that don't correspond to `src' if	     * unsafe mode is enabled or we are using SFTP (which	     * resolves remote wildcards on the client side and can	     * be trusted).	     */	    char *striptarget, *stripsrc;	    striptarget = stripslashes(act.name, 1);	    if (striptarget != act.name) {		tell_user(stderr, "warning: remote host sent a compound"			  " pathname '%s'", act.name);		tell_user(stderr, "         renaming local file to '%s'",                          striptarget);	    }	    /*	     * Also check to see if the target filename is '.' or	     * '..', or indeed '...' and so on because Windows	     * appears to interpret those like '..'.	     */	    if (is_dots(striptarget)) {		bump("security violation: remote host attempted to write to"		     " a '.' or '..' path!");	    }	    if (src) {		stripsrc = stripslashes(src, 1);		if (strcmp(striptarget, stripsrc) &&		    !using_sftp && !scp_unsafe_mode) {		    tell_user(stderr, "warning: remote host tried to write "			      "to a file called '%s'", striptarget);		    tell_user(stderr, "         when we requested a file "			      "called '%s'.", stripsrc);		    tell_user(stderr, "         If this is a wildcard, "			      "consider upgrading to SSH 2 or using");		    tell_user(stderr, "         the '-unsafe' option. Renaming"			      " of this file has been disallowed.");		    /* Override the name the server provided with our own. */		    striptarget = stripsrc;		}	    }	    if (targ[0] != '\0')		destfname = dupcat(targ, "\\", striptarget, NULL);	    else		destfname = dupstr(striptarget);	} else {	    /*	     * In this branch of the if, the target area is a	     * single file with an explicitly specified name in any	     * case, so there's no danger.	     */	    destfname = dupstr(targ);	}	attr = GetFileAttributes(destfname);	exists = (attr != (DWORD) - 1);	if (act.action == SCP_SINK_DIR) {	    if (exists && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {		run_err("%s: Not a directory", destfname);		continue;	    }	    if (!exists) {		if (!CreateDirectory(destfname, NULL)) {		    run_err("%s: Cannot create directory", destfname);		    continue;		}	    }	    sink(destfname, NULL);	    /* can we set the timestamp for directories ? */	    continue;	}	f = CreateFile(destfname, GENERIC_WRITE, 0, NULL,		       CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);	if (f == INVALID_HANDLE_VALUE) {	    run_err("%s: Cannot create file", destfname);	    continue;	}	if (scp_accept_filexfer())	    return;	stat_bytes = 0;	stat_starttime = time(NULL);	stat_lasttime = 0;	stat_name = stripslashes(destfname, 1);	received = 0;	while (received < act.size) {	    char transbuf[4096];	    DWORD blksize, read, written;	    blksize = 4096;	    if (blksize > act.size - received)		blksize = act.size - received;	    read = scp_recv_filedata(transbuf, blksize);	    if (read <= 0)		bump("Lost connection");	    if (wrerror)		continue;	    if (!WriteFile(f, transbuf, read, &written, NULL) ||		written != read) {		wrerror = 1;		/* FIXME: in sftp we can actually abort the transfer */		if (statistics)		    printf("\r%-25.25s | %50s\n",			   stat_name,			   "Write error.. waiting for end of file");		continue;	    }	    if (statistics) {		stat_bytes += read;		if (time(NULL) > stat_lasttime ||		    received + read == act.size) {		    stat_lasttime = time(NULL);		    print_stats(stat_name, act.size, stat_bytes,				stat_starttime, stat_lasttime);		}	    }	    received += read;	}	if (act.settime) {	    FILETIME actime, wrtime;	    TIME_POSIX_TO_WIN(act.atime, actime);	    TIME_POSIX_TO_WIN(act.mtime, wrtime);	    SetFileTime(f, NULL, &actime, &wrtime);	}	CloseHandle(f);	if (wrerror) {	    run_err("%s: Write error", destfname);	    continue;	}	(void) scp_finish_filerecv();	sfree(destfname);	sfree(act.name);    }}