From 34146444ce20c477cba7e9fe113e4387da32ae94 Mon Sep 17 00:00:00 2001 From: Nikolaus Rath Date: Wed, 21 Jun 2017 15:05:20 -0700 Subject: Switch to libfuse 3.0. --- sshfs.c | 562 +++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 293 insertions(+), 269 deletions(-) (limited to 'sshfs.c') diff --git a/sshfs.c b/sshfs.c index 42a622c..cbc0c79 100644 --- a/sshfs.c +++ b/sshfs.c @@ -224,7 +224,12 @@ struct sshfs { int idmap; int nomap; int disable_hardlink; - int cache; + int dir_cache; + int writeback_cache; + int show_version; + int show_help; + int singlethread; + char *mountpoint; char *uid_file; char *gid_file; GHashTable *uid_map; @@ -357,9 +362,6 @@ static const char *ssh_opts[] = { enum { KEY_PORT, KEY_COMPRESS, - KEY_HELP, - KEY_VERSION, - KEY_FOREGROUND, KEY_CONFIGFILE, }; @@ -404,18 +406,22 @@ static struct fuse_opt sshfs_opts[] = { SSHFS_OPT("delay_connect", delay_connect, 1), SSHFS_OPT("slave", slave, 1), SSHFS_OPT("disable_hardlink", disable_hardlink, 1), - SSHFS_OPT("cache=yes", cache, 1), - SSHFS_OPT("cache=no", cache, 0), + SSHFS_OPT("dir_cache=yes", dir_cache, 1), + SSHFS_OPT("dir_cache=no", dir_cache, 0), + SSHFS_OPT("writeback_cache=yes", writeback_cache, 1), + SSHFS_OPT("writeback_cache=no", writeback_cache, 0), + + SSHFS_OPT("-h", show_help, 1), + SSHFS_OPT("--help", show_help, 1), + SSHFS_OPT("-V", show_version, 1), + SSHFS_OPT("--version", show_version, 1), + SSHFS_OPT("-d", debug, 1), + SSHFS_OPT("debug", debug, 1), + SSHFS_OPT("-f", foreground, 1), + SSHFS_OPT("-s", singlethread, 1), FUSE_OPT_KEY("-p ", KEY_PORT), FUSE_OPT_KEY("-C", KEY_COMPRESS), - FUSE_OPT_KEY("-V", KEY_VERSION), - FUSE_OPT_KEY("--version", KEY_VERSION), - FUSE_OPT_KEY("-h", KEY_HELP), - FUSE_OPT_KEY("--help", KEY_HELP), - FUSE_OPT_KEY("debug", KEY_FOREGROUND), - FUSE_OPT_KEY("-d", KEY_FOREGROUND), - FUSE_OPT_KEY("-f", KEY_FOREGROUND), FUSE_OPT_KEY("-F ", KEY_CONFIGFILE), FUSE_OPT_END }; @@ -863,7 +869,7 @@ static int buf_get_entries(struct buffer *buf, void *dbuf, S_ISLNK(stbuf.st_mode)) { stbuf.st_mode = 0; } - filler(dbuf, name, &stbuf, 0); + filler(dbuf, name, &stbuf, 0, 0); } } free(name); @@ -1715,15 +1721,29 @@ static int start_processing_thread(void) return 0; } -static void *sshfs_init(struct fuse_conn_info *conn) +static void *sshfs_init(struct fuse_conn_info *conn, + struct fuse_config *cfg) { /* Readahead should be done by kernel or sshfs but not both */ - if (conn->async_read) + if (conn->capable & FUSE_CAP_ASYNC_READ) sshfs.sync_read = 1; + // These workarounds require the "path" argument. + cfg->nullpath_ok = ~(sshfs.truncate_workaround || sshfs.fstat_workaround); + + // Lookup of . and .. is supported + conn->capable |= FUSE_CAP_EXPORT_SUPPORT; + + // Enable writeback cache if supported + if (sshfs.writeback_cache && (conn->capable & FUSE_CAP_WRITEBACK_CACHE)) + conn->want |= FUSE_CAP_WRITEBACK_CACHE; + if (!sshfs.delay_connect) start_processing_thread(); + // SFTP only supports 1-second time resolution + conn->time_gran = 1000000000; + return NULL; } @@ -1883,30 +1903,13 @@ static int sftp_request(uint8_t type, const struct buffer *buf, return sftp_request_iov(type, &iov, 1, expect_type, outbuf); } -static int sshfs_getattr(const char *path, struct stat *stbuf) -{ - int err; - struct buffer buf; - struct buffer outbuf; - buf_init(&buf, 0); - buf_add_path(&buf, path); - err = sftp_request(sshfs.follow_symlinks ? SSH_FXP_STAT : SSH_FXP_LSTAT, - &buf, SSH_FXP_ATTRS, &outbuf); - if (!err) { - err = buf_get_attrs(&outbuf, stbuf, NULL); - buf_free(&outbuf); - } - buf_free(&buf); - return err; -} - static int sshfs_access(const char *path, int mask) { struct stat stbuf; int err = 0; if (mask & X_OK) { - err = sshfs.op->getattr(path, &stbuf); + err = sshfs.op->getattr(path, &stbuf, NULL); if (!err) { if (S_ISREG(stbuf.st_mode) && !(stbuf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))) @@ -2146,9 +2149,10 @@ static int sshfs_opendir(const char *path, struct fuse_file_info *fi) } static int sshfs_readdir(const char *path, void *dbuf, fuse_fill_dir_t filler, - off_t offset, struct fuse_file_info *fi) + off_t offset, struct fuse_file_info *fi, + enum fuse_readdir_flags flags) { - (void) path; + (void) path; (void) flags; int err; struct buffer *handle; @@ -2291,9 +2295,13 @@ static void random_string(char *str, int length) *str = '\0'; } -static int sshfs_rename(const char *from, const char *to) +static int sshfs_rename(const char *from, const char *to, unsigned int flags) { int err; + + if(flags != 0) + return EINVAL; + if (sshfs.ext_posix_rename) err = sshfs_ext_posix_rename(from, to); else @@ -2337,25 +2345,66 @@ static int sshfs_link(const char *from, const char *to) return err; } -static int sshfs_chmod(const char *path, mode_t mode) +static inline int sshfs_file_is_conn(struct sshfs_file *sf) { + int ret; + + pthread_mutex_lock(&sshfs.lock); + ret = (sf->connver == sshfs.connver); + pthread_mutex_unlock(&sshfs.lock); + + return ret; +} + +static inline struct sshfs_file *get_sshfs_file(struct fuse_file_info *fi) +{ + return (struct sshfs_file *) (uintptr_t) fi->fh; +} + +static int sshfs_chmod(const char *path, mode_t mode, + struct fuse_file_info *fi) +{ + (void) fi; int err; struct buffer buf; + struct sshfs_file *sf = NULL; + + if (fi != NULL) { + sf = get_sshfs_file(fi); + if (!sshfs_file_is_conn(sf)) + return -EIO; + } + buf_init(&buf, 0); - buf_add_path(&buf, path); + if (sf == NULL) + buf_add_path(&buf, path); + else + buf_add_buf(&buf, &sf->handle); + buf_add_uint32(&buf, SSH_FILEXFER_ATTR_PERMISSIONS); buf_add_uint32(&buf, mode); + /* FIXME: really needs LSETSTAT extension (debian Bug#640038) */ - err = sftp_request(SSH_FXP_SETSTAT, &buf, SSH_FXP_STATUS, NULL); + err = sftp_request(sf == NULL ? SSH_FXP_SETSTAT : SSH_FXP_FSETSTAT, + &buf, SSH_FXP_STATUS, NULL); buf_free(&buf); return err; } -static int sshfs_chown(const char *path, uid_t uid, gid_t gid) +static int sshfs_chown(const char *path, uid_t uid, gid_t gid, + struct fuse_file_info *fi) { + (void) fi; int err; struct buffer buf; + struct sshfs_file *sf = NULL; + if (fi != NULL) { + sf = get_sshfs_file(fi); + if (!sshfs_file_is_conn(sf)) + return -EIO; + } + #ifdef __APPLE__ if (sshfs.remote_uid_detected) { if (uid == sshfs.local_uid) @@ -2375,11 +2424,16 @@ static int sshfs_chown(const char *path, uid_t uid, gid_t gid) return -EPERM; buf_init(&buf, 0); - buf_add_path(&buf, path); + if (sf == NULL) + buf_add_path(&buf, path); + else + buf_add_buf(&buf, &sf->handle); buf_add_uint32(&buf, SSH_FILEXFER_ATTR_UIDGID); buf_add_uint32(&buf, uid); buf_add_uint32(&buf, gid); - err = sftp_request(SSH_FXP_SETSTAT, &buf, SSH_FXP_STATUS, NULL); + + err = sftp_request(sf == NULL ? SSH_FXP_SETSTAT : SSH_FXP_FSETSTAT, + &buf, SSH_FXP_STATUS, NULL); buf_free(&buf); return err; } @@ -2394,49 +2448,35 @@ static void sshfs_inc_modifver(void) pthread_mutex_unlock(&sshfs.lock); } -static int sshfs_truncate(const char *path, off_t size) +static int sshfs_utimens(const char *path, const struct timespec tv[2], + struct fuse_file_info *fi) { + (void) fi; int err; struct buffer buf; + struct sshfs_file *sf = NULL; - sshfs_inc_modifver(); - if (size == 0 || sshfs.truncate_workaround) - return sshfs_truncate_workaround(path, size, NULL); - - buf_init(&buf, 0); - buf_add_path(&buf, path); - buf_add_uint32(&buf, SSH_FILEXFER_ATTR_SIZE); - buf_add_uint64(&buf, size); - err = sftp_request(SSH_FXP_SETSTAT, &buf, SSH_FXP_STATUS, NULL); - buf_free(&buf); - return err; -} + if (fi != NULL) { + sf = get_sshfs_file(fi); + if (!sshfs_file_is_conn(sf)) + return -EIO; + } -static int sshfs_utime(const char *path, struct utimbuf *ubuf) -{ - int err; - struct buffer buf; buf_init(&buf, 0); - buf_add_path(&buf, path); + if (sf == NULL) + buf_add_path(&buf, path); + else + buf_add_buf(&buf, &sf->handle); buf_add_uint32(&buf, SSH_FILEXFER_ATTR_ACMODTIME); - buf_add_uint32(&buf, ubuf->actime); - buf_add_uint32(&buf, ubuf->modtime); - err = sftp_request(SSH_FXP_SETSTAT, &buf, SSH_FXP_STATUS, NULL); + buf_add_uint32(&buf, tv[0].tv_sec); + buf_add_uint32(&buf, tv[1].tv_sec); + + err = sftp_request(sf == NULL ? SSH_FXP_SETSTAT : SSH_FXP_FSETSTAT, + &buf, SSH_FXP_STATUS, NULL); buf_free(&buf); return err; } -static inline int sshfs_file_is_conn(struct sshfs_file *sf) -{ - int ret; - - pthread_mutex_lock(&sshfs.lock); - ret = (sf->connver == sshfs.connver); - pthread_mutex_unlock(&sshfs.lock); - - return ret; -} - static int sshfs_open_common(const char *path, mode_t mode, struct fuse_file_info *fi) { @@ -2450,9 +2490,9 @@ static int sshfs_open_common(const char *path, mode_t mode, uint32_t pflags = 0; struct iovec iov; uint8_t type; - uint64_t wrctr = 0; + uint64_t wrctr; - if (sshfs.cache) + if (sshfs.dir_cache) wrctr = cache_get_write_ctr(); if ((fi->flags & O_ACCMODE) == O_RDONLY) @@ -2510,12 +2550,12 @@ static int sshfs_open_common(const char *path, mode_t mode, } if (!err) { - if (sshfs.cache) + if (sshfs.dir_cache) cache_add_attr(path, &stbuf, wrctr); buf_finish(&sf->handle); fi->fh = (unsigned long) sf; } else { - if (sshfs.cache) + if (sshfs.dir_cache) cache_invalidate(path); g_free(sf); } @@ -2528,11 +2568,6 @@ static int sshfs_open(const char *path, struct fuse_file_info *fi) return sshfs_open_common(path, 0, fi); } -static inline struct sshfs_file *get_sshfs_file(struct fuse_file_info *fi) -{ - return (struct sshfs_file *) (uintptr_t) fi->fh; -} - static int sshfs_flush(const char *path, struct fuse_file_info *fi) { int err; @@ -2575,16 +2610,14 @@ static int sshfs_fsync(const char *path, int isdatasync, if (!sshfs.ext_fsync) return err; - { - struct buffer buf; - struct sshfs_file *sf = get_sshfs_file(fi); - buf_init(&buf, 0); - buf_add_string(&buf, SFTP_EXT_FSYNC); - buf_add_buf(&buf, &sf->handle); - err = sftp_request(SSH_FXP_EXTENDED, &buf, SSH_FXP_STATUS, NULL); - buf_free(&buf); - return err; - } + struct buffer buf; + struct sshfs_file *sf = get_sshfs_file(fi); + buf_init(&buf, 0); + buf_add_string(&buf, SFTP_EXT_FSYNC); + buf_add_buf(&buf, &sf->handle); + err = sftp_request(SSH_FXP_EXTENDED, &buf, SSH_FXP_STATUS, NULL); + buf_free(&buf); + return err; } static void sshfs_file_put(struct sshfs_file *sf) @@ -3052,51 +3085,64 @@ static int sshfs_create(const char *path, mode_t mode, return sshfs_open_common(path, mode, fi); } -static int sshfs_ftruncate(const char *path, off_t size, - struct fuse_file_info *fi) +static int sshfs_truncate(const char *path, off_t size, + struct fuse_file_info *fi) { int err; struct buffer buf; - struct sshfs_file *sf = get_sshfs_file(fi); - - (void) path; - - if (!sshfs_file_is_conn(sf)) - return -EIO; + struct sshfs_file *sf = NULL; + if (fi != NULL) { + sf = get_sshfs_file(fi); + if (!sshfs_file_is_conn(sf)) + return -EIO; + } + sshfs_inc_modifver(); if (sshfs.truncate_workaround) return sshfs_truncate_workaround(path, size, fi); - + buf_init(&buf, 0); - buf_add_buf(&buf, &sf->handle); + + if (sf != NULL) + buf_add_buf(&buf, &sf->handle); + else + buf_add_path(&buf, path); + buf_add_uint32(&buf, SSH_FILEXFER_ATTR_SIZE); buf_add_uint64(&buf, size); - err = sftp_request(SSH_FXP_FSETSTAT, &buf, SSH_FXP_STATUS, NULL); + err = sftp_request(sf == NULL ? SSH_FXP_SETSTAT : SSH_FXP_FSETSTAT, + &buf, SSH_FXP_STATUS, NULL); buf_free(&buf); return err; } -static int sshfs_fgetattr(const char *path, struct stat *stbuf, - struct fuse_file_info *fi) +static int sshfs_getattr(const char *path, struct stat *stbuf, + struct fuse_file_info *fi) { int err; struct buffer buf; struct buffer outbuf; - struct sshfs_file *sf = get_sshfs_file(fi); + struct sshfs_file *sf = NULL; - (void) path; - - if (!sshfs_file_is_conn(sf)) - return -EIO; - - if (sshfs.fstat_workaround) - return sshfs_getattr(path, stbuf); + if (fi != NULL || sshfs.fstat_workaround) { + sf = get_sshfs_file(fi); + if (!sshfs_file_is_conn(sf)) + return -EIO; + } + buf_init(&buf, 0); - buf_add_buf(&buf, &sf->handle); - err = sftp_request(SSH_FXP_FSTAT, &buf, SSH_FXP_ATTRS, &outbuf); + if(sf == NULL) { + buf_add_path(&buf, path); + err = sftp_request(sshfs.follow_symlinks ? SSH_FXP_STAT : SSH_FXP_LSTAT, + &buf, SSH_FXP_ATTRS, &outbuf); + } + else { + buf_add_buf(&buf, &sf->handle); + err = sftp_request(SSH_FXP_FSTAT, &buf, SSH_FXP_ATTRS, &outbuf); + } if (!err) { err = buf_get_attrs(&outbuf, stbuf, NULL); buf_free(&outbuf); @@ -3212,10 +3258,7 @@ static int sshfs_truncate_workaround(const char *path, off_t size, else { struct stat stbuf; int err; - if (fi) - err = sshfs_fgetattr(path, &stbuf, fi); - else - err = sshfs_getattr(path, &stbuf); + err = sshfs_getattr(path, &stbuf, fi); if (err) return err; if (stbuf.st_size == size) @@ -3260,7 +3303,7 @@ static struct fuse_operations sshfs_oper = { .chmod = sshfs_chmod, .chown = sshfs_chown, .truncate = sshfs_truncate, - .utime = sshfs_utime, + .utimens = sshfs_utimens, .open = sshfs_open, .flush = sshfs_flush, .fsync = sshfs_fsync, @@ -3269,10 +3312,6 @@ static struct fuse_operations sshfs_oper = { .write = sshfs_write, .statfs = sshfs_statfs, .create = sshfs_create, - .ftruncate = sshfs_ftruncate, - .fgetattr = sshfs_fgetattr, - .flag_nullpath_ok = 1, - .flag_nopath = 1, }; static void usage(const char *progname) @@ -3280,30 +3319,32 @@ static void usage(const char *progname) printf( "usage: %s [user@]host:[dir] mountpoint [options]\n" "\n" -"general options:\n" -" -o opt,[opt...] mount options\n" " -h --help print help\n" " -V --version print version\n" -"\n" -"SSHFS options:\n" +" -f foreground operation\n" +" -s disable multi-threaded operation\n" " -p PORT equivalent to '-o port=PORT'\n" " -C equivalent to '-o compression=yes'\n" " -F ssh_configfile specifies alternative ssh configuration file\n" " -1 equivalent to '-o ssh_protocol=1'\n" +" -o opt,[opt...] mount options\n" " -o reconnect reconnect to server\n" " -o delay_connect delay connection to server\n" " -o sshfs_sync synchronous writes\n" " -o no_readahead synchronous reads (no speculative readahead)\n" " -o sync_readdir synchronous readdir\n" -" -o sshfs_debug print some debugging information\n" -" -o cache=BOOL enable caching {yes,no} (default: yes)\n" -" -o cache_max_size=N sets the maximum size of the cache (default: 10000)\n" -" -o cache_timeout=N sets timeout for caches in seconds (default: 20)\n" -" -o cache_X_timeout=N sets timeout for {stat,dir,link} cache\n" -" -o cache_clean_interval=N\n" +" -d, --debug print some debugging information (implies -f)\n" +" -o writeback_cache=BOOL enable writeback cache {yes,no} (default: yes)\n" +" -o dir_cache=BOOL enable caching of directory contents (names,\n" +" attributes, symlink targets) {yes,no} (default: yes)\n" +" -o dcache_max_size=N sets the maximum size of the directory cache (default: 10000)\n" +" -o dcache_timeout=N sets timeout for directory cache in seconds (default: 20)\n" +" -o dcache_{stat,link,dir}_timeout=N\n" +" sets separate timeout for {attributes, symlinks, names}\n" +" -o dcache_clean_interval=N\n" " sets the interval for automatic cleaning of the\n" " cache (default: 60)\n" -" -o cache_min_clean_interval=N\n" +" -o dcache_min_clean_interval=N\n" " sets the interval for forced cleaning of the\n" " cache if full (default: 5)\n" " -o workaround=LIST colon separated list of workarounds\n" @@ -3311,7 +3352,7 @@ static void usage(const char *progname) " [no]rename fix renaming to existing file (default: off)\n" " [no]truncate fix truncate for old servers (default: off)\n" " [no]buflimit fix buffer fillup bug in server (default: on)\n" -" [no]fstat fix fstat for old servers (default: off)\n" +" [no]fstat always use stat() instead of fstat() (default: off)\n" " -o idmap=TYPE user/group ID mapping (default: " IDMAP_DEFAULT ")\n" " none no translation of the ID space\n" " user only translate UID/GID of connecting user\n" @@ -3332,7 +3373,9 @@ static void usage(const char *progname) " -o no_check_root don't check for existence of 'dir' on server\n" " -o password_stdin read password from stdin (only for pam_mount!)\n" " -o SSHOPT=VAL ssh options (see man ssh_config)\n" -"\n", progname); +"\n" +"FUSE Options:\n", +progname); } static int is_ssh_opt(const char *arg) @@ -3350,17 +3393,11 @@ static int is_ssh_opt(const char *arg) return 0; } -static int sshfs_fuse_main(struct fuse_args *args) -{ - sshfs.op = cache_init(&sshfs_oper); - return fuse_main(args->argc, args->argv, sshfs.op, NULL); -} - static int sshfs_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs) { + (void) outargs; (void) data; char *tmp; - (void) data; switch (key) { case FUSE_OPT_KEY_OPT: @@ -3370,6 +3407,7 @@ static int sshfs_opt_proc(void *data, const char *arg, int key, g_free(tmp); return 0; } + /* Pass through */ return 1; case FUSE_OPT_KEY_NONOPT: @@ -3377,7 +3415,18 @@ static int sshfs_opt_proc(void *data, const char *arg, int key, sshfs.host = strdup(arg); return 0; } - return 1; + else if (!sshfs.mountpoint) { + sshfs.mountpoint = realpath(arg, NULL); + if (!sshfs.mountpoint) { + fprintf(stderr, "sshfs: bad mount point `%s': %s\n", + arg, strerror(errno)); + return -1; + } + return 0; + } + fprintf(stderr, "sshfs: invalid argument `%s'\n", arg); + return -1; + case KEY_PORT: tmp = g_strdup_printf("-oPort=%s", arg + 2); @@ -3395,22 +3444,6 @@ static int sshfs_opt_proc(void *data, const char *arg, int key, g_free(tmp); return 0; - case KEY_HELP: - usage(outargs->argv[0]); - fuse_opt_add_arg(outargs, "-ho"); - sshfs_fuse_main(outargs); - exit(1); - - case KEY_VERSION: - printf("SSHFS version %s\n", PACKAGE_VERSION); - fuse_opt_add_arg(outargs, "--version"); - sshfs_fuse_main(outargs); - exit(0); - - case KEY_FOREGROUND: - sshfs.foreground = 1; - return 1; - default: fprintf(stderr, "internal error\n"); abort(); @@ -3448,15 +3481,6 @@ static int parse_workarounds(void) return res; } -static void check_large_read(struct fuse_args *args) -{ - struct utsname buf; - int err = uname(&buf); - if (!err && strcmp(buf.sysname, "Linux") == 0 && - strncmp(buf.release, "2.4.", 4) == 0) - fuse_opt_insert_arg(args, 1, "-olarge_read"); -} - static int read_password(void) { int size = getpagesize(); @@ -3794,6 +3818,11 @@ int main(int argc, char *argv[]) char *tmp; char *fsname; const char *sftp_server; + struct fuse *fuse; + struct fuse_session *se; +#if !defined(__CYGWIN__) + struct stat st; +#endif #ifdef __APPLE__ if (!realpath(*exec_path, sshfs_program_path)) { @@ -3817,7 +3846,12 @@ int main(int argc, char *argv[]) sshfs.rfd = -1; sshfs.wfd = -1; sshfs.ptyfd = -1; - sshfs.cache = 1; + sshfs.dir_cache = 1; + sshfs.writeback_cache = 1; + sshfs.show_help = 0; + sshfs.show_version = 0; + sshfs.singlethread = 0; + sshfs.foreground = 0; sshfs.ptyslavefd = -1; sshfs.delay_connect = 0; sshfs.slave = 0; @@ -3841,12 +3875,31 @@ int main(int argc, char *argv[]) parse_workarounds() == -1) exit(1); - // These workarounds require the "path" argument. - if (sshfs.truncate_workaround || sshfs.fstat_workaround) { - sshfs_oper.flag_nullpath_ok = 0; - sshfs_oper.flag_nopath = 0; + if (sshfs.show_version) { + printf("SSHFS version %s\n", PACKAGE_VERSION); + printf("FUSE library version %s\n", fuse_pkgversion()); + fuse_lowlevel_version(); + exit(0); } + if (sshfs.show_help) { + usage(args.argv[0]); + /* Re-add --help */ + if (fuse_opt_add_arg(&args, "--help") == -1) + exit(1); + /* Print FUSE help text */ + assert(fuse_new(&args, NULL, 0, NULL) == NULL); + exit(0); + } else if (!sshfs.host) { + fprintf(stderr, "missing host\n"); + fprintf(stderr, "see `%s -h' for usage\n", argv[0]); + exit(1); + } else if (!sshfs.mountpoint) { + fprintf(stderr, "error: no mountpoint specified\n"); + fprintf(stderr, "see `%s -h' for usage\n", argv[0]); + exit(1); + } + if (sshfs.idmap == IDMAP_USER) sshfs.detect_uid = 1; else if (sshfs.idmap == IDMAP_FILE) { @@ -3868,10 +3921,10 @@ int main(int argc, char *argv[]) DEBUG("SSHFS version %s\n", PACKAGE_VERSION); - if (sshfs.slave) { - /* Force sshfs to the foreground when using stdin+stdout */ + /* Force sshfs to the foreground when using stdin+stdout */ + if (sshfs.slave) sshfs.foreground = 1; - } + if (sshfs.slave && sshfs.password_stdin) { fprintf(stderr, "the password_stdin and slave options cannot both be specified\n"); @@ -3884,6 +3937,9 @@ int main(int argc, char *argv[]) exit(1); } + if (sshfs.debug) + sshfs.foreground = 1; + if (sshfs.buflimit_workaround) /* Work around buggy sftp-server in OpenSSH. Without this on a slow server a 10Mbyte buffer would fill up and the server @@ -3892,12 +3948,6 @@ int main(int argc, char *argv[]) else sshfs.max_outstanding_len = ~0; - if (!sshfs.host) { - fprintf(stderr, "missing host\n"); - fprintf(stderr, "see `%s -h' for usage\n", argv[0]); - exit(1); - } - fsname = g_strdup(sshfs.host); sshfs.base_path = g_strdup(find_base_path()); @@ -3921,7 +3971,6 @@ int main(int argc, char *argv[]) ssh_add_arg(sftp_server); free(sshfs.sftp_server); - res = cache_parse_options(&args); if (res == -1) exit(1); @@ -3933,107 +3982,82 @@ int main(int argc, char *argv[]) if (sshfs.max_write > 65536) sshfs.max_write = 65536; - if (fuse_is_lib_option("ac_attr_timeout=")) - fuse_opt_insert_arg(&args, 1, "-oauto_cache,ac_attr_timeout=0"); fsname = fsname_escape_commas(fsname); tmp = g_strdup_printf("-osubtype=sshfs,fsname=%s", fsname); fuse_opt_insert_arg(&args, 1, tmp); g_free(tmp); g_free(fsname); - check_large_read(&args); - - { - struct fuse *fuse; - struct fuse_chan *ch; - char *mountpoint; - int multithreaded; - int foreground; -#if !defined(__CYGWIN__) - struct stat st; -#endif - - res = fuse_parse_cmdline(&args, &mountpoint, &multithreaded, - &foreground); - if (res == -1) - exit(1); - if (sshfs.slave) { - /* Force sshfs to the foreground when using stdin+stdout */ - foreground = 1; - } #if !defined(__CYGWIN__) - res = stat(mountpoint, &st); - if (res == -1) { - perror(mountpoint); - exit(1); - } - sshfs.mnt_mode = st.st_mode; + res = stat(sshfs.mountpoint, &st); + if (res == -1) { + perror(sshfs.mountpoint); + exit(1); + } + sshfs.mnt_mode = st.st_mode; #elif defined(__CYGWIN__) - sshfs.mnt_mode = S_IFDIR | 0755; + sshfs.mnt_mode = S_IFDIR | 0755; #endif - ch = fuse_mount(mountpoint, &args); - if (!ch) - exit(1); + if(sshfs.dir_cache) + sshfs.op = cache_wrap(&sshfs_oper); + else + sshfs.op = &sshfs_oper; + fuse = fuse_new(&args, sshfs.op, + sizeof(struct fuse_operations), NULL); + if(fuse == NULL) + exit(1); + se = fuse_get_session(fuse); + res = fuse_set_signal_handlers(se); + if (res != 0) { + fuse_destroy(fuse); + exit(1); + } + + res = fuse_mount(fuse, sshfs.mountpoint); + if (res != 0) { + fuse_destroy(fuse); + exit(1); + } #if !defined(__CYGWIN__) - res = fcntl(fuse_chan_fd(ch), F_SETFD, FD_CLOEXEC); - if (res == -1) - perror("WARNING: failed to set FD_CLOEXEC on fuse device"); + res = fcntl(fuse_session_fd(se), F_SETFD, FD_CLOEXEC); + if (res == -1) + perror("WARNING: failed to set FD_CLOEXEC on fuse device"); #endif - if(sshfs.cache) - sshfs.op = cache_init(&sshfs_oper); - else - sshfs.op = &sshfs_oper; - fuse = fuse_new(ch, &args, sshfs.op, - sizeof(struct fuse_operations), NULL); - if (fuse == NULL) { - fuse_unmount(mountpoint, ch); - exit(1); - } - - res = fuse_set_signal_handlers(fuse_get_session(fuse)); - if (res == -1) { - fuse_unmount(mountpoint, ch); - fuse_destroy(fuse); - exit(1); - } - - /* - * FIXME: trim $PATH so it doesn't contain anything inside the - * mountpoint, which would deadlock. - */ - res = ssh_connect(); - if (res == -1) { - fuse_unmount(mountpoint, ch); - fuse_destroy(fuse); - exit(1); - } + /* + * FIXME: trim $PATH so it doesn't contain anything inside the + * mountpoint, which would deadlock. + */ + res = ssh_connect(); + if (res == -1) { + fuse_unmount(fuse); + fuse_destroy(fuse); + exit(1); + } - res = fuse_daemonize(foreground); - if (res == -1) { - fuse_unmount(mountpoint, ch); - fuse_destroy(fuse); - exit(1); - } + res = fuse_daemonize(sshfs.foreground); + if (res == -1) { + fuse_unmount(fuse); + fuse_destroy(fuse); + exit(1); + } - if (multithreaded) - res = fuse_loop_mt(fuse); - else - res = fuse_loop(fuse); + if (sshfs.singlethread) + res = fuse_loop(fuse); + else + res = fuse_loop_mt(fuse, 0); - if (res == -1) - res = 1; - else - res = 0; + if (res != 0) + res = 1; + else + res = 0; - fuse_remove_signal_handlers(fuse_get_session(fuse)); - fuse_unmount(mountpoint, ch); - fuse_destroy(fuse); - free(mountpoint); - } + fuse_remove_signal_handlers(se); + fuse_unmount(fuse); + fuse_destroy(fuse); if (sshfs.debug) { unsigned int avg_rtt = 0; -- cgit v1.2.3