From 4d952924e121b04cff652a2eb7eb5e284207eccd Mon Sep 17 00:00:00 2001 From: quamrulmina Date: Fri, 6 Nov 2015 03:02:51 -0600 Subject: [PATCH] sftp client and server code changed to build & work with MS Visual Studio Use new compile flag WIN32_VS to add/change logic of sftp client and sftp server codes so that MS Visual Studio 2015 compiler and runtime can be used. opendir(), readdir(), closedir() directory APIs and basename() API of Unix/Linux are implemented in Windows as they are not available in Windows/VisualStudio C-runtime. win32_dirent.c and win32_dirent.h files added as dirent.c and dirent.h are not available in Windows and we do not want to affect mingW/gcc builds for Windows which have those files available. --- contrib/win32/openssh/config.h.vs | 5 +- sftp-client.c | 7 +++ sftp-common.c | 4 ++ sftp-glob.c | 11 +++- sftp-server.c | 17 +++++- sftp.c | 6 ++ win32_dirent.c | 93 +++++++++++++++++++++++++++++++ win32_dirent.h | 33 +++++++++++ 8 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 win32_dirent.c create mode 100644 win32_dirent.h diff --git a/contrib/win32/openssh/config.h.vs b/contrib/win32/openssh/config.h.vs index e68ebfe..b673805 100644 --- a/contrib/win32/openssh/config.h.vs +++ b/contrib/win32/openssh/config.h.vs @@ -1703,6 +1703,9 @@ struct iovec -#define __attribute__(A) +#define __attribute__(A) + +// define building with MS Visual Studio Compiler and runtime and not with MingW/gcc compiler +#define WIN32_VS 1 diff --git a/sftp-client.c b/sftp-client.c index 582fb5f..70cf0d0 100644 --- a/sftp-client.c +++ b/sftp-client.c @@ -36,7 +36,12 @@ #endif #include +#ifdef WIN32_VS +#include "win32_dirent.h" +#else #include +#endif + #include #include #include @@ -1502,9 +1507,11 @@ do_download(struct sftp_conn *conn, const char *remote_path, "server reordered requests", local_path); } debug("truncating at %llu", (unsigned long long)highwater); + #ifndef WIN32_VS if (ftruncate(local_fd, highwater) == -1) error("ftruncate \"%s\": %s", local_path, strerror(errno)); + #endif } if (read_error) { error("Couldn't read from remote file \"%s\" : %s", diff --git a/sftp-common.c b/sftp-common.c index 22e1218..9fea144 100644 --- a/sftp-common.c +++ b/sftp-common.c @@ -234,6 +234,10 @@ ls_file(const char *name, const struct stat *st, int remote, int si_units) #endif if (!remote) { user = user_from_uid(st->st_uid, 0); + #ifdef WIN32_FIXME + snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid); + group = gbuf; + #endif } else { snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid); user = ubuf; diff --git a/sftp-glob.c b/sftp-glob.c index 43a1beb..5ba93f2 100644 --- a/sftp-glob.c +++ b/sftp-glob.c @@ -22,7 +22,12 @@ # include #endif +#ifdef WIN32_VS +#include "win32_dirent.h" +#else #include +#endif + #include #include #include @@ -32,6 +37,10 @@ #include "sftp-common.h" #include "sftp-client.h" +#ifdef WIN32_VS +#include "win32_dirent.c" +#endif + int remote_glob(struct sftp_conn *, const char *, int, int (*)(const char *, int), glob_t *); @@ -147,4 +156,4 @@ remote_glob(struct sftp_conn *conn, const char *pattern, int flags, cur.conn = conn; return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob)); -} +} \ No newline at end of file diff --git a/sftp-server.c b/sftp-server.c index 1f0b510..88bf5b9 100644 --- a/sftp-server.c +++ b/sftp-server.c @@ -42,7 +42,12 @@ #include #endif +#ifdef WIN32_VS +#include "win32_dirent.h" +#else #include +#endif + #include #include #include @@ -64,6 +69,10 @@ #include "sftp.h" #include "sftp-common.h" +#ifdef WIN32_VS +#include "win32_dirent.c" +#endif + #ifdef WIN32_FIXME #undef select @@ -738,6 +747,9 @@ process_init(void) sshbuf_free(msg); } +#ifdef WIN32_VS +#define O_ACCMODE 0x3 +#endif static void process_open(u_int32_t id) { @@ -1180,8 +1192,11 @@ process_readdir(u_int32_t id) /* * Convert names to UTF8 before send to network. */ - + #ifdef WIN32_VS + stats[count].name = xstrdup(dp->d_name); + #else stats[count].name = ConvertLocal8ToUtf8(dp -> d_name, -1, NULL); + #endif stats[count].long_name = ls_file(dp -> d_name, &st, 0, 0); /* diff --git a/sftp.c b/sftp.c index 2f7a277..7d5e0e2 100644 --- a/sftp.c +++ b/sftp.c @@ -83,6 +83,10 @@ typedef void EditLine; #endif +#ifdef WIN32_VS +#include "win32_dirent.h" +#endif + /* File to read commands from */ FILE* infile; @@ -2117,8 +2121,10 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) free(dir); } + #ifndef WIN32_VS setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(infile, NULL, _IOLBF, 0); + #endif interactive = !batchmode && isatty(STDIN_FILENO); err = 0; diff --git a/win32_dirent.c b/win32_dirent.c new file mode 100644 index 0000000..024e677 --- /dev/null +++ b/win32_dirent.c @@ -0,0 +1,93 @@ +// win32_dirent.c +// directory entry functions in Windows platform like Ubix/Linux +// opendir(), readdir(), closedir(). + +#include +#include +#include +#include +#include + +#include "win32_dirent.h" + +/* Open a directory stream on NAME. + Return a DIR stream on the directory, or NULL if it could not be opened. */ +DIR * opendir(char *name) +{ + struct _finddata_t c_file; + intptr_t hFile; + DIR *pdir; + char searchstr[256]; + + sprintf_s(searchstr, sizeof(searchstr), "%s\\*.*",name); // add *.* to it for NT + + if( (hFile = _findfirst( searchstr, &c_file )) == -1L ) { + if (1) // verbose + printf( "No files found for %s search.\n", name ); + return (DIR *) NULL; + } + else { + pdir = (DIR *) malloc( sizeof(DIR) ); + pdir->hFile = hFile ; + pdir->c_file = c_file ; + + return pdir ; + } +} + +/* Close the directory stream DIRP. + Return 0 if successful, -1 if not. */ +int closedir(DIR *dirp) +{ + if ( dirp && (dirp->hFile) ) { + _findclose( dirp->hFile ); + dirp->hFile = 0; + free (dirp); + } + + return 0; +} + +/* Read a directory entry from DIRP. + Return a pointer to a `struct dirent' describing the entry, + or NULL for EOF or error. The storage returned may be overwritten + by a later readdir call on the same DIR stream. */ +struct dirent *readdir(void *avp) +{ + struct dirent *pdirentry; + DIR *dirp = (DIR *)avp; + + for (;;) { + if ( _findnext( dirp->hFile, &(dirp->c_file) ) == 0 ) { + if ( ( strcmp (dirp->c_file.name,".") == 0 ) || + ( strcmp (dirp->c_file.name,"..") == 0 ) ) { + continue ; + } + pdirentry = (struct dirent *) malloc( sizeof(struct dirent) ); + pdirentry->d_name = dirp->c_file.name ; + pdirentry->d_ino = 1; // a fictious one like UNIX to say it is nonzero + return pdirentry ; + } + else { + return (struct dirent *) NULL; + } + } +} + +// return last part of a path. The last path being a filename. +char *basename(char *path) +{ + char *pdest; + + if (!path) + return "."; + pdest = strrchr(path, '/'); + if (pdest) + return (pdest+1); + pdest = strrchr(path, '\\'); + if (pdest) + return (pdest+1); + + return path; // path does not have a slash +} +// end of dirent functions in Windows diff --git a/win32_dirent.h b/win32_dirent.h new file mode 100644 index 0000000..29a3323 --- /dev/null +++ b/win32_dirent.h @@ -0,0 +1,33 @@ +// direntry functions in Windows platform like Ubix/Linux +// opendir(), readdir(), closedir(). +// NT_DIR * nt_opendir(char *name) ; +// struct nt_dirent *nt_readdir(NT_DIR *dirp); +// int nt_closedir(NT_DIR *dirp) ; + +#ifndef __DIRENT_H__ +#define __DIRENT_H__ + +#include +#include + +// Windows directory structure content +struct dirent { + char *d_name ; // name of the directory entry + int d_ino; // UNIX inode + //unsigned attrib ; // its attributes +}; + +typedef struct { + intptr_t hFile; + struct _finddata_t c_file; + int bRoot; + int bDrive; + char initName[260]; +} DIR; + +DIR * opendir(char *name); +int closedir(DIR *dirp); +struct dirent *readdir(void *avp); +char *basename(char *path); + +#endif \ No newline at end of file