Skip to content

Commit 46327a9

Browse files
committed
fix sftp-server not showing first entry in listing; code ls -l to show file attributes correctly
changing driver letter in sftp-server tested using usb drives; missing first entry on a top root directory is now shown correctly. ls -l output cleaned up and now correctly show file and directory attributes. strmode() function implemented for Windows like it is available in Unix/Linux OS.
1 parent 4857c27 commit 46327a9

File tree

3 files changed

+151
-3
lines changed

3 files changed

+151
-3
lines changed

sftp-common.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
#ifdef WIN32_FIXME
3434
#undef GSSAPI
3535
#undef KRB5
36+
37+
void strmode(mode_t mode, char *p);
38+
void strmode_from_attrib(unsigned attrib, char *p);
3639
#endif
3740

3841
#include <sys/param.h> /* MAX */
@@ -231,6 +234,9 @@ ls_file(const char *name, const struct stat *st, int remote, int si_units)
231234

232235
#ifndef WIN32_FIXME
233236
strmode(st->st_mode, mode);
237+
#else
238+
strmode(st->st_mode, mode);
239+
strmode_from_attrib(remote, mode);
234240
#endif
235241
if (!remote) {
236242
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)
281287
}
282288
return xstrdup(buf);
283289
}
290+
291+
#ifdef WIN32_FIXME
292+
293+
#include <sys/types.h>
294+
#include <windows.h>
295+
296+
void
297+
strmode_from_attrib(unsigned attrib, char *p)
298+
{
299+
if (attrib & FILE_ATTRIBUTE_REPARSE_POINT)
300+
*p = 'l';
301+
else if (attrib & FILE_ATTRIBUTE_DIRECTORY)
302+
*p = 'd';
303+
else
304+
*p = '-';
305+
}
306+
307+
308+
void
309+
strmode(mode_t mode, char *p)
310+
{
311+
/* print type */
312+
switch (mode & S_IFMT) {
313+
case S_IFDIR: /* directory */
314+
*p++ = 'd';
315+
break;
316+
case S_IFCHR: /* character special */
317+
*p++ = 'c';
318+
break;
319+
//case S_IFBLK: /* block special */
320+
// *p++ = 'b';
321+
// break;
322+
case S_IFREG: /* regular */
323+
*p++ = '-';
324+
break;
325+
//case S_IFLNK: /* symbolic link */
326+
// *p++ = 'l';
327+
// break;
328+
#ifdef S_IFSOCK
329+
case S_IFSOCK: /* socket */
330+
*p++ = 's';
331+
break;
332+
#endif
333+
case _S_IFIFO: /* fifo */
334+
*p++ = 'p';
335+
break;
336+
default: /* unknown */
337+
*p++ = '?';
338+
break;
339+
}
340+
/* usr */
341+
if (mode & S_IRUSR)
342+
*p++ = 'r';
343+
else
344+
*p++ = '-';
345+
if (mode & S_IWUSR)
346+
*p++ = 'w';
347+
else
348+
*p++ = '-';
349+
switch (mode & (S_IXUSR)) {
350+
case 0:
351+
*p++ = '-';
352+
break;
353+
case S_IXUSR:
354+
*p++ = 'x';
355+
break;
356+
//case S_ISUID:
357+
// *p++ = 'S';
358+
// break;
359+
//case S_IXUSR | S_ISUID:
360+
// *p++ = 's';
361+
// break;
362+
}
363+
/* group */
364+
if (mode & S_IRGRP)
365+
*p++ = 'r';
366+
else
367+
*p++ = '-';
368+
if (mode & S_IWGRP)
369+
*p++ = 'w';
370+
else
371+
*p++ = '-';
372+
switch (mode & (S_IXGRP)) {
373+
case 0:
374+
*p++ = '-';
375+
break;
376+
case S_IXGRP:
377+
*p++ = 'x';
378+
break;
379+
//case S_ISGID:
380+
// *p++ = 'S';
381+
// break;
382+
//case S_IXGRP | S_ISGID:
383+
// *p++ = 's';
384+
// break;
385+
}
386+
/* other */
387+
if (mode & S_IROTH)
388+
*p++ = 'r';
389+
else
390+
*p++ = '-';
391+
if (mode & S_IWOTH)
392+
*p++ = 'w';
393+
else
394+
*p++ = '-';
395+
switch (mode & (S_IXOTH)) {
396+
case 0:
397+
*p++ = '-';
398+
break;
399+
case S_IXOTH:
400+
*p++ = 'x';
401+
break;
402+
}
403+
*p++ = ' '; /* will be a '+' if ACL's implemented */
404+
*p = '\0';
405+
}
406+
#endif

sftp-server.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,29 @@ process_readdir(u_int32_t id)
11931193
int nstats = 10, count = 0, i;
11941194

11951195
stats = xcalloc(nstats, sizeof(Stat));
1196+
#ifdef WIN32_FIXME
1197+
// process the first entry that opendir() has found already
1198+
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
1199+
{ // put first dirp in list
1200+
if (!strcmp(path, "/")) {
1201+
snprintf(pathname, sizeof pathname,
1202+
"/%s", dirp->c_file.name);
1203+
}
1204+
else {
1205+
snprintf(pathname, sizeof pathname,
1206+
"%s/%s", path, dirp->c_file.name);
1207+
}
1208+
if (pathname) {
1209+
if (lstat(pathname, &st) >= 0) {
1210+
stat_to_attrib(&st, &(stats[count].attrib));
1211+
stats[count].name = xstrdup(dirp->c_file.name);
1212+
stats[count].long_name = ls_file(dirp->c_file.name, &st,0, 0);
1213+
count++;
1214+
}
1215+
}
1216+
}
1217+
#endif
1218+
11961219
while ((dp = readdir(dirp)) != NULL) {
11971220
if (count >= nstats) {
11981221
nstats *= 2;
@@ -1214,7 +1237,7 @@ process_readdir(u_int32_t id)
12141237
#else
12151238
stats[count].name = ConvertLocal8ToUtf8(dp -> d_name, -1, NULL);
12161239
#endif
1217-
stats[count].long_name = ls_file(dp -> d_name, &st, 0, 0);
1240+
stats[count].long_name = ls_file(dp -> d_name, &st, dirp->c_file.attrib, 0);
12181241

12191242
/*
12201243
debug3("putting name [%s]...\n", stats[count].name);

win32_dirent.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ DIR * opendir(char *name)
1919
DIR *pdir;
2020
char searchstr[256];
2121

22-
sprintf_s(searchstr, sizeof(searchstr), "%s\\*.*",name); // add *.* to it for NT
22+
// add *.* for Windows _findfirst() search pattern
23+
sprintf_s(searchstr, sizeof(searchstr), "%s\\*.*",name);
2324

24-
if( (hFile = _findfirst( searchstr, &c_file )) == -1L ) {
25+
if ((hFile = _findfirst(searchstr, &c_file)) == -1L) {
2526
if (1) // verbose
2627
printf( "No files found for %s search.\n", name );
2728
return (DIR *) NULL;
@@ -30,6 +31,7 @@ DIR * opendir(char *name)
3031
pdir = (DIR *) malloc( sizeof(DIR) );
3132
pdir->hFile = hFile ;
3233
pdir->c_file = c_file ;
34+
strcpy_s(pdir->initName,sizeof(pdir->initName), c_file.name);
3335

3436
return pdir ;
3537
}

0 commit comments

Comments
 (0)