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