From 8c7d710ce382c85e38ce4fb73fd357e00e7d5ed2 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 25 Aug 2003 14:30:59 +0000 Subject: [PATCH] ... and there's a Unix port of PSCP. Ooh. git-svn-id: svn://svn.tartarus.org/sgt/putty@3422 cda61777-01e9-0310-a592-d414129be87e --- psftp.h | 6 ++ scp.c | 2 +- unix/uxsftp.c | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ winsftp.c | 17 ++++- 4 files changed, 232 insertions(+), 3 deletions(-) diff --git a/psftp.h b/psftp.h index 8eb11877..44911f59 100644 --- a/psftp.h +++ b/psftp.h @@ -141,4 +141,10 @@ void finish_wildcard_matching(WildcardMatcher *dir); */ int create_directory(char *name); +/* + * Concatenate a directory name and a file name. The way this is + * done will depend on the OS. + */ +char *dir_file_cat(char *dir, char *file); + #endif /* PUTTY_PSFTP_H */ diff --git a/scp.c b/scp.c index 53cb60ab..00852bc4 100644 --- a/scp.c +++ b/scp.c @@ -1711,7 +1711,7 @@ static void sink(char *targ, char *src) } if (targ[0] != '\0') - destfname = dupcat(targ, "\\", striptarget, NULL); + destfname = dir_file_cat(targ, striptarget); else destfname = dupstr(striptarget); } else { diff --git a/unix/uxsftp.c b/unix/uxsftp.c index d1989f83..69d4c456 100644 --- a/unix/uxsftp.c +++ b/unix/uxsftp.c @@ -4,8 +4,13 @@ #include #include +#include +#include +#include #include +#include #include +#include #include "putty.h" #include "psftp.h" @@ -109,6 +114,211 @@ char *psftp_getcwd(void) } } +struct RFile { + int fd; +}; + +RFile *open_existing_file(char *name, unsigned long *size, + unsigned long *mtime, unsigned long *atime) +{ + int fd; + RFile *ret; + + fd = open(name, O_RDONLY); + if (fd < 0) + return NULL; + + ret = snew(RFile); + ret->fd = fd; + + if (size || mtime || atime) { + struct stat statbuf; + if (fstat(fd, &statbuf) < 0) { + fprintf(stderr, "%s: stat: %s\n", name, strerror(errno)); + memset(&statbuf, 0, sizeof(statbuf)); + } + + if (size) + *size = statbuf.st_size; + + if (mtime) + *mtime = statbuf.st_mtime; + + if (atime) + *atime = statbuf.st_atime; + } + + return ret; +} + +int read_from_file(RFile *f, void *buffer, int length) +{ + return read(f->fd, buffer, length); +} + +void close_rfile(RFile *f) +{ + close(f->fd); + sfree(f); +} + +struct WFile { + int fd; + char *name; +}; + +WFile *open_new_file(char *name) +{ + int fd; + WFile *ret; + + fd = open(name, O_CREAT | O_TRUNC | O_WRONLY, 0666); + if (fd < 0) + return NULL; + + ret = snew(WFile); + ret->fd = fd; + ret->name = dupstr(name); + + return ret; +} + +int write_to_file(WFile *f, void *buffer, int length) +{ + char *p = (char *)buffer; + int so_far = 0; + + /* Keep trying until we've really written as much as we can. */ + while (length > 0) { + int ret = write(f->fd, p, length); + + if (ret < 0) + return ret; + + if (ret == 0) + break; + + p += ret; + length -= ret; + so_far += ret; + } + + return so_far; +} + +void set_file_times(WFile *f, unsigned long mtime, unsigned long atime) +{ + struct utimbuf ut; + + ut.actime = atime; + ut.modtime = mtime; + + utime(f->name, &ut); +} + +/* Closes and frees the WFile */ +void close_wfile(WFile *f) +{ + close(f->fd); + sfree(f->name); + sfree(f); +} + +int file_type(char *name) +{ + struct stat statbuf; + + if (stat(name, &statbuf) < 0) { + if (errno != ENOENT) + fprintf(stderr, "%s: stat: %s\n", name, strerror(errno)); + return FILE_TYPE_NONEXISTENT; + } + + if (S_ISREG(statbuf.st_mode)) + return FILE_TYPE_FILE; + + if (S_ISDIR(statbuf.st_mode)) + return FILE_TYPE_DIRECTORY; + + return FILE_TYPE_WEIRD; +} + +struct DirHandle { + DIR *dir; +}; + +DirHandle *open_directory(char *name) +{ + DIR *dir; + DirHandle *ret; + + dir = opendir(name); + if (!dir) + return NULL; + + ret = snew(DirHandle); + ret->dir = dir; + return ret; +} + +char *read_filename(DirHandle *dir) +{ + struct dirent *de; + + do { + de = readdir(dir->dir); + if (de == NULL) + return NULL; + } while ((de->d_name[0] == '.' && + (de->d_name[1] == '\0' || + (de->d_name[1] == '.' && de->d_name[2] == '\0')))); + + return dupstr(de->d_name); +} + +void close_directory(DirHandle *dir) +{ + closedir(dir->dir); + sfree(dir); +} + +int test_wildcard(char *name, int cmdline) +{ + /* + * On Unix, we currently don't support local wildcards at all. + * We will have to do so (FIXME) once PSFTP starts implementing + * mput, but until then we can assume `cmdline' is always set. + */ + struct stat statbuf; + + assert(cmdline); + if (stat(name, &statbuf) < 0) + return WCTYPE_NONEXISTENT; + else + return WCTYPE_FILENAME; +} + +/* + * Actually return matching file names for a local wildcard. FIXME: + * we currently don't support this at all. + */ +struct WildcardMatcher { + int x; +}; +WildcardMatcher *begin_wildcard_matching(char *name) { return NULL; } +char *wildcard_get_filename(WildcardMatcher *dir) { return NULL; } +void finish_wildcard_matching(WildcardMatcher *dir) {} + +int create_directory(char *name) +{ + return mkdir(name, 0777) == 0; +} + +char *dir_file_cat(char *dir, char *file) +{ + return dupcat(dir, "/", file, NULL); +} + /* * Wait for some network data and process it. */ diff --git a/winsftp.c b/winsftp.c index a4dafd4a..6687210f 100644 --- a/winsftp.c +++ b/winsftp.c @@ -303,6 +303,7 @@ DirHandle *open_directory(char *name) h = FindFirstFile(findfile, &fdat); if (h == INVALID_HANDLE_VALUE) return NULL; + sfree(findfile); ret = snew(DirHandle); ret->h = h; @@ -312,11 +313,18 @@ DirHandle *open_directory(char *name) char *read_filename(DirHandle *dir) { - if (!dir->name) { + while (!dir->name) { WIN32_FIND_DATA fdat; int ok = FindNextFile(dir->h, &fdat); - if (ok) + 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 = dupstr(fdat.cFileName); } @@ -449,6 +457,11 @@ int create_directory(char *name) return CreateDirectory(name, NULL) != 0; } +char *dir_file_cat(char *dir, char *file) +{ + return dupcat(dir, "\\", file, NULL); +} + /* ---------------------------------------------------------------------- * Platform-specific network handling. */ -- 2.11.0