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 ;
@@ -542,6 +544,7 @@ static struct fuse_opt workaround_opts[] = {
542
544
SSHFS_OPT ("none" , truncate_workaround , 0 ),
543
545
SSHFS_OPT ("none" , buflimit_workaround , 0 ),
544
546
SSHFS_OPT ("none" , fstat_workaround , 0 ),
547
+ SSHFS_OPT ("none" , readdir_workaround , 0 ),
545
548
SSHFS_OPT ("rename" , rename_workaround , 1 ),
546
549
SSHFS_OPT ("norename" , rename_workaround , 0 ),
547
550
SSHFS_OPT ("renamexdev" , renamexdev_workaround , 1 ),
@@ -554,6 +557,8 @@ static struct fuse_opt workaround_opts[] = {
554
557
SSHFS_OPT ("nofstat" , fstat_workaround , 0 ),
555
558
SSHFS_OPT ("createmode" , createmode_workaround , 1 ),
556
559
SSHFS_OPT ("nocreatemode" , createmode_workaround , 0 ),
560
+ SSHFS_OPT ("readdir" , readdir_workaround , 1 ),
561
+ SSHFS_OPT ("noreaddir" , readdir_workaround , 0 ),
557
562
FUSE_OPT_END
558
563
};
559
564
@@ -1106,7 +1111,11 @@ static int pty_master(char **name)
1106
1111
{
1107
1112
int mfd ;
1108
1113
1114
+ #ifdef __FreeBSD__
1115
+ mfd = posix_openpt (O_RDWR | O_NOCTTY );
1116
+ #else
1109
1117
mfd = open ("/dev/ptmx" , O_RDWR | O_NOCTTY );
1118
+ #endif
1110
1119
if (mfd == -1 ) {
1111
1120
perror ("failed to open pty" );
1112
1121
return -1 ;
@@ -1886,12 +1895,20 @@ static void *sshfs_init(struct fuse_conn_info *conn,
1886
1895
if (conn -> capable & FUSE_CAP_ASYNC_READ )
1887
1896
sshfs .sync_read = 1 ;
1888
1897
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 )
1898
+ /* These workarounds require the "path" argument:
1899
+ * - truncate_workaround
1900
+ * - fstat_workaround
1901
+ * - readdir_workaround
1902
+ * Also it required when using multiple connections: release()
1903
+ * needs to know the path.
1904
+ */
1905
+ if (sshfs .truncate_workaround ||
1906
+ sshfs .fstat_workaround ||
1907
+ sshfs .readdir_workaround ||
1908
+ sshfs .max_conns > 1 )
1894
1909
cfg -> nullpath_ok = 0 ;
1910
+ else
1911
+ cfg -> nullpath_ok = 1 ;
1895
1912
1896
1913
// Lookup of . and .. is supported
1897
1914
conn -> capable |= FUSE_CAP_EXPORT_SUPPORT ;
@@ -2198,6 +2215,7 @@ static int sshfs_req_pending(struct request *req)
2198
2215
static int sftp_readdir_async (struct conn * conn , struct buffer * handle ,
2199
2216
void * buf , off_t offset , fuse_fill_dir_t filler )
2200
2217
{
2218
+ (void ) offset ;
2201
2219
int err = 0 ;
2202
2220
int outstanding = 0 ;
2203
2221
int max = READDIR_START ;
@@ -2276,6 +2294,7 @@ static int sftp_readdir_async(struct conn *conn, struct buffer *handle,
2276
2294
static int sftp_readdir_sync (struct conn * conn , struct buffer * handle ,
2277
2295
void * buf , off_t offset , fuse_fill_dir_t filler )
2278
2296
{
2297
+ (void ) offset ;
2279
2298
int err ;
2280
2299
assert (offset == 0 );
2281
2300
do {
@@ -2321,14 +2340,38 @@ static int sshfs_opendir(const char *path, struct fuse_file_info *fi)
2321
2340
return err ;
2322
2341
}
2323
2342
2343
+ static int sshfs_releasedir (const char * path , struct fuse_file_info * fi )
2344
+ {
2345
+ (void ) path ;
2346
+ int err ;
2347
+ struct dir_handle * handle ;
2348
+
2349
+ handle = (struct dir_handle * ) fi -> fh ;
2350
+ err = sftp_request (handle -> conn , SSH_FXP_CLOSE , & handle -> buf , 0 , NULL );
2351
+ pthread_mutex_lock (& sshfs .lock );
2352
+ handle -> conn -> dir_count -- ;
2353
+ pthread_mutex_unlock (& sshfs .lock );
2354
+ buf_free (& handle -> buf );
2355
+ g_free (handle );
2356
+ return err ;
2357
+ }
2358
+
2324
2359
static int sshfs_readdir (const char * path , void * dbuf , fuse_fill_dir_t filler ,
2325
2360
off_t offset , struct fuse_file_info * fi ,
2326
2361
enum fuse_readdir_flags flags )
2327
2362
{
2328
- (void ) path ; ( void ) flags ;
2363
+ (void ) flags ;
2329
2364
int err ;
2330
2365
struct dir_handle * handle ;
2331
2366
2367
+ if (sshfs .readdir_workaround ) {
2368
+ if (path == NULL )
2369
+ return - EIO ;
2370
+ err = sshfs_opendir (path , fi );
2371
+ if (err )
2372
+ return err ;
2373
+ }
2374
+
2332
2375
handle = (struct dir_handle * ) fi -> fh ;
2333
2376
2334
2377
if (sshfs .sync_readdir )
@@ -2338,22 +2381,9 @@ static int sshfs_readdir(const char *path, void *dbuf, fuse_fill_dir_t filler,
2338
2381
err = sftp_readdir_async (handle -> conn , & handle -> buf , dbuf ,
2339
2382
offset , filler );
2340
2383
2341
- return err ;
2342
- }
2384
+ if ( sshfs . readdir_workaround )
2385
+ err = sshfs_releasedir ( path , fi );
2343
2386
2344
- static int sshfs_releasedir (const char * path , struct fuse_file_info * fi )
2345
- {
2346
- (void ) path ;
2347
- int err ;
2348
- struct dir_handle * handle ;
2349
-
2350
- handle = (struct dir_handle * ) fi -> fh ;
2351
- err = sftp_request (handle -> conn , SSH_FXP_CLOSE , & handle -> buf , 0 , NULL );
2352
- pthread_mutex_lock (& sshfs .lock );
2353
- handle -> conn -> dir_count -- ;
2354
- pthread_mutex_unlock (& sshfs .lock );
2355
- buf_free (& handle -> buf );
2356
- g_free (handle );
2357
2387
return err ;
2358
2388
}
2359
2389
@@ -3616,6 +3646,7 @@ static void usage(const char *progname)
3616
3646
" [no]buflimit fix buffer fillup bug in server (default: off)\n"
3617
3647
" [no]fstat always use stat() instead of fstat() (default: off)\n"
3618
3648
" [no]createmode always pass mode 0 to create (default: off)\n"
3649
+ " [no]readdir always open/read/close dir on readdir (default: on for BSD)\n"
3619
3650
" -o idmap=TYPE user/group ID mapping (default: " IDMAP_DEFAULT ")\n"
3620
3651
" none no translation of the ID space\n"
3621
3652
" user only translate UID/GID of connecting user\n"
@@ -4173,6 +4204,11 @@ int main(int argc, char *argv[])
4173
4204
sshfs .truncate_workaround = 0 ;
4174
4205
sshfs .buflimit_workaround = 0 ;
4175
4206
sshfs .createmode_workaround = 0 ;
4207
+ #ifdef BSD
4208
+ sshfs .readdir_workaround = 1 ;
4209
+ #else
4210
+ sshfs .readdir_workaround = 0 ;
4211
+ #endif
4176
4212
sshfs .ssh_ver = 2 ;
4177
4213
sshfs .progname = argv [0 ];
4178
4214
sshfs .max_conns = 1 ;
0 commit comments