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