diff --git a/sftp-common.c b/sftp-common.c index 9fea144..f60309e 100644 --- a/sftp-common.c +++ b/sftp-common.c @@ -33,6 +33,9 @@ #ifdef WIN32_FIXME #undef GSSAPI #undef KRB5 + +void strmode(mode_t mode, char *p); +void strmode_from_attrib(unsigned attrib, char *p); #endif #include /* MAX */ @@ -231,6 +234,9 @@ ls_file(const char *name, const struct stat *st, int remote, int si_units) #ifndef WIN32_FIXME strmode(st->st_mode, mode); +#else + strmode(st->st_mode, mode); + strmode_from_attrib(remote, mode); #endif if (!remote) { user = user_from_uid(st->st_uid, 0); @@ -281,3 +287,120 @@ ls_file(const char *name, const struct stat *st, int remote, int si_units) } return xstrdup(buf); } + +#ifdef WIN32_FIXME + +#include +#include + +void +strmode_from_attrib(unsigned attrib, char *p) +{ + if (attrib & FILE_ATTRIBUTE_REPARSE_POINT) + *p = 'l'; + else if (attrib & FILE_ATTRIBUTE_DIRECTORY) + *p = 'd'; + else + *p = '-'; +} + + +void +strmode(mode_t mode, char *p) +{ + /* print type */ + switch (mode & S_IFMT) { + case S_IFDIR: /* directory */ + *p++ = 'd'; + break; + case S_IFCHR: /* character special */ + *p++ = 'c'; + break; + //case S_IFBLK: /* block special */ + // *p++ = 'b'; + // break; + case S_IFREG: /* regular */ + *p++ = '-'; + break; + //case S_IFLNK: /* symbolic link */ + // *p++ = 'l'; + // break; +#ifdef S_IFSOCK + case S_IFSOCK: /* socket */ + *p++ = 's'; + break; +#endif + case _S_IFIFO: /* fifo */ + *p++ = 'p'; + break; + default: /* unknown */ + *p++ = '?'; + break; + } + /* usr */ + if (mode & S_IRUSR) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWUSR) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXUSR)) { + case 0: + *p++ = '-'; + break; + case S_IXUSR: + *p++ = 'x'; + break; + //case S_ISUID: + // *p++ = 'S'; + // break; + //case S_IXUSR | S_ISUID: + // *p++ = 's'; + // break; + } + /* group */ + if (mode & S_IRGRP) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWGRP) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXGRP)) { + case 0: + *p++ = '-'; + break; + case S_IXGRP: + *p++ = 'x'; + break; + //case S_ISGID: + // *p++ = 'S'; + // break; + //case S_IXGRP | S_ISGID: + // *p++ = 's'; + // break; + } + /* other */ + if (mode & S_IROTH) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWOTH) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXOTH)) { + case 0: + *p++ = '-'; + break; + case S_IXOTH: + *p++ = 'x'; + break; + } + *p++ = ' '; /* will be a '+' if ACL's implemented */ + *p = '\0'; +} +#endif diff --git a/sftp-server.c b/sftp-server.c index 87e9375..1a74657 100644 --- a/sftp-server.c +++ b/sftp-server.c @@ -1193,6 +1193,29 @@ process_readdir(u_int32_t id) int nstats = 10, count = 0, i; stats = xcalloc(nstats, sizeof(Stat)); + #ifdef WIN32_FIXME + // process the first entry that opendir() has found already + if (_stricmp(dirp->c_file.name, ".") && !_stricmp(dirp->c_file.name, dirp->initName)) // a firstfile that's not ".", this can happen for shared root drives + { // put first dirp in list + if (!strcmp(path, "/")) { + snprintf(pathname, sizeof pathname, + "/%s", dirp->c_file.name); + } + else { + snprintf(pathname, sizeof pathname, + "%s/%s", path, dirp->c_file.name); + } + if (pathname) { + if (lstat(pathname, &st) >= 0) { + stat_to_attrib(&st, &(stats[count].attrib)); + stats[count].name = xstrdup(dirp->c_file.name); + stats[count].long_name = ls_file(dirp->c_file.name, &st,0, 0); + count++; + } + } + } + #endif + while ((dp = readdir(dirp)) != NULL) { if (count >= nstats) { nstats *= 2; @@ -1214,7 +1237,7 @@ process_readdir(u_int32_t id) #else stats[count].name = ConvertLocal8ToUtf8(dp -> d_name, -1, NULL); #endif - stats[count].long_name = ls_file(dp -> d_name, &st, 0, 0); + stats[count].long_name = ls_file(dp -> d_name, &st, dirp->c_file.attrib, 0); /* debug3("putting name [%s]...\n", stats[count].name); diff --git a/win32_dirent.c b/win32_dirent.c index 024e677..4036a8d 100644 --- a/win32_dirent.c +++ b/win32_dirent.c @@ -19,9 +19,10 @@ DIR * opendir(char *name) DIR *pdir; char searchstr[256]; - sprintf_s(searchstr, sizeof(searchstr), "%s\\*.*",name); // add *.* to it for NT + // add *.* for Windows _findfirst() search pattern + sprintf_s(searchstr, sizeof(searchstr), "%s\\*.*",name); - if( (hFile = _findfirst( searchstr, &c_file )) == -1L ) { + if ((hFile = _findfirst(searchstr, &c_file)) == -1L) { if (1) // verbose printf( "No files found for %s search.\n", name ); return (DIR *) NULL; @@ -30,6 +31,7 @@ DIR * opendir(char *name) pdir = (DIR *) malloc( sizeof(DIR) ); pdir->hFile = hFile ; pdir->c_file = c_file ; + strcpy_s(pdir->initName,sizeof(pdir->initName), c_file.name); return pdir ; }