3232#include <netdb.h>
3333#include <signal.h>
3434#include <sys/uio.h>
35+ #include <sys/param.h>
3536#include <sys/types.h>
3637#include <sys/time.h>
3738#include <sys/wait.h>
@@ -311,6 +312,7 @@ struct sshfs {
311312 int unrel_append ;
312313 int fstat_workaround ;
313314 int createmode_workaround ;
315+ int readdir_workaround ;
314316 int transform_symlinks ;
315317 int follow_symlinks ;
316318 int no_check_root ;
@@ -542,6 +544,7 @@ static struct fuse_opt workaround_opts[] = {
542544 SSHFS_OPT ("none" , truncate_workaround , 0 ),
543545 SSHFS_OPT ("none" , buflimit_workaround , 0 ),
544546 SSHFS_OPT ("none" , fstat_workaround , 0 ),
547+ SSHFS_OPT ("none" , readdir_workaround , 0 ),
545548 SSHFS_OPT ("rename" , rename_workaround , 1 ),
546549 SSHFS_OPT ("norename" , rename_workaround , 0 ),
547550 SSHFS_OPT ("renamexdev" , renamexdev_workaround , 1 ),
@@ -554,6 +557,8 @@ static struct fuse_opt workaround_opts[] = {
554557 SSHFS_OPT ("nofstat" , fstat_workaround , 0 ),
555558 SSHFS_OPT ("createmode" , createmode_workaround , 1 ),
556559 SSHFS_OPT ("nocreatemode" , createmode_workaround , 0 ),
560+ SSHFS_OPT ("readdir" , readdir_workaround , 1 ),
561+ SSHFS_OPT ("noreaddir" , readdir_workaround , 0 ),
557562 FUSE_OPT_END
558563};
559564
@@ -601,6 +606,9 @@ static const char *type_name(uint8_t type)
601606#define list_entry (ptr , type , member ) \
602607 container_of(ptr, type, member)
603608
609+ static int sshfs_releasedir (const char * path , struct fuse_file_info * fi );
610+
611+
604612static void list_init (struct list_head * head )
605613{
606614 head -> next = head ;
@@ -1106,7 +1114,11 @@ static int pty_master(char **name)
11061114{
11071115 int mfd ;
11081116
1117+ #ifdef __FreeBSD__
1118+ mfd = posix_openpt (O_RDWR | O_NOCTTY );
1119+ #else
11091120 mfd = open ("/dev/ptmx" , O_RDWR | O_NOCTTY );
1121+ #endif
11101122 if (mfd == -1 ) {
11111123 perror ("failed to open pty" );
11121124 return -1 ;
@@ -1886,12 +1898,20 @@ static void *sshfs_init(struct fuse_conn_info *conn,
18861898 if (conn -> capable & FUSE_CAP_ASYNC_READ )
18871899 sshfs .sync_read = 1 ;
18881900
1889- // These workarounds require the "path" argument.
1890- cfg -> nullpath_ok = !(sshfs .truncate_workaround || sshfs .fstat_workaround );
1891-
1892- // When using multiple connections, release() needs to know the path
1893- if (sshfs .max_conns > 1 )
1901+ /* These workarounds require the "path" argument:
1902+ * - truncate_workaround
1903+ * - fstat_workaround
1904+ * - readdir_workaround
1905+ * Also it required when using multiple connections: release()
1906+ * needs to know the path.
1907+ */
1908+ if (sshfs .truncate_workaround ||
1909+ sshfs .fstat_workaround ||
1910+ sshfs .readdir_workaround ||
1911+ sshfs .max_conns > 1 )
18941912 cfg -> nullpath_ok = 0 ;
1913+ else
1914+ cfg -> nullpath_ok = 1 ;
18951915
18961916 // Lookup of . and .. is supported
18971917 conn -> capable |= FUSE_CAP_EXPORT_SUPPORT ;
@@ -2198,6 +2218,7 @@ static int sshfs_req_pending(struct request *req)
21982218static int sftp_readdir_async (struct conn * conn , struct buffer * handle ,
21992219 void * buf , off_t offset , fuse_fill_dir_t filler )
22002220{
2221+ (void ) offset ;
22012222 int err = 0 ;
22022223 int outstanding = 0 ;
22032224 int max = READDIR_START ;
@@ -2276,6 +2297,7 @@ static int sftp_readdir_async(struct conn *conn, struct buffer *handle,
22762297static int sftp_readdir_sync (struct conn * conn , struct buffer * handle ,
22772298 void * buf , off_t offset , fuse_fill_dir_t filler )
22782299{
2300+ (void ) offset ;
22792301 int err ;
22802302 assert (offset == 0 );
22812303 do {
@@ -2325,10 +2347,19 @@ static int sshfs_readdir(const char *path, void *dbuf, fuse_fill_dir_t filler,
23252347 off_t offset , struct fuse_file_info * fi ,
23262348 enum fuse_readdir_flags flags )
23272349{
2328- (void ) path ; ( void ) flags ;
2350+ (void ) flags ;
23292351 int err ;
23302352 struct dir_handle * handle ;
23312353
2354+ if (sshfs .readdir_workaround ) {
2355+ if (path == NULL )
2356+ return - EIO ;
2357+ err = sshfs_opendir (path , fi );
2358+ if (err )
2359+ return err ;
2360+ offset = 0 ;
2361+ }
2362+
23322363 handle = (struct dir_handle * ) fi -> fh ;
23332364
23342365 if (sshfs .sync_readdir )
@@ -2338,6 +2369,9 @@ static int sshfs_readdir(const char *path, void *dbuf, fuse_fill_dir_t filler,
23382369 err = sftp_readdir_async (handle -> conn , & handle -> buf , dbuf ,
23392370 offset , filler );
23402371
2372+ if (sshfs .readdir_workaround )
2373+ sshfs_releasedir (path , fi );
2374+
23412375 return err ;
23422376}
23432377
@@ -3616,6 +3650,7 @@ static void usage(const char *progname)
36163650" [no]buflimit fix buffer fillup bug in server (default: off)\n"
36173651" [no]fstat always use stat() instead of fstat() (default: off)\n"
36183652" [no]createmode always pass mode 0 to create (default: off)\n"
3653+ " [no]readdir always open/read/close dir on readdir (default: on)\n"
36193654" -o idmap=TYPE user/group ID mapping (default: " IDMAP_DEFAULT ")\n"
36203655" none no translation of the ID space\n"
36213656" user only translate UID/GID of connecting user\n"
@@ -4173,6 +4208,7 @@ int main(int argc, char *argv[])
41734208 sshfs .truncate_workaround = 0 ;
41744209 sshfs .buflimit_workaround = 0 ;
41754210 sshfs .createmode_workaround = 0 ;
4211+ sshfs .readdir_workaround = 1 ;
41764212 sshfs .ssh_ver = 2 ;
41774213 sshfs .progname = argv [0 ];
41784214 sshfs .max_conns = 1 ;
0 commit comments