32
32
#include <netdb.h>
33
33
#include <signal.h>
34
34
#include <sys/uio.h>
35
+ #include <sys/param.h>
35
36
#include <sys/types.h>
36
37
#include <sys/time.h>
37
38
#include <sys/wait.h>
@@ -311,6 +312,7 @@ struct sshfs {
311
312
int unrel_append ;
312
313
int fstat_workaround ;
313
314
int createmode_workaround ;
315
+ int readdir_workaround ;
314
316
int transform_symlinks ;
315
317
int follow_symlinks ;
316
318
int no_check_root ;
@@ -543,6 +545,7 @@ static struct fuse_opt workaround_opts[] = {
543
545
SSHFS_OPT ("none" , truncate_workaround , 0 ),
544
546
SSHFS_OPT ("none" , buflimit_workaround , 0 ),
545
547
SSHFS_OPT ("none" , fstat_workaround , 0 ),
548
+ SSHFS_OPT ("none" , readdir_workaround , 0 ),
546
549
SSHFS_OPT ("rename" , rename_workaround , 1 ),
547
550
SSHFS_OPT ("norename" , rename_workaround , 0 ),
548
551
SSHFS_OPT ("renamexdev" , renamexdev_workaround , 1 ),
@@ -555,6 +558,8 @@ static struct fuse_opt workaround_opts[] = {
555
558
SSHFS_OPT ("nofstat" , fstat_workaround , 0 ),
556
559
SSHFS_OPT ("createmode" , createmode_workaround , 1 ),
557
560
SSHFS_OPT ("nocreatemode" , createmode_workaround , 0 ),
561
+ SSHFS_OPT ("readdir" , readdir_workaround , 1 ),
562
+ SSHFS_OPT ("noreaddir" , readdir_workaround , 0 ),
558
563
FUSE_OPT_END
559
564
};
560
565
@@ -602,6 +607,9 @@ static const char *type_name(uint8_t type)
602
607
#define list_entry (ptr , type , member ) \
603
608
container_of(ptr, type, member)
604
609
610
+ static int sshfs_releasedir (const char * path , struct fuse_file_info * fi );
611
+
612
+
605
613
static void list_init (struct list_head * head )
606
614
{
607
615
head -> next = head ;
@@ -1108,7 +1116,11 @@ static int pty_master(char **name)
1108
1116
{
1109
1117
int mfd ;
1110
1118
1119
+ #ifdef __FreeBSD__
1120
+ mfd = posix_openpt (O_RDWR | O_NOCTTY );
1121
+ #else
1111
1122
mfd = open ("/dev/ptmx" , O_RDWR | O_NOCTTY );
1123
+ #endif
1112
1124
if (mfd == -1 ) {
1113
1125
perror ("failed to open pty" );
1114
1126
return -1 ;
@@ -1891,12 +1903,20 @@ static void *sshfs_init(struct fuse_conn_info *conn,
1891
1903
if (conn -> capable & FUSE_CAP_ASYNC_READ )
1892
1904
sshfs .sync_read = 1 ;
1893
1905
1894
- // These workarounds require the "path" argument.
1895
- cfg -> nullpath_ok = !(sshfs .truncate_workaround || sshfs .fstat_workaround );
1896
-
1897
- // When using multiple connections, release() needs to know the path
1898
- if (sshfs .max_conns > 1 )
1906
+ /* These workarounds require the "path" argument:
1907
+ * - truncate_workaround
1908
+ * - fstat_workaround
1909
+ * - readdir_workaround
1910
+ * Also it required when using multiple connections: release()
1911
+ * needs to know the path.
1912
+ */
1913
+ if (sshfs .truncate_workaround ||
1914
+ sshfs .fstat_workaround ||
1915
+ sshfs .readdir_workaround ||
1916
+ sshfs .max_conns > 1 )
1899
1917
cfg -> nullpath_ok = 0 ;
1918
+ else
1919
+ cfg -> nullpath_ok = 1 ;
1900
1920
1901
1921
// Lookup of . and .. is supported
1902
1922
conn -> capable |= FUSE_CAP_EXPORT_SUPPORT ;
@@ -2200,6 +2220,7 @@ static int sshfs_req_pending(struct request *req)
2200
2220
static int sftp_readdir_async (struct conn * conn , struct buffer * handle ,
2201
2221
void * buf , off_t offset , fuse_fill_dir_t filler )
2202
2222
{
2223
+ (void ) offset ;
2203
2224
int err = 0 ;
2204
2225
int outstanding = 0 ;
2205
2226
int max = READDIR_START ;
@@ -2278,6 +2299,7 @@ static int sftp_readdir_async(struct conn *conn, struct buffer *handle,
2278
2299
static int sftp_readdir_sync (struct conn * conn , struct buffer * handle ,
2279
2300
void * buf , off_t offset , fuse_fill_dir_t filler )
2280
2301
{
2302
+ (void ) offset ;
2281
2303
int err ;
2282
2304
assert (offset == 0 );
2283
2305
do {
@@ -2327,10 +2349,19 @@ static int sshfs_readdir(const char *path, void *dbuf, fuse_fill_dir_t filler,
2327
2349
off_t offset , struct fuse_file_info * fi ,
2328
2350
enum fuse_readdir_flags flags )
2329
2351
{
2330
- (void ) path ; ( void ) flags ;
2352
+ (void ) flags ;
2331
2353
int err ;
2332
2354
struct dir_handle * handle ;
2333
2355
2356
+ if (sshfs .readdir_workaround ) {
2357
+ if (path == NULL )
2358
+ return - EIO ;
2359
+ err = sshfs_opendir (path , fi );
2360
+ if (err )
2361
+ return err ;
2362
+ offset = 0 ;
2363
+ }
2364
+
2334
2365
handle = (struct dir_handle * ) fi -> fh ;
2335
2366
2336
2367
if (sshfs .sync_readdir )
@@ -2340,6 +2371,9 @@ static int sshfs_readdir(const char *path, void *dbuf, fuse_fill_dir_t filler,
2340
2371
err = sftp_readdir_async (handle -> conn , & handle -> buf , dbuf ,
2341
2372
offset , filler );
2342
2373
2374
+ if (sshfs .readdir_workaround )
2375
+ sshfs_releasedir (path , fi );
2376
+
2343
2377
return err ;
2344
2378
}
2345
2379
@@ -3625,6 +3659,7 @@ static void usage(const char *progname)
3625
3659
" [no]buflimit fix buffer fillup bug in server (default: off)\n"
3626
3660
" [no]fstat always use stat() instead of fstat() (default: off)\n"
3627
3661
" [no]createmode always pass mode 0 to create (default: off)\n"
3662
+ " [no]readdir always open/read/close dir on readdir (default: on)\n"
3628
3663
" -o idmap=TYPE user/group ID mapping (default: " IDMAP_DEFAULT ")\n"
3629
3664
" none no translation of the ID space\n"
3630
3665
" user only translate UID/GID of connecting user\n"
@@ -4182,6 +4217,7 @@ int main(int argc, char *argv[])
4182
4217
sshfs .truncate_workaround = 0 ;
4183
4218
sshfs .buflimit_workaround = 0 ;
4184
4219
sshfs .createmode_workaround = 0 ;
4220
+ sshfs .readdir_workaround = 1 ;
4185
4221
sshfs .ssh_ver = 2 ;
4186
4222
sshfs .progname = argv [0 ];
4187
4223
sshfs .max_conns = 1 ;
0 commit comments