⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winsftp.c

📁 putty
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * winsftp.c: the Windows-specific parts of PSFTP and PSCP.
 */

#include <assert.h>

#include "putty.h"
#include "psftp.h"
#include "int64.h"

char *get_ttymode(void *frontend, const char *mode) { return NULL; }

int get_userpass_input(prompts_t *p, unsigned char *in, int inlen)
{
    int ret;
    ret = cmdline_get_passwd_input(p, in, inlen);
    if (ret == -1)
	ret = console_get_userpass_input(p, in, inlen);
    return ret;
}

/* ----------------------------------------------------------------------
 * File access abstraction.
 */

/*
 * Set local current directory. Returns NULL on success, or else an
 * error message which must be freed after printing.
 */
char *psftp_lcd(char *dir)
{
    char *ret = NULL;

    if (!SetCurrentDirectory(dir)) {
	LPVOID message;
	int i;
	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
		      FORMAT_MESSAGE_FROM_SYSTEM |
		      FORMAT_MESSAGE_IGNORE_INSERTS,
		      NULL, GetLastError(),
		      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		      (LPTSTR)&message, 0, NULL);
	i = strcspn((char *)message, "\n");
	ret = dupprintf("%.*s", i, (LPCTSTR)message);
	LocalFree(message);
    }

    return ret;
}

/*
 * Get local current directory. Returns a string which must be
 * freed.
 */
char *psftp_getcwd(void)
{
    char *ret = snewn(256, char);
    int len = GetCurrentDirectory(256, ret);
    if (len > 256)
	ret = sresize(ret, len, char);
    GetCurrentDirectory(len, 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, uint64 *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->lo=GetFileSize(h, &(size->hi));

    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;
}

WFile *open_existing_wfile(char *name, uint64 *size)
{
    HANDLE h;
    WFile *ret;

    h = CreateFile(name, GENERIC_WRITE, FILE_SHARE_READ, NULL,
		   OPEN_EXISTING, 0, 0);
    if (h == INVALID_HANDLE_VALUE)
	return NULL;

    ret = snew(WFile);
    ret->h = h;

    if (size)
	size->lo=GetFileSize(h, &(size->hi));

    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);
}

/* Seek offset bytes through file, from whence, where whence is
   FROM_START, FROM_CURRENT, or FROM_END */
int seek_file(WFile *f, uint64 offset, int whence)
{
    DWORD movemethod;

    switch (whence) {
    case FROM_START:
	movemethod = FILE_BEGIN;
	break;
    case FROM_CURRENT:
	movemethod = FILE_CURRENT;
	break;
    case FROM_END:
	movemethod = FILE_END;
	break;
    default:
	return -1;
    }

    SetFilePointer(f->h, offset.lo, &(offset.hi), movemethod);
    
    if (GetLastError() != NO_ERROR)
	return -1;
    else 
	return 0;
}

uint64 get_file_posn(WFile *f)
{
    uint64 ret;

    ret.hi = 0L;
    ret.lo = SetFilePointer(f->h, 0L, &(ret.hi), FILE_CURRENT);

    return ret;
}

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;

    /* Enumerate files in dir `foo'. */
    findfile = dupcat(name, "/*", NULL);
    h = FindFirstFile(findfile, &fdat);
    if (h == INVALID_HANDLE_VALUE)
	return NULL;
    sfree(findfile);

    ret = snew(DirHandle);
    ret->h = h;
    ret->name = dupstr(fdat.cFileName);
    return ret;
}

char *read_filename(DirHandle *dir)
{
    do {

	if (!dir->name) {
	    WIN32_FIND_DATA fdat;
	    int ok = FindNextFile(dir->h, &fdat);
	    if (!ok)
		return NULL;
	    else
		dir->name = dupstr(fdat.cFileName);
	}

	assert(dir->name);
	if (dir->name[0] == '.' &&
	    (dir->name[1] == '\0' ||
	     (dir->name[1] == '.' && dir->name[2] == '\0'))) {
	    sfree(dir->name);
	    dir->name = NULL;
	}

    } while (!dir->name);

    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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -