22c1e2dee62fc05c84148f93c82e76682f0c88e1
[platform/upstream/sshfs.git] / sshfs.c
1 /*
2   SSH file system
3   Copyright (C) 2004  Miklos Szeredi <miklos@szeredi.hu>
4
5   This program can be distributed under the terms of the GNU GPL.
6   See the file COPYING.
7 */
8
9 #define _GNU_SOURCE /* avoid implicit declaration of *pt* functions */
10 #include "config.h"
11
12 #include <fuse.h>
13 #include <fuse_opt.h>
14 #include <fuse_lowlevel.h>
15 #include <assert.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <fcntl.h>
20 #include <string.h>
21 #include <stdint.h>
22 #include <errno.h>
23 #include <semaphore.h>
24 #include <pthread.h>
25 #include <netdb.h>
26 #include <signal.h>
27 #include <sys/uio.h>
28 #include <sys/types.h>
29 #include <sys/time.h>
30 #include <sys/wait.h>
31 #include <sys/socket.h>
32 #include <sys/utsname.h>
33 #include <sys/mman.h>
34 #include <sys/poll.h>
35 #include <netinet/in.h>
36 #include <netinet/tcp.h>
37 #include <glib.h>
38
39 #include "cache.h"
40
41 #ifndef MAP_LOCKED
42 #define MAP_LOCKED 0
43 #endif
44
45 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
46 #define MAP_ANONYMOUS MAP_ANON
47 #endif
48
49
50 #define SSH_FXP_INIT                1
51 #define SSH_FXP_VERSION             2
52 #define SSH_FXP_OPEN                3
53 #define SSH_FXP_CLOSE               4
54 #define SSH_FXP_READ                5
55 #define SSH_FXP_WRITE               6
56 #define SSH_FXP_LSTAT               7
57 #define SSH_FXP_FSTAT               8
58 #define SSH_FXP_SETSTAT             9
59 #define SSH_FXP_FSETSTAT           10
60 #define SSH_FXP_OPENDIR            11
61 #define SSH_FXP_READDIR            12
62 #define SSH_FXP_REMOVE             13
63 #define SSH_FXP_MKDIR              14
64 #define SSH_FXP_RMDIR              15
65 #define SSH_FXP_REALPATH           16
66 #define SSH_FXP_STAT               17
67 #define SSH_FXP_RENAME             18
68 #define SSH_FXP_READLINK           19
69 #define SSH_FXP_SYMLINK            20
70 #define SSH_FXP_STATUS            101
71 #define SSH_FXP_HANDLE            102
72 #define SSH_FXP_DATA              103
73 #define SSH_FXP_NAME              104
74 #define SSH_FXP_ATTRS             105
75 #define SSH_FXP_EXTENDED          200
76 #define SSH_FXP_EXTENDED_REPLY    201
77
78 #define SSH_FILEXFER_ATTR_SIZE          0x00000001
79 #define SSH_FILEXFER_ATTR_UIDGID        0x00000002
80 #define SSH_FILEXFER_ATTR_PERMISSIONS   0x00000004
81 #define SSH_FILEXFER_ATTR_ACMODTIME     0x00000008
82 #define SSH_FILEXFER_ATTR_EXTENDED      0x80000000
83
84 #define SSH_FX_OK                            0
85 #define SSH_FX_EOF                           1
86 #define SSH_FX_NO_SUCH_FILE                  2
87 #define SSH_FX_PERMISSION_DENIED             3
88 #define SSH_FX_FAILURE                       4
89 #define SSH_FX_BAD_MESSAGE                   5
90 #define SSH_FX_NO_CONNECTION                 6
91 #define SSH_FX_CONNECTION_LOST               7
92 #define SSH_FX_OP_UNSUPPORTED                8
93
94 #define SSH_FXF_READ            0x00000001
95 #define SSH_FXF_WRITE           0x00000002
96 #define SSH_FXF_APPEND          0x00000004
97 #define SSH_FXF_CREAT           0x00000008
98 #define SSH_FXF_TRUNC           0x00000010
99 #define SSH_FXF_EXCL            0x00000020
100
101 /* statvfs@openssh.com f_flag flags */
102 #define SSH2_FXE_STATVFS_ST_RDONLY      0x00000001
103 #define SSH2_FXE_STATVFS_ST_NOSUID      0x00000002
104
105 #define SFTP_EXT_POSIX_RENAME "posix-rename@openssh.com"
106 #define SFTP_EXT_STATVFS "statvfs@openssh.com"
107 #define SFTP_EXT_HARDLINK "hardlink@openssh.com"
108
109 #define PROTO_VERSION 3
110
111 #define MY_EOF 1
112
113 #define MAX_REPLY_LEN (1 << 17)
114
115 #define RENAME_TEMP_CHARS 8
116
117 #define SFTP_SERVER_PATH "/usr/lib/sftp-server"
118
119 #define SSHNODELAY_SO "sshnodelay.so"
120
121 struct buffer {
122         uint8_t *p;
123         size_t len;
124         size_t size;
125 };
126
127 struct list_head {
128         struct list_head *prev;
129         struct list_head *next;
130 };
131
132 struct request;
133 typedef void (*request_func)(struct request *);
134
135 struct request {
136         unsigned int want_reply;
137         sem_t ready;
138         uint8_t reply_type;
139         int replied;
140         int error;
141         struct buffer reply;
142         struct timeval start;
143         void *data;
144         request_func end_func;
145         size_t len;
146         struct list_head list;
147 };
148
149 struct sshfs_io {
150         int num_reqs;
151         pthread_cond_t finished;
152         int error;
153 };
154
155 struct read_req {
156         struct sshfs_io *sio;
157         struct list_head list;
158         struct buffer data;
159         size_t size;
160         ssize_t res;
161 };
162
163 struct read_chunk {
164         off_t offset;
165         size_t size;
166         int refs;
167         long modifver;
168         struct list_head reqs;
169         struct sshfs_io sio;
170 };
171
172 struct sshfs_file {
173         struct buffer handle;
174         struct list_head write_reqs;
175         pthread_cond_t write_finished;
176         int write_error;
177         struct read_chunk *readahead;
178         off_t next_pos;
179         int is_seq;
180         int connver;
181         int modifver;
182         int refs;
183 };
184
185 struct sshfs {
186         char *directport;
187         char *ssh_command;
188         char *sftp_server;
189         struct fuse_args ssh_args;
190         char *workarounds;
191         int rename_workaround;
192         int nodelay_workaround;
193         int nodelaysrv_workaround;
194         int truncate_workaround;
195         int buflimit_workaround;
196         int fstat_workaround;
197         int transform_symlinks;
198         int follow_symlinks;
199         int no_check_root;
200         int detect_uid;
201         unsigned max_read;
202         unsigned max_write;
203         unsigned ssh_ver;
204         int sync_write;
205         int sync_read;
206         int debug;
207         int foreground;
208         int reconnect;
209         int delay_connect;
210         char *host;
211         char *base_path;
212         GHashTable *reqtab;
213         pthread_mutex_t lock;
214         pthread_mutex_t lock_write;
215         int processing_thread_started;
216         unsigned int randseed;
217         int fd;
218         int ptyfd;
219         int ptyslavefd;
220         int connver;
221         int server_version;
222         unsigned remote_uid;
223         unsigned local_uid;
224         int remote_uid_detected;
225         unsigned blksize;
226         char *progname;
227         long modifver;
228         unsigned outstanding_len;
229         unsigned max_outstanding_len;
230         pthread_cond_t outstanding_cond;
231         int password_stdin;
232         char *password;
233         int ext_posix_rename;
234         int ext_statvfs;
235         int ext_hardlink;
236         mode_t mnt_mode;
237
238         /* statistics */
239         uint64_t bytes_sent;
240         uint64_t bytes_received;
241         uint64_t num_sent;
242         uint64_t num_received;
243         unsigned int min_rtt;
244         unsigned int max_rtt;
245         uint64_t total_rtt;
246         unsigned int num_connect;
247 };
248
249 static struct sshfs sshfs;
250
251 static const char *ssh_opts[] = {
252         "AddressFamily",
253         "BatchMode",
254         "BindAddress",
255         "ChallengeResponseAuthentication",
256         "CheckHostIP",
257         "Cipher",
258         "Ciphers",
259         "Compression",
260         "CompressionLevel",
261         "ConnectionAttempts",
262         "ConnectTimeout",
263         "ControlMaster",
264         "ControlPath",
265         "GlobalKnownHostsFile",
266         "GSSAPIAuthentication",
267         "GSSAPIDelegateCredentials",
268         "HostbasedAuthentication",
269         "HostKeyAlgorithms",
270         "HostKeyAlias",
271         "HostName",
272         "IdentitiesOnly",
273         "IdentityFile",
274         "KbdInteractiveAuthentication",
275         "KbdInteractiveDevices",
276         "LocalCommand",
277         "LogLevel",
278         "MACs",
279         "NoHostAuthenticationForLocalhost",
280         "NumberOfPasswordPrompts",
281         "PasswordAuthentication",
282         "Port",
283         "PreferredAuthentications",
284         "ProxyCommand",
285         "PubkeyAuthentication",
286         "RekeyLimit",
287         "RhostsRSAAuthentication",
288         "RSAAuthentication",
289         "ServerAliveCountMax",
290         "ServerAliveInterval",
291         "SmartcardDevice",
292         "StrictHostKeyChecking",
293         "TCPKeepAlive",
294         "UsePrivilegedPort",
295         "UserKnownHostsFile",
296         "VerifyHostKeyDNS",
297         NULL,
298 };
299
300 enum {
301         KEY_PORT,
302         KEY_COMPRESS,
303         KEY_HELP,
304         KEY_VERSION,
305         KEY_FOREGROUND,
306         KEY_CONFIGFILE,
307 };
308
309 #define SSHFS_OPT(t, p, v) { t, offsetof(struct sshfs, p), v }
310
311 static struct fuse_opt sshfs_opts[] = {
312         SSHFS_OPT("directport=%s",     directport, 0),
313         SSHFS_OPT("ssh_command=%s",    ssh_command, 0),
314         SSHFS_OPT("sftp_server=%s",    sftp_server, 0),
315         SSHFS_OPT("max_read=%u",       max_read, 0),
316         SSHFS_OPT("max_write=%u",      max_write, 0),
317         SSHFS_OPT("ssh_protocol=%u",   ssh_ver, 0),
318         SSHFS_OPT("-1",                ssh_ver, 1),
319         SSHFS_OPT("workaround=%s",     workarounds, 0),
320         SSHFS_OPT("idmap=none",        detect_uid, 0),
321         SSHFS_OPT("idmap=user",        detect_uid, 1),
322         SSHFS_OPT("sshfs_sync",        sync_write, 1),
323         SSHFS_OPT("no_readahead",      sync_read, 1),
324         SSHFS_OPT("sshfs_debug",       debug, 1),
325         SSHFS_OPT("reconnect",         reconnect, 1),
326         SSHFS_OPT("transform_symlinks", transform_symlinks, 1),
327         SSHFS_OPT("follow_symlinks",   follow_symlinks, 1),
328         SSHFS_OPT("no_check_root",     no_check_root, 1),
329         SSHFS_OPT("password_stdin",    password_stdin, 1),
330         SSHFS_OPT("delay_connect",     delay_connect, 1),
331
332         FUSE_OPT_KEY("-p ",            KEY_PORT),
333         FUSE_OPT_KEY("-C",             KEY_COMPRESS),
334         FUSE_OPT_KEY("-V",             KEY_VERSION),
335         FUSE_OPT_KEY("--version",      KEY_VERSION),
336         FUSE_OPT_KEY("-h",             KEY_HELP),
337         FUSE_OPT_KEY("--help",         KEY_HELP),
338         FUSE_OPT_KEY("debug",          KEY_FOREGROUND),
339         FUSE_OPT_KEY("-d",             KEY_FOREGROUND),
340         FUSE_OPT_KEY("-f",             KEY_FOREGROUND),
341         FUSE_OPT_KEY("-F ",            KEY_CONFIGFILE),
342         FUSE_OPT_END
343 };
344
345 static struct fuse_opt workaround_opts[] = {
346         SSHFS_OPT("none",       rename_workaround, 0),
347         SSHFS_OPT("none",       nodelay_workaround, 0),
348         SSHFS_OPT("none",       nodelaysrv_workaround, 0),
349         SSHFS_OPT("none",       truncate_workaround, 0),
350         SSHFS_OPT("none",       buflimit_workaround, 0),
351         SSHFS_OPT("none",       fstat_workaround, 0),
352         SSHFS_OPT("all",        rename_workaround, 1),
353         SSHFS_OPT("all",        nodelay_workaround, 1),
354         SSHFS_OPT("all",        nodelaysrv_workaround, 1),
355         SSHFS_OPT("all",        truncate_workaround, 1),
356         SSHFS_OPT("all",        buflimit_workaround, 1),
357         SSHFS_OPT("all",        fstat_workaround, 1),
358         SSHFS_OPT("rename",     rename_workaround, 1),
359         SSHFS_OPT("norename",   rename_workaround, 0),
360         SSHFS_OPT("nodelay",    nodelay_workaround, 1),
361         SSHFS_OPT("nonodelay",  nodelay_workaround, 0),
362         SSHFS_OPT("nodelaysrv", nodelaysrv_workaround, 1),
363         SSHFS_OPT("nonodelaysrv", nodelaysrv_workaround, 0),
364         SSHFS_OPT("truncate",   truncate_workaround, 1),
365         SSHFS_OPT("notruncate", truncate_workaround, 0),
366         SSHFS_OPT("buflimit",   buflimit_workaround, 1),
367         SSHFS_OPT("nobuflimit", buflimit_workaround, 0),
368         SSHFS_OPT("fstat",      fstat_workaround, 1),
369         SSHFS_OPT("nofstat",    fstat_workaround, 0),
370         FUSE_OPT_END
371 };
372
373 #define DEBUG(format, args...)                                          \
374         do { if (sshfs.debug) fprintf(stderr, format, args); } while(0)
375
376 static const char *type_name(uint8_t type)
377 {
378         switch(type) {
379         case SSH_FXP_INIT:           return "INIT";
380         case SSH_FXP_VERSION:        return "VERSION";
381         case SSH_FXP_OPEN:           return "OPEN";
382         case SSH_FXP_CLOSE:          return "CLOSE";
383         case SSH_FXP_READ:           return "READ";
384         case SSH_FXP_WRITE:          return "WRITE";
385         case SSH_FXP_LSTAT:          return "LSTAT";
386         case SSH_FXP_FSTAT:          return "FSTAT";
387         case SSH_FXP_SETSTAT:        return "SETSTAT";
388         case SSH_FXP_FSETSTAT:       return "FSETSTAT";
389         case SSH_FXP_OPENDIR:        return "OPENDIR";
390         case SSH_FXP_READDIR:        return "READDIR";
391         case SSH_FXP_REMOVE:         return "REMOVE";
392         case SSH_FXP_MKDIR:          return "MKDIR";
393         case SSH_FXP_RMDIR:          return "RMDIR";
394         case SSH_FXP_REALPATH:       return "REALPATH";
395         case SSH_FXP_STAT:           return "STAT";
396         case SSH_FXP_RENAME:         return "RENAME";
397         case SSH_FXP_READLINK:       return "READLINK";
398         case SSH_FXP_SYMLINK:        return "SYMLINK";
399         case SSH_FXP_STATUS:         return "STATUS";
400         case SSH_FXP_HANDLE:         return "HANDLE";
401         case SSH_FXP_DATA:           return "DATA";
402         case SSH_FXP_NAME:           return "NAME";
403         case SSH_FXP_ATTRS:          return "ATTRS";
404         case SSH_FXP_EXTENDED:       return "EXTENDED";
405         case SSH_FXP_EXTENDED_REPLY: return "EXTENDED_REPLY";
406         default:                     return "???";
407         }
408 }
409
410 #define container_of(ptr, type, member) ({                              \
411                         const typeof( ((type *)0)->member ) *__mptr = (ptr); \
412                         (type *)( (char *)__mptr - offsetof(type,member) );})
413
414 #define list_entry(ptr, type, member)           \
415         container_of(ptr, type, member)
416
417 static void list_init(struct list_head *head)
418 {
419         head->next = head;
420         head->prev = head;
421 }
422
423 static void list_add(struct list_head *new, struct list_head *head)
424 {
425         struct list_head *prev = head;
426         struct list_head *next = head->next;
427         next->prev = new;
428         new->next = next;
429         new->prev = prev;
430         prev->next = new;
431 }
432
433 static void list_del(struct list_head *entry)
434 {
435         struct list_head *prev = entry->prev;
436         struct list_head *next = entry->next;
437         next->prev = prev;
438         prev->next = next;
439
440 }
441
442 static int list_empty(const struct list_head *head)
443 {
444         return head->next == head;
445 }
446
447 static inline void buf_init(struct buffer *buf, size_t size)
448 {
449         if (size) {
450                 buf->p = (uint8_t *) malloc(size);
451                 if (!buf->p) {
452                         fprintf(stderr, "sshfs: memory allocation failed\n");
453                         abort();
454                 }
455         } else
456                 buf->p = NULL;
457         buf->len = 0;
458         buf->size = size;
459 }
460
461 static inline void buf_free(struct buffer *buf)
462 {
463         free(buf->p);
464 }
465
466 static inline void buf_finish(struct buffer *buf)
467 {
468         buf->len = buf->size;
469 }
470
471 static inline void buf_clear(struct buffer *buf)
472 {
473         buf_free(buf);
474         buf_init(buf, 0);
475 }
476
477 static void buf_resize(struct buffer *buf, size_t len)
478 {
479         buf->size = (buf->len + len + 63) & ~31;
480         buf->p = (uint8_t *) realloc(buf->p, buf->size);
481         if (!buf->p) {
482                 fprintf(stderr, "sshfs: memory allocation failed\n");
483                 abort();
484         }
485 }
486
487 static inline void buf_check_add(struct buffer *buf, size_t len)
488 {
489         if (buf->len + len > buf->size)
490                 buf_resize(buf, len);
491 }
492
493 #define _buf_add_mem(b, d, l)                   \
494         buf_check_add(b, l);                    \
495         memcpy(b->p + b->len, d, l);            \
496         b->len += l;
497
498
499 static inline void buf_add_mem(struct buffer *buf, const void *data,
500                                size_t len)
501 {
502         _buf_add_mem(buf, data, len);
503 }
504
505 static inline void buf_add_buf(struct buffer *buf, const struct buffer *bufa)
506 {
507         _buf_add_mem(buf, bufa->p, bufa->len);
508 }
509
510 static inline void buf_add_uint8(struct buffer *buf, uint8_t val)
511 {
512         _buf_add_mem(buf, &val, 1);
513 }
514
515 static inline void buf_add_uint32(struct buffer *buf, uint32_t val)
516 {
517         uint32_t nval = htonl(val);
518         _buf_add_mem(buf, &nval, 4);
519 }
520
521 static inline void buf_add_uint64(struct buffer *buf, uint64_t val)
522 {
523         buf_add_uint32(buf, val >> 32);
524         buf_add_uint32(buf, val & 0xffffffff);
525 }
526
527 static inline void buf_add_data(struct buffer *buf, const struct buffer *data)
528 {
529         buf_add_uint32(buf, data->len);
530         buf_add_mem(buf, data->p, data->len);
531 }
532
533 static inline void buf_add_string(struct buffer *buf, const char *str)
534 {
535         struct buffer data;
536         data.p = (uint8_t *) str;
537         data.len = strlen(str);
538         buf_add_data(buf, &data);
539 }
540
541 static inline void buf_add_path(struct buffer *buf, const char *path)
542 {
543         char *realpath;
544
545         if (sshfs.base_path[0]) {
546                 if (path[1]) {
547                         if (sshfs.base_path[strlen(sshfs.base_path)-1] != '/') {
548                                 realpath = g_strdup_printf("%s/%s",
549                                                            sshfs.base_path,
550                                                            path + 1);
551                         } else {
552                                 realpath = g_strdup_printf("%s%s",
553                                                            sshfs.base_path,
554                                                            path + 1);
555                         }
556                 } else {
557                         realpath = g_strdup(sshfs.base_path);
558                 }
559         } else {
560                 if (path[1])
561                         realpath = g_strdup(path + 1);
562                 else
563                         realpath = g_strdup(".");
564         }
565         buf_add_string(buf, realpath);
566         g_free(realpath);
567 }
568
569 static int buf_check_get(struct buffer *buf, size_t len)
570 {
571         if (buf->len + len > buf->size) {
572                 fprintf(stderr, "buffer too short\n");
573                 return -1;
574         } else
575                 return 0;
576 }
577
578 static inline int buf_get_mem(struct buffer *buf, void *data, size_t len)
579 {
580         if (buf_check_get(buf, len) == -1)
581                 return -1;
582         memcpy(data, buf->p + buf->len, len);
583         buf->len += len;
584         return 0;
585 }
586
587 static inline int buf_get_uint8(struct buffer *buf, uint8_t *val)
588 {
589         return buf_get_mem(buf, val, 1);
590 }
591
592 static inline int buf_get_uint32(struct buffer *buf, uint32_t *val)
593 {
594         uint32_t nval;
595         if (buf_get_mem(buf, &nval, 4) == -1)
596                 return -1;
597         *val = ntohl(nval);
598         return 0;
599 }
600
601 static inline int buf_get_uint64(struct buffer *buf, uint64_t *val)
602 {
603         uint32_t val1;
604         uint32_t val2;
605         if (buf_get_uint32(buf, &val1) == -1 ||
606             buf_get_uint32(buf, &val2) == -1) {
607                 return -1;
608         }
609         *val = ((uint64_t) val1 << 32) + val2;
610         return 0;
611 }
612
613 static inline int buf_get_data(struct buffer *buf, struct buffer *data)
614 {
615         uint32_t len;
616         if (buf_get_uint32(buf, &len) == -1 || len > buf->size - buf->len)
617                 return -1;
618         buf_init(data, len + 1);
619         data->size = len;
620         if (buf_get_mem(buf, data->p, data->size) == -1) {
621                 buf_free(data);
622                 return -1;
623         }
624         return 0;
625 }
626
627 static inline int buf_get_string(struct buffer *buf, char **str)
628 {
629         struct buffer data;
630         if (buf_get_data(buf, &data) == -1)
631                 return -1;
632         data.p[data.size] = '\0';
633         *str = (char *) data.p;
634         return 0;
635 }
636
637 static int buf_get_attrs(struct buffer *buf, struct stat *stbuf, int *flagsp)
638 {
639         uint32_t flags;
640         uint64_t size = 0;
641         uint32_t uid = 0;
642         uint32_t gid = 0;
643         uint32_t atime = 0;
644         uint32_t mtime = 0;
645         uint32_t mode = S_IFREG | 0777;
646
647         if (buf_get_uint32(buf, &flags) == -1)
648                 return -1;
649         if (flagsp)
650                 *flagsp = flags;
651         if ((flags & SSH_FILEXFER_ATTR_SIZE) &&
652             buf_get_uint64(buf, &size) == -1)
653                 return -1;
654         if ((flags & SSH_FILEXFER_ATTR_UIDGID) &&
655             (buf_get_uint32(buf, &uid) == -1 ||
656              buf_get_uint32(buf, &gid) == -1))
657                 return -1;
658         if ((flags & SSH_FILEXFER_ATTR_PERMISSIONS) &&
659             buf_get_uint32(buf, &mode) == -1)
660                 return -1;
661         if ((flags & SSH_FILEXFER_ATTR_ACMODTIME)) {
662                 if (buf_get_uint32(buf, &atime) == -1 ||
663                     buf_get_uint32(buf, &mtime) == -1)
664                         return -1;
665         }
666         if ((flags & SSH_FILEXFER_ATTR_EXTENDED)) {
667                 uint32_t extcount;
668                 unsigned i;
669                 if (buf_get_uint32(buf, &extcount) == -1)
670                         return -1;
671                 for (i = 0; i < extcount; i++) {
672                         struct buffer tmp;
673                         if (buf_get_data(buf, &tmp) == -1)
674                                 return -1;
675                         buf_free(&tmp);
676                         if (buf_get_data(buf, &tmp) == -1)
677                                 return -1;
678                         buf_free(&tmp);
679                 }
680         }
681
682         if (sshfs.remote_uid_detected && uid == sshfs.remote_uid)
683                 uid = sshfs.local_uid;
684
685         memset(stbuf, 0, sizeof(struct stat));
686         stbuf->st_mode = mode;
687         stbuf->st_nlink = 1;
688         stbuf->st_size = size;
689         if (sshfs.blksize) {
690                 stbuf->st_blksize = sshfs.blksize;
691                 stbuf->st_blocks = ((size + sshfs.blksize - 1) &
692                         ~((unsigned long long) sshfs.blksize - 1)) >> 9;
693         }
694         stbuf->st_uid = uid;
695         stbuf->st_gid = gid;
696         stbuf->st_atime = atime;
697         stbuf->st_ctime = stbuf->st_mtime = mtime;
698         return 0;
699 }
700
701 static int buf_get_statvfs(struct buffer *buf, struct statvfs *stbuf)
702 {
703         uint64_t bsize;
704         uint64_t frsize;
705         uint64_t blocks;
706         uint64_t bfree;
707         uint64_t bavail;
708         uint64_t files;
709         uint64_t ffree;
710         uint64_t favail;
711         uint64_t fsid;
712         uint64_t flag;
713         uint64_t namemax;
714
715         if (buf_get_uint64(buf, &bsize) == -1 ||
716             buf_get_uint64(buf, &frsize) == -1 ||
717             buf_get_uint64(buf, &blocks) == -1 ||
718             buf_get_uint64(buf, &bfree) == -1 ||
719             buf_get_uint64(buf, &bavail) == -1 ||
720             buf_get_uint64(buf, &files) == -1 ||
721             buf_get_uint64(buf, &ffree) == -1 ||
722             buf_get_uint64(buf, &favail) == -1 ||
723             buf_get_uint64(buf, &fsid) == -1 ||
724             buf_get_uint64(buf, &flag) == -1 ||
725             buf_get_uint64(buf, &namemax) == -1) {
726                 return -1;
727         }
728
729         memset(stbuf, 0, sizeof(struct statvfs));
730         stbuf->f_bsize = bsize;
731         stbuf->f_frsize = frsize;
732         stbuf->f_blocks = blocks;
733         stbuf->f_bfree = bfree;
734         stbuf->f_bavail = bavail;
735         stbuf->f_files = files;
736         stbuf->f_ffree = ffree;
737         stbuf->f_favail = favail;
738         stbuf->f_namemax = namemax;
739
740         return 0;
741 }
742
743 static int buf_get_entries(struct buffer *buf, fuse_cache_dirh_t h,
744                            fuse_cache_dirfil_t filler)
745 {
746         uint32_t count;
747         unsigned i;
748
749         if (buf_get_uint32(buf, &count) == -1)
750                 return -1;
751
752         for (i = 0; i < count; i++) {
753                 int err = -1;
754                 char *name;
755                 char *longname;
756                 struct stat stbuf;
757                 if (buf_get_string(buf, &name) == -1)
758                         return -1;
759                 if (buf_get_string(buf, &longname) != -1) {
760                         free(longname);
761                         if (buf_get_attrs(buf, &stbuf, NULL) != -1) {
762                                 if (sshfs.follow_symlinks &&
763                                     S_ISLNK(stbuf.st_mode)) {
764                                         stbuf.st_mode = 0;
765                                 }
766                                 filler(h, name, &stbuf);
767                                 err = 0;
768                         }
769                 }
770                 free(name);
771                 if (err)
772                         return err;
773         }
774         return 0;
775 }
776
777 static void ssh_add_arg(const char *arg)
778 {
779         if (fuse_opt_add_arg(&sshfs.ssh_args, arg) == -1)
780                 _exit(1);
781 }
782
783 #ifdef SSH_NODELAY_WORKAROUND
784 static int do_ssh_nodelay_workaround(void)
785 {
786         char *oldpreload = getenv("LD_PRELOAD");
787         char *newpreload;
788         char sopath[PATH_MAX];
789         int res;
790
791         snprintf(sopath, sizeof(sopath), "%s/%s", LIBDIR, SSHNODELAY_SO);
792         res = access(sopath, R_OK);
793         if (res == -1) {
794                 char *s;
795                 if (!realpath(sshfs.progname, sopath))
796                         return -1;
797
798                 s = strrchr(sopath, '/');
799                 if (!s)
800                         s = sopath;
801                 else
802                         s++;
803
804                 if (s + strlen(SSHNODELAY_SO) >= sopath + sizeof(sopath))
805                         return -1;
806
807                 strcpy(s, SSHNODELAY_SO);
808                 res = access(sopath, R_OK);
809                 if (res == -1) {
810                         fprintf(stderr, "sshfs: cannot find %s\n",
811                                 SSHNODELAY_SO);
812                         return -1;
813                 }
814         }
815
816         newpreload = g_strdup_printf("%s%s%s",
817                                      oldpreload ? oldpreload : "",
818                                      oldpreload ? " " : "",
819                                      sopath);
820
821         if (!newpreload || setenv("LD_PRELOAD", newpreload, 1) == -1) {
822                 fprintf(stderr, "warning: failed set LD_PRELOAD "
823                         "for ssh nodelay workaround\n");
824         }
825         g_free(newpreload);
826         return 0;
827 }
828 #endif
829
830 static int pty_expect_loop(void)
831 {
832         int res;
833         char buf[256];
834         const char *passwd_str = "assword:";
835         int timeout = 60 * 1000; /* 1min timeout for the prompt to appear */
836         int passwd_len = strlen(passwd_str);
837         int len = 0;
838         char c;
839
840         while (1) {
841                 struct pollfd fds[2];
842
843                 fds[0].fd = sshfs.fd;
844                 fds[0].events = POLLIN;
845                 fds[1].fd = sshfs.ptyfd;
846                 fds[1].events = POLLIN;
847                 res = poll(fds, 2, timeout);
848                 if (res == -1) {
849                         perror("poll");
850                         return -1;
851                 }
852                 if (res == 0) {
853                         fprintf(stderr, "Timeout waiting for prompt\n");
854                         return -1;
855                 }
856                 if (fds[0].revents) {
857                         /*
858                          * Something happened on stdout of ssh, this
859                          * either means, that we are connected, or
860                          * that we are disconnected.  In any case the
861                          * password doesn't matter any more.
862                          */
863                         break;
864                 }
865
866                 res = read(sshfs.ptyfd, &c, 1);
867                 if (res == -1) {
868                         perror("read");
869                         return -1;
870                 }
871                 if (res == 0) {
872                         fprintf(stderr, "EOF while waiting for prompt\n");
873                         return -1;
874                 }
875                 buf[len] = c;
876                 len++;
877                 if (len == passwd_len) {
878                         if (memcmp(buf, passwd_str, passwd_len) == 0) {
879                                 write(sshfs.ptyfd, sshfs.password,
880                                       strlen(sshfs.password));
881                         }
882                         memmove(buf, buf + 1, passwd_len - 1);
883                         len--;
884                 }
885         }
886
887         if (!sshfs.reconnect) {
888                 size_t size = getpagesize();
889
890                 memset(sshfs.password, 0, size);
891                 munmap(sshfs.password, size);
892                 sshfs.password = NULL;
893         }
894
895         return 0;
896 }
897
898 static int pty_master(char **name)
899 {
900         int mfd;
901
902         mfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
903         if (mfd == -1) {
904                 perror("failed to open pty");
905                 return -1;
906         }
907         if (grantpt(mfd) != 0) {
908                 perror("grantpt");
909                 return -1;
910         }
911         if (unlockpt(mfd) != 0) {
912                 perror("unlockpt");
913                 return -1;
914         }
915         *name = ptsname(mfd);
916
917         return mfd;
918 }
919
920 static void replace_arg(char **argp, const char *newarg)
921 {
922         free(*argp);
923         *argp = strdup(newarg);
924         if (*argp == NULL) {
925                 fprintf(stderr, "sshfs: memory allocation failed\n");
926                 abort();
927         }
928 }
929
930 static int start_ssh(void)
931 {
932         char *ptyname = NULL;
933         int sockpair[2];
934         int pid;
935
936         if (sshfs.password_stdin) {
937
938                 sshfs.ptyfd = pty_master(&ptyname);
939                 if (sshfs.ptyfd == -1)
940                         return -1;
941
942                 sshfs.ptyslavefd = open(ptyname, O_RDWR | O_NOCTTY);
943                 if (sshfs.ptyslavefd == -1)
944                         return -1;
945         }
946
947         if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair) == -1) {
948                 perror("failed to create socket pair");
949                 return -1;
950         }
951         sshfs.fd = sockpair[0];
952
953         pid = fork();
954         if (pid == -1) {
955                 perror("failed to fork");
956                 close(sockpair[1]);
957                 return -1;
958         } else if (pid == 0) {
959                 int devnull;
960
961 #ifdef SSH_NODELAY_WORKAROUND
962                 if (sshfs.nodelay_workaround &&
963                     do_ssh_nodelay_workaround() == -1) {
964                         fprintf(stderr,
965                                 "warning: ssh nodelay workaround disabled\n");
966                 }
967 #endif
968
969                 if (sshfs.nodelaysrv_workaround) {
970                         int i;
971                         /*
972                          * Hack to work around missing TCP_NODELAY
973                          * setting in sshd
974                          */
975                         for (i = 1; i < sshfs.ssh_args.argc; i++) {
976                                 if (strcmp(sshfs.ssh_args.argv[i], "-x") == 0) {
977                                         replace_arg(&sshfs.ssh_args.argv[i],
978                                                     "-X");
979                                         break;
980                                 }
981                         }
982                 }
983
984                 devnull = open("/dev/null", O_WRONLY);
985
986                 if (dup2(sockpair[1], 0) == -1 || dup2(sockpair[1], 1) == -1) {
987                         perror("failed to redirect input/output");
988                         _exit(1);
989                 }
990                 if (!sshfs.foreground && devnull != -1)
991                         dup2(devnull, 2);
992
993                 close(devnull);
994                 close(sockpair[0]);
995                 close(sockpair[1]);
996
997                 switch (fork()) {
998                 case -1:
999                         perror("failed to fork");
1000                         _exit(1);
1001                 case 0:
1002                         break;
1003                 default:
1004                         _exit(0);
1005                 }
1006                 chdir("/");
1007
1008                 if (sshfs.password_stdin) {
1009                         int sfd;
1010
1011                         setsid();
1012                         sfd = open(ptyname, O_RDWR);
1013                         if (sfd == -1) {
1014                                 perror(ptyname);
1015                                 _exit(1);
1016                         }
1017                         close(sfd);
1018                         close(sshfs.ptyslavefd);
1019                         close(sshfs.ptyfd);
1020                 }
1021
1022                 if (sshfs.debug) {
1023                         int i;
1024
1025                         fprintf(stderr, "executing");
1026                         for (i = 0; i < sshfs.ssh_args.argc; i++)
1027                                 fprintf(stderr, " <%s>",
1028                                         sshfs.ssh_args.argv[i]);
1029                         fprintf(stderr, "\n");
1030                 }
1031
1032                 execvp(sshfs.ssh_args.argv[0], sshfs.ssh_args.argv);
1033                 fprintf(stderr, "failed to execute '%s': %s\n",
1034                         sshfs.ssh_args.argv[0], strerror(errno));
1035                 _exit(1);
1036         }
1037         waitpid(pid, NULL, 0);
1038         close(sockpair[1]);
1039         return 0;
1040 }
1041
1042 static int connect_to(char *host, char *port)
1043 {
1044         int err;
1045         int sock;
1046         int opt;
1047         struct addrinfo *ai;
1048         struct addrinfo hint;
1049
1050         memset(&hint, 0, sizeof(hint));
1051         hint.ai_family = PF_INET;
1052         hint.ai_socktype = SOCK_STREAM;
1053         err = getaddrinfo(host, port, &hint, &ai);
1054         if (err) {
1055                 fprintf(stderr, "failed to resolve %s:%s: %s\n", host, port,
1056                         gai_strerror(err));
1057                 return -1;
1058         }
1059         sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
1060         if (sock == -1) {
1061                 perror("failed to create socket");
1062                 return -1;
1063         }
1064         err = connect(sock, ai->ai_addr, ai->ai_addrlen);
1065         if (err == -1) {
1066                 perror("failed to connect");
1067                 return -1;
1068         }
1069         opt = 1;
1070         err = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
1071         if (err == -1)
1072                 perror("warning: failed to set TCP_NODELAY");
1073
1074         freeaddrinfo(ai);
1075
1076         sshfs.fd = sock;
1077         return 0;
1078 }
1079
1080 static int do_write(struct iovec *iov, size_t count)
1081 {
1082         int res;
1083         while (count) {
1084                 res = writev(sshfs.fd, iov, count);
1085                 if (res == -1) {
1086                         perror("write");
1087                         return -1;
1088                 } else if (res == 0) {
1089                         fprintf(stderr, "zero write\n");
1090                         return -1;
1091                 }
1092                 do {
1093                         if ((unsigned) res < iov->iov_len) {
1094                                 iov->iov_len -= res;
1095                                 iov->iov_base += res;
1096                                 break;
1097                         } else {
1098                                 res -= iov->iov_len;
1099                                 count --;
1100                                 iov ++;
1101                         }
1102                 } while(count);
1103         }
1104         return 0;
1105 }
1106
1107 static uint32_t sftp_get_id(void)
1108 {
1109         static uint32_t idctr;
1110         return idctr++;
1111 }
1112
1113 static void buf_to_iov(const struct buffer *buf, struct iovec *iov)
1114 {
1115         iov->iov_base = buf->p;
1116         iov->iov_len = buf->len;
1117 }
1118
1119 static size_t iov_length(const struct iovec *iov, unsigned long nr_segs)
1120 {
1121         unsigned long seg;
1122         size_t ret = 0;
1123
1124         for (seg = 0; seg < nr_segs; seg++)
1125                 ret += iov[seg].iov_len;
1126         return ret;
1127 }
1128
1129 #define SFTP_MAX_IOV 3
1130
1131 static int sftp_send_iov(uint8_t type, uint32_t id, struct iovec iov[],
1132                          size_t count)
1133 {
1134         int res;
1135         struct buffer buf;
1136         struct iovec iovout[SFTP_MAX_IOV];
1137         unsigned i;
1138         unsigned nout = 0;
1139
1140         assert(count <= SFTP_MAX_IOV - 1);
1141         buf_init(&buf, 9);
1142         buf_add_uint32(&buf, iov_length(iov, count) + 5);
1143         buf_add_uint8(&buf, type);
1144         buf_add_uint32(&buf, id);
1145         buf_to_iov(&buf, &iovout[nout++]);
1146         for (i = 0; i < count; i++)
1147                 iovout[nout++] = iov[i];
1148         pthread_mutex_lock(&sshfs.lock_write);
1149         res = do_write(iovout, nout);
1150         pthread_mutex_unlock(&sshfs.lock_write);
1151         buf_free(&buf);
1152         return res;
1153 }
1154
1155 static int do_read(struct buffer *buf)
1156 {
1157         int res;
1158         uint8_t *p = buf->p;
1159         size_t size = buf->size;
1160         while (size) {
1161                 res = read(sshfs.fd, p, size);
1162                 if (res == -1) {
1163                         perror("read");
1164                         return -1;
1165                 } else if (res == 0) {
1166                         fprintf(stderr, "remote host has disconnected\n");
1167                         return -1;
1168                 }
1169                 size -= res;
1170                 p += res;
1171         }
1172         return 0;
1173 }
1174
1175 static int sftp_read(uint8_t *type, struct buffer *buf)
1176 {
1177         int res;
1178         struct buffer buf2;
1179         uint32_t len;
1180         buf_init(&buf2, 5);
1181         res = do_read(&buf2);
1182         if (res != -1) {
1183                 if (buf_get_uint32(&buf2, &len) == -1)
1184                         return -1;
1185                 if (len > MAX_REPLY_LEN) {
1186                         fprintf(stderr, "reply len too large: %u\n", len);
1187                         return -1;
1188                 }
1189                 if (buf_get_uint8(&buf2, type) == -1)
1190                         return -1;
1191                 buf_init(buf, len - 1);
1192                 res = do_read(buf);
1193         }
1194         buf_free(&buf2);
1195         return res;
1196 }
1197
1198 static void request_free(struct request *req)
1199 {
1200         buf_free(&req->reply);
1201         sem_destroy(&req->ready);
1202         g_free(req);
1203 }
1204
1205 static void chunk_free(struct read_chunk *chunk)
1206 {
1207         while (!list_empty(&chunk->reqs)) {
1208                 struct read_req *rreq;
1209
1210                 rreq = list_entry(chunk->reqs.prev, struct read_req, list);
1211                 list_del(&rreq->list);
1212                 buf_free(&rreq->data);
1213                 g_free(rreq);
1214         }
1215         g_free(chunk);
1216 }
1217
1218 static void chunk_put(struct read_chunk *chunk)
1219 {
1220         if (chunk) {
1221                 chunk->refs--;
1222                 if (!chunk->refs)
1223                         chunk_free(chunk);
1224         }
1225 }
1226
1227 static void chunk_put_locked(struct read_chunk *chunk)
1228 {
1229         pthread_mutex_lock(&sshfs.lock);
1230         chunk_put(chunk);
1231         pthread_mutex_unlock(&sshfs.lock);
1232 }
1233
1234 static int clean_req(void *key_, struct request *req)
1235 {
1236         (void) key_;
1237
1238         req->error = -EIO;
1239         if (req->want_reply)
1240                 sem_post(&req->ready);
1241         else {
1242                 if (req->end_func)
1243                         req->end_func(req);
1244                 request_free(req);
1245         }
1246         return TRUE;
1247 }
1248
1249 static int process_one_request(void)
1250 {
1251         int res;
1252         struct buffer buf;
1253         uint8_t type;
1254         struct request *req;
1255         uint32_t id;
1256
1257         buf_init(&buf, 0);
1258         res = sftp_read(&type, &buf);
1259         if (res == -1)
1260                 return -1;
1261         if (buf_get_uint32(&buf, &id) == -1)
1262                 return -1;
1263
1264         pthread_mutex_lock(&sshfs.lock);
1265         req = (struct request *)
1266                 g_hash_table_lookup(sshfs.reqtab, GUINT_TO_POINTER(id));
1267         if (req == NULL)
1268                 fprintf(stderr, "request %i not found\n", id);
1269         else {
1270                 int was_over;
1271
1272                 was_over = sshfs.outstanding_len > sshfs.max_outstanding_len;
1273                 sshfs.outstanding_len -= req->len;
1274                 if (was_over &&
1275                     sshfs.outstanding_len <= sshfs.max_outstanding_len) {
1276                         pthread_cond_broadcast(&sshfs.outstanding_cond);
1277                 }
1278                 g_hash_table_remove(sshfs.reqtab, GUINT_TO_POINTER(id));
1279         }
1280         pthread_mutex_unlock(&sshfs.lock);
1281         if (req != NULL) {
1282                 if (sshfs.debug) {
1283                         struct timeval now;
1284                         unsigned int difftime;
1285                         unsigned msgsize = buf.size + 5;
1286
1287                         gettimeofday(&now, NULL);
1288                         difftime = (now.tv_sec - req->start.tv_sec) * 1000;
1289                         difftime += (now.tv_usec - req->start.tv_usec) / 1000;
1290                         DEBUG("  [%05i] %14s %8ubytes (%ims)\n", id,
1291                               type_name(type), msgsize, difftime);
1292
1293                         if (difftime < sshfs.min_rtt || !sshfs.num_received)
1294                                 sshfs.min_rtt = difftime;
1295                         if (difftime > sshfs.max_rtt)
1296                                 sshfs.max_rtt = difftime;
1297                         sshfs.total_rtt += difftime;
1298                         sshfs.num_received++;
1299                         sshfs.bytes_received += msgsize;
1300                 }
1301                 req->reply = buf;
1302                 req->reply_type = type;
1303                 req->replied = 1;
1304                 if (req->want_reply)
1305                         sem_post(&req->ready);
1306                 else {
1307                         if (req->end_func) {
1308                                 pthread_mutex_lock(&sshfs.lock);
1309                                 req->end_func(req);
1310                                 pthread_mutex_unlock(&sshfs.lock);
1311                         }
1312                         request_free(req);
1313                 }
1314         } else
1315                 buf_free(&buf);
1316
1317         return 0;
1318 }
1319
1320 static void close_conn(void)
1321 {
1322         close(sshfs.fd);
1323         sshfs.fd = -1;
1324         if (sshfs.ptyfd != -1) {
1325                 close(sshfs.ptyfd);
1326                 sshfs.ptyfd = -1;
1327         }
1328         if (sshfs.ptyslavefd != -1) {
1329                 close(sshfs.ptyslavefd);
1330                 sshfs.ptyslavefd = -1;
1331         }
1332 }
1333
1334 static void *process_requests(void *data_)
1335 {
1336         (void) data_;
1337
1338         while (1) {
1339                 if (process_one_request() == -1)
1340                         break;
1341         }
1342
1343         pthread_mutex_lock(&sshfs.lock);
1344         sshfs.processing_thread_started = 0;
1345         close_conn();
1346         g_hash_table_foreach_remove(sshfs.reqtab, (GHRFunc) clean_req, NULL);
1347         sshfs.connver ++;
1348         sshfs.outstanding_len = 0;
1349         pthread_cond_broadcast(&sshfs.outstanding_cond);
1350         pthread_mutex_unlock(&sshfs.lock);
1351
1352         if (!sshfs.reconnect) {
1353                 /* harakiri */
1354                 kill(getpid(), SIGTERM);
1355         }
1356         return NULL;
1357 }
1358
1359 static int sftp_init_reply_ok(struct buffer *buf, uint32_t *version)
1360 {
1361         uint32_t len;
1362         uint8_t type;
1363
1364         if (buf_get_uint32(buf, &len) == -1)
1365                 return -1;
1366
1367         if (len < 5 || len > MAX_REPLY_LEN)
1368                 return 1;
1369
1370         if (buf_get_uint8(buf, &type) == -1)
1371                 return -1;
1372
1373         if (type != SSH_FXP_VERSION)
1374                 return 1;
1375
1376         if (buf_get_uint32(buf, version) == -1)
1377                 return -1;
1378
1379         DEBUG("Server version: %u\n", *version);
1380
1381         if (len > 5) {
1382                 struct buffer buf2;
1383
1384                 buf_init(&buf2, len - 5);
1385                 if (do_read(&buf2) == -1)
1386                         return -1;
1387
1388                 do {
1389                         char *ext;
1390                         char *extdata;
1391
1392                         if (buf_get_string(&buf2, &ext) == -1 ||
1393                             buf_get_string(&buf2, &extdata) == -1)
1394                                 return -1;
1395
1396                         DEBUG("Extension: %s <%s>\n", ext, extdata);
1397
1398                         if (strcmp(ext, SFTP_EXT_POSIX_RENAME) == 0 &&
1399                             strcmp(extdata, "1") == 0) {
1400                                 sshfs.ext_posix_rename = 1;
1401                                 sshfs.rename_workaround = 0;
1402                         }
1403                         if (strcmp(ext, SFTP_EXT_STATVFS) == 0 &&
1404                             strcmp(extdata, "2") == 0)
1405                                 sshfs.ext_statvfs = 1;
1406                         if (strcmp(ext, SFTP_EXT_HARDLINK) == 0 &&
1407                             strcmp(extdata, "1") == 0)
1408                                 sshfs.ext_hardlink = 1;
1409                 } while (buf2.len < buf2.size);
1410         }
1411         return 0;
1412 }
1413
1414 static int sftp_find_init_reply(uint32_t *version)
1415 {
1416         int res;
1417         struct buffer buf;
1418
1419         buf_init(&buf, 9);
1420         res = do_read(&buf);
1421         while (res != -1) {
1422                 struct buffer buf2;
1423
1424                 res = sftp_init_reply_ok(&buf, version);
1425                 if (res <= 0)
1426                         break;
1427
1428                 /* Iterate over any rubbish until the version reply is found */
1429                 DEBUG("%c", *buf.p);
1430                 memmove(buf.p, buf.p + 1, buf.size - 1);
1431                 buf.len = 0;
1432                 buf2.p = buf.p + buf.size - 1;
1433                 buf2.size = 1;
1434                 res = do_read(&buf2);
1435         }
1436         buf_free(&buf);
1437         return res;
1438 }
1439
1440 static int sftp_init()
1441 {
1442         int res = -1;
1443         uint32_t version = 0;
1444         struct buffer buf;
1445         buf_init(&buf, 0);
1446         if (sftp_send_iov(SSH_FXP_INIT, PROTO_VERSION, NULL, 0) == -1)
1447                 goto out;
1448
1449         if (sshfs.password_stdin && pty_expect_loop() == -1)
1450                 goto out;
1451
1452         if (sftp_find_init_reply(&version) == -1)
1453                 goto out;
1454
1455         sshfs.server_version = version;
1456         if (version > PROTO_VERSION) {
1457                 fprintf(stderr,
1458                         "Warning: server uses version: %i, we support: %i\n",
1459                         version, PROTO_VERSION);
1460         }
1461         res = 0;
1462
1463 out:
1464         buf_free(&buf);
1465         return res;
1466 }
1467
1468 static int sftp_error_to_errno(uint32_t error)
1469 {
1470         switch (error) {
1471         case SSH_FX_OK:                return 0;
1472         case SSH_FX_NO_SUCH_FILE:      return ENOENT;
1473         case SSH_FX_PERMISSION_DENIED: return EACCES;
1474         case SSH_FX_FAILURE:           return EPERM;
1475         case SSH_FX_BAD_MESSAGE:       return EBADMSG;
1476         case SSH_FX_NO_CONNECTION:     return ENOTCONN;
1477         case SSH_FX_CONNECTION_LOST:   return ECONNABORTED;
1478         case SSH_FX_OP_UNSUPPORTED:    return EOPNOTSUPP;
1479         default:                       return EIO;
1480         }
1481 }
1482
1483 static void sftp_detect_uid()
1484 {
1485         int flags;
1486         uint32_t id = sftp_get_id();
1487         uint32_t replid;
1488         uint8_t type;
1489         struct buffer buf;
1490         struct stat stbuf;
1491         struct iovec iov[1];
1492
1493         buf_init(&buf, 5);
1494         buf_add_string(&buf, ".");
1495         buf_to_iov(&buf, &iov[0]);
1496         if (sftp_send_iov(SSH_FXP_STAT, id, iov, 1) == -1)
1497                 goto out;
1498         buf_clear(&buf);
1499         if (sftp_read(&type, &buf) == -1)
1500                 goto out;
1501         if (type != SSH_FXP_ATTRS && type != SSH_FXP_STATUS) {
1502                 fprintf(stderr, "protocol error\n");
1503                 goto out;
1504         }
1505         if (buf_get_uint32(&buf, &replid) == -1)
1506                 goto out;
1507         if (replid != id) {
1508                 fprintf(stderr, "bad reply ID\n");
1509                 goto out;
1510         }
1511         if (type == SSH_FXP_STATUS) {
1512                 uint32_t serr;
1513                 if (buf_get_uint32(&buf, &serr) == -1)
1514                         goto out;
1515
1516                 fprintf(stderr, "failed to stat home directory (%i)\n", serr);
1517                 goto out;
1518         }
1519         if (buf_get_attrs(&buf, &stbuf, &flags) == -1)
1520                 goto out;
1521
1522         if (!(flags & SSH_FILEXFER_ATTR_UIDGID))
1523                 goto out;
1524
1525         sshfs.remote_uid = stbuf.st_uid;
1526         sshfs.local_uid = getuid();
1527         sshfs.remote_uid_detected = 1;
1528         DEBUG("remote_uid = %i\n", sshfs.remote_uid);
1529
1530 out:
1531         if (!sshfs.remote_uid_detected)
1532                 fprintf(stderr, "failed to detect remote user ID\n");
1533
1534         buf_free(&buf);
1535 }
1536
1537 static int sftp_check_root(const char *base_path)
1538 {
1539         int flags;
1540         uint32_t id = sftp_get_id();
1541         uint32_t replid;
1542         uint8_t type;
1543         struct buffer buf;
1544         struct stat stbuf;
1545         struct iovec iov[1];
1546         int err = -1;
1547         const char *remote_dir = base_path[0] ? base_path : ".";
1548
1549         buf_init(&buf, 0);
1550         buf_add_string(&buf, remote_dir);
1551         buf_to_iov(&buf, &iov[0]);
1552         if (sftp_send_iov(SSH_FXP_STAT, id, iov, 1) == -1)
1553                 goto out;
1554         buf_clear(&buf);
1555         if (sftp_read(&type, &buf) == -1)
1556                 goto out;
1557         if (type != SSH_FXP_ATTRS && type != SSH_FXP_STATUS) {
1558                 fprintf(stderr, "protocol error\n");
1559                 goto out;
1560         }
1561         if (buf_get_uint32(&buf, &replid) == -1)
1562                 goto out;
1563         if (replid != id) {
1564                 fprintf(stderr, "bad reply ID\n");
1565                 goto out;
1566         }
1567         if (type == SSH_FXP_STATUS) {
1568                 uint32_t serr;
1569                 if (buf_get_uint32(&buf, &serr) == -1)
1570                         goto out;
1571
1572                 fprintf(stderr, "%s:%s: %s\n", sshfs.host, remote_dir,
1573                         strerror(sftp_error_to_errno(serr)));
1574
1575                 goto out;
1576         }
1577         if (buf_get_attrs(&buf, &stbuf, &flags) == -1)
1578                 goto out;
1579
1580         if (!(flags & SSH_FILEXFER_ATTR_PERMISSIONS))
1581                 goto out;
1582
1583         if (S_ISDIR(sshfs.mnt_mode) && !S_ISDIR(stbuf.st_mode)) {
1584                 fprintf(stderr, "%s:%s: Not a directory\n", sshfs.host,
1585                         remote_dir);
1586                 goto out;
1587         }
1588         if ((sshfs.mnt_mode ^ stbuf.st_mode) & S_IFMT) {
1589                 fprintf(stderr, "%s:%s: type of file differs from mountpoint\n",
1590                         sshfs.host, remote_dir);
1591                 goto out;
1592         }
1593
1594         err = 0;
1595
1596 out:
1597         buf_free(&buf);
1598         return err;
1599 }
1600
1601 static int connect_remote(void)
1602 {
1603         int err;
1604
1605         if (sshfs.directport)
1606                 err = connect_to(sshfs.host, sshfs.directport);
1607         else
1608                 err = start_ssh();
1609         if (!err)
1610                 err = sftp_init();
1611
1612         if (err)
1613                 close_conn();
1614         else
1615                 sshfs.num_connect++;
1616
1617         return err;
1618 }
1619
1620 static int start_processing_thread(void)
1621 {
1622         int err;
1623         pthread_t thread_id;
1624         sigset_t oldset;
1625         sigset_t newset;
1626
1627         if (sshfs.processing_thread_started)
1628                 return 0;
1629
1630         if (sshfs.fd == -1) {
1631                 err = connect_remote();
1632                 if (err)
1633                         return -EIO;
1634         }
1635
1636         if (sshfs.detect_uid) {
1637                 sftp_detect_uid();
1638                 sshfs.detect_uid = 0;
1639         }
1640
1641         sigemptyset(&newset);
1642         sigaddset(&newset, SIGTERM);
1643         sigaddset(&newset, SIGINT);
1644         sigaddset(&newset, SIGHUP);
1645         sigaddset(&newset, SIGQUIT);
1646         pthread_sigmask(SIG_BLOCK, &newset, &oldset);
1647         err = pthread_create(&thread_id, NULL, process_requests, NULL);
1648         if (err) {
1649                 fprintf(stderr, "failed to create thread: %s\n", strerror(err));
1650                 return -EIO;
1651         }
1652         pthread_detach(thread_id);
1653         pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1654         sshfs.processing_thread_started = 1;
1655         return 0;
1656 }
1657
1658 #if FUSE_VERSION >= 26
1659 static void *sshfs_init(struct fuse_conn_info *conn)
1660 #else
1661 static void *sshfs_init(void)
1662 #endif
1663 {
1664 #if FUSE_VERSION >= 26
1665         /* Readahead should be done by kernel or sshfs but not both */
1666         if (conn->async_read)
1667                 sshfs.sync_read = 1;
1668 #endif
1669
1670         if (!sshfs.delay_connect)
1671                 start_processing_thread();
1672
1673         return NULL;
1674 }
1675
1676 static int sftp_request_wait(struct request *req, uint8_t type,
1677                              uint8_t expect_type, struct buffer *outbuf)
1678 {
1679         int err;
1680
1681         if (req->error) {
1682                 err = req->error;
1683                 goto out;
1684         }
1685         while (sem_wait(&req->ready));
1686         if (req->error) {
1687                 err = req->error;
1688                 goto out;
1689         }
1690         err = -EIO;
1691         if (req->reply_type != expect_type &&
1692             req->reply_type != SSH_FXP_STATUS) {
1693                 fprintf(stderr, "protocol error\n");
1694                 goto out;
1695         }
1696         if (req->reply_type == SSH_FXP_STATUS) {
1697                 uint32_t serr;
1698                 if (buf_get_uint32(&req->reply, &serr) == -1)
1699                         goto out;
1700
1701                 switch (serr) {
1702                 case SSH_FX_OK:
1703                         if (expect_type == SSH_FXP_STATUS)
1704                                 err = 0;
1705                         else
1706                                 err = -EIO;
1707                         break;
1708
1709                 case SSH_FX_EOF:
1710                         if (type == SSH_FXP_READ || type == SSH_FXP_READDIR)
1711                                 err = MY_EOF;
1712                         else
1713                                 err = -EIO;
1714                         break;
1715
1716                 default:
1717                         err = -sftp_error_to_errno(serr);
1718                 }
1719         } else {
1720                 buf_init(outbuf, req->reply.size - req->reply.len);
1721                 buf_get_mem(&req->reply, outbuf->p, outbuf->size);
1722                 err = 0;
1723         }
1724
1725 out:
1726         if (req->end_func) {
1727                 pthread_mutex_lock(&sshfs.lock);
1728                 req->end_func(req);
1729                 pthread_mutex_unlock(&sshfs.lock);
1730         }
1731         request_free(req);
1732         return err;
1733 }
1734
1735 static int sftp_request_send(uint8_t type, struct iovec *iov, size_t count,
1736                              request_func begin_func, request_func end_func,
1737                              int want_reply, void *data,
1738                              struct request **reqp)
1739 {
1740         int err;
1741         uint32_t id;
1742         struct request *req = g_new0(struct request, 1);
1743
1744         req->want_reply = want_reply;
1745         req->end_func = end_func;
1746         req->data = data;
1747         sem_init(&req->ready, 0, 0);
1748         buf_init(&req->reply, 0);
1749         pthread_mutex_lock(&sshfs.lock);
1750         if (begin_func)
1751                 begin_func(req);
1752         id = sftp_get_id();
1753         err = start_processing_thread();
1754         if (err) {
1755                 pthread_mutex_unlock(&sshfs.lock);
1756                 goto out;
1757         }
1758         req->len = iov_length(iov, count) + 9;
1759         sshfs.outstanding_len += req->len;
1760         while (sshfs.outstanding_len > sshfs.max_outstanding_len)
1761                 pthread_cond_wait(&sshfs.outstanding_cond, &sshfs.lock);
1762
1763         g_hash_table_insert(sshfs.reqtab, GUINT_TO_POINTER(id), req);
1764         if (sshfs.debug) {
1765                 gettimeofday(&req->start, NULL);
1766                 sshfs.num_sent++;
1767                 sshfs.bytes_sent += req->len;
1768         }
1769         DEBUG("[%05i] %s\n", id, type_name(type));
1770         pthread_mutex_unlock(&sshfs.lock);
1771
1772         err = -EIO;
1773         if (sftp_send_iov(type, id, iov, count) == -1) {
1774                 gboolean rmed;
1775
1776                 pthread_mutex_lock(&sshfs.lock);
1777                 rmed = g_hash_table_remove(sshfs.reqtab, GUINT_TO_POINTER(id));
1778                 pthread_mutex_unlock(&sshfs.lock);
1779
1780                 if (!rmed && !want_reply) {
1781                         /* request already freed */
1782                         return err;
1783                 }
1784                 goto out;
1785         }
1786         if (want_reply)
1787                 *reqp = req;
1788         return 0;
1789
1790 out:
1791         req->error = err;
1792         if (!want_reply)
1793                 sftp_request_wait(req, type, 0, NULL);
1794         else
1795                 *reqp = req;
1796
1797         return err;
1798 }
1799
1800
1801 static int sftp_request_iov(uint8_t type, struct iovec *iov, size_t count,
1802                             uint8_t expect_type, struct buffer *outbuf)
1803 {
1804         int err;
1805         struct request *req;
1806
1807         err = sftp_request_send(type, iov, count, NULL, NULL, expect_type, NULL,
1808                                 &req);
1809         if (expect_type == 0)
1810                 return err;
1811
1812         return sftp_request_wait(req, type, expect_type, outbuf);
1813 }
1814
1815 static int sftp_request(uint8_t type, const struct buffer *buf,
1816                         uint8_t expect_type, struct buffer *outbuf)
1817 {
1818         struct iovec iov;
1819
1820         buf_to_iov(buf, &iov);
1821         return sftp_request_iov(type, &iov, 1, expect_type, outbuf);
1822 }
1823
1824 static int sshfs_getattr(const char *path, struct stat *stbuf)
1825 {
1826         int err;
1827         struct buffer buf;
1828         struct buffer outbuf;
1829         buf_init(&buf, 0);
1830         buf_add_path(&buf, path);
1831         err = sftp_request(sshfs.follow_symlinks ? SSH_FXP_STAT : SSH_FXP_LSTAT,
1832                            &buf, SSH_FXP_ATTRS, &outbuf);
1833         if (!err) {
1834                 if (buf_get_attrs(&outbuf, stbuf, NULL) == -1)
1835                         err = -EIO;
1836                 buf_free(&outbuf);
1837         }
1838         buf_free(&buf);
1839         return err;
1840 }
1841
1842 static int count_components(const char *p)
1843 {
1844         int ctr;
1845
1846         for (; *p == '/'; p++);
1847         for (ctr = 0; *p; ctr++) {
1848                 for (; *p && *p != '/'; p++);
1849                 for (; *p == '/'; p++);
1850         }
1851         return ctr;
1852 }
1853
1854 static void strip_common(const char **sp, const char **tp)
1855 {
1856         const char *s = *sp;
1857         const char *t = *tp;
1858         do {
1859                 for (; *s == '/'; s++);
1860                 for (; *t == '/'; t++);
1861                 *tp = t;
1862                 *sp = s;
1863                 for (; *s == *t && *s && *s != '/'; s++, t++);
1864         } while ((*s == *t && *s) || (!*s && *t == '/') || (*s == '/' && !*t));
1865 }
1866
1867 static void transform_symlink(const char *path, char **linkp)
1868 {
1869         const char *l = *linkp;
1870         const char *b = sshfs.base_path;
1871         char *newlink;
1872         char *s;
1873         int dotdots;
1874         int i;
1875
1876         if (l[0] != '/' || b[0] != '/')
1877                 return;
1878
1879         strip_common(&l, &b);
1880         if (*b)
1881                 return;
1882
1883         strip_common(&l, &path);
1884         dotdots = count_components(path);
1885         if (!dotdots)
1886                 return;
1887         dotdots--;
1888
1889         newlink = malloc(dotdots * 3 + strlen(l) + 2);
1890         if (!newlink) {
1891                 fprintf(stderr, "sshfs: memory allocation failed\n");
1892                 abort();
1893         }
1894         for (s = newlink, i = 0; i < dotdots; i++, s += 3)
1895                 strcpy(s, "../");
1896
1897         if (l[0])
1898                 strcpy(s, l);
1899         else if (!dotdots)
1900                 strcpy(s, ".");
1901         else
1902                 s[0] = '\0';
1903
1904         free(*linkp);
1905         *linkp = newlink;
1906 }
1907
1908 static int sshfs_readlink(const char *path, char *linkbuf, size_t size)
1909 {
1910         int err;
1911         struct buffer buf;
1912         struct buffer name;
1913
1914         assert(size > 0);
1915
1916         if (sshfs.server_version < 3)
1917                 return -EPERM;
1918
1919         buf_init(&buf, 0);
1920         buf_add_path(&buf, path);
1921         err = sftp_request(SSH_FXP_READLINK, &buf, SSH_FXP_NAME, &name);
1922         if (!err) {
1923                 uint32_t count;
1924                 char *link;
1925                 err = -EIO;
1926                 if(buf_get_uint32(&name, &count) != -1 && count == 1 &&
1927                    buf_get_string(&name, &link) != -1) {
1928                         if (sshfs.transform_symlinks)
1929                                 transform_symlink(path, &link);
1930                         strncpy(linkbuf, link, size - 1);
1931                         linkbuf[size - 1] = '\0';
1932                         free(link);
1933                         err = 0;
1934                 }
1935                 buf_free(&name);
1936         }
1937         buf_free(&buf);
1938         return err;
1939 }
1940
1941 static int sshfs_getdir(const char *path, fuse_cache_dirh_t h,
1942                         fuse_cache_dirfil_t filler)
1943 {
1944         int err;
1945         struct buffer buf;
1946         struct buffer handle;
1947         buf_init(&buf, 0);
1948         buf_add_path(&buf, path);
1949         err = sftp_request(SSH_FXP_OPENDIR, &buf, SSH_FXP_HANDLE, &handle);
1950         if (!err) {
1951                 int err2;
1952                 buf_finish(&handle);
1953                 do {
1954                         struct buffer name;
1955                         err = sftp_request(SSH_FXP_READDIR, &handle, SSH_FXP_NAME, &name);
1956                         if (!err) {
1957                                 if (buf_get_entries(&name, h, filler) == -1)
1958                                         err = -EIO;
1959                                 buf_free(&name);
1960                         }
1961                 } while (!err);
1962                 if (err == MY_EOF)
1963                         err = 0;
1964
1965                 err2 = sftp_request(SSH_FXP_CLOSE, &handle, 0, NULL);
1966                 if (!err)
1967                         err = err2;
1968                 buf_free(&handle);
1969         }
1970         buf_free(&buf);
1971         return err;
1972 }
1973
1974 static int sshfs_mkdir(const char *path, mode_t mode)
1975 {
1976         int err;
1977         struct buffer buf;
1978         buf_init(&buf, 0);
1979         buf_add_path(&buf, path);
1980         buf_add_uint32(&buf, SSH_FILEXFER_ATTR_PERMISSIONS);
1981         buf_add_uint32(&buf, mode);
1982         err = sftp_request(SSH_FXP_MKDIR, &buf, SSH_FXP_STATUS, NULL);
1983         buf_free(&buf);
1984         return err;
1985 }
1986
1987 static int sshfs_mknod(const char *path, mode_t mode, dev_t rdev)
1988 {
1989         int err;
1990         struct buffer buf;
1991         struct buffer handle;
1992         (void) rdev;
1993
1994         if ((mode & S_IFMT) != S_IFREG)
1995                 return -EPERM;
1996
1997         buf_init(&buf, 0);
1998         buf_add_path(&buf, path);
1999         buf_add_uint32(&buf, SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_EXCL);
2000         buf_add_uint32(&buf, SSH_FILEXFER_ATTR_PERMISSIONS);
2001         buf_add_uint32(&buf, mode);
2002         err = sftp_request(SSH_FXP_OPEN, &buf, SSH_FXP_HANDLE, &handle);
2003         if (!err) {
2004                 int err2;
2005                 buf_finish(&handle);
2006                 err2 = sftp_request(SSH_FXP_CLOSE, &handle, SSH_FXP_STATUS,
2007                                     NULL);
2008                 if (!err)
2009                         err = err2;
2010                 buf_free(&handle);
2011         }
2012         buf_free(&buf);
2013         return err;
2014 }
2015
2016 static int sshfs_symlink(const char *from, const char *to)
2017 {
2018         int err;
2019         struct buffer buf;
2020
2021         if (sshfs.server_version < 3)
2022                 return -EPERM;
2023
2024         /* openssh sftp server doesn't follow standard: link target and
2025            link name are mixed up, so we must also be non-standard :( */
2026         buf_init(&buf, 0);
2027         buf_add_string(&buf, from);
2028         buf_add_path(&buf, to);
2029         err = sftp_request(SSH_FXP_SYMLINK, &buf, SSH_FXP_STATUS, NULL);
2030         buf_free(&buf);
2031         return err;
2032 }
2033
2034 static int sshfs_unlink(const char *path)
2035 {
2036         int err;
2037         struct buffer buf;
2038         buf_init(&buf, 0);
2039         buf_add_path(&buf, path);
2040         err = sftp_request(SSH_FXP_REMOVE, &buf, SSH_FXP_STATUS, NULL);
2041         buf_free(&buf);
2042         return err;
2043 }
2044
2045 static int sshfs_rmdir(const char *path)
2046 {
2047         int err;
2048         struct buffer buf;
2049         buf_init(&buf, 0);
2050         buf_add_path(&buf, path);
2051         err = sftp_request(SSH_FXP_RMDIR, &buf, SSH_FXP_STATUS, NULL);
2052         buf_free(&buf);
2053         return err;
2054 }
2055
2056 static int sshfs_do_rename(const char *from, const char *to)
2057 {
2058         int err;
2059         struct buffer buf;
2060         buf_init(&buf, 0);
2061         buf_add_path(&buf, from);
2062         buf_add_path(&buf, to);
2063         err = sftp_request(SSH_FXP_RENAME, &buf, SSH_FXP_STATUS, NULL);
2064         buf_free(&buf);
2065         return err;
2066 }
2067
2068 static int sshfs_ext_posix_rename(const char *from, const char *to)
2069 {
2070         int err;
2071         struct buffer buf;
2072         buf_init(&buf, 0);
2073         buf_add_string(&buf, SFTP_EXT_POSIX_RENAME);
2074         buf_add_path(&buf, from);
2075         buf_add_path(&buf, to);
2076         err = sftp_request(SSH_FXP_EXTENDED, &buf, SSH_FXP_STATUS, NULL);
2077         buf_free(&buf);
2078         return err;
2079 }
2080
2081 static void random_string(char *str, int length)
2082 {
2083         int i;
2084         for (i = 0; i < length; i++)
2085                 *str++ = (char)('0' + rand_r(&sshfs.randseed) % 10);
2086         *str = '\0';
2087 }
2088
2089 static int sshfs_rename(const char *from, const char *to)
2090 {
2091         int err;
2092         if (sshfs.ext_posix_rename)
2093                 err = sshfs_ext_posix_rename(from, to);
2094         else
2095                 err = sshfs_do_rename(from, to);
2096         if (err == -EPERM && sshfs.rename_workaround) {
2097                 size_t tolen = strlen(to);
2098                 if (tolen + RENAME_TEMP_CHARS < PATH_MAX) {
2099                         int tmperr;
2100                         char totmp[PATH_MAX];
2101                         strcpy(totmp, to);
2102                         random_string(totmp + tolen, RENAME_TEMP_CHARS);
2103                         tmperr = sshfs_do_rename(to, totmp);
2104                         if (!tmperr) {
2105                                 err = sshfs_do_rename(from, to);
2106                                 if (!err)
2107                                         err = sshfs_unlink(totmp);
2108                                 else
2109                                         sshfs_do_rename(totmp, to);
2110                         }
2111                 }
2112         }
2113         return err;
2114 }
2115
2116 static int sshfs_link(const char *from, const char *to)
2117 {
2118         int err = -ENOSYS;
2119
2120         if (sshfs.ext_hardlink) {
2121                 struct buffer buf;
2122
2123                 buf_init(&buf, 0);
2124                 buf_add_string(&buf, SFTP_EXT_HARDLINK);
2125                 buf_add_path(&buf, from);
2126                 buf_add_path(&buf, to);
2127                 err = sftp_request(SSH_FXP_EXTENDED, &buf, SSH_FXP_STATUS,
2128                                    NULL);
2129                 buf_free(&buf);
2130         }
2131
2132         return err;
2133 }
2134
2135 static int sshfs_chmod(const char *path, mode_t mode)
2136 {
2137         int err;
2138         struct buffer buf;
2139         buf_init(&buf, 0);
2140         buf_add_path(&buf, path);
2141         buf_add_uint32(&buf, SSH_FILEXFER_ATTR_PERMISSIONS);
2142         buf_add_uint32(&buf, mode);
2143         /* FIXME: really needs LSETSTAT extension (debian Bug#640038) */
2144         err = sftp_request(SSH_FXP_SETSTAT, &buf, SSH_FXP_STATUS, NULL);
2145         buf_free(&buf);
2146         return err;
2147 }
2148
2149 static int sshfs_chown(const char *path, uid_t uid, gid_t gid)
2150 {
2151         int err;
2152         struct buffer buf;
2153
2154         if (sshfs.remote_uid_detected && uid == sshfs.local_uid)
2155                 uid = sshfs.remote_uid;
2156
2157         buf_init(&buf, 0);
2158         buf_add_path(&buf, path);
2159         buf_add_uint32(&buf, SSH_FILEXFER_ATTR_UIDGID);
2160         buf_add_uint32(&buf, uid);
2161         buf_add_uint32(&buf, gid);
2162         err = sftp_request(SSH_FXP_SETSTAT, &buf, SSH_FXP_STATUS, NULL);
2163         buf_free(&buf);
2164         return err;
2165 }
2166
2167 static int sshfs_truncate_workaround(const char *path, off_t size,
2168                                      struct fuse_file_info *fi);
2169
2170 static void sshfs_inc_modifver(void)
2171 {
2172         pthread_mutex_lock(&sshfs.lock);
2173         sshfs.modifver++;
2174         pthread_mutex_unlock(&sshfs.lock);
2175 }
2176
2177 static int sshfs_truncate(const char *path, off_t size)
2178 {
2179         int err;
2180         struct buffer buf;
2181
2182         sshfs_inc_modifver();
2183         if (size == 0 || sshfs.truncate_workaround)
2184                 return sshfs_truncate_workaround(path, size, NULL);
2185
2186         buf_init(&buf, 0);
2187         buf_add_path(&buf, path);
2188         buf_add_uint32(&buf, SSH_FILEXFER_ATTR_SIZE);
2189         buf_add_uint64(&buf, size);
2190         err = sftp_request(SSH_FXP_SETSTAT, &buf, SSH_FXP_STATUS, NULL);
2191         buf_free(&buf);
2192         return err;
2193 }
2194
2195 static int sshfs_utime(const char *path, struct utimbuf *ubuf)
2196 {
2197         int err;
2198         struct buffer buf;
2199         buf_init(&buf, 0);
2200         buf_add_path(&buf, path);
2201         buf_add_uint32(&buf, SSH_FILEXFER_ATTR_ACMODTIME);
2202         buf_add_uint32(&buf, ubuf->actime);
2203         buf_add_uint32(&buf, ubuf->modtime);
2204         err = sftp_request(SSH_FXP_SETSTAT, &buf, SSH_FXP_STATUS, NULL);
2205         buf_free(&buf);
2206         return err;
2207 }
2208
2209 static inline int sshfs_file_is_conn(struct sshfs_file *sf)
2210 {
2211         int ret;
2212
2213         pthread_mutex_lock(&sshfs.lock);
2214         ret = (sf->connver == sshfs.connver);
2215         pthread_mutex_unlock(&sshfs.lock);
2216
2217         return ret;
2218 }
2219
2220 static int sshfs_open_common(const char *path, mode_t mode,
2221                              struct fuse_file_info *fi)
2222 {
2223         int err;
2224         int err2;
2225         struct buffer buf;
2226         struct buffer outbuf;
2227         struct stat stbuf;
2228         struct sshfs_file *sf;
2229         struct request *open_req;
2230         uint32_t pflags = 0;
2231         struct iovec iov;
2232         uint8_t type;
2233         uint64_t wrctr = cache_get_write_ctr();
2234
2235         if ((fi->flags & O_ACCMODE) == O_RDONLY)
2236                 pflags = SSH_FXF_READ;
2237         else if((fi->flags & O_ACCMODE) == O_WRONLY)
2238                 pflags = SSH_FXF_WRITE;
2239         else if ((fi->flags & O_ACCMODE) == O_RDWR)
2240                 pflags = SSH_FXF_READ | SSH_FXF_WRITE;
2241         else
2242                 return -EINVAL;
2243
2244         if (fi->flags & O_CREAT)
2245                 pflags |= SSH_FXF_CREAT;
2246
2247         if (fi->flags & O_EXCL)
2248                 pflags |= SSH_FXF_EXCL;
2249
2250         if (fi->flags & O_TRUNC)
2251                 pflags |= SSH_FXF_TRUNC;
2252
2253         sf = g_new0(struct sshfs_file, 1);
2254         list_init(&sf->write_reqs);
2255         pthread_cond_init(&sf->write_finished, NULL);
2256         /* Assume random read after open */
2257         sf->is_seq = 0;
2258         sf->refs = 1;
2259         sf->next_pos = 0;
2260         pthread_mutex_lock(&sshfs.lock);
2261         sf->modifver= sshfs.modifver;
2262         sf->connver = sshfs.connver;
2263         pthread_mutex_unlock(&sshfs.lock);
2264         buf_init(&buf, 0);
2265         buf_add_path(&buf, path);
2266         buf_add_uint32(&buf, pflags);
2267         buf_add_uint32(&buf, SSH_FILEXFER_ATTR_PERMISSIONS);
2268         buf_add_uint32(&buf, mode);
2269         buf_to_iov(&buf, &iov);
2270         sftp_request_send(SSH_FXP_OPEN, &iov, 1, NULL, NULL, 1, NULL,
2271                           &open_req);
2272         buf_clear(&buf);
2273         buf_add_path(&buf, path);
2274         type = sshfs.follow_symlinks ? SSH_FXP_STAT : SSH_FXP_LSTAT;
2275         err2 = sftp_request(type, &buf, SSH_FXP_ATTRS, &outbuf);
2276         if (!err2) {
2277                 if (buf_get_attrs(&outbuf, &stbuf, NULL) == -1)
2278                         err2 = -EIO;
2279                 buf_free(&outbuf);
2280         }
2281         err = sftp_request_wait(open_req, SSH_FXP_OPEN, SSH_FXP_HANDLE,
2282                                 &sf->handle);
2283         if (!err && err2) {
2284                 buf_finish(&sf->handle);
2285                 sftp_request(SSH_FXP_CLOSE, &sf->handle, 0, NULL);
2286                 buf_free(&sf->handle);
2287                 err = err2;
2288         }
2289
2290         if (!err) {
2291                 cache_add_attr(path, &stbuf, wrctr);
2292                 buf_finish(&sf->handle);
2293                 fi->fh = (unsigned long) sf;
2294         } else {
2295                 cache_invalidate(path);
2296                 g_free(sf);
2297         }
2298         buf_free(&buf);
2299         return err;
2300 }
2301
2302 static int sshfs_open(const char *path, struct fuse_file_info *fi)
2303 {
2304         return sshfs_open_common(path, 0, fi);
2305 }
2306
2307 static inline struct sshfs_file *get_sshfs_file(struct fuse_file_info *fi)
2308 {
2309         return (struct sshfs_file *) (uintptr_t) fi->fh;
2310 }
2311
2312 static int sshfs_flush(const char *path, struct fuse_file_info *fi)
2313 {
2314         int err;
2315         struct sshfs_file *sf = get_sshfs_file(fi);
2316         struct list_head write_reqs;
2317         struct list_head *curr_list;
2318
2319         if (!sshfs_file_is_conn(sf))
2320                 return -EIO;
2321
2322         if (sshfs.sync_write)
2323                 return 0;
2324
2325         (void) path;
2326         pthread_mutex_lock(&sshfs.lock);
2327         if (!list_empty(&sf->write_reqs)) {
2328                 curr_list = sf->write_reqs.prev;
2329                 list_del(&sf->write_reqs);
2330                 list_init(&sf->write_reqs);
2331                 list_add(&write_reqs, curr_list);
2332                 while (!list_empty(&write_reqs))
2333                         pthread_cond_wait(&sf->write_finished, &sshfs.lock);
2334         }
2335         err = sf->write_error;
2336         sf->write_error = 0;
2337         pthread_mutex_unlock(&sshfs.lock);
2338         return err;
2339 }
2340
2341 static int sshfs_fsync(const char *path, int isdatasync,
2342                        struct fuse_file_info *fi)
2343 {
2344         (void) isdatasync;
2345         return sshfs_flush(path, fi);
2346 }
2347
2348 static void sshfs_file_put(struct sshfs_file *sf)
2349 {
2350         sf->refs--;
2351         if (!sf->refs)
2352                 g_free(sf);
2353 }
2354
2355 static void sshfs_file_get(struct sshfs_file *sf)
2356 {
2357         sf->refs++;
2358 }
2359
2360 static int sshfs_release(const char *path, struct fuse_file_info *fi)
2361 {
2362         struct sshfs_file *sf = get_sshfs_file(fi);
2363         struct buffer *handle = &sf->handle;
2364         if (sshfs_file_is_conn(sf)) {
2365                 sshfs_flush(path, fi);
2366                 sftp_request(SSH_FXP_CLOSE, handle, 0, NULL);
2367         }
2368         buf_free(handle);
2369         chunk_put_locked(sf->readahead);
2370         sshfs_file_put(sf);
2371         return 0;
2372 }
2373
2374 static void sshfs_read_end(struct request *req)
2375 {
2376         struct read_req *rreq = (struct read_req *) req->data;
2377         if (req->error)
2378                 rreq->res = req->error;
2379         else if (req->replied) {
2380                 rreq->res = -EIO;
2381
2382                 if (req->reply_type == SSH_FXP_STATUS) {
2383                         uint32_t serr;
2384                         if (buf_get_uint32(&req->reply, &serr) != -1) {
2385                                 if (serr == SSH_FX_EOF)
2386                                         rreq->res = 0;
2387                                 else
2388                                         rreq->res = -sftp_error_to_errno(serr);
2389                         }
2390                 } else if (req->reply_type == SSH_FXP_DATA) {
2391                         uint32_t retsize;
2392                         if (buf_get_uint32(&req->reply, &retsize) != -1) {
2393                                 if (retsize > rreq->size) {
2394                                         fprintf(stderr, "long read\n");
2395                                 } else if (buf_check_get(&req->reply, retsize) != -1) {
2396                                         rreq->res = retsize;
2397                                         rreq->data = req->reply;
2398                                         buf_init(&req->reply, 0);
2399                                 }
2400                         }
2401                 } else {
2402                         fprintf(stderr, "protocol error\n");
2403                 }
2404         } else {
2405                 rreq->res = -EIO;
2406         }
2407
2408         rreq->sio->num_reqs--;
2409         if (!rreq->sio->num_reqs)
2410                 pthread_cond_broadcast(&rreq->sio->finished);
2411 }
2412
2413 static void sshfs_read_begin(struct request *req)
2414 {
2415         struct read_req *rreq = (struct read_req *) req->data;
2416         rreq->sio->num_reqs++;
2417 }
2418
2419 static struct read_chunk *sshfs_send_read(struct sshfs_file *sf, size_t size,
2420                                           off_t offset)
2421 {
2422         struct read_chunk *chunk = g_new0(struct read_chunk, 1);
2423         struct buffer *handle = &sf->handle;
2424
2425         pthread_cond_init(&chunk->sio.finished, NULL);
2426         list_init(&chunk->reqs);
2427         chunk->size = size;
2428         chunk->offset = offset;
2429         chunk->refs = 1;
2430
2431         while (size) {
2432                 int err;
2433                 struct buffer buf;
2434                 struct iovec iov[1];
2435                 struct read_req *rreq;
2436                 size_t bsize = size < sshfs.max_read ? size : sshfs.max_read;
2437
2438                 rreq = g_new0(struct read_req, 1);
2439                 rreq->sio = &chunk->sio;
2440                 rreq->size = bsize;
2441                 buf_init(&rreq->data, 0);
2442                 list_add(&rreq->list, &chunk->reqs);
2443
2444                 buf_init(&buf, 0);
2445                 buf_add_buf(&buf, handle);
2446                 buf_add_uint64(&buf, offset);
2447                 buf_add_uint32(&buf, bsize);
2448                 buf_to_iov(&buf, &iov[0]);
2449                 err = sftp_request_send(SSH_FXP_READ, iov, 1, 
2450                                         sshfs_read_begin,
2451                                         sshfs_read_end,
2452                                         0, rreq, NULL);
2453
2454                 buf_free(&buf);
2455                 if (err)
2456                         break;
2457
2458                 size -= bsize;
2459                 offset += bsize;
2460         }
2461
2462         return chunk;
2463 }
2464
2465 static int wait_chunk(struct read_chunk *chunk, char *buf, size_t size)
2466 {
2467         int res = 0;
2468         struct read_req *rreq;
2469
2470         pthread_mutex_lock(&sshfs.lock);
2471         while (chunk->sio.num_reqs)
2472                pthread_cond_wait(&chunk->sio.finished, &sshfs.lock);
2473         pthread_mutex_unlock(&sshfs.lock);
2474
2475
2476         if (chunk->sio.error) {
2477                 if (chunk->sio.error != MY_EOF)
2478                         res = chunk->sio.error;
2479
2480                 goto out;
2481         }
2482
2483         while (!list_empty(&chunk->reqs) && size) {
2484                 rreq = list_entry(chunk->reqs.prev, struct read_req, list);
2485
2486                 if (rreq->res < 0) {
2487                         chunk->sio.error = rreq->res;
2488                         break;
2489                 } if (rreq->res == 0) {
2490                         chunk->sio.error = MY_EOF;
2491                         break;
2492                 } else if (size < (size_t) rreq->res) {
2493                         buf_get_mem(&rreq->data, buf, size);
2494                         rreq->res -= size;
2495                         rreq->size -= size;
2496                         res += size;
2497                         break;
2498                 } else {
2499                         buf_get_mem(&rreq->data, buf, rreq->res);
2500                         res += rreq->res;
2501                         if ((size_t) rreq->res < rreq->size) {
2502                                 chunk->sio.error = MY_EOF;
2503                                 break;
2504                         }
2505                         buf += rreq->res;
2506                         size -= rreq->res;
2507                         list_del(&rreq->list);
2508                         buf_free(&rreq->data);
2509                         g_free(rreq);
2510                 }
2511         }
2512
2513         if (res > 0) {
2514                 chunk->offset += res;
2515                 chunk->size -= res;
2516         }
2517
2518 out:
2519         chunk_put_locked(chunk);
2520         return res;
2521 }
2522
2523 static int sshfs_sync_read(struct sshfs_file *sf, char *buf, size_t size,
2524                            off_t offset)
2525 {
2526         struct read_chunk *chunk;
2527
2528         chunk = sshfs_send_read(sf, size, offset);
2529         return wait_chunk(chunk, buf, size);
2530 }
2531
2532 static void submit_read(struct sshfs_file *sf, size_t size, off_t offset,
2533                         struct read_chunk **chunkp)
2534 {
2535         struct read_chunk *chunk;
2536
2537         chunk = sshfs_send_read(sf, size, offset);
2538         pthread_mutex_lock(&sshfs.lock);        
2539         chunk->modifver = sshfs.modifver;
2540         chunk_put(*chunkp);
2541         *chunkp = chunk;
2542         chunk->refs++;
2543         pthread_mutex_unlock(&sshfs.lock);
2544 }
2545
2546 static struct read_chunk *search_read_chunk(struct sshfs_file *sf, off_t offset)
2547 {
2548         struct read_chunk *ch = sf->readahead;
2549         if (ch && ch->offset == offset && ch->modifver == sshfs.modifver) {
2550                 ch->refs++;
2551                 return ch;
2552         } else
2553                 return NULL;
2554 }
2555
2556 static int sshfs_async_read(struct sshfs_file *sf, char *rbuf, size_t size,
2557                             off_t offset)
2558 {
2559         int res = 0;
2560         size_t total = 0;
2561         struct read_chunk *chunk;
2562         struct read_chunk *chunk_prev = NULL;
2563         size_t origsize = size;
2564         int curr_is_seq;
2565
2566         pthread_mutex_lock(&sshfs.lock);
2567         curr_is_seq = sf->is_seq;
2568         sf->is_seq = (sf->next_pos == offset && sf->modifver == sshfs.modifver);
2569         sf->next_pos = offset + size;
2570         sf->modifver = sshfs.modifver;
2571         chunk = search_read_chunk(sf, offset);
2572         pthread_mutex_unlock(&sshfs.lock);
2573
2574         if (chunk && chunk->size < size) {
2575                 chunk_prev = chunk;
2576                 size -= chunk->size;
2577                 offset += chunk->size;
2578                 chunk = NULL;
2579         }
2580
2581         if (!chunk)
2582                 submit_read(sf, size, offset, &chunk);
2583
2584         if (curr_is_seq && chunk && chunk->size <= size)
2585                 submit_read(sf, origsize, offset + size, &sf->readahead);
2586
2587         if (chunk_prev) {
2588                 size_t prev_size = chunk_prev->size;
2589                 res = wait_chunk(chunk_prev, rbuf, prev_size);
2590                 if (res < (int) prev_size) {
2591                         chunk_put_locked(chunk);
2592                         return res;
2593                 }
2594                 rbuf += res;
2595                 total += res;
2596         }
2597         res = wait_chunk(chunk, rbuf, size);
2598         if (res > 0)
2599                 total += res;
2600         if (res < 0)
2601                 return res;
2602
2603         return total;
2604 }
2605
2606 static int sshfs_read(const char *path, char *rbuf, size_t size, off_t offset,
2607                       struct fuse_file_info *fi)
2608 {
2609         struct sshfs_file *sf = get_sshfs_file(fi);
2610         (void) path;
2611
2612         if (!sshfs_file_is_conn(sf))
2613                 return -EIO;
2614
2615         if (sshfs.sync_read)
2616                 return sshfs_sync_read(sf, rbuf, size, offset);
2617         else
2618                 return sshfs_async_read(sf, rbuf, size, offset);
2619 }
2620
2621 static void sshfs_write_begin(struct request *req)
2622 {
2623         struct sshfs_file *sf = (struct sshfs_file *) req->data;
2624
2625         sshfs_file_get(sf);
2626         list_add(&req->list, &sf->write_reqs);
2627 }
2628
2629 static void sshfs_write_end(struct request *req)
2630 {
2631         uint32_t serr;
2632         struct sshfs_file *sf = (struct sshfs_file *) req->data;
2633
2634         if (req->error)
2635                 sf->write_error = req->error;
2636         else if (req->replied) {
2637                 if (req->reply_type != SSH_FXP_STATUS) {
2638                         fprintf(stderr, "protocol error\n");
2639                 } else if (buf_get_uint32(&req->reply, &serr) != -1 &&
2640                          serr != SSH_FX_OK) {
2641                         sf->write_error = -EIO;
2642                 }
2643         }
2644         list_del(&req->list);
2645         pthread_cond_broadcast(&sf->write_finished);
2646         sshfs_file_put(sf);
2647 }
2648
2649 static int sshfs_async_write(struct sshfs_file *sf, const char *wbuf,
2650                              size_t size, off_t offset)
2651 {
2652         int err = 0;
2653         struct buffer *handle = &sf->handle;
2654
2655         while (!err && size) {
2656                 struct buffer buf;
2657                 struct iovec iov[2];
2658                 size_t bsize = size < sshfs.max_write ? size : sshfs.max_write;
2659
2660                 buf_init(&buf, 0);
2661                 buf_add_buf(&buf, handle);
2662                 buf_add_uint64(&buf, offset);
2663                 buf_add_uint32(&buf, bsize);
2664                 buf_to_iov(&buf, &iov[0]);
2665                 iov[1].iov_base = (void *) wbuf;
2666                 iov[1].iov_len = bsize;
2667                 err = sftp_request_send(SSH_FXP_WRITE, iov, 2,
2668                                         sshfs_write_begin, sshfs_write_end,
2669                                         0, sf, NULL);
2670                 buf_free(&buf);
2671                 size -= bsize;
2672                 wbuf += bsize;
2673                 offset += bsize;
2674         }
2675
2676         return err;
2677 }
2678
2679 static void sshfs_sync_write_begin(struct request *req)
2680 {
2681         struct sshfs_io *sio = (struct sshfs_io *) req->data;
2682         sio->num_reqs++;
2683 }
2684
2685 static void sshfs_sync_write_end(struct request *req)
2686 {
2687         uint32_t serr;
2688         struct sshfs_io *sio = (struct sshfs_io *) req->data;
2689
2690         if (req->error) {
2691                 sio->error = req->error;
2692         } else if (req->replied) {
2693                 if (req->reply_type != SSH_FXP_STATUS) {
2694                         fprintf(stderr, "protocol error\n");
2695                 } else if (buf_get_uint32(&req->reply, &serr) != -1 &&
2696                          serr != SSH_FX_OK) {
2697                         sio->error = -EIO;
2698                 }
2699         }
2700         sio->num_reqs--;
2701         if (!sio->num_reqs)
2702                 pthread_cond_broadcast(&sio->finished);
2703 }
2704
2705
2706 static int sshfs_sync_write(struct sshfs_file *sf, const char *wbuf,
2707                             size_t size, off_t offset)
2708 {
2709         int err = 0;
2710         struct buffer *handle = &sf->handle;
2711         struct sshfs_io sio = { .error = 0, .num_reqs = 0 };
2712
2713         pthread_cond_init(&sio.finished, NULL);
2714
2715         while (!err && size) {
2716                 struct buffer buf;
2717                 struct iovec iov[2];
2718                 size_t bsize = size < sshfs.max_write ? size : sshfs.max_write;
2719
2720                 buf_init(&buf, 0);
2721                 buf_add_buf(&buf, handle);
2722                 buf_add_uint64(&buf, offset);
2723                 buf_add_uint32(&buf, bsize);
2724                 buf_to_iov(&buf, &iov[0]);
2725                 iov[1].iov_base = (void *) wbuf;
2726                 iov[1].iov_len = bsize;
2727                 err = sftp_request_send(SSH_FXP_WRITE, iov, 2,
2728                                         sshfs_sync_write_begin,
2729                                         sshfs_sync_write_end,
2730                                         0, &sio, NULL);
2731                 buf_free(&buf);
2732                 size -= bsize;
2733                 wbuf += bsize;
2734                 offset += bsize;
2735         }
2736
2737         pthread_mutex_lock(&sshfs.lock);
2738         while (sio.num_reqs)
2739                pthread_cond_wait(&sio.finished, &sshfs.lock);
2740         pthread_mutex_unlock(&sshfs.lock);
2741
2742         if (!err)
2743                 err = sio.error;
2744
2745         return err;
2746 }
2747
2748 static int sshfs_write(const char *path, const char *wbuf, size_t size,
2749                        off_t offset, struct fuse_file_info *fi)
2750 {
2751         int err;
2752         struct sshfs_file *sf = get_sshfs_file(fi);
2753
2754         (void) path;
2755
2756         if (!sshfs_file_is_conn(sf))
2757                 return -EIO;
2758
2759         sshfs_inc_modifver();
2760
2761         if (!sshfs.sync_write && !sf->write_error)
2762                 err = sshfs_async_write(sf, wbuf, size, offset);
2763         else
2764                 err = sshfs_sync_write(sf, wbuf, size, offset);
2765
2766         return err ? err : (int) size;
2767 }
2768
2769 static int sshfs_ext_statvfs(const char *path, struct statvfs *stbuf)
2770 {
2771         int err;
2772         struct buffer buf;
2773         struct buffer outbuf;
2774         buf_init(&buf, 0);
2775         buf_add_string(&buf, SFTP_EXT_STATVFS);
2776         buf_add_path(&buf, path);
2777         err = sftp_request(SSH_FXP_EXTENDED, &buf, SSH_FXP_EXTENDED_REPLY,
2778                            &outbuf);
2779         if (!err) {
2780                 if (buf_get_statvfs(&outbuf, stbuf) == -1)
2781                         err = -EIO;
2782                 buf_free(&outbuf);
2783         }
2784         buf_free(&buf);
2785         return err;
2786 }
2787
2788
2789 #if FUSE_VERSION >= 25
2790 static int sshfs_statfs(const char *path, struct statvfs *buf)
2791 {
2792         if (sshfs.ext_statvfs)
2793                 return sshfs_ext_statvfs(path, buf);
2794
2795         buf->f_namemax = 255;
2796         buf->f_bsize = sshfs.blksize;
2797         /*
2798          * df seems to use f_bsize instead of f_frsize, so make them
2799          * the same
2800          */
2801         buf->f_frsize = buf->f_bsize;
2802         buf->f_blocks = buf->f_bfree =  buf->f_bavail =
2803                 1000ULL * 1024 * 1024 * 1024 / buf->f_frsize;
2804         buf->f_files = buf->f_ffree = 1000000000;
2805         return 0;
2806 }
2807 #else
2808 static int sshfs_statfs(const char *path, struct statfs *buf)
2809 {
2810         if (sshfs.ext_statvfs) {
2811                 int err;
2812                 struct statvfs vbuf;
2813
2814                 err = sshfs_ext_statvfs(path, &vbuf);
2815                 if (!err) {
2816                         buf->f_bsize = vbuf.f_bsize;
2817                         buf->f_blocks = vbuf.f_blocks;
2818                         buf->f_bfree = vbuf.f_bfree;
2819                         buf->f_bavail = vbuf.f_bavail;
2820                         buf->f_files = vbuf.f_files;
2821                         buf->f_ffree = vbuf.f_ffree;
2822                         buf->f_namelen = vbuf.f_namemax;
2823                 }
2824                 return err;
2825         }
2826
2827         buf->f_namelen = 255;
2828         buf->f_bsize = sshfs.blksize;
2829         buf->f_blocks = buf->f_bfree = buf->f_bavail =
2830                 1000ULL * 1024 * 1024 * 1024 / buf->f_bsize;
2831         buf->f_files = buf->f_ffree = 1000000000;
2832         return 0;
2833 }
2834 #endif
2835
2836 #if FUSE_VERSION >= 25
2837 static int sshfs_create(const char *path, mode_t mode,
2838                         struct fuse_file_info *fi)
2839 {
2840         return sshfs_open_common(path, mode, fi);
2841 }
2842
2843 static int sshfs_ftruncate(const char *path, off_t size,
2844                            struct fuse_file_info *fi)
2845 {
2846         int err;
2847         struct buffer buf;
2848         struct sshfs_file *sf = get_sshfs_file(fi);
2849
2850         (void) path;
2851
2852         if (!sshfs_file_is_conn(sf))
2853                 return -EIO;
2854
2855         sshfs_inc_modifver();
2856         if (sshfs.truncate_workaround)
2857                 return sshfs_truncate_workaround(path, size, fi);
2858
2859         buf_init(&buf, 0);
2860         buf_add_buf(&buf, &sf->handle);
2861         buf_add_uint32(&buf, SSH_FILEXFER_ATTR_SIZE);
2862         buf_add_uint64(&buf, size);
2863         err = sftp_request(SSH_FXP_FSETSTAT, &buf, SSH_FXP_STATUS, NULL);
2864         buf_free(&buf);
2865
2866         return err;
2867 }
2868 #endif
2869
2870 static int sshfs_fgetattr(const char *path, struct stat *stbuf,
2871                           struct fuse_file_info *fi)
2872 {
2873         int err;
2874         struct buffer buf;
2875         struct buffer outbuf;
2876         struct sshfs_file *sf = get_sshfs_file(fi);
2877
2878         (void) path;
2879
2880         if (!sshfs_file_is_conn(sf))
2881                 return -EIO;
2882
2883         if (sshfs.fstat_workaround)
2884                 return sshfs_getattr(path, stbuf);
2885
2886         buf_init(&buf, 0);
2887         buf_add_buf(&buf, &sf->handle);
2888         err = sftp_request(SSH_FXP_FSTAT, &buf, SSH_FXP_ATTRS, &outbuf);
2889         if (!err) {
2890                 if (buf_get_attrs(&outbuf, stbuf, NULL) == -1)
2891                         err = -EIO;
2892                 buf_free(&outbuf);
2893         }
2894         buf_free(&buf);
2895         return err;
2896 }
2897
2898 static int sshfs_truncate_zero(const char *path)
2899 {
2900         int err;
2901         struct fuse_file_info fi;
2902
2903         fi.flags = O_WRONLY | O_TRUNC;
2904         err = sshfs_open(path, &fi);
2905         if (!err)
2906                 sshfs_release(path, &fi);
2907
2908         return err;
2909 }
2910
2911 static size_t calc_buf_size(off_t size, off_t offset)
2912 {
2913         return offset + sshfs.max_read < size ? sshfs.max_read : size - offset;
2914 }
2915
2916 static int sshfs_truncate_shrink(const char *path, off_t size)
2917 {
2918         int res;
2919         char *data;
2920         off_t offset;
2921         struct fuse_file_info fi;
2922
2923         data = calloc(size, 1);
2924         if (!data)
2925                 return -ENOMEM;
2926
2927         fi.flags = O_RDONLY;
2928         res = sshfs_open(path, &fi);
2929         if (res)
2930                 goto out;
2931
2932         for (offset = 0; offset < size; offset += res) {
2933                 size_t bufsize = calc_buf_size(size, offset);
2934                 res = sshfs_read(path, data + offset, bufsize, offset, &fi);
2935                 if (res <= 0)
2936                         break;
2937         }
2938         sshfs_release(path, &fi);
2939         if (res < 0)
2940                 goto out;
2941
2942         fi.flags = O_WRONLY | O_TRUNC;
2943         res = sshfs_open(path, &fi);
2944         if (res)
2945                 goto out;
2946
2947         for (offset = 0; offset < size; offset += res) {
2948                 size_t bufsize = calc_buf_size(size, offset);
2949                 res = sshfs_write(path, data + offset, bufsize, offset, &fi);
2950                 if (res < 0)
2951                         break;
2952         }
2953         if (res >= 0)
2954                 res = sshfs_flush(path, &fi);
2955         sshfs_release(path, &fi);
2956
2957 out:
2958         free(data);
2959         return res;
2960 }
2961
2962 static int sshfs_truncate_extend(const char *path, off_t size,
2963                                  struct fuse_file_info *fi)
2964 {
2965         int res;
2966         char c = 0;
2967         struct fuse_file_info tmpfi;
2968         struct fuse_file_info *openfi = fi;
2969         if (!fi) {
2970                 openfi = &tmpfi;
2971                 openfi->flags = O_WRONLY;
2972                 res = sshfs_open(path, openfi);
2973                 if (res)
2974                         return res;
2975         }
2976         res = sshfs_write(path, &c, 1, size - 1, openfi);
2977         if (res == 1)
2978                 res = sshfs_flush(path, openfi);
2979         if (!fi)
2980                 sshfs_release(path, openfi);
2981
2982         return res;
2983 }
2984
2985 /*
2986  * Work around broken sftp servers which don't handle
2987  * SSH_FILEXFER_ATTR_SIZE in SETSTAT request.
2988  *
2989  * If new size is zero, just open the file with O_TRUNC.
2990  *
2991  * If new size is smaller than current size, then copy file locally,
2992  * then open/trunc and send it back.
2993  *
2994  * If new size is greater than current size, then write a zero byte to
2995  * the new end of the file.
2996  */
2997 static int sshfs_truncate_workaround(const char *path, off_t size,
2998                                      struct fuse_file_info *fi)
2999 {
3000         if (size == 0)
3001                 return sshfs_truncate_zero(path);
3002         else {
3003                 struct stat stbuf;
3004                 int err;
3005                 if (fi)
3006                         err = sshfs_fgetattr(path, &stbuf, fi);
3007                 else
3008                         err = sshfs_getattr(path, &stbuf);
3009                 if (err)
3010                         return err;
3011                 if (stbuf.st_size == size)
3012                         return 0;
3013                 else if (stbuf.st_size > size)
3014                         return sshfs_truncate_shrink(path, size);
3015                 else
3016                         return sshfs_truncate_extend(path, size, fi);
3017         }
3018 }
3019
3020 static int processing_init(void)
3021 {
3022         signal(SIGPIPE, SIG_IGN);
3023
3024         pthread_mutex_init(&sshfs.lock, NULL);
3025         pthread_mutex_init(&sshfs.lock_write, NULL);
3026         pthread_cond_init(&sshfs.outstanding_cond, NULL);
3027         sshfs.reqtab = g_hash_table_new(NULL, NULL);
3028         if (!sshfs.reqtab) {
3029                 fprintf(stderr, "failed to create hash table\n");
3030                 return -1;
3031         }
3032         return 0;
3033 }
3034
3035 static struct fuse_cache_operations sshfs_oper = {
3036         .oper = {
3037                 .init       = sshfs_init,
3038                 .getattr    = sshfs_getattr,
3039                 .readlink   = sshfs_readlink,
3040                 .mknod      = sshfs_mknod,
3041                 .mkdir      = sshfs_mkdir,
3042                 .symlink    = sshfs_symlink,
3043                 .unlink     = sshfs_unlink,
3044                 .rmdir      = sshfs_rmdir,
3045                 .rename     = sshfs_rename,
3046                 .link       = sshfs_link,
3047                 .chmod      = sshfs_chmod,
3048                 .chown      = sshfs_chown,
3049                 .truncate   = sshfs_truncate,
3050                 .utime      = sshfs_utime,
3051                 .open       = sshfs_open,
3052                 .flush      = sshfs_flush,
3053                 .fsync      = sshfs_fsync,
3054                 .release    = sshfs_release,
3055                 .read       = sshfs_read,
3056                 .write      = sshfs_write,
3057                 .statfs     = sshfs_statfs,
3058 #if FUSE_VERSION >= 25
3059                 .create     = sshfs_create,
3060                 .ftruncate  = sshfs_ftruncate,
3061                 .fgetattr   = sshfs_fgetattr,
3062 #endif
3063         },
3064         .cache_getdir = sshfs_getdir,
3065 };
3066
3067 static void usage(const char *progname)
3068 {
3069         printf(
3070 "usage: %s [user@]host:[dir] mountpoint [options]\n"
3071 "\n"
3072 "general options:\n"
3073 "    -o opt,[opt...]        mount options\n"
3074 "    -h   --help            print help\n"
3075 "    -V   --version         print version\n"
3076 "\n"
3077 "SSHFS options:\n"
3078 "    -p PORT                equivalent to '-o port=PORT'\n"
3079 "    -C                     equivalent to '-o compression=yes'\n"
3080 "    -F ssh_configfile      specifies alternative ssh configuration file\n"
3081 "    -1                     equivalent to '-o ssh_protocol=1'\n"
3082 "    -o reconnect           reconnect to server\n"
3083 "    -o delay_connect       delay connection to server\n"
3084 "    -o sshfs_sync          synchronous writes\n"
3085 "    -o no_readahead        synchronous reads (no speculative readahead)\n"
3086 "    -o sshfs_debug         print some debugging information\n"
3087 "    -o cache=BOOL          enable caching {yes,no} (default: yes)\n"
3088 "    -o cache_timeout=N     sets timeout for caches in seconds (default: 20)\n"
3089 "    -o cache_X_timeout=N   sets timeout for {stat,dir,link} cache\n"
3090 "    -o workaround=LIST     colon separated list of workarounds\n"
3091 "             none             no workarounds enabled\n"
3092 "             all              all workarounds enabled\n"
3093 "             [no]rename       fix renaming to existing file (default: off)\n"
3094 #ifdef SSH_NODELAY_WORKAROUND
3095 "             [no]nodelay      set nodelay tcp flag in ssh (default: on)\n"
3096 #endif
3097 "             [no]nodelaysrv   set nodelay tcp flag in sshd (default: off)\n"
3098 "             [no]truncate     fix truncate for old servers (default: off)\n"
3099 "             [no]buflimit     fix buffer fillup bug in server (default: on)\n"
3100 "    -o idmap=TYPE          user/group ID mapping, possible types are:\n"
3101 "             none             no translation of the ID space (default)\n"
3102 "             user             only translate UID of connecting user\n"
3103 "    -o ssh_command=CMD     execute CMD instead of 'ssh'\n"
3104 "    -o ssh_protocol=N      ssh protocol to use (default: 2)\n"
3105 "    -o sftp_server=SERV    path to sftp server or subsystem (default: sftp)\n"
3106 "    -o directport=PORT     directly connect to PORT bypassing ssh\n"
3107 "    -o transform_symlinks  transform absolute symlinks to relative\n"
3108 "    -o follow_symlinks     follow symlinks on the server\n"
3109 "    -o no_check_root       don't check for existence of 'dir' on server\n"
3110 "    -o password_stdin      read password from stdin (only for pam_mount!)\n"
3111 "    -o SSHOPT=VAL          ssh options (see man ssh_config)\n"
3112 "\n", progname);
3113 }
3114
3115 static int is_ssh_opt(const char *arg)
3116 {
3117         if (arg[0] != '-') {
3118                 unsigned arglen = strlen(arg);
3119                 const char **o;
3120                 for (o = ssh_opts; *o; o++) {
3121                         unsigned olen = strlen(*o);
3122                         if (arglen > olen && arg[olen] == '=' &&
3123                             strncasecmp(arg, *o, olen) == 0)
3124                                 return 1;
3125                 }
3126         }
3127         return 0;
3128 }
3129
3130 static int sshfs_fuse_main(struct fuse_args *args)
3131 {
3132 #if FUSE_VERSION >= 26
3133         return fuse_main(args->argc, args->argv, cache_init(&sshfs_oper), NULL);
3134 #else
3135         return fuse_main(args->argc, args->argv, cache_init(&sshfs_oper));
3136 #endif
3137 }
3138
3139 static int sshfs_opt_proc(void *data, const char *arg, int key,
3140                           struct fuse_args *outargs)
3141 {
3142         char *tmp;
3143         (void) data;
3144
3145         switch (key) {
3146         case FUSE_OPT_KEY_OPT:
3147                 if (is_ssh_opt(arg)) {
3148                         tmp = g_strdup_printf("-o%s", arg);
3149                         ssh_add_arg(tmp);
3150                         g_free(tmp);
3151                         return 0;
3152                 }
3153                 return 1;
3154
3155         case FUSE_OPT_KEY_NONOPT:
3156                 if (!sshfs.host && strchr(arg, ':')) {
3157                         sshfs.host = strdup(arg);
3158                         return 0;
3159                 }
3160                 return 1;
3161
3162         case KEY_PORT:
3163                 tmp = g_strdup_printf("-oPort=%s", arg + 2);
3164                 ssh_add_arg(tmp);
3165                 g_free(tmp);
3166                 return 0;
3167
3168         case KEY_COMPRESS:
3169                 ssh_add_arg("-oCompression=yes");
3170                 return 0;
3171
3172         case KEY_CONFIGFILE:
3173                 tmp = g_strdup_printf("-F%s", arg + 2);
3174                 ssh_add_arg(tmp);
3175                 g_free(tmp);
3176                 return 0;
3177
3178         case KEY_HELP:
3179                 usage(outargs->argv[0]);
3180                 fuse_opt_add_arg(outargs, "-ho");
3181                 sshfs_fuse_main(outargs);
3182                 exit(1);
3183
3184         case KEY_VERSION:
3185                 printf("SSHFS version %s\n", PACKAGE_VERSION);
3186 #if FUSE_VERSION >= 25
3187                 fuse_opt_add_arg(outargs, "--version");
3188                 sshfs_fuse_main(outargs);
3189 #endif
3190                 exit(0);
3191
3192         case KEY_FOREGROUND:
3193                 sshfs.foreground = 1;
3194                 return 1;
3195
3196         default:
3197                 fprintf(stderr, "internal error\n");
3198                 abort();
3199         }
3200 }
3201
3202 static int workaround_opt_proc(void *data, const char *arg, int key,
3203                                struct fuse_args *outargs)
3204 {
3205         (void) data; (void) key; (void) outargs;
3206         fprintf(stderr, "unknown workaround: '%s'\n", arg);
3207         return -1;
3208 }
3209
3210 int parse_workarounds(void)
3211 {
3212         int res;
3213         char *argv[] = { "", "-o", sshfs.workarounds, NULL };
3214         struct fuse_args args = FUSE_ARGS_INIT(3, argv);
3215         char *s = sshfs.workarounds;
3216         if (!s)
3217                 return 0;
3218
3219         while ((s = strchr(s, ':')))
3220                 *s = ',';
3221
3222         res = fuse_opt_parse(&args, &sshfs, workaround_opts,
3223                              workaround_opt_proc);
3224         fuse_opt_free_args(&args);
3225
3226         return res;
3227 }
3228
3229 #if FUSE_VERSION == 25
3230 static int fuse_opt_insert_arg(struct fuse_args *args, int pos,
3231                                const char *arg)
3232 {
3233         assert(pos <= args->argc);
3234         if (fuse_opt_add_arg(args, arg) == -1)
3235                 return -1;
3236
3237         if (pos != args->argc - 1) {
3238                 char *newarg = args->argv[args->argc - 1];
3239                 memmove(&args->argv[pos + 1], &args->argv[pos],
3240                         sizeof(char *) * (args->argc - pos - 1));
3241                 args->argv[pos] = newarg;
3242         }
3243         return 0;
3244 }
3245 #endif
3246
3247 static void check_large_read(struct fuse_args *args)
3248 {
3249         struct utsname buf;
3250         int err = uname(&buf);
3251         if (!err && strcmp(buf.sysname, "Linux") == 0 &&
3252             strncmp(buf.release, "2.4.", 4) == 0)
3253                 fuse_opt_insert_arg(args, 1, "-olarge_read");
3254 }
3255
3256 static int read_password(void)
3257 {
3258         int size = getpagesize();
3259         int max_password = 64;
3260         int n;
3261
3262         sshfs.password = mmap(NULL, size, PROT_READ | PROT_WRITE,
3263                               MAP_PRIVATE | MAP_ANONYMOUS | MAP_LOCKED,
3264                               -1, 0);
3265         if (sshfs.password == MAP_FAILED) {
3266                 perror("Failed to allocate locked page for password");
3267                 return -1;
3268         }
3269
3270         /* Don't use fgets() because password might stay in memory */
3271         for (n = 0; n < max_password; n++) {
3272                 int res;
3273
3274                 res = read(0, &sshfs.password[n], 1);
3275                 if (res == -1) {
3276                         perror("Reading password");
3277                         return -1;
3278                 }
3279                 if (res == 0) {
3280                         sshfs.password[n] = '\n';
3281                         break;
3282                 }
3283                 if (sshfs.password[n] == '\n')
3284                         break;
3285         }
3286         if (n == max_password) {
3287                 fprintf(stderr, "Password too long\n");
3288                 return -1;
3289         }
3290         sshfs.password[n+1] = '\0';
3291         ssh_add_arg("-oNumberOfPasswordPrompts=1");
3292
3293         return 0;
3294 }
3295
3296 static void set_ssh_command(void)
3297 {
3298         char *s;
3299         char *d;
3300         int i = 0;
3301         int end = 0;
3302
3303         d = sshfs.ssh_command;
3304         s = sshfs.ssh_command;
3305         while (!end) {
3306                 switch (*s) {
3307                 case '\0':
3308                         end = 1;
3309                 case ' ':
3310                         *d = '\0';
3311                         if (i == 0) {
3312                                 replace_arg(&sshfs.ssh_args.argv[0],
3313                                             sshfs.ssh_command);
3314                         } else {
3315                                 if (fuse_opt_insert_arg(&sshfs.ssh_args, i, 
3316                                                 sshfs.ssh_command) == -1)
3317                                         _exit(1);
3318                         }
3319                         i++;
3320                         d = sshfs.ssh_command;
3321                         break;
3322
3323                 case '\\':
3324                         if (s[1])
3325                                 s++;
3326                 default:
3327                         *d++ = *s;
3328                 }
3329                 s++;
3330         }
3331 }
3332
3333 static char *find_base_path(void)
3334 {
3335         char *s = sshfs.host;
3336         char *d = s;
3337
3338         for (; *s && *s != ':'; s++) {
3339                 if (*s == '[') {
3340                         /*
3341                          * Handle IPv6 numerical address enclosed in square
3342                          * brackets
3343                          */
3344                         s++;
3345                         for (; *s != ']'; s++) {
3346                                 if (!*s) {
3347                                         fprintf(stderr, "missing ']' in hostname\n");
3348                                         exit(1);
3349                                 }
3350                                 *d++ = *s;
3351                         }
3352                 } else {
3353                         *d++ = *s;
3354                 }
3355
3356         }
3357         *d++ = '\0';
3358         s++;
3359
3360         return s;
3361 }
3362
3363 /*
3364  * Remove commas from fsname, as it confuses the fuse option parser.
3365  */
3366 static void fsname_remove_commas(char *fsname)
3367 {
3368         if (strchr(fsname, ',') != NULL) {
3369                 char *s = fsname;
3370                 char *d = s;
3371
3372                 for (; *s; s++) {
3373                         if (*s != ',')
3374                                 *d++ = *s;
3375                 }
3376                 *d = *s;
3377         }
3378 }
3379
3380 #if FUSE_VERSION >= 27
3381 static char *fsname_escape_commas(char *fsnameold)
3382 {
3383         char *fsname = g_malloc(strlen(fsnameold) * 2 + 1);
3384         char *d = fsname;
3385         char *s;
3386
3387         for (s = fsnameold; *s; s++) {
3388                 if (*s == '\\' || *s == ',')
3389                         *d++ = '\\';
3390                 *d++ = *s;
3391         }
3392         *d = '\0';
3393         g_free(fsnameold);
3394
3395         return fsname;
3396 }
3397 #endif
3398
3399 static int ssh_connect(void)
3400 {
3401         int res;
3402
3403         res = processing_init();
3404         if (res == -1)
3405                 return -1;
3406
3407         if (!sshfs.delay_connect) {
3408                 if (connect_remote() == -1)
3409                         return -1;
3410
3411                 if (!sshfs.no_check_root &&
3412                     sftp_check_root(sshfs.base_path) == -1)
3413                         return -1;
3414
3415         }
3416         return 0;
3417 }
3418
3419 int main(int argc, char *argv[])
3420 {
3421         int res;
3422         struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
3423         char *tmp;
3424         char *fsname;
3425         const char *sftp_server;
3426         int libver;
3427
3428         g_thread_init(NULL);
3429
3430         sshfs.blksize = 4096;
3431         /* SFTP spec says all servers should allow at least 32k I/O */
3432         sshfs.max_read = 32768;
3433         sshfs.max_write = 32768;
3434         sshfs.nodelay_workaround = 1;
3435         sshfs.nodelaysrv_workaround = 0;
3436         sshfs.rename_workaround = 0;
3437         sshfs.truncate_workaround = 0;
3438         sshfs.buflimit_workaround = 1;
3439         sshfs.ssh_ver = 2;
3440         sshfs.progname = argv[0];
3441         sshfs.fd = -1;
3442         sshfs.ptyfd = -1;
3443         sshfs.ptyslavefd = -1;
3444         sshfs.delay_connect = 0;
3445         ssh_add_arg("ssh");
3446         ssh_add_arg("-x");
3447         ssh_add_arg("-a");
3448         ssh_add_arg("-oClearAllForwardings=yes");
3449
3450         if (fuse_opt_parse(&args, &sshfs, sshfs_opts, sshfs_opt_proc) == -1 ||
3451             parse_workarounds() == -1)
3452                 exit(1);
3453
3454         DEBUG("SSHFS version %s\n", PACKAGE_VERSION);
3455
3456         if (sshfs.password_stdin) {
3457                 res = read_password();
3458                 if (res == -1)
3459                         exit(1);
3460         }
3461
3462         if (sshfs.buflimit_workaround)
3463                 /* Work around buggy sftp-server in OpenSSH.  Without this on
3464                    a slow server a 10Mbyte buffer would fill up and the server
3465                    would abort */
3466                 sshfs.max_outstanding_len = 8388608;
3467         else
3468                 sshfs.max_outstanding_len = ~0;
3469
3470         if (!sshfs.host) {
3471                 fprintf(stderr, "missing host\n");
3472                 fprintf(stderr, "see `%s -h' for usage\n", argv[0]);
3473                 exit(1);
3474         }
3475
3476         fsname = g_strdup(sshfs.host);
3477         sshfs.base_path = g_strdup(find_base_path());
3478
3479         if (sshfs.ssh_command)
3480                 set_ssh_command();
3481
3482         tmp = g_strdup_printf("-%i", sshfs.ssh_ver);
3483         ssh_add_arg(tmp);
3484         g_free(tmp);
3485         ssh_add_arg(sshfs.host);
3486         if (sshfs.sftp_server)
3487                 sftp_server = sshfs.sftp_server;
3488         else if (sshfs.ssh_ver == 1)
3489                 sftp_server = SFTP_SERVER_PATH;
3490         else
3491                 sftp_server = "sftp";
3492
3493         if (sshfs.ssh_ver != 1 && strchr(sftp_server, '/') == NULL)
3494                 ssh_add_arg("-s");
3495
3496         ssh_add_arg(sftp_server);
3497         free(sshfs.sftp_server);
3498
3499
3500         res = cache_parse_options(&args);
3501         if (res == -1)
3502                 exit(1);
3503
3504         sshfs.randseed = time(0);
3505
3506         if (sshfs.max_read > 65536)
3507                 sshfs.max_read = 65536;
3508         if (sshfs.max_write > 65536)
3509                 sshfs.max_write = 65536;
3510
3511         if (fuse_is_lib_option("ac_attr_timeout="))
3512                 fuse_opt_insert_arg(&args, 1, "-oauto_cache,ac_attr_timeout=0");
3513 #if FUSE_VERSION >= 27
3514         libver = fuse_version();
3515         assert(libver >= 27);
3516         if (libver >= 28)
3517                 fsname = fsname_escape_commas(fsname);
3518         else
3519                 fsname_remove_commas(fsname);
3520         tmp = g_strdup_printf("-osubtype=sshfs,fsname=%s", fsname);
3521 #else
3522         fsname_remove_commas(fsname);
3523         tmp = g_strdup_printf("-ofsname=sshfs#%s", fsname);
3524 #endif
3525         fuse_opt_insert_arg(&args, 1, tmp);
3526         g_free(tmp);
3527         g_free(fsname);
3528         check_large_read(&args);
3529
3530 #if FUSE_VERSION >= 26
3531         {
3532                 struct fuse *fuse;
3533                 struct fuse_chan *ch;
3534                 char *mountpoint;
3535                 int multithreaded;
3536                 int foreground;
3537                 struct stat st;
3538
3539                 res = fuse_parse_cmdline(&args, &mountpoint, &multithreaded, 
3540                                          &foreground);
3541                 if (res == -1)
3542                         exit(1);
3543
3544                 res = stat(mountpoint, &st);
3545                 if (res == -1) {
3546                         perror(mountpoint);
3547                         exit(1);
3548                 }
3549                 sshfs.mnt_mode = st.st_mode;
3550
3551                 ch = fuse_mount(mountpoint, &args);
3552                 if (!ch)
3553                         exit(1);
3554
3555                 res = fcntl(fuse_chan_fd(ch), F_SETFD, FD_CLOEXEC);
3556                 if (res == -1)
3557                         perror("WARNING: failed to set FD_CLOESEC on fuse device");
3558
3559                 fuse = fuse_new(ch, &args, cache_init(&sshfs_oper),
3560                                 sizeof(struct fuse_operations), NULL);
3561                 if (fuse == NULL) {
3562                         fuse_unmount(mountpoint, ch);
3563                         exit(1);
3564                 }
3565
3566                 res = ssh_connect();
3567                 if (res == -1) {
3568                         fuse_unmount(mountpoint, ch);
3569                         fuse_destroy(fuse);
3570                         exit(1);
3571                 }
3572
3573                 res = fuse_daemonize(foreground);
3574                 if (res != -1)
3575                         res = fuse_set_signal_handlers(fuse_get_session(fuse));
3576
3577                 if (res == -1) {
3578                         fuse_unmount(mountpoint, ch);
3579                         fuse_destroy(fuse);
3580                         exit(1);
3581                 }
3582
3583                 if (multithreaded)
3584                         res = fuse_loop_mt(fuse);
3585                 else
3586                         res = fuse_loop(fuse);
3587
3588                 if (res == -1)
3589                         res = 1;
3590                 else
3591                         res = 0;
3592
3593                 fuse_remove_signal_handlers(fuse_get_session(fuse));
3594                 fuse_unmount(mountpoint, ch);
3595                 fuse_destroy(fuse);
3596                 free(mountpoint);
3597         }
3598 #else
3599         res = ssh_connect();
3600         if (res == -1)
3601                 exit(1);
3602
3603         res = sshfs_fuse_main(&args);
3604 #endif
3605
3606         if (sshfs.debug) {
3607                 unsigned int avg_rtt = 0;
3608
3609                 if (sshfs.num_sent)
3610                         avg_rtt = sshfs.total_rtt / sshfs.num_sent;
3611
3612                 DEBUG("\n"
3613                       "sent:               %llu messages, %llu bytes\n"
3614                       "received:           %llu messages, %llu bytes\n"
3615                       "rtt min/max/avg:    %ums/%ums/%ums\n"
3616                       "num connect:        %u\n",
3617                       (unsigned long long) sshfs.num_sent,
3618                       (unsigned long long) sshfs.bytes_sent,
3619                       (unsigned long long) sshfs.num_received,
3620                       (unsigned long long) sshfs.bytes_received,
3621                       sshfs.min_rtt, sshfs.max_rtt, avg_rtt,
3622                       sshfs.num_connect);
3623         }
3624
3625         fuse_opt_free_args(&args);
3626         fuse_opt_free_args(&sshfs.ssh_args);
3627         free(sshfs.directport);
3628
3629         return res;
3630 }