mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-03-22 14:39:24 -05:00
Windows PSCP now links against winsftp.c, and scp.c is now a
platform-independent source file. Haven't yet added the extra abstraction routines to uxsftp.c to create a Unix PSCP port, but it shouldn't take long. Also in this checkin, a change of semantics in platform_default_s(): now strings returned from it are expected to be dynamically allocated. [originally from svn r3420]
This commit is contained in:
parent
66fa6f320e
commit
bfb9b28393
4
Recipe
4
Recipe
@ -139,7 +139,8 @@ putty : [G] GUITERM NONSSH WINSSH be_all WINMISC win_res.res LIBS1
|
|||||||
puttytel : [G] GUITERM NONSSH be_nossh WINMISC win_res.res LIBS1
|
puttytel : [G] GUITERM NONSSH be_nossh WINMISC win_res.res LIBS1
|
||||||
plink : [C] plink console NONSSH WINSSH be_all logging WINMISC
|
plink : [C] plink console NONSSH WINSSH be_all logging WINMISC
|
||||||
+ plink.res LIBS2
|
+ plink.res LIBS2
|
||||||
pscp : [C] scp console WINSSH be_none SFTP wildcard WINMISC scp.res LIBS1
|
pscp : [C] scp winsftp console WINSSH be_none SFTP wildcard WINMISC
|
||||||
|
+ scp.res LIBS1
|
||||||
psftp : [C] psftp winsftp console WINSSH be_none SFTP WINMISC scp.res LIBS1
|
psftp : [C] psftp winsftp console WINSSH be_none SFTP WINMISC scp.res LIBS1
|
||||||
|
|
||||||
pageant : [G] pageant sshrsa sshpubk sshdes sshbn sshmd5 version tree234
|
pageant : [G] pageant sshrsa sshpubk sshdes sshbn sshmd5 version tree234
|
||||||
@ -159,6 +160,7 @@ puttytel : [X] UXTERM uxmisc misc ldisc settings pty uxsel be_nossh uxstore
|
|||||||
|
|
||||||
plink : [U] uxplink uxcons NONSSH UXSSH be_all logging UXMISC signal ux_x11
|
plink : [U] uxplink uxcons NONSSH UXSSH be_all logging UXMISC signal ux_x11
|
||||||
|
|
||||||
|
pscp : [U] scp uxsftp uxcons UXSSH be_none SFTP wildcard UXMISC
|
||||||
psftp : [U] psftp uxsftp uxcons UXSSH be_none SFTP UXMISC
|
psftp : [U] psftp uxsftp uxcons UXSSH be_none SFTP UXMISC
|
||||||
|
|
||||||
PuTTY : [M] terminal wcwidth ldiscucs logging be_all mac macdlg macevlog
|
PuTTY : [M] terminal wcwidth ldiscucs logging be_all mac macdlg macevlog
|
||||||
|
114
psftp.h
114
psftp.h
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* psftp.h: interface between psftp.c and each platform-specific
|
* psftp.h: interface between psftp.c / scp.c and each
|
||||||
* SFTP module.
|
* platform-specific SFTP module.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PUTTY_PSFTP_H
|
#ifndef PUTTY_PSFTP_H
|
||||||
@ -19,6 +19,13 @@ char *psftp_getcwd(void);
|
|||||||
*/
|
*/
|
||||||
char *psftp_lcd(char *newdir);
|
char *psftp_lcd(char *newdir);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieve file times on a local file. Must return two unsigned
|
||||||
|
* longs in POSIX time_t format.
|
||||||
|
*/
|
||||||
|
void get_file_times(char *filename, unsigned long *mtime,
|
||||||
|
unsigned long *atime);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* One iteration of the PSFTP event loop: wait for network data and
|
* One iteration of the PSFTP event loop: wait for network data and
|
||||||
* process it, once.
|
* process it, once.
|
||||||
@ -31,4 +38,107 @@ int ssh_sftp_loop_iteration(void);
|
|||||||
*/
|
*/
|
||||||
int psftp_main(int argc, char *argv[]);
|
int psftp_main(int argc, char *argv[]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These functions are used by PSCP to transmit progress updates
|
||||||
|
* and error information to a GUI window managing it. This will
|
||||||
|
* probably only ever be supported on Windows, so these functions
|
||||||
|
* can safely be stubs on all other platforms.
|
||||||
|
*/
|
||||||
|
void gui_update_stats(char *name, unsigned long size,
|
||||||
|
int percentage, unsigned long elapsed,
|
||||||
|
unsigned long done, unsigned long eta,
|
||||||
|
unsigned long ratebs);
|
||||||
|
void gui_send_errcount(int list, int errs);
|
||||||
|
void gui_send_char(int is_stderr, int c);
|
||||||
|
void gui_enable(char *arg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It's likely that a given platform's implementation of file
|
||||||
|
* transfer utilities is going to want to do things with them that
|
||||||
|
* aren't present in stdio. Hence we supply an alternative
|
||||||
|
* abstraction for file access functions.
|
||||||
|
*
|
||||||
|
* This abstraction tells you the size and access times when you
|
||||||
|
* open an existing file (platforms may choose the meaning of the
|
||||||
|
* file times if it's not clear; whatever they choose will be what
|
||||||
|
* PSCP sends to the server as mtime and atime), and lets you set
|
||||||
|
* the times when saving a new file.
|
||||||
|
*
|
||||||
|
* On the other hand, the abstraction is pretty simple: it supports
|
||||||
|
* only opening a file and reading it, or creating a file and
|
||||||
|
* writing it. (FIXME: to use this in PSFTP it will also need to
|
||||||
|
* support seeking to a starting point for restarted transfers.)
|
||||||
|
* None of this read-and-write, seeking-back-and-forth stuff.
|
||||||
|
*/
|
||||||
|
typedef struct RFile RFile;
|
||||||
|
typedef struct WFile WFile;
|
||||||
|
/* Output params size, mtime and atime can all be NULL if desired */
|
||||||
|
RFile *open_existing_file(char *name, unsigned long *size,
|
||||||
|
unsigned long *mtime, unsigned long *atime);
|
||||||
|
/* Returns <0 on error, 0 on eof, or number of bytes read, as usual */
|
||||||
|
int read_from_file(RFile *f, void *buffer, int length);
|
||||||
|
/* Closes and frees the RFile */
|
||||||
|
void close_rfile(RFile *f);
|
||||||
|
WFile *open_new_file(char *name);
|
||||||
|
/* Returns <0 on error, 0 on eof, or number of bytes written, as usual */
|
||||||
|
int write_to_file(WFile *f, void *buffer, int length);
|
||||||
|
void set_file_times(WFile *f, unsigned long mtime, unsigned long atime);
|
||||||
|
/* Closes and frees the WFile */
|
||||||
|
void close_wfile(WFile *f);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine the type of a file: nonexistent, file, directory or
|
||||||
|
* weird. `weird' covers anything else - named pipes, Unix sockets,
|
||||||
|
* device files, fish, badgers, you name it. Things marked `weird'
|
||||||
|
* will be skipped over in recursive file transfers, so the only
|
||||||
|
* real reason for not lumping them in with `nonexistent' is that
|
||||||
|
* it allows a slightly more sane error message.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
FILE_TYPE_NONEXISTENT, FILE_TYPE_FILE, FILE_TYPE_DIRECTORY, FILE_TYPE_WEIRD
|
||||||
|
};
|
||||||
|
int file_type(char *name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read all the file names out of a directory.
|
||||||
|
*/
|
||||||
|
typedef struct DirHandle DirHandle;
|
||||||
|
DirHandle *open_directory(char *name);
|
||||||
|
/* The string returned from this will need freeing if not NULL */
|
||||||
|
char *read_filename(DirHandle *dir);
|
||||||
|
void close_directory(DirHandle *dir);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test a filespec to see whether it's a local wildcard or not.
|
||||||
|
* Return values:
|
||||||
|
*
|
||||||
|
* - WCTYPE_WILDCARD (this is a wildcard).
|
||||||
|
* - WCTYPE_FILENAME (this is a single file name).
|
||||||
|
* - WCTYPE_NONEXISTENT (whichever it was, nothing of that name exists).
|
||||||
|
*
|
||||||
|
* Some platforms may choose not to support local wildcards when
|
||||||
|
* they come from the command line; in this case they simply never
|
||||||
|
* return WCTYPE_WILDCARD, but still test the file's existence.
|
||||||
|
* (However, all platforms will probably want to support wildcards
|
||||||
|
* inside the PSFTP CLI.)
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
WCTYPE_NONEXISTENT, WCTYPE_FILENAME, WCTYPE_WILDCARD
|
||||||
|
};
|
||||||
|
int test_wildcard(char *name, int cmdline);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Actually return matching file names for a local wildcard.
|
||||||
|
*/
|
||||||
|
typedef struct WildcardMatcher WildcardMatcher;
|
||||||
|
WildcardMatcher *begin_wildcard_matching(char *name);
|
||||||
|
/* The string returned from this will need freeing if not NULL */
|
||||||
|
char *wildcard_get_filename(WildcardMatcher *dir);
|
||||||
|
void finish_wildcard_matching(WildcardMatcher *dir);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a directory. Returns 0 on error, !=0 on success.
|
||||||
|
*/
|
||||||
|
int create_directory(char *name);
|
||||||
|
|
||||||
#endif /* PUTTY_PSFTP_H */
|
#endif /* PUTTY_PSFTP_H */
|
||||||
|
1
putty.h
1
putty.h
@ -845,5 +845,6 @@ Filename filename_from_str(const char *string);
|
|||||||
const char *filename_to_str(const Filename *fn);
|
const char *filename_to_str(const Filename *fn);
|
||||||
int filename_equal(Filename f1, Filename f2);
|
int filename_equal(Filename f1, Filename f2);
|
||||||
int filename_is_null(Filename fn);
|
int filename_is_null(Filename fn);
|
||||||
|
char *get_username(void); /* return value needs freeing */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
429
scp.c
429
scp.c
@ -12,14 +12,6 @@
|
|||||||
* to licensing issues.)
|
* to licensing issues.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#ifndef AUTO_WINSOCK
|
|
||||||
#ifdef WINSOCK_TWO
|
|
||||||
#include <winsock2.h>
|
|
||||||
#else
|
|
||||||
#include <winsock.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -29,54 +21,11 @@
|
|||||||
|
|
||||||
#define PUTTY_DO_GLOBALS
|
#define PUTTY_DO_GLOBALS
|
||||||
#include "putty.h"
|
#include "putty.h"
|
||||||
|
#include "psftp.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "sftp.h"
|
#include "sftp.h"
|
||||||
#include "winstuff.h"
|
|
||||||
#include "storage.h"
|
#include "storage.h"
|
||||||
|
|
||||||
#define TIME_POSIX_TO_WIN(t, ft) (*(LONGLONG*)&(ft) = \
|
|
||||||
((LONGLONG) (t) + (LONGLONG) 11644473600) * (LONGLONG) 10000000)
|
|
||||||
#define TIME_WIN_TO_POSIX(ft, t) ((t) = (unsigned long) \
|
|
||||||
((*(LONGLONG*)&(ft)) / (LONGLONG) 10000000 - (LONGLONG) 11644473600))
|
|
||||||
|
|
||||||
/* GUI Adaptation - Sept 2000 */
|
|
||||||
|
|
||||||
/* This is just a base value from which the main message numbers are
|
|
||||||
* derived. */
|
|
||||||
#define WM_APP_BASE 0x8000
|
|
||||||
|
|
||||||
/* These two pass a single character value in wParam. They represent
|
|
||||||
* the visible output from PSCP. */
|
|
||||||
#define WM_STD_OUT_CHAR ( WM_APP_BASE+400 )
|
|
||||||
#define WM_STD_ERR_CHAR ( WM_APP_BASE+401 )
|
|
||||||
|
|
||||||
/* These pass a transfer status update. WM_STATS_CHAR passes a single
|
|
||||||
* character in wParam, and is called repeatedly to pass the name of
|
|
||||||
* the file, terminated with "\n". WM_STATS_SIZE passes the size of
|
|
||||||
* the file being transferred in wParam. WM_STATS_ELAPSED is called
|
|
||||||
* to pass the elapsed time (in seconds) in wParam, and
|
|
||||||
* WM_STATS_PERCENT passes the percentage of the transfer which is
|
|
||||||
* complete, also in wParam. */
|
|
||||||
#define WM_STATS_CHAR ( WM_APP_BASE+402 )
|
|
||||||
#define WM_STATS_SIZE ( WM_APP_BASE+403 )
|
|
||||||
#define WM_STATS_PERCENT ( WM_APP_BASE+404 )
|
|
||||||
#define WM_STATS_ELAPSED ( WM_APP_BASE+405 )
|
|
||||||
|
|
||||||
/* These are used at the end of a run to pass an error code in
|
|
||||||
* wParam: zero means success, nonzero means failure. WM_RET_ERR_CNT
|
|
||||||
* is used after a copy, and WM_LS_RET_ERR_CNT is used after a file
|
|
||||||
* list operation. */
|
|
||||||
#define WM_RET_ERR_CNT ( WM_APP_BASE+406 )
|
|
||||||
#define WM_LS_RET_ERR_CNT ( WM_APP_BASE+407 )
|
|
||||||
|
|
||||||
/* More transfer status update messages. WM_STATS_DONE passes the
|
|
||||||
* number of bytes sent so far in wParam. WM_STATS_ETA passes the
|
|
||||||
* estimated time to completion (in seconds). WM_STATS_RATEBS passes
|
|
||||||
* the average transfer rate (in bytes per second). */
|
|
||||||
#define WM_STATS_DONE ( WM_APP_BASE+408 )
|
|
||||||
#define WM_STATS_ETA ( WM_APP_BASE+409 )
|
|
||||||
#define WM_STATS_RATEBS ( WM_APP_BASE+410 )
|
|
||||||
|
|
||||||
static int list = 0;
|
static int list = 0;
|
||||||
static int verbose = 0;
|
static int verbose = 0;
|
||||||
static int recursive = 0;
|
static int recursive = 0;
|
||||||
@ -86,17 +35,7 @@ static int statistics = 1;
|
|||||||
static int prev_stats_len = 0;
|
static int prev_stats_len = 0;
|
||||||
static int scp_unsafe_mode = 0;
|
static int scp_unsafe_mode = 0;
|
||||||
static int errs = 0;
|
static int errs = 0;
|
||||||
/* GUI Adaptation - Sept 2000 */
|
|
||||||
#define NAME_STR_MAX 2048
|
|
||||||
static char statname[NAME_STR_MAX + 1];
|
|
||||||
static unsigned long statsize = 0;
|
|
||||||
static unsigned long statdone = 0;
|
|
||||||
static unsigned long stateta = 0;
|
|
||||||
static unsigned long statratebs = 0;
|
|
||||||
static int statperct = 0;
|
|
||||||
static unsigned long statelapsed = 0;
|
|
||||||
static int gui_mode = 0;
|
static int gui_mode = 0;
|
||||||
static char *gui_hwnd = NULL;
|
|
||||||
static int using_sftp = 0;
|
static int using_sftp = 0;
|
||||||
|
|
||||||
static Backend *back;
|
static Backend *back;
|
||||||
@ -106,14 +45,6 @@ static Config cfg;
|
|||||||
static void source(char *src);
|
static void source(char *src);
|
||||||
static void rsource(char *src);
|
static void rsource(char *src);
|
||||||
static void sink(char *targ, char *src);
|
static void sink(char *targ, char *src);
|
||||||
/* GUI Adaptation - Sept 2000 */
|
|
||||||
static void tell_char(FILE * stream, char c);
|
|
||||||
static void tell_str(FILE * stream, char *str);
|
|
||||||
static void tell_user(FILE * stream, char *fmt, ...);
|
|
||||||
static void gui_update_stats(char *name, unsigned long size,
|
|
||||||
int percentage, unsigned long elapsed,
|
|
||||||
unsigned long done, unsigned long eta,
|
|
||||||
unsigned long ratebs);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The maximum amount of queued data we accept before we stop and
|
* The maximum amount of queued data we accept before we stop and
|
||||||
@ -132,23 +63,12 @@ void ldisc_send(void *handle, char *buf, int len, int interactive)
|
|||||||
assert(len == 0);
|
assert(len == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GUI Adaptation - Sept 2000 */
|
|
||||||
static void send_msg(HWND h, UINT message, WPARAM wParam)
|
|
||||||
{
|
|
||||||
while (!PostMessage(h, message, wParam, 0))
|
|
||||||
SleepEx(1000, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tell_char(FILE * stream, char c)
|
static void tell_char(FILE * stream, char c)
|
||||||
{
|
{
|
||||||
if (!gui_mode)
|
if (!gui_mode)
|
||||||
fputc(c, stream);
|
fputc(c, stream);
|
||||||
else {
|
else
|
||||||
unsigned int msg_id = WM_STD_OUT_CHAR;
|
gui_send_char(stream == stderr, c);
|
||||||
if (stream == stderr)
|
|
||||||
msg_id = WM_STD_ERR_CHAR;
|
|
||||||
send_msg((HWND) atoi(gui_hwnd), msg_id, (WPARAM) c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tell_str(FILE * stream, char *str)
|
static void tell_str(FILE * stream, char *str)
|
||||||
@ -172,48 +92,6 @@ static void tell_user(FILE * stream, char *fmt, ...)
|
|||||||
sfree(str2);
|
sfree(str2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gui_update_stats(char *name, unsigned long size,
|
|
||||||
int percentage, unsigned long elapsed,
|
|
||||||
unsigned long done, unsigned long eta,
|
|
||||||
unsigned long ratebs)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
if (strcmp(name, statname) != 0) {
|
|
||||||
for (i = 0; i < strlen(name); ++i)
|
|
||||||
send_msg((HWND) atoi(gui_hwnd), WM_STATS_CHAR,
|
|
||||||
(WPARAM) name[i]);
|
|
||||||
send_msg((HWND) atoi(gui_hwnd), WM_STATS_CHAR, (WPARAM) '\n');
|
|
||||||
strcpy(statname, name);
|
|
||||||
}
|
|
||||||
if (statsize != size) {
|
|
||||||
send_msg((HWND) atoi(gui_hwnd), WM_STATS_SIZE, (WPARAM) size);
|
|
||||||
statsize = size;
|
|
||||||
}
|
|
||||||
if (statdone != done) {
|
|
||||||
send_msg((HWND) atoi(gui_hwnd), WM_STATS_DONE, (WPARAM) done);
|
|
||||||
statdone = done;
|
|
||||||
}
|
|
||||||
if (stateta != eta) {
|
|
||||||
send_msg((HWND) atoi(gui_hwnd), WM_STATS_ETA, (WPARAM) eta);
|
|
||||||
stateta = eta;
|
|
||||||
}
|
|
||||||
if (statratebs != ratebs) {
|
|
||||||
send_msg((HWND) atoi(gui_hwnd), WM_STATS_RATEBS, (WPARAM) ratebs);
|
|
||||||
statratebs = ratebs;
|
|
||||||
}
|
|
||||||
if (statelapsed != elapsed) {
|
|
||||||
send_msg((HWND) atoi(gui_hwnd), WM_STATS_ELAPSED,
|
|
||||||
(WPARAM) elapsed);
|
|
||||||
statelapsed = elapsed;
|
|
||||||
}
|
|
||||||
if (statperct != percentage) {
|
|
||||||
send_msg((HWND) atoi(gui_hwnd), WM_STATS_PERCENT,
|
|
||||||
(WPARAM) percentage);
|
|
||||||
statperct = percentage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print an error message and perform a fatal exit.
|
* Print an error message and perform a fatal exit.
|
||||||
*/
|
*/
|
||||||
@ -230,14 +108,8 @@ void fatalbox(char *fmt, ...)
|
|||||||
sfree(str2);
|
sfree(str2);
|
||||||
errs++;
|
errs++;
|
||||||
|
|
||||||
if (gui_mode) {
|
if (gui_mode)
|
||||||
unsigned int msg_id = WM_RET_ERR_CNT;
|
gui_send_errcount(list, errs);
|
||||||
if (list)
|
|
||||||
msg_id = WM_LS_RET_ERR_CNT;
|
|
||||||
while (!PostMessage
|
|
||||||
((HWND) atoi(gui_hwnd), msg_id, (WPARAM) errs,
|
|
||||||
0 /*lParam */ ))SleepEx(1000, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup_exit(1);
|
cleanup_exit(1);
|
||||||
}
|
}
|
||||||
@ -254,14 +126,8 @@ void modalfatalbox(char *fmt, ...)
|
|||||||
sfree(str2);
|
sfree(str2);
|
||||||
errs++;
|
errs++;
|
||||||
|
|
||||||
if (gui_mode) {
|
if (gui_mode)
|
||||||
unsigned int msg_id = WM_RET_ERR_CNT;
|
gui_send_errcount(list, errs);
|
||||||
if (list)
|
|
||||||
msg_id = WM_LS_RET_ERR_CNT;
|
|
||||||
while (!PostMessage
|
|
||||||
((HWND) atoi(gui_hwnd), msg_id, (WPARAM) errs,
|
|
||||||
0 /*lParam */ ))SleepEx(1000, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup_exit(1);
|
cleanup_exit(1);
|
||||||
}
|
}
|
||||||
@ -278,32 +144,12 @@ void connection_fatal(void *frontend, char *fmt, ...)
|
|||||||
sfree(str2);
|
sfree(str2);
|
||||||
errs++;
|
errs++;
|
||||||
|
|
||||||
if (gui_mode) {
|
if (gui_mode)
|
||||||
unsigned int msg_id = WM_RET_ERR_CNT;
|
gui_send_errcount(list, errs);
|
||||||
if (list)
|
|
||||||
msg_id = WM_LS_RET_ERR_CNT;
|
|
||||||
while (!PostMessage
|
|
||||||
((HWND) atoi(gui_hwnd), msg_id, (WPARAM) errs,
|
|
||||||
0 /*lParam */ ))SleepEx(1000, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup_exit(1);
|
cleanup_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Be told what socket we're supposed to be using.
|
|
||||||
*/
|
|
||||||
static SOCKET scp_ssh_socket;
|
|
||||||
char *do_select(SOCKET skt, int startup)
|
|
||||||
{
|
|
||||||
if (startup)
|
|
||||||
scp_ssh_socket = skt;
|
|
||||||
else
|
|
||||||
scp_ssh_socket = INVALID_SOCKET;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
extern int select_result(WPARAM, LPARAM);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In pscp, all agent requests should be synchronous, so this is a
|
* In pscp, all agent requests should be synchronous, so this is a
|
||||||
* never-called stub.
|
* never-called stub.
|
||||||
@ -373,17 +219,6 @@ int from_backend(void *frontend, int is_stderr, const char *data, int datalen)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static int scp_process_network_event(void)
|
|
||||||
{
|
|
||||||
fd_set readfds;
|
|
||||||
|
|
||||||
FD_ZERO(&readfds);
|
|
||||||
FD_SET(scp_ssh_socket, &readfds);
|
|
||||||
if (select(1, &readfds, NULL, NULL, NULL) < 0)
|
|
||||||
return 0; /* doom */
|
|
||||||
select_result((WPARAM) scp_ssh_socket, (LPARAM) FD_READ);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
static int ssh_scp_recv(unsigned char *buf, int len)
|
static int ssh_scp_recv(unsigned char *buf, int len)
|
||||||
{
|
{
|
||||||
outptr = buf;
|
outptr = buf;
|
||||||
@ -412,7 +247,7 @@ static int ssh_scp_recv(unsigned char *buf, int len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (outlen > 0) {
|
while (outlen > 0) {
|
||||||
if (!scp_process_network_event())
|
if (ssh_sftp_loop_iteration() < 0)
|
||||||
return 0; /* doom */
|
return 0; /* doom */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,15 +259,9 @@ static int ssh_scp_recv(unsigned char *buf, int len)
|
|||||||
*/
|
*/
|
||||||
static void ssh_scp_init(void)
|
static void ssh_scp_init(void)
|
||||||
{
|
{
|
||||||
if (scp_ssh_socket == INVALID_SOCKET)
|
|
||||||
return;
|
|
||||||
while (!back->sendok(backhandle)) {
|
while (!back->sendok(backhandle)) {
|
||||||
fd_set readfds;
|
if (ssh_sftp_loop_iteration() < 0)
|
||||||
FD_ZERO(&readfds);
|
|
||||||
FD_SET(scp_ssh_socket, &readfds);
|
|
||||||
if (select(1, &readfds, NULL, NULL, NULL) < 0)
|
|
||||||
return; /* doom */
|
return; /* doom */
|
||||||
select_result((WPARAM) scp_ssh_socket, (LPARAM) FD_READ);
|
|
||||||
}
|
}
|
||||||
using_sftp = !ssh_fallback_cmd(backhandle);
|
using_sftp = !ssh_fallback_cmd(backhandle);
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
@ -465,14 +294,8 @@ static void bump(char *fmt, ...)
|
|||||||
ssh_scp_recv(&ch, 1);
|
ssh_scp_recv(&ch, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gui_mode) {
|
if (gui_mode)
|
||||||
unsigned int msg_id = WM_RET_ERR_CNT;
|
gui_send_errcount(list, errs);
|
||||||
if (list)
|
|
||||||
msg_id = WM_LS_RET_ERR_CNT;
|
|
||||||
while (!PostMessage
|
|
||||||
((HWND) atoi(gui_hwnd), msg_id, (WPARAM) errs,
|
|
||||||
0 /*lParam */ ))SleepEx(1000, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup_exit(1);
|
cleanup_exit(1);
|
||||||
}
|
}
|
||||||
@ -484,7 +307,7 @@ static void do_cmd(char *host, char *user, char *cmd)
|
|||||||
{
|
{
|
||||||
const char *err;
|
const char *err;
|
||||||
char *realhost;
|
char *realhost;
|
||||||
DWORD namelen;
|
void *logctx;
|
||||||
|
|
||||||
if (host == NULL || host[0] == '\0')
|
if (host == NULL || host[0] == '\0')
|
||||||
bump("Empty host name");
|
bump("Empty host name");
|
||||||
@ -558,16 +381,16 @@ static void do_cmd(char *host, char *user, char *cmd)
|
|||||||
strncpy(cfg.username, user, sizeof(cfg.username) - 1);
|
strncpy(cfg.username, user, sizeof(cfg.username) - 1);
|
||||||
cfg.username[sizeof(cfg.username) - 1] = '\0';
|
cfg.username[sizeof(cfg.username) - 1] = '\0';
|
||||||
} else if (cfg.username[0] == '\0') {
|
} else if (cfg.username[0] == '\0') {
|
||||||
namelen = 0;
|
user = get_username();
|
||||||
if (GetUserName(user, &namelen) == FALSE)
|
if (!user)
|
||||||
bump("Empty user name");
|
bump("Empty user name");
|
||||||
user = snewn(namelen, char);
|
else {
|
||||||
GetUserName(user, &namelen);
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
tell_user(stderr, "Guessing user name: %s", user);
|
tell_user(stderr, "Guessing user name: %s", user);
|
||||||
strncpy(cfg.username, user, sizeof(cfg.username) - 1);
|
strncpy(cfg.username, user, sizeof(cfg.username) - 1);
|
||||||
cfg.username[sizeof(cfg.username) - 1] = '\0';
|
cfg.username[sizeof(cfg.username) - 1] = '\0';
|
||||||
free(user);
|
sfree(user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -632,11 +455,10 @@ static void print_stats(char *name, unsigned long size, unsigned long done,
|
|||||||
|
|
||||||
pct = (int) (100 * (done * 1.0 / size));
|
pct = (int) (100 * (done * 1.0 / size));
|
||||||
|
|
||||||
if (gui_mode)
|
if (gui_mode) {
|
||||||
/* GUI Adaptation - Sept 2000 */
|
|
||||||
gui_update_stats(name, size, pct, elap, done, eta,
|
gui_update_stats(name, size, pct, elap, done, eta,
|
||||||
(unsigned long) ratebs);
|
(unsigned long) ratebs);
|
||||||
else {
|
} else {
|
||||||
len = printf("\r%-25.25s | %10ld kB | %5.1f kB/s | ETA: %8s | %3d%%",
|
len = printf("\r%-25.25s | %10ld kB | %5.1f kB/s | ETA: %8s | %3d%%",
|
||||||
name, done / 1024, ratebs / 1024.0, etastr, pct);
|
name, done / 1024, ratebs / 1024.0, etastr, pct);
|
||||||
if (len < prev_stats_len)
|
if (len < prev_stats_len)
|
||||||
@ -991,7 +813,7 @@ int scp_send_filedata(char *data, int len)
|
|||||||
* we have space in the buffer again.
|
* we have space in the buffer again.
|
||||||
*/
|
*/
|
||||||
while (bufsize > MAX_SCP_BUFSIZE) {
|
while (bufsize > MAX_SCP_BUFSIZE) {
|
||||||
if (!scp_process_network_event())
|
if (ssh_sftp_loop_iteration() < 0)
|
||||||
return 1;
|
return 1;
|
||||||
bufsize = back->sendbuffer(backhandle);
|
bufsize = back->sendbuffer(backhandle);
|
||||||
}
|
}
|
||||||
@ -1645,20 +1467,23 @@ static void run_err(const char *fmt, ...)
|
|||||||
static void source(char *src)
|
static void source(char *src)
|
||||||
{
|
{
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
|
unsigned long mtime, atime;
|
||||||
char *last;
|
char *last;
|
||||||
HANDLE f;
|
RFile *f;
|
||||||
DWORD attr;
|
int attr;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
unsigned long stat_bytes;
|
unsigned long stat_bytes;
|
||||||
time_t stat_starttime, stat_lasttime;
|
time_t stat_starttime, stat_lasttime;
|
||||||
|
|
||||||
attr = GetFileAttributes(src);
|
attr = file_type(src);
|
||||||
if (attr == (DWORD) - 1) {
|
if (attr == FILE_TYPE_NONEXISTENT ||
|
||||||
run_err("%s: No such file or directory", src);
|
attr == FILE_TYPE_WEIRD) {
|
||||||
|
run_err("%s: %s file or directory", src,
|
||||||
|
(attr == FILE_TYPE_WEIRD ? "Not a" : "No such"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
|
if (attr == FILE_TYPE_DIRECTORY) {
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
/*
|
/*
|
||||||
* Avoid . and .. directories.
|
* Avoid . and .. directories.
|
||||||
@ -1690,24 +1515,16 @@ static void source(char *src)
|
|||||||
if (last == src && strchr(src, ':') != NULL)
|
if (last == src && strchr(src, ':') != NULL)
|
||||||
last = strchr(src, ':') + 1;
|
last = strchr(src, ':') + 1;
|
||||||
|
|
||||||
f = CreateFile(src, GENERIC_READ, FILE_SHARE_READ, NULL,
|
f = open_existing_file(src, &size, &mtime, &atime);
|
||||||
OPEN_EXISTING, 0, 0);
|
if (f == NULL) {
|
||||||
if (f == INVALID_HANDLE_VALUE) {
|
|
||||||
run_err("%s: Cannot open file", src);
|
run_err("%s: Cannot open file", src);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preserve) {
|
if (preserve) {
|
||||||
FILETIME actime, wrtime;
|
|
||||||
unsigned long mtime, atime;
|
|
||||||
GetFileTime(f, NULL, &actime, &wrtime);
|
|
||||||
TIME_WIN_TO_POSIX(actime, atime);
|
|
||||||
TIME_WIN_TO_POSIX(wrtime, mtime);
|
|
||||||
if (scp_send_filetimes(mtime, atime))
|
if (scp_send_filetimes(mtime, atime))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = GetFileSize(f, NULL);
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
tell_user(stderr, "Sending file %s, size=%lu", last, size);
|
tell_user(stderr, "Sending file %s, size=%lu", last, size);
|
||||||
if (scp_send_filename(last, size, 0644))
|
if (scp_send_filename(last, size, 0644))
|
||||||
@ -1719,11 +1536,11 @@ static void source(char *src)
|
|||||||
|
|
||||||
for (i = 0; i < size; i += 4096) {
|
for (i = 0; i < size; i += 4096) {
|
||||||
char transbuf[4096];
|
char transbuf[4096];
|
||||||
DWORD j, k = 4096;
|
int j, k = 4096;
|
||||||
|
|
||||||
if (i + k > size)
|
if (i + k > size)
|
||||||
k = size - i;
|
k = size - i;
|
||||||
if (!ReadFile(f, transbuf, k, &j, NULL) || j != k) {
|
if ((j = read_from_file(f, transbuf, k)) != k) {
|
||||||
if (statistics)
|
if (statistics)
|
||||||
printf("\n");
|
printf("\n");
|
||||||
bump("%s: Read error", src);
|
bump("%s: Read error", src);
|
||||||
@ -1741,7 +1558,7 @@ static void source(char *src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
CloseHandle(f);
|
close_rfile(f);
|
||||||
|
|
||||||
(void) scp_send_finish();
|
(void) scp_send_finish();
|
||||||
}
|
}
|
||||||
@ -1751,11 +1568,9 @@ static void source(char *src)
|
|||||||
*/
|
*/
|
||||||
static void rsource(char *src)
|
static void rsource(char *src)
|
||||||
{
|
{
|
||||||
char *last, *findfile;
|
char *last;
|
||||||
char *save_target;
|
char *save_target;
|
||||||
HANDLE dir;
|
DirHandle *dir;
|
||||||
WIN32_FIND_DATA fdat;
|
|
||||||
int ok;
|
|
||||||
|
|
||||||
if ((last = strrchr(src, '/')) == NULL)
|
if ((last = strrchr(src, '/')) == NULL)
|
||||||
last = src;
|
last = src;
|
||||||
@ -1775,22 +1590,17 @@ static void rsource(char *src)
|
|||||||
if (scp_send_dirname(last, 0755))
|
if (scp_send_dirname(last, 0755))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
findfile = dupcat(src, "/*", NULL);
|
dir = open_directory(src);
|
||||||
dir = FindFirstFile(findfile, &fdat);
|
if (dir != NULL) {
|
||||||
ok = (dir != INVALID_HANDLE_VALUE);
|
char *filename;
|
||||||
while (ok) {
|
while ((filename = read_filename(dir)) != NULL) {
|
||||||
if (strcmp(fdat.cFileName, ".") == 0 ||
|
char *foundfile = dupcat(src, "/", filename, NULL);
|
||||||
strcmp(fdat.cFileName, "..") == 0) {
|
|
||||||
/* ignore . and .. */
|
|
||||||
} else {
|
|
||||||
char *foundfile = dupcat(src, "/", fdat.cFileName, NULL);
|
|
||||||
source(foundfile);
|
source(foundfile);
|
||||||
sfree(foundfile);
|
sfree(foundfile);
|
||||||
|
sfree(filename);
|
||||||
}
|
}
|
||||||
ok = FindNextFile(dir, &fdat);
|
|
||||||
}
|
}
|
||||||
FindClose(dir);
|
close_directory(dir);
|
||||||
sfree(findfile);
|
|
||||||
|
|
||||||
(void) scp_send_enddir();
|
(void) scp_send_enddir();
|
||||||
|
|
||||||
@ -1805,16 +1615,16 @@ static void sink(char *targ, char *src)
|
|||||||
char *destfname;
|
char *destfname;
|
||||||
int targisdir = 0;
|
int targisdir = 0;
|
||||||
int exists;
|
int exists;
|
||||||
DWORD attr;
|
int attr;
|
||||||
HANDLE f;
|
WFile *f;
|
||||||
unsigned long received;
|
unsigned long received;
|
||||||
int wrerror = 0;
|
int wrerror = 0;
|
||||||
unsigned long stat_bytes;
|
unsigned long stat_bytes;
|
||||||
time_t stat_starttime, stat_lasttime;
|
time_t stat_starttime, stat_lasttime;
|
||||||
char *stat_name;
|
char *stat_name;
|
||||||
|
|
||||||
attr = GetFileAttributes(targ);
|
attr = file_type(targ);
|
||||||
if (attr != (DWORD) - 1 && (attr & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
if (attr == FILE_TYPE_DIRECTORY)
|
||||||
targisdir = 1;
|
targisdir = 1;
|
||||||
|
|
||||||
if (targetshouldbedirectory && !targisdir)
|
if (targetshouldbedirectory && !targisdir)
|
||||||
@ -1912,16 +1722,16 @@ static void sink(char *targ, char *src)
|
|||||||
*/
|
*/
|
||||||
destfname = dupstr(targ);
|
destfname = dupstr(targ);
|
||||||
}
|
}
|
||||||
attr = GetFileAttributes(destfname);
|
attr = file_type(destfname);
|
||||||
exists = (attr != (DWORD) - 1);
|
exists = (attr != FILE_TYPE_NONEXISTENT);
|
||||||
|
|
||||||
if (act.action == SCP_SINK_DIR) {
|
if (act.action == SCP_SINK_DIR) {
|
||||||
if (exists && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
|
if (exists && attr != FILE_TYPE_DIRECTORY) {
|
||||||
run_err("%s: Not a directory", destfname);
|
run_err("%s: Not a directory", destfname);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
if (!CreateDirectory(destfname, NULL)) {
|
if (!create_directory(destfname)) {
|
||||||
run_err("%s: Cannot create directory", destfname);
|
run_err("%s: Cannot create directory", destfname);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1931,9 +1741,8 @@ static void sink(char *targ, char *src)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = CreateFile(destfname, GENERIC_WRITE, 0, NULL,
|
f = open_new_file(destfname);
|
||||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
if (f == NULL) {
|
||||||
if (f == INVALID_HANDLE_VALUE) {
|
|
||||||
run_err("%s: Cannot create file", destfname);
|
run_err("%s: Cannot create file", destfname);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1949,17 +1758,16 @@ static void sink(char *targ, char *src)
|
|||||||
received = 0;
|
received = 0;
|
||||||
while (received < act.size) {
|
while (received < act.size) {
|
||||||
char transbuf[4096];
|
char transbuf[4096];
|
||||||
DWORD blksize, read, written;
|
int blksize, read;
|
||||||
blksize = 4096;
|
blksize = 4096;
|
||||||
if (blksize > act.size - received)
|
if (blksize > (int)(act.size - received))
|
||||||
blksize = act.size - received;
|
blksize = act.size - received;
|
||||||
read = scp_recv_filedata(transbuf, blksize);
|
read = scp_recv_filedata(transbuf, blksize);
|
||||||
if (read <= 0)
|
if (read <= 0)
|
||||||
bump("Lost connection");
|
bump("Lost connection");
|
||||||
if (wrerror)
|
if (wrerror)
|
||||||
continue;
|
continue;
|
||||||
if (!WriteFile(f, transbuf, read, &written, NULL) ||
|
if (write_to_file(f, transbuf, read) != (int)read) {
|
||||||
written != read) {
|
|
||||||
wrerror = 1;
|
wrerror = 1;
|
||||||
/* FIXME: in sftp we can actually abort the transfer */
|
/* FIXME: in sftp we can actually abort the transfer */
|
||||||
if (statistics)
|
if (statistics)
|
||||||
@ -1980,13 +1788,10 @@ static void sink(char *targ, char *src)
|
|||||||
received += read;
|
received += read;
|
||||||
}
|
}
|
||||||
if (act.settime) {
|
if (act.settime) {
|
||||||
FILETIME actime, wrtime;
|
set_file_times(f, act.mtime, act.atime);
|
||||||
TIME_POSIX_TO_WIN(act.atime, actime);
|
|
||||||
TIME_POSIX_TO_WIN(act.mtime, wrtime);
|
|
||||||
SetFileTime(f, NULL, &actime, &wrtime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(f);
|
close_wfile(f);
|
||||||
if (wrerror) {
|
if (wrerror) {
|
||||||
run_err("%s: Write error", destfname);
|
run_err("%s: Write error", destfname);
|
||||||
continue;
|
continue;
|
||||||
@ -2004,7 +1809,7 @@ static void toremote(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
char *src, *targ, *host, *user;
|
char *src, *targ, *host, *user;
|
||||||
char *cmd;
|
char *cmd;
|
||||||
int i;
|
int i, wc_type;
|
||||||
|
|
||||||
targ = argv[argc - 1];
|
targ = argv[argc - 1];
|
||||||
|
|
||||||
@ -2031,18 +1836,14 @@ static void toremote(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (argc == 2) {
|
if (argc == 2) {
|
||||||
/* Find out if the source filespec covers multiple files
|
|
||||||
if so, we should set the targetshouldbedirectory flag */
|
|
||||||
HANDLE fh;
|
|
||||||
WIN32_FIND_DATA fdat;
|
|
||||||
if (colon(argv[0]) != NULL)
|
if (colon(argv[0]) != NULL)
|
||||||
bump("%s: Remote to remote not supported", argv[0]);
|
bump("%s: Remote to remote not supported", argv[0]);
|
||||||
fh = FindFirstFile(argv[0], &fdat);
|
|
||||||
if (fh == INVALID_HANDLE_VALUE)
|
wc_type = test_wildcard(argv[0], 1);
|
||||||
|
if (wc_type == WCTYPE_NONEXISTENT)
|
||||||
bump("%s: No such file or directory\n", argv[0]);
|
bump("%s: No such file or directory\n", argv[0]);
|
||||||
if (FindNextFile(fh, &fdat))
|
else if (wc_type == WCTYPE_WILDCARD)
|
||||||
targetshouldbedirectory = 1;
|
targetshouldbedirectory = 1;
|
||||||
FindClose(fh);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = dupprintf("scp%s%s%s%s -t %s",
|
cmd = dupprintf("scp%s%s%s%s -t %s",
|
||||||
@ -2056,9 +1857,6 @@ static void toremote(int argc, char *argv[])
|
|||||||
scp_source_setup(targ, targetshouldbedirectory);
|
scp_source_setup(targ, targetshouldbedirectory);
|
||||||
|
|
||||||
for (i = 0; i < argc - 1; i++) {
|
for (i = 0; i < argc - 1; i++) {
|
||||||
char *srcpath, *last;
|
|
||||||
HANDLE dir;
|
|
||||||
WIN32_FIND_DATA fdat;
|
|
||||||
src = argv[i];
|
src = argv[i];
|
||||||
if (colon(src) != NULL) {
|
if (colon(src) != NULL) {
|
||||||
tell_user(stderr, "%s: Remote to remote not supported\n", src);
|
tell_user(stderr, "%s: Remote to remote not supported\n", src);
|
||||||
@ -2066,49 +1864,30 @@ static void toremote(int argc, char *argv[])
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
wc_type = test_wildcard(src, 1);
|
||||||
* Trim off the last pathname component of `src', to
|
if (wc_type == WCTYPE_NONEXISTENT) {
|
||||||
* provide the base pathname which will be prepended to
|
run_err("%s: No such file or directory", src);
|
||||||
* filenames returned from Find{First,Next}File.
|
continue;
|
||||||
*/
|
} else if (wc_type == WCTYPE_FILENAME) {
|
||||||
srcpath = dupstr(src);
|
source(src);
|
||||||
last = stripslashes(srcpath, 1);
|
continue;
|
||||||
*last = '\0';
|
} else {
|
||||||
|
WildcardMatcher *wc;
|
||||||
|
char *filename;
|
||||||
|
|
||||||
dir = FindFirstFile(src, &fdat);
|
wc = begin_wildcard_matching(src);
|
||||||
if (dir == INVALID_HANDLE_VALUE) {
|
if (wc == NULL) {
|
||||||
run_err("%s: No such file or directory", src);
|
run_err("%s: No such file or directory", src);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
do {
|
|
||||||
char *filename;
|
while ((filename = wildcard_get_filename(wc)) != NULL) {
|
||||||
/*
|
|
||||||
* Ensure that . and .. are never matched by wildcards,
|
|
||||||
* but only by deliberate action.
|
|
||||||
*/
|
|
||||||
if (!strcmp(fdat.cFileName, ".") ||
|
|
||||||
!strcmp(fdat.cFileName, "..")) {
|
|
||||||
/*
|
|
||||||
* Find*File has returned a special dir. We require
|
|
||||||
* that _either_ `src' ends in a backslash followed
|
|
||||||
* by that string, _or_ `src' is precisely that
|
|
||||||
* string.
|
|
||||||
*/
|
|
||||||
int len = strlen(src), dlen = strlen(fdat.cFileName);
|
|
||||||
if (len == dlen && !strcmp(src, fdat.cFileName)) {
|
|
||||||
/* ok */ ;
|
|
||||||
} else if (len > dlen + 1 && src[len - dlen - 1] == '\\' &&
|
|
||||||
!strcmp(src + len - dlen, fdat.cFileName)) {
|
|
||||||
/* ok */ ;
|
|
||||||
} else
|
|
||||||
continue; /* ignore this one */
|
|
||||||
}
|
|
||||||
filename = dupcat(srcpath, fdat.cFileName, NULL);
|
|
||||||
source(filename);
|
source(filename);
|
||||||
sfree(filename);
|
sfree(filename);
|
||||||
} while (FindNextFile(dir, &fdat));
|
}
|
||||||
FindClose(dir);
|
|
||||||
sfree(srcpath);
|
finish_wildcard_matching(wc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2222,21 +2001,6 @@ static void get_dir_list(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize the Win$ock driver.
|
|
||||||
*/
|
|
||||||
static void init_winsock(void)
|
|
||||||
{
|
|
||||||
WORD winsock_ver;
|
|
||||||
WSADATA wsadata;
|
|
||||||
|
|
||||||
winsock_ver = MAKEWORD(1, 1);
|
|
||||||
if (WSAStartup(winsock_ver, &wsadata))
|
|
||||||
bump("Unable to initialise WinSock");
|
|
||||||
if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1)
|
|
||||||
bump("WinSock version is incompatible with 1.1");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Short description of parameters.
|
* Short description of parameters.
|
||||||
*/
|
*/
|
||||||
@ -2288,18 +2052,22 @@ void cmdline_error(char *p, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Main program (no, really?)
|
* Main program. (Called `psftp_main' because it gets called from
|
||||||
|
* *sftp.c; bit silly, I know, but it had to be called _something_.)
|
||||||
*/
|
*/
|
||||||
int main(int argc, char *argv[])
|
int psftp_main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
default_protocol = PROT_TELNET;
|
default_protocol = PROT_TELNET;
|
||||||
|
|
||||||
flags = FLAG_STDERR | FLAG_SYNCAGENT;
|
flags = FLAG_STDERR
|
||||||
|
#ifdef FLAG_SYNCAGENT
|
||||||
|
| FLAG_SYNCAGENT
|
||||||
|
#endif
|
||||||
|
;
|
||||||
cmdline_tooltype = TOOLTYPE_FILETRANSFER;
|
cmdline_tooltype = TOOLTYPE_FILETRANSFER;
|
||||||
ssh_get_line = &console_get_line;
|
ssh_get_line = &console_get_line;
|
||||||
init_winsock();
|
|
||||||
sk_init();
|
sk_init();
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
@ -2324,7 +2092,7 @@ int main(int argc, char *argv[])
|
|||||||
} else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-?") == 0) {
|
} else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-?") == 0) {
|
||||||
usage();
|
usage();
|
||||||
} else if (strcmp(argv[i], "-gui") == 0 && i + 1 < argc) {
|
} else if (strcmp(argv[i], "-gui") == 0 && i + 1 < argc) {
|
||||||
gui_hwnd = argv[++i];
|
gui_enable(argv[++i]);
|
||||||
gui_mode = 1;
|
gui_mode = 1;
|
||||||
console_batch_mode = TRUE;
|
console_batch_mode = TRUE;
|
||||||
} else if (strcmp(argv[i], "-ls") == 0) {
|
} else if (strcmp(argv[i], "-ls") == 0) {
|
||||||
@ -2367,18 +2135,11 @@ int main(int argc, char *argv[])
|
|||||||
back->special(backhandle, TS_EOF);
|
back->special(backhandle, TS_EOF);
|
||||||
ssh_scp_recv(&ch, 1);
|
ssh_scp_recv(&ch, 1);
|
||||||
}
|
}
|
||||||
WSACleanup();
|
|
||||||
random_save_seed();
|
random_save_seed();
|
||||||
|
|
||||||
/* GUI Adaptation - August 2000 */
|
if (gui_mode)
|
||||||
if (gui_mode) {
|
gui_send_errcount(list, errs);
|
||||||
unsigned int msg_id = WM_RET_ERR_CNT;
|
|
||||||
if (list)
|
|
||||||
msg_id = WM_LS_RET_ERR_CNT;
|
|
||||||
while (!PostMessage
|
|
||||||
((HWND) atoi(gui_hwnd), msg_id, (WPARAM) errs,
|
|
||||||
0 /*lParam */ ))SleepEx(1000, TRUE);
|
|
||||||
}
|
|
||||||
return (errs == 0 ? 0 : 1);
|
return (errs == 0 ? 0 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ static void gpps(void *handle, const char *name, const char *def,
|
|||||||
pdef = platform_default_s(name);
|
pdef = platform_default_s(name);
|
||||||
if (pdef) {
|
if (pdef) {
|
||||||
strncpy(val, pdef, len);
|
strncpy(val, pdef, len);
|
||||||
|
sfree(pdef);
|
||||||
} else {
|
} else {
|
||||||
strncpy(val, def, len);
|
strncpy(val, def, len);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
|
||||||
#include "putty.h"
|
#include "putty.h"
|
||||||
|
|
||||||
@ -19,6 +21,8 @@ unsigned long getticks(void)
|
|||||||
return tv.tv_sec * 1000000 + tv.tv_usec;
|
return tv.tv_sec * 1000000 + tv.tv_usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Filename filename_from_str(const char *str)
|
Filename filename_from_str(const char *str)
|
||||||
{
|
{
|
||||||
Filename ret;
|
Filename ret;
|
||||||
@ -57,3 +61,43 @@ void dputs(char *buf)
|
|||||||
fflush(debug_fp);
|
fflush(debug_fp);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
char *get_username(void)
|
||||||
|
{
|
||||||
|
struct passwd *p;
|
||||||
|
uid_t uid = getuid();
|
||||||
|
char *user, *ret = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First, find who we think we are using getlogin. If this
|
||||||
|
* agrees with our uid, we'll go along with it. This should
|
||||||
|
* allow sharing of uids between several login names whilst
|
||||||
|
* coping correctly with people who have su'ed.
|
||||||
|
*/
|
||||||
|
user = getlogin();
|
||||||
|
setpwent();
|
||||||
|
if (user)
|
||||||
|
p = getpwnam(user);
|
||||||
|
else
|
||||||
|
p = NULL;
|
||||||
|
if (p && p->pw_uid == uid) {
|
||||||
|
/*
|
||||||
|
* The result of getlogin() really does correspond to
|
||||||
|
* our uid. Fine.
|
||||||
|
*/
|
||||||
|
ret = user;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* If that didn't work, for whatever reason, we'll do
|
||||||
|
* the simpler version: look up our uid in the password
|
||||||
|
* file and map it straight to a name.
|
||||||
|
*/
|
||||||
|
p = getpwuid(uid);
|
||||||
|
if (!p)
|
||||||
|
return NULL;
|
||||||
|
ret = p->pw_name;
|
||||||
|
}
|
||||||
|
endpwent();
|
||||||
|
|
||||||
|
return dupstr(ret);
|
||||||
|
}
|
||||||
|
@ -74,48 +74,11 @@ static Config cfg;
|
|||||||
char *platform_default_s(const char *name)
|
char *platform_default_s(const char *name)
|
||||||
{
|
{
|
||||||
if (!strcmp(name, "X11Display"))
|
if (!strcmp(name, "X11Display"))
|
||||||
return getenv("DISPLAY");
|
return dupstr(getenv("DISPLAY"));
|
||||||
if (!strcmp(name, "TermType"))
|
if (!strcmp(name, "TermType"))
|
||||||
return getenv("TERM");
|
return dupstr(getenv("TERM"));
|
||||||
if (!strcmp(name, "UserName")) {
|
if (!strcmp(name, "UserName"))
|
||||||
/*
|
return get_username();
|
||||||
* Remote login username will default to the local username.
|
|
||||||
*/
|
|
||||||
struct passwd *p;
|
|
||||||
uid_t uid = getuid();
|
|
||||||
char *user, *ret = NULL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* First, find who we think we are using getlogin. If this
|
|
||||||
* agrees with our uid, we'll go along with it. This should
|
|
||||||
* allow sharing of uids between several login names whilst
|
|
||||||
* coping correctly with people who have su'ed.
|
|
||||||
*/
|
|
||||||
user = getlogin();
|
|
||||||
setpwent();
|
|
||||||
if (user)
|
|
||||||
p = getpwnam(user);
|
|
||||||
else
|
|
||||||
p = NULL;
|
|
||||||
if (p && p->pw_uid == uid) {
|
|
||||||
/*
|
|
||||||
* The result of getlogin() really does correspond to
|
|
||||||
* our uid. Fine.
|
|
||||||
*/
|
|
||||||
ret = user;
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* If that didn't work, for whatever reason, we'll do
|
|
||||||
* the simpler version: look up our uid in the password
|
|
||||||
* file and map it straight to a name.
|
|
||||||
*/
|
|
||||||
p = getpwuid(uid);
|
|
||||||
ret = p->pw_name;
|
|
||||||
}
|
|
||||||
endpwent();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* uxsftp.c: the Unix-specific parts of PSFTP.
|
* uxsftp.c: the Unix-specific parts of PSFTP and PSCP.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <pwd.h>
|
|
||||||
|
|
||||||
#include "putty.h"
|
#include "putty.h"
|
||||||
#include "psftp.h"
|
#include "psftp.h"
|
||||||
@ -34,45 +33,6 @@ void platform_get_x11_auth(char *display, int *protocol,
|
|||||||
*/
|
*/
|
||||||
char *platform_default_s(const char *name)
|
char *platform_default_s(const char *name)
|
||||||
{
|
{
|
||||||
if (!strcmp(name, "UserName")) {
|
|
||||||
/*
|
|
||||||
* Remote login username will default to the local username.
|
|
||||||
*/
|
|
||||||
struct passwd *p;
|
|
||||||
uid_t uid = getuid();
|
|
||||||
char *user, *ret = NULL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* First, find who we think we are using getlogin. If this
|
|
||||||
* agrees with our uid, we'll go along with it. This should
|
|
||||||
* allow sharing of uids between several login names whilst
|
|
||||||
* coping correctly with people who have su'ed.
|
|
||||||
*/
|
|
||||||
user = getlogin();
|
|
||||||
setpwent();
|
|
||||||
if (user)
|
|
||||||
p = getpwnam(user);
|
|
||||||
else
|
|
||||||
p = NULL;
|
|
||||||
if (p && p->pw_uid == uid) {
|
|
||||||
/*
|
|
||||||
* The result of getlogin() really does correspond to
|
|
||||||
* our uid. Fine.
|
|
||||||
*/
|
|
||||||
ret = user;
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* If that didn't work, for whatever reason, we'll do
|
|
||||||
* the simpler version: look up our uid in the password
|
|
||||||
* file and map it straight to a name.
|
|
||||||
*/
|
|
||||||
p = getpwuid(uid);
|
|
||||||
ret = p->pw_name;
|
|
||||||
}
|
|
||||||
endpwent();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,6 +58,18 @@ Filename platform_default_filename(const char *name)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stubs for the GUI feedback mechanism in Windows PSCP.
|
||||||
|
*/
|
||||||
|
void gui_update_stats(char *name, unsigned long size,
|
||||||
|
int percentage, unsigned long elapsed,
|
||||||
|
unsigned long done, unsigned long eta,
|
||||||
|
unsigned long ratebs) {}
|
||||||
|
void gui_send_errcount(int list, int errs) {}
|
||||||
|
void gui_send_char(int is_stderr, int c) {}
|
||||||
|
void gui_enable(char *arg) {}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set local current directory. Returns NULL on success, or else an
|
* Set local current directory. Returns NULL on success, or else an
|
||||||
* error message which must be freed after printing.
|
* error message which must be freed after printing.
|
||||||
|
15
winmisc.c
15
winmisc.c
@ -39,6 +39,21 @@ int filename_is_null(Filename fn)
|
|||||||
return !*fn.path;
|
return !*fn.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *get_username(void)
|
||||||
|
{
|
||||||
|
DWORD namelen;
|
||||||
|
char *user;
|
||||||
|
|
||||||
|
namelen = 0;
|
||||||
|
if (GetUserName(NULL, &namelen) == FALSE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
user = snewn(namelen, char);
|
||||||
|
GetUserName(user, &namelen);
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
int SaneDialogBox(HINSTANCE hinst,
|
int SaneDialogBox(HINSTANCE hinst,
|
||||||
LPCTSTR tmpl,
|
LPCTSTR tmpl,
|
||||||
HWND hwndparent,
|
HWND hwndparent,
|
||||||
|
469
winsftp.c
469
winsftp.c
@ -1,44 +1,140 @@
|
|||||||
/*
|
/*
|
||||||
* winsftp.c: the Windows-specific parts of PSFTP.
|
* winsftp.c: the Windows-specific parts of PSFTP and PSCP.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#ifndef AUTO_WINSOCK
|
||||||
|
#ifdef WINSOCK_TWO
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
|
#include <winsock.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "putty.h"
|
#include "putty.h"
|
||||||
#include "psftp.h"
|
#include "psftp.h"
|
||||||
|
|
||||||
/*
|
/* ----------------------------------------------------------------------
|
||||||
* Be told what socket we're supposed to be using.
|
* Interface to GUI driver program.
|
||||||
*/
|
*/
|
||||||
static SOCKET sftp_ssh_socket;
|
|
||||||
char *do_select(SOCKET skt, int startup)
|
|
||||||
{
|
|
||||||
if (startup)
|
|
||||||
sftp_ssh_socket = skt;
|
|
||||||
else
|
|
||||||
sftp_ssh_socket = INVALID_SOCKET;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
extern int select_result(WPARAM, LPARAM);
|
|
||||||
|
|
||||||
/*
|
/* This is just a base value from which the main message numbers are
|
||||||
* Initialize the WinSock driver.
|
* derived. */
|
||||||
|
#define WM_APP_BASE 0x8000
|
||||||
|
|
||||||
|
/* These two pass a single character value in wParam. They represent
|
||||||
|
* the visible output from PSCP. */
|
||||||
|
#define WM_STD_OUT_CHAR ( WM_APP_BASE+400 )
|
||||||
|
#define WM_STD_ERR_CHAR ( WM_APP_BASE+401 )
|
||||||
|
|
||||||
|
/* These pass a transfer status update. WM_STATS_CHAR passes a single
|
||||||
|
* character in wParam, and is called repeatedly to pass the name of
|
||||||
|
* the file, terminated with "\n". WM_STATS_SIZE passes the size of
|
||||||
|
* the file being transferred in wParam. WM_STATS_ELAPSED is called
|
||||||
|
* to pass the elapsed time (in seconds) in wParam, and
|
||||||
|
* WM_STATS_PERCENT passes the percentage of the transfer which is
|
||||||
|
* complete, also in wParam. */
|
||||||
|
#define WM_STATS_CHAR ( WM_APP_BASE+402 )
|
||||||
|
#define WM_STATS_SIZE ( WM_APP_BASE+403 )
|
||||||
|
#define WM_STATS_PERCENT ( WM_APP_BASE+404 )
|
||||||
|
#define WM_STATS_ELAPSED ( WM_APP_BASE+405 )
|
||||||
|
|
||||||
|
/* These are used at the end of a run to pass an error code in
|
||||||
|
* wParam: zero means success, nonzero means failure. WM_RET_ERR_CNT
|
||||||
|
* is used after a copy, and WM_LS_RET_ERR_CNT is used after a file
|
||||||
|
* list operation. */
|
||||||
|
#define WM_RET_ERR_CNT ( WM_APP_BASE+406 )
|
||||||
|
#define WM_LS_RET_ERR_CNT ( WM_APP_BASE+407 )
|
||||||
|
|
||||||
|
/* More transfer status update messages. WM_STATS_DONE passes the
|
||||||
|
* number of bytes sent so far in wParam. WM_STATS_ETA passes the
|
||||||
|
* estimated time to completion (in seconds). WM_STATS_RATEBS passes
|
||||||
|
* the average transfer rate (in bytes per second). */
|
||||||
|
#define WM_STATS_DONE ( WM_APP_BASE+408 )
|
||||||
|
#define WM_STATS_ETA ( WM_APP_BASE+409 )
|
||||||
|
#define WM_STATS_RATEBS ( WM_APP_BASE+410 )
|
||||||
|
|
||||||
|
#define NAME_STR_MAX 2048
|
||||||
|
static char statname[NAME_STR_MAX + 1];
|
||||||
|
static unsigned long statsize = 0;
|
||||||
|
static unsigned long statdone = 0;
|
||||||
|
static unsigned long stateta = 0;
|
||||||
|
static unsigned long statratebs = 0;
|
||||||
|
static int statperct = 0;
|
||||||
|
static unsigned long statelapsed = 0;
|
||||||
|
|
||||||
|
static HWND gui_hwnd = NULL;
|
||||||
|
|
||||||
|
static void send_msg(HWND h, UINT message, WPARAM wParam)
|
||||||
|
{
|
||||||
|
while (!PostMessage(h, message, wParam, 0))
|
||||||
|
SleepEx(1000, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gui_send_char(int is_stderr, int c)
|
||||||
|
{
|
||||||
|
unsigned int msg_id = WM_STD_OUT_CHAR;
|
||||||
|
if (is_stderr)
|
||||||
|
msg_id = WM_STD_ERR_CHAR;
|
||||||
|
send_msg(gui_hwnd, msg_id, (WPARAM) c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gui_send_errcount(int list, int errs)
|
||||||
|
{
|
||||||
|
unsigned int msg_id = WM_RET_ERR_CNT;
|
||||||
|
if (list)
|
||||||
|
msg_id = WM_LS_RET_ERR_CNT;
|
||||||
|
while (!PostMessage(gui_hwnd, msg_id, (WPARAM) errs, 0))
|
||||||
|
SleepEx(1000, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gui_update_stats(char *name, unsigned long size,
|
||||||
|
int percentage, unsigned long elapsed,
|
||||||
|
unsigned long done, unsigned long eta,
|
||||||
|
unsigned long ratebs)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (strcmp(name, statname) != 0) {
|
||||||
|
for (i = 0; i < strlen(name); ++i)
|
||||||
|
send_msg(gui_hwnd, WM_STATS_CHAR, (WPARAM) name[i]);
|
||||||
|
send_msg(gui_hwnd, WM_STATS_CHAR, (WPARAM) '\n');
|
||||||
|
strcpy(statname, name);
|
||||||
|
}
|
||||||
|
if (statsize != size) {
|
||||||
|
send_msg(gui_hwnd, WM_STATS_SIZE, (WPARAM) size);
|
||||||
|
statsize = size;
|
||||||
|
}
|
||||||
|
if (statdone != done) {
|
||||||
|
send_msg(gui_hwnd, WM_STATS_DONE, (WPARAM) done);
|
||||||
|
statdone = done;
|
||||||
|
}
|
||||||
|
if (stateta != eta) {
|
||||||
|
send_msg(gui_hwnd, WM_STATS_ETA, (WPARAM) eta);
|
||||||
|
stateta = eta;
|
||||||
|
}
|
||||||
|
if (statratebs != ratebs) {
|
||||||
|
send_msg(gui_hwnd, WM_STATS_RATEBS, (WPARAM) ratebs);
|
||||||
|
statratebs = ratebs;
|
||||||
|
}
|
||||||
|
if (statelapsed != elapsed) {
|
||||||
|
send_msg(gui_hwnd, WM_STATS_ELAPSED, (WPARAM) elapsed);
|
||||||
|
statelapsed = elapsed;
|
||||||
|
}
|
||||||
|
if (statperct != percentage) {
|
||||||
|
send_msg(gui_hwnd, WM_STATS_PERCENT, (WPARAM) percentage);
|
||||||
|
statperct = percentage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gui_enable(char *arg)
|
||||||
|
{
|
||||||
|
gui_hwnd = (HWND) atoi(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
* File access abstraction.
|
||||||
*/
|
*/
|
||||||
static void init_winsock(void)
|
|
||||||
{
|
|
||||||
WORD winsock_ver;
|
|
||||||
WSADATA wsadata;
|
|
||||||
|
|
||||||
winsock_ver = MAKEWORD(1, 1);
|
|
||||||
if (WSAStartup(winsock_ver, &wsadata)) {
|
|
||||||
fprintf(stderr, "Unable to initialise WinSock");
|
|
||||||
cleanup_exit(1);
|
|
||||||
}
|
|
||||||
if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1) {
|
|
||||||
fprintf(stderr, "WinSock version is incompatible with 1.1");
|
|
||||||
cleanup_exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set local current directory. Returns NULL on success, or else an
|
* Set local current directory. Returns NULL on success, or else an
|
||||||
@ -79,6 +175,317 @@ char *psftp_getcwd(void)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define TIME_POSIX_TO_WIN(t, ft) (*(LONGLONG*)&(ft) = \
|
||||||
|
((LONGLONG) (t) + (LONGLONG) 11644473600) * (LONGLONG) 10000000)
|
||||||
|
#define TIME_WIN_TO_POSIX(ft, t) ((t) = (unsigned long) \
|
||||||
|
((*(LONGLONG*)&(ft)) / (LONGLONG) 10000000 - (LONGLONG) 11644473600))
|
||||||
|
|
||||||
|
struct RFile {
|
||||||
|
HANDLE h;
|
||||||
|
};
|
||||||
|
|
||||||
|
RFile *open_existing_file(char *name, unsigned long *size,
|
||||||
|
unsigned long *mtime, unsigned long *atime)
|
||||||
|
{
|
||||||
|
HANDLE h;
|
||||||
|
RFile *ret;
|
||||||
|
|
||||||
|
h = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||||
|
OPEN_EXISTING, 0, 0);
|
||||||
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = snew(RFile);
|
||||||
|
ret->h = h;
|
||||||
|
|
||||||
|
if (size)
|
||||||
|
*size = GetFileSize(h, NULL);
|
||||||
|
|
||||||
|
if (mtime || atime) {
|
||||||
|
FILETIME actime, wrtime;
|
||||||
|
GetFileTime(h, NULL, &actime, &wrtime);
|
||||||
|
if (atime)
|
||||||
|
TIME_WIN_TO_POSIX(actime, *atime);
|
||||||
|
if (mtime)
|
||||||
|
TIME_WIN_TO_POSIX(wrtime, *mtime);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_from_file(RFile *f, void *buffer, int length)
|
||||||
|
{
|
||||||
|
int ret, read;
|
||||||
|
ret = ReadFile(f->h, buffer, length, &read, NULL);
|
||||||
|
if (!ret)
|
||||||
|
return -1; /* error */
|
||||||
|
else
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_rfile(RFile *f)
|
||||||
|
{
|
||||||
|
CloseHandle(f->h);
|
||||||
|
sfree(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WFile {
|
||||||
|
HANDLE h;
|
||||||
|
};
|
||||||
|
|
||||||
|
WFile *open_new_file(char *name)
|
||||||
|
{
|
||||||
|
HANDLE h;
|
||||||
|
WFile *ret;
|
||||||
|
|
||||||
|
h = CreateFile(name, GENERIC_WRITE, 0, NULL,
|
||||||
|
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = snew(WFile);
|
||||||
|
ret->h = h;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int write_to_file(WFile *f, void *buffer, int length)
|
||||||
|
{
|
||||||
|
int ret, written;
|
||||||
|
ret = WriteFile(f->h, buffer, length, &written, NULL);
|
||||||
|
if (!ret)
|
||||||
|
return -1; /* error */
|
||||||
|
else
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_file_times(WFile *f, unsigned long mtime, unsigned long atime)
|
||||||
|
{
|
||||||
|
FILETIME actime, wrtime;
|
||||||
|
TIME_POSIX_TO_WIN(atime, actime);
|
||||||
|
TIME_POSIX_TO_WIN(mtime, wrtime);
|
||||||
|
SetFileTime(f->h, NULL, &actime, &wrtime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_wfile(WFile *f)
|
||||||
|
{
|
||||||
|
CloseHandle(f->h);
|
||||||
|
sfree(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int file_type(char *name)
|
||||||
|
{
|
||||||
|
DWORD attr;
|
||||||
|
attr = GetFileAttributes(name);
|
||||||
|
/* We know of no `weird' files under Windows. */
|
||||||
|
if (attr == (DWORD)-1)
|
||||||
|
return FILE_TYPE_NONEXISTENT;
|
||||||
|
else if (attr & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
return FILE_TYPE_DIRECTORY;
|
||||||
|
else
|
||||||
|
return FILE_TYPE_FILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DirHandle {
|
||||||
|
HANDLE h;
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
DirHandle *open_directory(char *name)
|
||||||
|
{
|
||||||
|
HANDLE h;
|
||||||
|
WIN32_FIND_DATA fdat;
|
||||||
|
char *findfile;
|
||||||
|
DirHandle *ret;
|
||||||
|
|
||||||
|
/* To enumerate files in dir `foo', we search for `foo/*'. */
|
||||||
|
findfile = dupcat(name, "/*", NULL);
|
||||||
|
h = FindFirstFile(findfile, &fdat);
|
||||||
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = snew(DirHandle);
|
||||||
|
ret->h = h;
|
||||||
|
ret->name = dupstr(fdat.cFileName);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *read_filename(DirHandle *dir)
|
||||||
|
{
|
||||||
|
if (!dir->name) {
|
||||||
|
WIN32_FIND_DATA fdat;
|
||||||
|
int ok = FindNextFile(dir->h, &fdat);
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
dir->name = dupstr(fdat.cFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir->name) {
|
||||||
|
char *ret = dir->name;
|
||||||
|
dir->name = NULL;
|
||||||
|
return ret;
|
||||||
|
} else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_directory(DirHandle *dir)
|
||||||
|
{
|
||||||
|
FindClose(dir->h);
|
||||||
|
if (dir->name)
|
||||||
|
sfree(dir->name);
|
||||||
|
sfree(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_wildcard(char *name, int cmdline)
|
||||||
|
{
|
||||||
|
HANDLE fh;
|
||||||
|
WIN32_FIND_DATA fdat;
|
||||||
|
|
||||||
|
/* First see if the exact name exists. */
|
||||||
|
if (GetFileAttributes(name) != (DWORD)-1)
|
||||||
|
return WCTYPE_FILENAME;
|
||||||
|
|
||||||
|
/* Otherwise see if a wildcard match finds anything. */
|
||||||
|
fh = FindFirstFile(name, &fdat);
|
||||||
|
if (fh == INVALID_HANDLE_VALUE)
|
||||||
|
return WCTYPE_NONEXISTENT;
|
||||||
|
|
||||||
|
FindClose(fh);
|
||||||
|
return WCTYPE_WILDCARD;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WildcardMatcher {
|
||||||
|
HANDLE h;
|
||||||
|
char *name;
|
||||||
|
char *srcpath;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a pointer to the portion of str that comes after the last
|
||||||
|
* slash (or backslash or colon, if `local' is TRUE).
|
||||||
|
*/
|
||||||
|
static char *stripslashes(char *str, int local)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (local) {
|
||||||
|
p = strchr(str, ':');
|
||||||
|
if (p) str = p+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = strrchr(str, '/');
|
||||||
|
if (p) str = p+1;
|
||||||
|
|
||||||
|
if (local) {
|
||||||
|
p = strrchr(str, '\\');
|
||||||
|
if (p) str = p+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
WildcardMatcher *begin_wildcard_matching(char *name)
|
||||||
|
{
|
||||||
|
HANDLE h;
|
||||||
|
WIN32_FIND_DATA fdat;
|
||||||
|
WildcardMatcher *ret;
|
||||||
|
char *last;
|
||||||
|
|
||||||
|
h = FindFirstFile(name, &fdat);
|
||||||
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = snew(WildcardMatcher);
|
||||||
|
ret->h = h;
|
||||||
|
ret->srcpath = dupstr(name);
|
||||||
|
last = stripslashes(ret->srcpath, 1);
|
||||||
|
*last = '\0';
|
||||||
|
if (fdat.cFileName[0] == '.' &&
|
||||||
|
(fdat.cFileName[1] == '\0' ||
|
||||||
|
(fdat.cFileName[1] == '.' && fdat.cFileName[2] == '\0')))
|
||||||
|
ret->name = NULL;
|
||||||
|
else
|
||||||
|
ret->name = dupcat(ret->srcpath, fdat.cFileName, NULL);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *wildcard_get_filename(WildcardMatcher *dir)
|
||||||
|
{
|
||||||
|
while (!dir->name) {
|
||||||
|
WIN32_FIND_DATA fdat;
|
||||||
|
int ok = FindNextFile(dir->h, &fdat);
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (fdat.cFileName[0] == '.' &&
|
||||||
|
(fdat.cFileName[1] == '\0' ||
|
||||||
|
(fdat.cFileName[1] == '.' && fdat.cFileName[2] == '\0')))
|
||||||
|
dir->name = NULL;
|
||||||
|
else
|
||||||
|
dir->name = dupcat(dir->srcpath, fdat.cFileName, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir->name) {
|
||||||
|
char *ret = dir->name;
|
||||||
|
dir->name = NULL;
|
||||||
|
return ret;
|
||||||
|
} else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void finish_wildcard_matching(WildcardMatcher *dir)
|
||||||
|
{
|
||||||
|
FindClose(dir->h);
|
||||||
|
if (dir->name)
|
||||||
|
sfree(dir->name);
|
||||||
|
sfree(dir->srcpath);
|
||||||
|
sfree(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
int create_directory(char *name)
|
||||||
|
{
|
||||||
|
return CreateDirectory(name, NULL) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
* Platform-specific network handling.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Be told what socket we're supposed to be using.
|
||||||
|
*/
|
||||||
|
static SOCKET sftp_ssh_socket;
|
||||||
|
char *do_select(SOCKET skt, int startup)
|
||||||
|
{
|
||||||
|
if (startup)
|
||||||
|
sftp_ssh_socket = skt;
|
||||||
|
else
|
||||||
|
sftp_ssh_socket = INVALID_SOCKET;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
extern int select_result(WPARAM, LPARAM);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the WinSock driver.
|
||||||
|
*/
|
||||||
|
static void init_winsock(void)
|
||||||
|
{
|
||||||
|
WORD winsock_ver;
|
||||||
|
WSADATA wsadata;
|
||||||
|
|
||||||
|
winsock_ver = MAKEWORD(1, 1);
|
||||||
|
if (WSAStartup(winsock_ver, &wsadata)) {
|
||||||
|
fprintf(stderr, "Unable to initialise WinSock");
|
||||||
|
cleanup_exit(1);
|
||||||
|
}
|
||||||
|
if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1) {
|
||||||
|
fprintf(stderr, "WinSock version is incompatible with 1.1");
|
||||||
|
cleanup_exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait for some network data and process it.
|
* Wait for some network data and process it.
|
||||||
*/
|
*/
|
||||||
@ -98,7 +505,7 @@ int ssh_sftp_loop_iteration(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* ----------------------------------------------------------------------
|
||||||
* Main program. Parse arguments etc.
|
* Main program. Parse arguments etc.
|
||||||
*/
|
*/
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user