This source file includes following definitions.
- ftpfs_set_blksize
- ftpfs_default_stat
- ftpfs_translate_path
- ftpfs_correct_url_parameters
- ftpfs_get_reply
- ftpfs_reconnect
- G_GNUC_PRINTF
- ftpfs_new_archive
- ftpfs_free_archive
- ftpfs_changetype
- ftpfs_login_server
- ftpfs_load_no_proxy_list
- ftpfs_check_proxy
- ftpfs_get_proxy_host_and_port
- ftpfs_open_socket
- ftpfs_open_archive_int
- ftpfs_open_archive
- ftpfs_archive_same
- ftpfs_get_current_directory
- ftpfs_setup_passive_pasv
- ftpfs_setup_passive_epsv
- ftpfs_setup_passive
- ftpfs_setup_active
- ftpfs_init_data_socket
- ftpfs_initconn
- ftpfs_open_data_connection
- ftpfs_linear_abort
- resolve_symlink_without_ls_options
- resolve_symlink_with_ls_options
- resolve_symlink
- ftpfs_dir_load
- ftpfs_file_store
- ftpfs_linear_start
- ftpfs_linear_read
- ftpfs_linear_close
- ftpfs_ctl
- ftpfs_send_command
- ftpfs_stat
- ftpfs_lstat
- ftpfs_fstat
- ftpfs_chmod
- ftpfs_chown
- ftpfs_unlink
- ftpfs_is_same_dir
- ftpfs_chdir_internal
- ftpfs_rename
- ftpfs_mkdir
- ftpfs_rmdir
- ftpfs_fh_new
- ftpfs_fh_open
- ftpfs_fh_close
- ftpfs_done
- ftpfs_fill_names
- ftpfs_netrc_next
- ftpfs_netrc_bad_mode
- ftpfs_find_machine
- ftpfs_netrc_lookup
- ftpfs_init_passwd
- vfs_init_ftpfs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 #include <config.h>
78 #include <stdio.h>
79 #include <stdlib.h>
80 #include <sys/types.h>
81 #include <netdb.h>
82 #include <sys/socket.h>
83 #include <netinet/in.h>
84 #ifdef HAVE_ARPA_INET_H
85 #include <arpa/inet.h>
86 #endif
87 #include <arpa/ftp.h>
88 #include <arpa/telnet.h>
89 #ifdef HAVE_SYS_PARAM_H
90 #include <sys/param.h>
91 #endif
92 #include <errno.h>
93 #include <ctype.h>
94 #include <fcntl.h>
95 #include <inttypes.h>
96
97 #include "lib/global.h"
98 #include "lib/file-entry.h"
99 #include "lib/util.h"
100 #include "lib/strutil.h"
101 #include "lib/mcconfig.h"
102
103 #include "lib/tty/tty.h"
104 #include "lib/widget.h"
105
106 #include "src/history.h"
107 #include "src/setup.h"
108
109 #include "lib/vfs/vfs.h"
110 #include "lib/vfs/utilvfs.h"
111 #include "lib/vfs/netutil.h"
112 #include "lib/vfs/xdirentry.h"
113 #include "lib/vfs/gc.h"
114
115 #include "ftpfs.h"
116
117
118
119
120 int ftpfs_retry_seconds = 30;
121
122
123 gboolean ftpfs_use_passive_connections = TRUE;
124 gboolean ftpfs_use_passive_connections_over_proxy = FALSE;
125
126
127
128
129
130
131 gboolean ftpfs_use_unix_list_options = TRUE;
132
133
134 gboolean ftpfs_first_cd_then_ls = TRUE;
135
136
137 gboolean ftpfs_use_netrc = TRUE;
138
139
140 char *ftpfs_anonymous_passwd = NULL;
141 int ftpfs_directory_timeout = 900;
142
143
144 char *ftpfs_proxy_host = NULL;
145
146
147 gboolean ftpfs_always_use_proxy = FALSE;
148
149 gboolean ftpfs_ignore_chattr_errors = TRUE;
150
151
152
153 #ifndef MAXHOSTNAMELEN
154 #define MAXHOSTNAMELEN 64
155 #endif
156
157 #define FTP_SUPER(super) ((ftp_super_t *) (super))
158 #define FTP_FILE_HANDLER(fh) ((ftp_file_handler_t *) (fh))
159 #define FH_SOCK FTP_FILE_HANDLER (fh)->sock
160
161 #ifndef INADDR_NONE
162 #define INADDR_NONE 0xffffffff
163 #endif
164
165 #define RFC_AUTODETECT 0
166 #define RFC_DARING 1
167 #define RFC_STRICT 2
168
169
170 #define NONE 0x00
171 #define WAIT_REPLY 0x01
172 #define WANT_STRING 0x02
173
174 #define FTP_COMMAND_PORT 21
175
176
177
178 #define TYPE_ASCII 0
179 #define TYPE_BINARY 1
180
181
182
183 #define TYPE_UNKNOWN -1
184
185 #define ABORT_TIMEOUT (5 * G_USEC_PER_SEC)
186
187
188 #ifndef HAVE_SOCKLEN_T
189 typedef int socklen_t;
190 #endif
191
192
193 typedef enum
194 {
195 NETRC_NONE = 0,
196 NETRC_DEFAULT,
197 NETRC_MACHINE,
198 NETRC_LOGIN,
199 NETRC_PASSWORD,
200 NETRC_PASSWD,
201 NETRC_ACCOUNT,
202 NETRC_MACDEF,
203 NETRC_UNKNOWN
204 } keyword_t;
205
206 typedef struct
207 {
208 struct vfs_s_super base;
209
210 int sock;
211
212 char *proxy;
213 gboolean failed_on_login;
214 gboolean use_passive_connection;
215 gboolean remote_is_amiga;
216 int isbinary;
217 gboolean cwd_deferred;
218
219 int strict;
220
221
222
223 gboolean ctl_connection_busy;
224 char *current_dir;
225 } ftp_super_t;
226
227 typedef struct
228 {
229 vfs_file_handler_t base;
230
231 int sock;
232 gboolean append;
233 } ftp_file_handler_t;
234
235
236
237 static char *ftpfs_get_current_directory (struct vfs_class *me, struct vfs_s_super *super);
238 static int ftpfs_chdir_internal (struct vfs_class *me, struct vfs_s_super *super,
239 const char *remote_path);
240 static int ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super);
241 static gboolean ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super,
242 const char *netrcpass);
243 static gboolean ftpfs_netrc_lookup (const char *host, char **login, char **pass);
244
245
246
247 static int code;
248
249 static char reply_str[80];
250
251 static struct vfs_s_subclass ftpfs_subclass;
252 static struct vfs_class *vfs_ftpfs_ops = VFS_CLASS (&ftpfs_subclass);
253
254 static GSList *no_proxy = NULL;
255
256 static char buffer[BUF_MEDIUM];
257 static char *netrc = NULL;
258 static const char *netrcp;
259
260
261
262
263
264 static void
265 ftpfs_set_blksize (struct stat *s)
266 {
267 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
268
269 s->st_blksize = 64 * 1024;
270 #endif
271 }
272
273
274
275 static struct stat *
276 ftpfs_default_stat (struct vfs_class *me)
277 {
278 struct stat *s;
279
280 s = vfs_s_default_stat (me, S_IFDIR | 0755);
281 ftpfs_set_blksize (s);
282 vfs_adjust_stat (s);
283
284 return s;
285 }
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300 static char *
301 ftpfs_translate_path (struct vfs_class *me, struct vfs_s_super *super, const char *remote_path)
302 {
303 char *ret, *p;
304
305 if (!FTP_SUPER (super)->remote_is_amiga)
306 return g_strdup (remote_path);
307
308 if (me->logfile != NULL)
309 {
310 fprintf (me->logfile, "MC -- ftpfs_translate_path: %s\n", remote_path);
311 fflush (me->logfile);
312 }
313
314
315 while (IS_PATH_SEP (*remote_path))
316 remote_path++;
317
318
319 if (*remote_path == '\0')
320 return g_strdup (".");
321
322 ret = g_strdup (remote_path);
323
324
325 p = strchr (ret, ':');
326 if (p != NULL && IS_PATH_SEP (p[1]))
327 str_move (p + 1, p + 2);
328
329
330 p = strrchr (ret, PATH_SEP);
331 if ((p != NULL) && (*(p + 1) == '.') && (*(p + 2) == '\0'))
332 *p = '\0';
333
334 return ret;
335 }
336
337
338
339
340
341
342
343
344
345
346
347
348
349 static vfs_path_element_t *
350 ftpfs_correct_url_parameters (const vfs_path_element_t *velement)
351 {
352 vfs_path_element_t *path_element = vfs_path_element_clone (velement);
353
354 if (path_element->port == 0)
355 path_element->port = FTP_COMMAND_PORT;
356
357 if (path_element->user == NULL)
358 {
359
360 if (ftpfs_use_netrc)
361 ftpfs_netrc_lookup (path_element->host, &path_element->user, &path_element->password);
362 }
363 if (path_element->user == NULL)
364 path_element->user = g_strdup ("anonymous");
365
366
367 if (ftpfs_use_netrc && path_element->password == NULL)
368 {
369 char *new_user = NULL;
370 char *new_passwd = NULL;
371
372 ftpfs_netrc_lookup (path_element->host, &new_user, &new_passwd);
373
374
375 if (new_user != NULL && strcmp (path_element->user, new_user) != 0)
376 MC_PTR_FREE (path_element->password);
377
378 g_free (new_user);
379 g_free (new_passwd);
380 }
381
382 return path_element;
383 }
384
385
386
387
388 static int
389 ftpfs_get_reply (struct vfs_class *me, int sock, char *string_buf, int string_len)
390 {
391 while (TRUE)
392 {
393 char answer[BUF_1K];
394
395 if (vfs_s_get_line (me, sock, answer, sizeof (answer), '\n') == 0)
396 {
397 if (string_buf != NULL)
398 *string_buf = '\0';
399 code = 421;
400 return 4;
401 }
402
403 switch (sscanf (answer, "%d", &code))
404 {
405 case 0:
406 if (string_buf != NULL)
407 g_strlcpy (string_buf, answer, string_len);
408 code = 500;
409 return 5;
410 case 1:
411 if (answer[3] == '-')
412 {
413 while (TRUE)
414 {
415 int i;
416
417 if (vfs_s_get_line (me, sock, answer, sizeof (answer), '\n') == 0)
418 {
419 if (string_buf != NULL)
420 *string_buf = '\0';
421 code = 421;
422 return 4;
423 }
424 if ((sscanf (answer, "%d", &i) > 0) && (code == i) && (answer[3] == ' '))
425 break;
426 }
427 }
428 if (string_buf != NULL)
429 g_strlcpy (string_buf, answer, string_len);
430 return code / 100;
431 default:
432 break;
433 }
434 }
435 }
436
437
438
439 static gboolean
440 ftpfs_reconnect (struct vfs_class *me, struct vfs_s_super *super)
441 {
442 ftp_super_t *ftp_super = FTP_SUPER (super);
443 int sock;
444
445 sock = ftpfs_open_socket (me, super);
446 if (sock != -1)
447 {
448 char *cwdir = ftp_super->current_dir;
449
450 close (ftp_super->sock);
451 ftp_super->sock = sock;
452 ftp_super->current_dir = NULL;
453
454 if (ftpfs_login_server (me, super, super->path_element->password))
455 {
456 if (cwdir == NULL)
457 return TRUE;
458
459 sock = ftpfs_chdir_internal (me, super, cwdir);
460 g_free (cwdir);
461 return (sock == COMPLETE);
462 }
463
464 ftp_super->current_dir = cwdir;
465 }
466
467 return FALSE;
468 }
469
470
471
472 static int G_GNUC_PRINTF (4, 5)
473 ftpfs_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply, const char *fmt,
474 ...)
475 {
476 ftp_super_t *ftp_super = FTP_SUPER (super);
477 va_list ap;
478 GString *cmdstr;
479 int status;
480 static gboolean retry = FALSE;
481 static int level = 0;
482
483 cmdstr = g_string_sized_new (32);
484 va_start (ap, fmt);
485 g_string_vprintf (cmdstr, fmt, ap);
486 va_end (ap);
487 g_string_append (cmdstr, "\r\n");
488
489 if (me->logfile != NULL)
490 {
491 if (strncmp (cmdstr->str, "PASS ", 5) == 0)
492 fputs ("PASS <Password not logged>\r\n", me->logfile);
493 else
494 {
495 size_t ret;
496
497 ret = fwrite (cmdstr->str, cmdstr->len, 1, me->logfile);
498 (void) ret;
499 }
500
501 fflush (me->logfile);
502 }
503
504 got_sigpipe = 0;
505 tty_enable_interrupt_key ();
506 status = write (ftp_super->sock, cmdstr->str, cmdstr->len);
507
508 if (status < 0)
509 {
510 code = 421;
511
512 if (errno == EPIPE)
513 {
514 if (level == 0)
515 {
516 level = 1;
517 status = ftpfs_reconnect (me, super) ? 1 : 0;
518 level = 0;
519 if (status != 0 && (write (ftp_super->sock, cmdstr->str, cmdstr->len) > 0))
520 goto ok;
521 }
522 got_sigpipe = 1;
523 }
524 g_string_free (cmdstr, TRUE);
525 tty_disable_interrupt_key ();
526 return TRANSIENT;
527 }
528
529 retry = FALSE;
530
531 ok:
532 tty_disable_interrupt_key ();
533
534 if (wait_reply != NONE)
535 {
536 status = ftpfs_get_reply (me, ftp_super->sock,
537 (wait_reply & WANT_STRING) != 0 ? reply_str : NULL,
538 sizeof (reply_str) - 1);
539 if ((wait_reply & WANT_STRING) != 0 && !retry && level == 0 && code == 421)
540 {
541 retry = TRUE;
542 level = 1;
543 status = ftpfs_reconnect (me, super) ? 1 : 0;
544 level = 0;
545 if (status != 0 && (write (ftp_super->sock, cmdstr->str, cmdstr->len) > 0))
546 goto ok;
547 }
548 retry = FALSE;
549 g_string_free (cmdstr, TRUE);
550 return status;
551 }
552
553 g_string_free (cmdstr, TRUE);
554 return COMPLETE;
555 }
556
557
558
559 static struct vfs_s_super *
560 ftpfs_new_archive (struct vfs_class *me)
561 {
562 ftp_super_t *arch;
563
564 arch = g_new0 (ftp_super_t, 1);
565 arch->base.me = me;
566 arch->base.name = g_strdup (PATH_SEP_STR);
567 arch->sock = -1;
568 arch->use_passive_connection = ftpfs_use_passive_connections;
569 arch->strict = ftpfs_use_unix_list_options ? RFC_AUTODETECT : RFC_STRICT;
570 arch->isbinary = TYPE_UNKNOWN;
571
572 return VFS_SUPER (arch);
573 }
574
575
576
577 static void
578 ftpfs_free_archive (struct vfs_class *me, struct vfs_s_super *super)
579 {
580 ftp_super_t *ftp_super = FTP_SUPER (super);
581
582 if (ftp_super->sock != -1)
583 {
584 vfs_print_message (_ ("ftpfs: Disconnecting from %s"), super->path_element->host);
585 ftpfs_command (me, super, NONE, "%s", "QUIT");
586 close (ftp_super->sock);
587 }
588 g_free (ftp_super->current_dir);
589 }
590
591
592
593 static int
594 ftpfs_changetype (struct vfs_class *me, struct vfs_s_super *super, int binary)
595 {
596 if (binary != FTP_SUPER (super)->isbinary)
597 {
598 if (ftpfs_command (me, super, WAIT_REPLY, "TYPE %c", binary ? 'I' : 'A') != COMPLETE)
599 ERRNOR (EIO, -1);
600 FTP_SUPER (super)->isbinary = binary;
601 }
602 return binary;
603 }
604
605
606
607
608 static int
609 ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char *netrcpass)
610 {
611 ftp_super_t *ftp_super = FTP_SUPER (super);
612 char *pass;
613 char *op;
614 char *name;
615 gboolean anon = FALSE;
616 char reply_string[BUF_MEDIUM];
617
618 ftp_super->isbinary = TYPE_UNKNOWN;
619
620 if (super->path_element->password != NULL)
621 op = g_strdup (super->path_element->password);
622 else if (netrcpass != NULL)
623 op = g_strdup (netrcpass);
624 else if (strcmp (super->path_element->user, "anonymous") == 0
625 || strcmp (super->path_element->user, "ftp") == 0)
626 {
627 if (ftpfs_anonymous_passwd == NULL)
628 ftpfs_init_passwd ();
629 op = g_strdup (ftpfs_anonymous_passwd);
630 anon = TRUE;
631 }
632 else
633 {
634 char *p;
635
636 p = g_strdup_printf (_ ("FTP: Password required for %s"), super->path_element->user);
637 op = vfs_get_password (p);
638 g_free (p);
639 if (op == NULL)
640 ERRNOR (EPERM, 0);
641 super->path_element->password = g_strdup (op);
642 }
643
644 if (!anon || me->logfile != NULL)
645 pass = op;
646 else
647 {
648 pass = g_strconcat ("-", op, (char *) NULL);
649 wipe_password (op);
650 }
651
652
653 if (ftp_super->proxy != NULL)
654 name = g_strconcat (super->path_element->user, "@",
655 super->path_element->host[0] == '!' ? super->path_element->host + 1
656 : super->path_element->host,
657 (char *) NULL);
658 else
659 name = g_strdup (super->path_element->user);
660
661 if (ftpfs_get_reply (me, ftp_super->sock, reply_string, sizeof (reply_string) - 1) == COMPLETE)
662 {
663 char *reply_up;
664
665 reply_up = g_ascii_strup (reply_string, -1);
666 ftp_super->remote_is_amiga = strstr (reply_up, "AMIGA") != NULL;
667 if (strstr (reply_up, " SPFTP/1.0.0000 SERVER ")
668 != NULL)
669 ftp_super->strict = RFC_STRICT;
670 g_free (reply_up);
671
672 if (me->logfile != NULL)
673 {
674 fprintf (me->logfile, "MC -- remote_is_amiga = %s\n",
675 ftp_super->remote_is_amiga ? "yes" : "no");
676 fflush (me->logfile);
677 }
678
679 vfs_print_message ("%s", _ ("ftpfs: sending login name"));
680
681 switch (ftpfs_command (me, super, WAIT_REPLY, "USER %s", name))
682 {
683 case CONTINUE:
684 vfs_print_message ("%s", _ ("ftpfs: sending user password"));
685 code = ftpfs_command (me, super, WAIT_REPLY, "PASS %s", pass);
686 if (code == CONTINUE)
687 {
688 char *p;
689
690 p = g_strdup_printf (_ ("FTP: Account required for user %s"),
691 super->path_element->user);
692 op = input_dialog (p, _ ("Account:"), MC_HISTORY_FTPFS_ACCOUNT, "",
693 INPUT_COMPLETE_USERNAMES);
694 g_free (p);
695 if (op == NULL)
696 ERRNOR (EPERM, 0);
697 vfs_print_message ("%s", _ ("ftpfs: sending user account"));
698 code = ftpfs_command (me, super, WAIT_REPLY, "ACCT %s", op);
699 g_free (op);
700 }
701 if (code != COMPLETE)
702 break;
703
704 MC_FALLTHROUGH;
705
706 case COMPLETE:
707 vfs_print_message ("%s", _ ("ftpfs: logged in"));
708 wipe_password (pass);
709 g_free (name);
710 return TRUE;
711
712 default:
713 ftp_super->failed_on_login = TRUE;
714 wipe_password (super->path_element->password);
715 super->path_element->password = NULL;
716 goto login_fail;
717 }
718 }
719
720 message (D_ERROR, MSG_ERROR, _ ("ftpfs: Login incorrect for user %s "),
721 super->path_element->user);
722
723 login_fail:
724 wipe_password (pass);
725 g_free (name);
726 ERRNOR (EPERM, FALSE);
727 }
728
729
730
731 static void
732 ftpfs_load_no_proxy_list (void)
733 {
734
735 char *mc_file;
736
737 mc_file = g_build_filename (mc_global.sysconfig_dir, "mc.no_proxy", (char *) NULL);
738 if (exist_file (mc_file))
739 {
740 FILE *npf;
741
742 npf = fopen (mc_file, "r");
743 if (npf != NULL)
744 {
745 char s[BUF_LARGE];
746
747 while (fgets (s, sizeof (s), npf) != NULL)
748 {
749 char *p;
750
751 p = strchr (s, '\n');
752 if (p == NULL)
753 {
754 int c;
755
756 while ((c = fgetc (npf)) != EOF && c != '\n')
757 ;
758 }
759 else if (p != s)
760 {
761 *p = '\0';
762 no_proxy = g_slist_prepend (no_proxy, g_strdup (s));
763 }
764 }
765
766 fclose (npf);
767 }
768 }
769
770 g_free (mc_file);
771 }
772
773
774
775
776 static gboolean
777 ftpfs_check_proxy (const char *host)
778 {
779
780 if (ftpfs_proxy_host == NULL || *ftpfs_proxy_host == '\0' || host == NULL || *host == '\0')
781 return FALSE;
782
783 if (*host == '!')
784 return TRUE;
785
786 if (!ftpfs_always_use_proxy)
787 return FALSE;
788
789 if (strchr (host, '.') == NULL)
790 return FALSE;
791
792 if (no_proxy == NULL)
793 {
794 GSList *npe;
795
796 ftpfs_load_no_proxy_list ();
797
798 for (npe = no_proxy; npe != NULL; npe = g_slist_next (npe))
799 {
800 const char *domain = (const char *) npe->data;
801
802 if (domain[0] == '.')
803 {
804 size_t ld, lh;
805
806 ld = strlen (domain);
807 lh = strlen (host);
808
809 while (ld != 0 && lh != 0 && host[lh - 1] == domain[ld - 1])
810 {
811 ld--;
812 lh--;
813 }
814
815 if (ld == 0)
816 return FALSE;
817 }
818 else if (g_ascii_strcasecmp (host, domain) == 0)
819 return FALSE;
820 }
821 }
822
823 return TRUE;
824 }
825
826
827
828 static void
829 ftpfs_get_proxy_host_and_port (const char *proxy, char **host, int *port)
830 {
831 vfs_path_element_t *path_element;
832
833 path_element = vfs_url_split (proxy, FTP_COMMAND_PORT, URL_USE_ANONYMOUS);
834 *host = path_element->host;
835 path_element->host = NULL;
836 *port = path_element->port;
837 vfs_path_element_free (path_element);
838 }
839
840
841
842 static int
843 ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super)
844 {
845 struct addrinfo hints, *res, *curr_res;
846 int my_socket = 0;
847 char *host = NULL;
848 char port[8];
849 int tmp_port = 0;
850 int e;
851
852 (void) me;
853
854 if (super->path_element->host == NULL || *super->path_element->host == '\0')
855 {
856 vfs_print_message ("%s", _ ("ftpfs: Invalid host name."));
857 me->verrno = EINVAL;
858 return (-1);
859 }
860
861
862
863 if (FTP_SUPER (super)->proxy != NULL)
864 ftpfs_get_proxy_host_and_port (ftpfs_proxy_host, &host, &tmp_port);
865 else
866 {
867 host = g_strdup (super->path_element->host);
868 tmp_port = super->path_element->port;
869 }
870
871 g_snprintf (port, sizeof (port), "%hu", (unsigned short) tmp_port);
872
873 tty_enable_interrupt_key ();
874
875 memset (&hints, 0, sizeof (hints));
876 hints.ai_family = AF_UNSPEC;
877 hints.ai_socktype = SOCK_STREAM;
878
879 #ifdef AI_ADDRCONFIG
880
881
882
883 hints.ai_flags = AI_ADDRCONFIG;
884 #endif
885
886 e = getaddrinfo (host, port, &hints, &res);
887
888 #ifdef AI_ADDRCONFIG
889 if (e == EAI_BADFLAGS)
890 {
891
892 hints.ai_flags = 0;
893 e = getaddrinfo (host, port, &hints, &res);
894 }
895 #endif
896
897 *port = '\0';
898
899 if (e != 0)
900 {
901 tty_disable_interrupt_key ();
902 vfs_print_message (_ ("ftpfs: %s"), gai_strerror (e));
903 g_free (host);
904 me->verrno = EINVAL;
905 return (-1);
906 }
907
908 for (curr_res = res; curr_res != NULL; curr_res = curr_res->ai_next)
909 {
910 my_socket = socket (curr_res->ai_family, curr_res->ai_socktype, curr_res->ai_protocol);
911
912 if (my_socket < 0)
913 {
914 if (curr_res->ai_next != NULL)
915 continue;
916
917 tty_disable_interrupt_key ();
918 vfs_print_message (_ ("ftpfs: %s"), unix_error_string (errno));
919 g_free (host);
920 freeaddrinfo (res);
921 me->verrno = errno;
922 return (-1);
923 }
924
925 vfs_print_message (_ ("ftpfs: making connection to %s"), host);
926 MC_PTR_FREE (host);
927
928 if (connect (my_socket, curr_res->ai_addr, curr_res->ai_addrlen) >= 0)
929 break;
930
931 me->verrno = errno;
932 close (my_socket);
933
934 if (me->verrno == EINTR && tty_got_interrupt ())
935 vfs_print_message ("%s", _ ("ftpfs: connection interrupted by user"));
936 else if (res->ai_next == NULL)
937 vfs_print_message (_ ("ftpfs: connection to server failed: %s"),
938 unix_error_string (errno));
939 else
940 continue;
941
942 freeaddrinfo (res);
943 tty_disable_interrupt_key ();
944 return (-1);
945 }
946
947 freeaddrinfo (res);
948 tty_disable_interrupt_key ();
949 return my_socket;
950 }
951
952
953
954 static int
955 ftpfs_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
956 {
957 ftp_super_t *ftp_super = FTP_SUPER (super);
958 int retry_seconds = 0;
959
960
961 if (ftp_super->proxy != NULL)
962 ftp_super->use_passive_connection = ftpfs_use_passive_connections_over_proxy;
963
964 do
965 {
966 ftp_super->failed_on_login = FALSE;
967
968 ftp_super->sock = ftpfs_open_socket (me, super);
969 if (ftp_super->sock == -1)
970 return (-1);
971
972 if (ftpfs_login_server (me, super, NULL))
973 {
974
975 break;
976 }
977
978 if (!ftp_super->failed_on_login)
979 return (-1);
980
981
982 close (ftp_super->sock);
983
984 if (ftpfs_retry_seconds != 0)
985 {
986 int count_down;
987
988 retry_seconds = ftpfs_retry_seconds;
989 tty_enable_interrupt_key ();
990 for (count_down = retry_seconds; count_down != 0; count_down--)
991 {
992 vfs_print_message (_ ("Waiting to retry... %d (Control-G to cancel)"), count_down);
993 sleep (1);
994 if (tty_got_interrupt ())
995 {
996
997 tty_disable_interrupt_key ();
998 return 0;
999 }
1000 }
1001 tty_disable_interrupt_key ();
1002 }
1003 }
1004 while (retry_seconds != 0);
1005
1006 ftp_super->current_dir = ftpfs_get_current_directory (me, super);
1007 if (ftp_super->current_dir == NULL)
1008 ftp_super->current_dir = g_strdup (PATH_SEP_STR);
1009
1010 return 0;
1011 }
1012
1013
1014
1015 static int
1016 ftpfs_open_archive (struct vfs_s_super *super, const vfs_path_t *vpath,
1017 const vfs_path_element_t *vpath_element)
1018 {
1019 (void) vpath;
1020
1021 super->path_element = ftpfs_correct_url_parameters (vpath_element);
1022 if (ftpfs_check_proxy (super->path_element->host))
1023 FTP_SUPER (super)->proxy = ftpfs_proxy_host;
1024 super->root =
1025 vfs_s_new_inode (vpath_element->class, super, ftpfs_default_stat (vpath_element->class));
1026
1027 return ftpfs_open_archive_int (vpath_element->class, super);
1028 }
1029
1030
1031
1032 static int
1033 ftpfs_archive_same (const vfs_path_element_t *vpath_element, struct vfs_s_super *super,
1034 const vfs_path_t *vpath, void *cookie)
1035 {
1036 vfs_path_element_t *path_element;
1037 int result;
1038
1039 (void) vpath;
1040 (void) cookie;
1041
1042 path_element = ftpfs_correct_url_parameters (vpath_element);
1043
1044 result = ((strcmp (path_element->host, super->path_element->host) == 0)
1045 && (strcmp (path_element->user, super->path_element->user) == 0)
1046 && (path_element->port == super->path_element->port))
1047 ? 1
1048 : 0;
1049
1050 vfs_path_element_free (path_element);
1051 return result;
1052 }
1053
1054
1055
1056
1057 static char *
1058 ftpfs_get_current_directory (struct vfs_class *me, struct vfs_s_super *super)
1059 {
1060 char buf[MC_MAXPATHLEN + 1];
1061
1062 if (ftpfs_command (me, super, NONE, "%s", "PWD") == COMPLETE
1063 && ftpfs_get_reply (me, FTP_SUPER (super)->sock, buf, sizeof (buf)) == COMPLETE)
1064 {
1065 char *bufp = NULL;
1066 char *bufq;
1067
1068 for (bufq = buf; *bufq != '\0'; bufq++)
1069 if (*bufq == '"')
1070 {
1071 if (bufp == NULL)
1072 bufp = bufq + 1;
1073 else
1074 {
1075 *bufq = '\0';
1076
1077 if (*bufp != '\0')
1078 {
1079 if (!IS_PATH_SEP (bufq[-1]))
1080 {
1081 *bufq++ = PATH_SEP;
1082 *bufq = '\0';
1083 }
1084
1085 if (IS_PATH_SEP (*bufp))
1086 return g_strdup (bufp);
1087
1088
1089
1090
1091 return g_strconcat (PATH_SEP_STR, bufp, (char *) NULL);
1092 }
1093
1094 break;
1095 }
1096 }
1097 }
1098
1099 me->verrno = EIO;
1100 return NULL;
1101 }
1102
1103
1104
1105
1106 static gboolean
1107 ftpfs_setup_passive_pasv (struct vfs_class *me, struct vfs_s_super *super, int my_socket,
1108 struct sockaddr_storage *sa, socklen_t *salen)
1109 {
1110 char *c;
1111 char n[6];
1112 int xa, xb, xc, xd, xe, xf;
1113
1114 if (ftpfs_command (me, super, WAIT_REPLY | WANT_STRING, "%s", "PASV") != COMPLETE)
1115 return FALSE;
1116
1117
1118 for (c = reply_str + 4; *c != '\0' && !isdigit ((unsigned char) *c); c++)
1119 ;
1120
1121 if (*c == '\0' || !isdigit ((unsigned char) *c))
1122 return FALSE;
1123
1124 if (sscanf (c, "%d,%d,%d,%d,%d,%d", &xa, &xb, &xc, &xd, &xe, &xf) != 6)
1125 return FALSE;
1126
1127 n[0] = (unsigned char) xa;
1128 n[1] = (unsigned char) xb;
1129 n[2] = (unsigned char) xc;
1130 n[3] = (unsigned char) xd;
1131 n[4] = (unsigned char) xe;
1132 n[5] = (unsigned char) xf;
1133
1134 memcpy (&(((struct sockaddr_in *) sa)->sin_addr.s_addr), (void *) n, 4);
1135 memcpy (&(((struct sockaddr_in *) sa)->sin_port), (void *) &n[4], 2);
1136
1137 return (connect (my_socket, (struct sockaddr *) sa, *salen) >= 0);
1138 }
1139
1140
1141
1142
1143 static gboolean
1144 ftpfs_setup_passive_epsv (struct vfs_class *me, struct vfs_s_super *super, int my_socket,
1145 struct sockaddr_storage *sa, socklen_t *salen)
1146 {
1147 char *c;
1148 int port;
1149
1150 if (ftpfs_command (me, super, WAIT_REPLY | WANT_STRING, "%s", "EPSV") != COMPLETE)
1151 return FALSE;
1152
1153
1154 c = strchr (reply_str, '|');
1155 if (c == NULL || strlen (c) <= 3)
1156 return FALSE;
1157
1158 c += 3;
1159 port = atoi (c);
1160 if (port < 0 || port > 65535)
1161 return FALSE;
1162
1163 port = htons (port);
1164
1165 switch (sa->ss_family)
1166 {
1167 case AF_INET:
1168 ((struct sockaddr_in *) sa)->sin_port = port;
1169 break;
1170 case AF_INET6:
1171 ((struct sockaddr_in6 *) sa)->sin6_port = port;
1172 break;
1173 default:
1174 break;
1175 }
1176
1177 return (connect (my_socket, (struct sockaddr *) sa, *salen) >= 0);
1178 }
1179
1180
1181
1182
1183 static gboolean
1184 ftpfs_setup_passive (struct vfs_class *me, struct vfs_s_super *super, int my_socket,
1185 struct sockaddr_storage *sa, socklen_t *salen)
1186 {
1187
1188 if (sa->ss_family == AF_INET)
1189 {
1190 if (!ftpfs_setup_passive_pasv (me, super, my_socket, sa, salen))
1191
1192 if (!ftpfs_setup_passive_epsv (me, super, my_socket, sa, salen))
1193 return FALSE;
1194 }
1195
1196 else if (!ftpfs_setup_passive_epsv (me, super, my_socket, sa, salen))
1197 return FALSE;
1198
1199 return TRUE;
1200 }
1201
1202
1203
1204
1205 static int
1206 ftpfs_setup_active (struct vfs_class *me, struct vfs_s_super *super,
1207 struct sockaddr_storage data_addr, socklen_t data_addrlen)
1208 {
1209 unsigned short int port;
1210 char *addr;
1211 unsigned int af;
1212 int res;
1213
1214 switch (data_addr.ss_family)
1215 {
1216 case AF_INET:
1217 af = FTP_INET;
1218 port = ((struct sockaddr_in *) &data_addr)->sin_port;
1219 break;
1220 case AF_INET6:
1221 af = FTP_INET6;
1222 port = ((struct sockaddr_in6 *) &data_addr)->sin6_port;
1223 break;
1224 default:
1225
1226 return 0;
1227 }
1228
1229 addr = g_try_malloc (NI_MAXHOST);
1230 if (addr == NULL)
1231 ERRNOR (ENOMEM, -1);
1232
1233 res = getnameinfo ((struct sockaddr *) &data_addr, data_addrlen, addr, NI_MAXHOST, NULL, 0,
1234 NI_NUMERICHOST);
1235 if (res != 0)
1236 {
1237 const char *err_str;
1238
1239 g_free (addr);
1240
1241 if (res == EAI_SYSTEM)
1242 {
1243 me->verrno = errno;
1244 err_str = unix_error_string (me->verrno);
1245 }
1246 else
1247 {
1248 me->verrno = EIO;
1249 err_str = gai_strerror (res);
1250 }
1251
1252 vfs_print_message (_ ("ftpfs: could not make address-to-name translation: %s"), err_str);
1253
1254 return (-1);
1255 }
1256
1257
1258 if (af == FTP_INET)
1259 {
1260 unsigned char *a = (unsigned char *) &((struct sockaddr_in *) &data_addr)->sin_addr;
1261 unsigned char *p = (unsigned char *) &port;
1262
1263 if (ftpfs_command (me, super, WAIT_REPLY, "PORT %u,%u,%u,%u,%u,%u", a[0], a[1], a[2], a[3],
1264 p[0], p[1])
1265 == COMPLETE)
1266 {
1267 g_free (addr);
1268 return 1;
1269 }
1270 }
1271
1272
1273
1274
1275
1276
1277
1278 port = ntohs (port);
1279
1280
1281 res = (ftpfs_command (me, super, WAIT_REPLY, "EPRT |%u|%s|%hu|", af, addr, port) == COMPLETE)
1282 ? 1
1283 : 0;
1284 g_free (addr);
1285 return res;
1286 }
1287
1288
1289
1290
1291 static int
1292 ftpfs_init_data_socket (struct vfs_class *me, struct vfs_s_super *super,
1293 struct sockaddr_storage *data_addr, socklen_t *data_addrlen)
1294 {
1295 const unsigned int attempts = 10;
1296 unsigned int i;
1297 ftp_super_t *ftp_super = FTP_SUPER (super);
1298 int result;
1299
1300 for (i = 0; i < attempts; i++)
1301 {
1302 memset (data_addr, 0, sizeof (*data_addr));
1303 *data_addrlen = sizeof (*data_addr);
1304
1305 if (ftp_super->use_passive_connection)
1306 {
1307 result = getpeername (ftp_super->sock, (struct sockaddr *) data_addr, data_addrlen);
1308 if (result == 0)
1309 break;
1310
1311 me->verrno = errno;
1312
1313 if (me->verrno == ENOTCONN)
1314 {
1315 vfs_print_message (_ ("ftpfs: try reconnect to server, attempt %u"), i);
1316 if (ftpfs_reconnect (me, super))
1317 continue;
1318 }
1319 else
1320 {
1321
1322 vfs_print_message (_ ("ftpfs: could not get socket name: %s"),
1323 unix_error_string (me->verrno));
1324 }
1325 }
1326 else
1327 {
1328 result = getsockname (ftp_super->sock, (struct sockaddr *) data_addr, data_addrlen);
1329 if (result == 0)
1330 break;
1331
1332 me->verrno = errno;
1333
1334 vfs_print_message (_ ("ftpfs: try reconnect to server, attempt %u"), i);
1335 if (ftpfs_reconnect (me, super))
1336 continue;
1337
1338
1339 vfs_print_message ("%s", _ ("ftpfs: could not reconnect to server"));
1340 }
1341
1342 i = attempts;
1343 }
1344
1345 if (i >= attempts)
1346 return (-1);
1347
1348 switch (data_addr->ss_family)
1349 {
1350 case AF_INET:
1351 ((struct sockaddr_in *) data_addr)->sin_port = 0;
1352 break;
1353 case AF_INET6:
1354 ((struct sockaddr_in6 *) data_addr)->sin6_port = 0;
1355 break;
1356 default:
1357 vfs_print_message ("%s", _ ("ftpfs: invalid address family"));
1358 ERRNOR (EINVAL, -1);
1359 }
1360
1361 result = socket (data_addr->ss_family, SOCK_STREAM, IPPROTO_TCP);
1362 if (result < 0)
1363 {
1364 me->verrno = errno;
1365 vfs_print_message (_ ("ftpfs: could not create socket: %s"),
1366 unix_error_string (me->verrno));
1367 result = -1;
1368 }
1369
1370 return result;
1371 }
1372
1373
1374
1375
1376 static int
1377 ftpfs_initconn (struct vfs_class *me, struct vfs_s_super *super)
1378 {
1379 ftp_super_t *ftp_super = FTP_SUPER (super);
1380 struct sockaddr_storage data_addr;
1381 socklen_t data_addrlen;
1382
1383
1384
1385
1386
1387
1388
1389
1390 if (ftp_super->use_passive_connection)
1391 {
1392 int data_sock;
1393
1394 data_sock = ftpfs_init_data_socket (me, super, &data_addr, &data_addrlen);
1395 if (data_sock < 0)
1396 return (-1);
1397
1398 if (ftpfs_setup_passive (me, super, data_sock, &data_addr, &data_addrlen))
1399 return data_sock;
1400
1401 vfs_print_message ("%s", _ ("ftpfs: could not setup passive mode"));
1402 ftp_super->use_passive_connection = FALSE;
1403
1404 close (data_sock);
1405 }
1406
1407
1408 if (!ftp_super->use_passive_connection)
1409 {
1410 int data_sock;
1411
1412 data_sock = ftpfs_init_data_socket (me, super, &data_addr, &data_addrlen);
1413 if (data_sock < 0)
1414 return (-1);
1415
1416 if ((bind (data_sock, (struct sockaddr *) &data_addr, data_addrlen) != 0)
1417 || (getsockname (data_sock, (struct sockaddr *) &data_addr, &data_addrlen) != 0)
1418 || (listen (data_sock, 1) != 0))
1419 {
1420 close (data_sock);
1421 ERRNOR (errno, -1);
1422 }
1423
1424 if (ftpfs_setup_active (me, super, data_addr, data_addrlen) != 0)
1425 return data_sock;
1426
1427 close (data_sock);
1428 }
1429
1430
1431 ftp_super->use_passive_connection = ftp_super->proxy != NULL
1432 ? ftpfs_use_passive_connections_over_proxy
1433 : ftpfs_use_passive_connections;
1434
1435 me->verrno = EIO;
1436 return (-1);
1437 }
1438
1439
1440
1441 static int
1442 ftpfs_open_data_connection (struct vfs_class *me, struct vfs_s_super *super, const char *cmd,
1443 const char *remote, int isbinary, int reget)
1444 {
1445 ftp_super_t *ftp_super = FTP_SUPER (super);
1446 int s, j, data;
1447
1448
1449 if (ftp_super->ctl_connection_busy)
1450 return (-1);
1451
1452 s = ftpfs_initconn (me, super);
1453 if (s == -1)
1454 return (-1);
1455
1456 if (ftpfs_changetype (me, super, isbinary) == -1)
1457 {
1458 close (s);
1459 return (-1);
1460 }
1461
1462 if (reget > 0)
1463 {
1464 j = ftpfs_command (me, super, WAIT_REPLY, "REST %d", reget);
1465 if (j != CONTINUE)
1466 {
1467 close (s);
1468 ERRNOR (EIO, -1);
1469 }
1470 }
1471
1472 if (remote == NULL)
1473 j = ftpfs_command (me, super, WAIT_REPLY, "%s", cmd);
1474 else
1475 {
1476 char *remote_path;
1477
1478 remote_path = ftpfs_translate_path (me, super, remote);
1479 j = ftpfs_command (me, super, WAIT_REPLY, "%s /%s", cmd,
1480
1481 IS_PATH_SEP (*remote_path) ? remote_path + 1 : remote_path);
1482 g_free (remote_path);
1483 }
1484
1485 if (j != PRELIM)
1486 {
1487 close (s);
1488 ERRNOR (EPERM, -1);
1489 }
1490
1491 if (ftp_super->use_passive_connection)
1492 data = s;
1493 else
1494 {
1495 struct sockaddr_storage from;
1496 socklen_t fromlen = sizeof (from);
1497
1498 tty_enable_interrupt_key ();
1499 data = accept (s, (struct sockaddr *) &from, &fromlen);
1500 if (data < 0)
1501 me->verrno = errno;
1502 tty_disable_interrupt_key ();
1503 close (s);
1504 if (data < 0)
1505 return (-1);
1506 }
1507
1508 ftp_super->ctl_connection_busy = TRUE;
1509 return data;
1510 }
1511
1512
1513
1514 static void
1515 ftpfs_linear_abort (struct vfs_class *me, vfs_file_handler_t *fh)
1516 {
1517 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
1518 ftp_super_t *ftp_super = FTP_SUPER (super);
1519 static unsigned char const ipbuf[3] = { IAC, IP, IAC };
1520 fd_set mask;
1521 int dsock = FH_SOCK;
1522
1523 FH_SOCK = -1;
1524 ftp_super->ctl_connection_busy = FALSE;
1525
1526 vfs_print_message ("%s", _ ("ftpfs: aborting transfer."));
1527
1528 if (send (ftp_super->sock, ipbuf, sizeof (ipbuf), MSG_OOB) != sizeof (ipbuf))
1529 {
1530 vfs_print_message (_ ("ftpfs: abort error: %s"), unix_error_string (errno));
1531 if (dsock != -1)
1532 close (dsock);
1533 return;
1534 }
1535
1536 if (ftpfs_command (me, super, NONE, "%cABOR", DM) != COMPLETE)
1537 {
1538 vfs_print_message ("%s", _ ("ftpfs: abort failed"));
1539 if (dsock != -1)
1540 close (dsock);
1541 return;
1542 }
1543
1544 if (dsock != -1)
1545 {
1546 FD_ZERO (&mask);
1547 FD_SET (dsock, &mask);
1548
1549 if (select (dsock + 1, &mask, NULL, NULL, NULL) > 0)
1550 {
1551 gint64 start_tim;
1552 char buf[BUF_8K];
1553
1554 start_tim = g_get_monotonic_time ();
1555
1556
1557 while (read (dsock, buf, sizeof (buf)) > 0)
1558 {
1559 gint64 tim;
1560
1561 tim = g_get_monotonic_time ();
1562
1563 if (tim > start_tim + ABORT_TIMEOUT)
1564 {
1565
1566 close (dsock);
1567 ftpfs_reconnect (me, super);
1568 return;
1569 }
1570 }
1571 }
1572 close (dsock);
1573 }
1574
1575 if ((ftpfs_get_reply (me, ftp_super->sock, NULL, 0) == TRANSIENT) && (code == 426))
1576 ftpfs_get_reply (me, ftp_super->sock, NULL, 0);
1577 }
1578
1579
1580
1581 #if 0
1582 static void
1583 resolve_symlink_without_ls_options (struct vfs_class *me, struct vfs_s_super *super,
1584 struct vfs_s_inode *dir)
1585 {
1586 struct linklist *flist;
1587 struct direntry *fe, *fel;
1588 char tmp[MC_MAXPATHLEN];
1589
1590 dir->symlink_status = FTPFS_RESOLVING_SYMLINKS;
1591 for (flist = dir->file_list->next; flist != dir->file_list; flist = flist->next)
1592 {
1593
1594 fel = flist->data;
1595 if (S_ISLNK (fel->s.st_mode) && fel->linkname != NULL)
1596 {
1597 int depth;
1598
1599 if (IS_PATH_SEP (fel->linkname[0]))
1600 {
1601 if (strlen (fel->linkname) >= MC_MAXPATHLEN)
1602 continue;
1603 strcpy (tmp, fel->linkname);
1604 }
1605 else
1606 {
1607 if ((strlen (dir->remote_path) + strlen (fel->linkname)) >= MC_MAXPATHLEN)
1608 continue;
1609 strcpy (tmp, dir->remote_path);
1610 if (tmp[1] != '\0')
1611 strcat (tmp, PATH_SEP_STR);
1612 strcat (tmp + 1, fel->linkname);
1613 }
1614
1615 for (depth = 0; depth < 100; depth++)
1616 {
1617 canonicalize_pathname (tmp);
1618 fe = _get_file_entry_t (bucket, tmp, 0, 0);
1619 if (fe != NULL)
1620 {
1621 if (S_ISLNK (fe->s.st_mode) && fe->l_stat == 0)
1622 {
1623
1624 if (IS_PATH_SEP (fe->linkname[0]))
1625 {
1626 if (strlen (fe->linkname) >= MC_MAXPATHLEN)
1627 break;
1628 strcpy (tmp, fe->linkname);
1629 }
1630 else
1631 {
1632
1633
1634
1635 *(strrchr (tmp, PATH_SEP) + 1) = '\0';
1636 if ((strlen (tmp) + strlen (fe->linkname)) >= MC_MAXPATHLEN)
1637 break;
1638 strcat (tmp, fe->linkname);
1639 }
1640 continue;
1641 }
1642 else
1643 {
1644 fel->l_stat = g_new (struct stat, 1);
1645 if (S_ISLNK (fe->s.st_mode))
1646 *fel->l_stat = *fe->l_stat;
1647 else
1648 *fel->l_stat = fe->s;
1649 (*fel->l_stat).st_ino = bucket->__inode_counter++;
1650 }
1651 }
1652 break;
1653 }
1654 }
1655 }
1656
1657 dir->symlink_status = FTPFS_RESOLVED_SYMLINKS;
1658 }
1659
1660
1661
1662 static void
1663 resolve_symlink_with_ls_options (struct vfs_class *me, struct vfs_s_super *super,
1664 struct vfs_s_inode *dir)
1665 {
1666 char buffer[BUF_2K] = "";
1667 char *filename;
1668 int sock;
1669 FILE *fp;
1670 struct stat s;
1671 struct linklist *flist;
1672 struct direntry *fe;
1673 int switch_method = 0;
1674
1675 dir->symlink_status = FTPFS_RESOLVED_SYMLINKS;
1676 if (strchr (dir->remote_path, ' ') == NULL)
1677 sock = ftpfs_open_data_connection (bucket, "LIST -lLa", dir->remote_path, TYPE_ASCII, 0);
1678 else
1679 {
1680 if (ftpfs_chdir_internal (bucket, dir->remote_path) != COMPLETE)
1681 {
1682 vfs_print_message ("%s", _("ftpfs: CWD failed."));
1683 return;
1684 }
1685
1686 sock = ftpfs_open_data_connection (bucket, "LIST -lLa", ".", TYPE_ASCII, 0);
1687 }
1688
1689 if (sock == -1)
1690 {
1691 vfs_print_message ("%s", _("ftpfs: couldn't resolve symlink"));
1692 return;
1693 }
1694
1695 fp = fdopen (sock, "r");
1696 if (fp == NULL)
1697 {
1698 close (sock);
1699 vfs_print_message ("%s", _("ftpfs: couldn't resolve symlink"));
1700 return;
1701 }
1702 tty_enable_interrupt_key ();
1703 flist = dir->file_list->next;
1704
1705 while (TRUE)
1706 {
1707 do
1708 {
1709 if (flist == dir->file_list)
1710 goto done;
1711
1712 fe = flist->data;
1713 flist = flist->next;
1714 }
1715 while (!S_ISLNK (fe->s.st_mode));
1716
1717 while (TRUE)
1718 {
1719 if (fgets (buffer, sizeof (buffer), fp) == NULL)
1720 goto done;
1721
1722 if (me->logfile != NULL)
1723 {
1724 fputs (buffer, me->logfile);
1725 fflush (me->logfile);
1726 }
1727
1728 vfs_die ("This code should be commented out\n");
1729
1730 if (vfs_parse_ls_lga (buffer, &s, &filename, NULL))
1731 {
1732 int r;
1733
1734 r = strcmp (fe->name, filename);
1735 g_free (filename);
1736 if (r == 0)
1737 {
1738 if (S_ISLNK (s.st_mode))
1739 {
1740
1741 switch_method = 1;
1742 goto done;
1743 }
1744
1745 fe->l_stat = g_try_new (struct stat, 1);
1746 if (fe->l_stat == NULL)
1747 goto done;
1748
1749 *fe->l_stat = s;
1750 (*fe->l_stat).st_ino = bucket->__inode_counter++;
1751 break;
1752 }
1753
1754 if (r < 0)
1755 break;
1756 }
1757 }
1758 }
1759
1760 done:
1761 while (fgets (buffer, sizeof (buffer), fp) != NULL)
1762 ;
1763 tty_disable_interrupt_key ();
1764 fclose (fp);
1765 ftpfs_get_reply (me, FTP_SUPER (super)->sock, NULL, 0);
1766 }
1767
1768
1769
1770 static void
1771 resolve_symlink (struct vfs_class *me, struct vfs_s_super *super, struct vfs_s_inode *dir)
1772 {
1773 vfs_print_message ("%s", _("Resolving symlink..."));
1774
1775 if (FTP_SUPER (super)->strict_rfc959_list_cmd)
1776 resolve_symlink_without_ls_options (me, super, dir);
1777 else
1778 resolve_symlink_with_ls_options (me, super, dir);
1779 }
1780 #endif
1781
1782
1783
1784 static int
1785 ftpfs_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, const char *remote_path)
1786 {
1787 struct vfs_s_super *super = dir->super;
1788 ftp_super_t *ftp_super = FTP_SUPER (super);
1789 int sock;
1790 char lc_buffer[BUF_8K];
1791 int res;
1792 gboolean cd_first;
1793 GSList *dirlist = NULL;
1794 GSList *entlist;
1795 GSList *iter;
1796 int err_count = 0;
1797
1798 cd_first = ftpfs_first_cd_then_ls || (ftp_super->strict == RFC_STRICT)
1799 || (strchr (remote_path, ' ') != NULL);
1800
1801 again:
1802 vfs_print_message (_ ("ftpfs: Reading FTP directory %s... %s%s"), remote_path,
1803 ftp_super->strict == RFC_STRICT ? _ ("(strict rfc959)") : "",
1804 cd_first ? _ ("(chdir first)") : "");
1805
1806 if (cd_first && ftpfs_chdir_internal (me, super, remote_path) != COMPLETE)
1807 {
1808 me->verrno = ENOENT;
1809 vfs_print_message ("%s", _ ("ftpfs: CWD failed."));
1810 return (-1);
1811 }
1812
1813 dir->timestamp = g_get_monotonic_time () + ftpfs_directory_timeout * G_USEC_PER_SEC;
1814
1815 if (ftp_super->strict == RFC_STRICT)
1816 sock = ftpfs_open_data_connection (me, super, "LIST", 0, TYPE_ASCII, 0);
1817 else if (cd_first)
1818
1819
1820 sock = ftpfs_open_data_connection (me, super, "LIST -la", 0, TYPE_ASCII, 0);
1821 else
1822 {
1823 char *path;
1824
1825
1826 path = g_strconcat (remote_path, PATH_SEP_STR ".", (char *) NULL);
1827 sock = ftpfs_open_data_connection (me, super, "LIST -la", path, TYPE_ASCII, 0);
1828 g_free (path);
1829 }
1830
1831 if (sock == -1)
1832 {
1833 fallback:
1834 if (ftp_super->strict == RFC_AUTODETECT)
1835 {
1836
1837
1838 ftp_super->strict = RFC_STRICT;
1839
1840
1841 cd_first = TRUE;
1842 goto again;
1843 }
1844
1845 vfs_print_message ("%s", _ ("ftpfs: failed; nowhere to fallback to"));
1846 ERRNOR (EACCES, -1);
1847 }
1848
1849
1850 while ((res = vfs_s_get_line_interruptible (me, lc_buffer, sizeof (lc_buffer), sock)) != 0)
1851 {
1852 if (res == EINTR)
1853 {
1854 me->verrno = ECONNRESET;
1855 close (sock);
1856 ftp_super->ctl_connection_busy = FALSE;
1857 ftpfs_get_reply (me, ftp_super->sock, NULL, 0);
1858 g_slist_free_full (dirlist, g_free);
1859 vfs_print_message (_ ("%s: failure"), me->name);
1860 return (-1);
1861 }
1862
1863 if (me->logfile != NULL)
1864 {
1865 fputs (lc_buffer, me->logfile);
1866 fputs ("\n", me->logfile);
1867 fflush (me->logfile);
1868 }
1869
1870 dirlist = g_slist_prepend (dirlist, g_strdup (lc_buffer));
1871 }
1872
1873 close (sock);
1874 ftp_super->ctl_connection_busy = FALSE;
1875 me->verrno = E_REMOTE;
1876 if ((ftpfs_get_reply (me, ftp_super->sock, NULL, 0) != COMPLETE))
1877 {
1878 g_slist_free_full (dirlist, g_free);
1879 goto fallback;
1880 }
1881
1882 if (dirlist == NULL && !cd_first)
1883 {
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894 cd_first = TRUE;
1895 goto again;
1896 }
1897
1898
1899 dirlist = g_slist_reverse (dirlist);
1900 entlist = ftpfs_parse_long_list (me, dir, dirlist, &err_count);
1901 g_slist_free_full (dirlist, g_free);
1902
1903 for (iter = entlist; iter != NULL; iter = g_slist_next (iter))
1904 vfs_s_insert_entry (me, dir, VFS_ENTRY (iter->data));
1905
1906 g_slist_free (entlist);
1907
1908 if (ftp_super->strict == RFC_AUTODETECT)
1909 ftp_super->strict = RFC_DARING;
1910
1911 vfs_print_message (_ ("%s: done."), me->name);
1912 return 0;
1913 }
1914
1915
1916
1917 static int
1918 ftpfs_file_store (struct vfs_class *me, vfs_file_handler_t *fh, char *name, char *localname)
1919 {
1920 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
1921 ftp_super_t *ftp_super = FTP_SUPER (super);
1922 ftp_file_handler_t *ftp = FTP_FILE_HANDLER (fh);
1923
1924 int h, sock;
1925 off_t n_stored = 0;
1926 #ifdef HAVE_STRUCT_LINGER_L_LINGER
1927 struct linger li;
1928 #else
1929 int flag_one = 1;
1930 #endif
1931 char lc_buffer[BUF_8K];
1932 struct stat s;
1933 char *w_buf;
1934
1935 h = open (localname, O_RDONLY);
1936 if (h == -1)
1937 ERRNOR (EIO, -1);
1938
1939 if (fstat (h, &s) == -1)
1940 {
1941 me->verrno = errno;
1942 close (h);
1943 return (-1);
1944 }
1945
1946 sock =
1947 ftpfs_open_data_connection (me, super, ftp->append ? "APPE" : "STOR", name, TYPE_BINARY, 0);
1948 if (sock < 0)
1949 {
1950 close (h);
1951 return (-1);
1952 }
1953 #ifdef HAVE_STRUCT_LINGER_L_LINGER
1954 li.l_onoff = 1;
1955 li.l_linger = 120;
1956 setsockopt (sock, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof (li));
1957 #else
1958 setsockopt (sock, SOL_SOCKET, SO_LINGER, &flag_one, sizeof (flag_one));
1959 #endif
1960
1961 tty_enable_interrupt_key ();
1962 while (TRUE)
1963 {
1964 ssize_t n_read, n_written;
1965
1966 while ((n_read = read (h, lc_buffer, sizeof (lc_buffer))) == -1)
1967 {
1968 if (errno != EINTR)
1969 {
1970 me->verrno = errno;
1971 goto error_return;
1972 }
1973 if (tty_got_interrupt ())
1974 {
1975 me->verrno = EINTR;
1976 goto error_return;
1977 }
1978 }
1979 if (n_read == 0)
1980 break;
1981
1982 n_stored += n_read;
1983 w_buf = lc_buffer;
1984
1985 while ((n_written = write (sock, w_buf, n_read)) != n_read)
1986 {
1987 if (n_written == -1)
1988 {
1989 if (errno == EINTR && !tty_got_interrupt ())
1990 continue;
1991
1992 me->verrno = errno;
1993 goto error_return;
1994 }
1995
1996 w_buf += n_written;
1997 n_read -= n_written;
1998 }
1999
2000 vfs_print_message ("%s: %" PRIuMAX "/%" PRIuMAX, _ ("ftpfs: storing file"),
2001 (uintmax_t) n_stored, (uintmax_t) s.st_size);
2002 }
2003 tty_disable_interrupt_key ();
2004
2005 close (sock);
2006 ftp_super->ctl_connection_busy = FALSE;
2007 close (h);
2008
2009 if (ftpfs_get_reply (me, ftp_super->sock, NULL, 0) != COMPLETE)
2010 ERRNOR (EIO, -1);
2011 return 0;
2012
2013 error_return:
2014 tty_disable_interrupt_key ();
2015 close (sock);
2016 ftp_super->ctl_connection_busy = FALSE;
2017 close (h);
2018
2019 ftpfs_get_reply (me, ftp_super->sock, NULL, 0);
2020 return (-1);
2021 }
2022
2023
2024
2025 static int
2026 ftpfs_linear_start (struct vfs_class *me, vfs_file_handler_t *fh, off_t offset)
2027 {
2028 char *name;
2029
2030 name = vfs_s_fullpath (me, fh->ino);
2031 if (name == NULL)
2032 return 0;
2033
2034 FH_SOCK = ftpfs_open_data_connection (me, VFS_FILE_HANDLER_SUPER (fh), "RETR", name,
2035 TYPE_BINARY, offset);
2036 g_free (name);
2037 if (FH_SOCK == -1)
2038 ERRNOR (EACCES, 0);
2039
2040 fh->linear = LS_LINEAR_OPEN;
2041 FTP_FILE_HANDLER (fh)->append = FALSE;
2042 return 1;
2043 }
2044
2045
2046
2047 static ssize_t
2048 ftpfs_linear_read (struct vfs_class *me, vfs_file_handler_t *fh, void *buf, size_t len)
2049 {
2050 ssize_t n;
2051 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
2052
2053 while ((n = read (FH_SOCK, buf, len)) < 0)
2054 {
2055 if ((errno == EINTR) && !tty_got_interrupt ())
2056 continue;
2057 break;
2058 }
2059
2060 if (n < 0)
2061 ftpfs_linear_abort (me, fh);
2062 else if (n == 0)
2063 {
2064 FTP_SUPER (super)->ctl_connection_busy = FALSE;
2065 close (FH_SOCK);
2066 FH_SOCK = -1;
2067 if ((ftpfs_get_reply (me, FTP_SUPER (super)->sock, NULL, 0) != COMPLETE))
2068 ERRNOR (E_REMOTE, -1);
2069 return 0;
2070 }
2071
2072 ERRNOR (errno, n);
2073 }
2074
2075
2076
2077 static void
2078 ftpfs_linear_close (struct vfs_class *me, vfs_file_handler_t *fh)
2079 {
2080 if (FH_SOCK != -1)
2081 ftpfs_linear_abort (me, fh);
2082 }
2083
2084
2085
2086 static int
2087 ftpfs_ctl (void *fh, int ctlop, void *arg)
2088 {
2089 (void) arg;
2090
2091 switch (ctlop)
2092 {
2093 case VFS_CTL_IS_NOTREADY:
2094 {
2095 vfs_file_handler_t *file = VFS_FILE_HANDLER (fh);
2096 int v;
2097
2098 if (file->linear == LS_NOT_LINEAR)
2099 vfs_die ("You may not do this");
2100 if (file->linear == LS_LINEAR_CLOSED || file->linear == LS_LINEAR_PREOPEN)
2101 return 0;
2102
2103 v = vfs_s_select_on_two (FH_SOCK, 0);
2104 return (((v < 0) && (errno == EINTR)) || v == 0) ? 1 : 0;
2105 }
2106 default:
2107 return 0;
2108 }
2109 }
2110
2111
2112
2113 static int
2114 ftpfs_send_command (const vfs_path_t *vpath, const char *cmd, int flags)
2115 {
2116 const char *rpath;
2117 char *p;
2118 struct vfs_s_super *super;
2119 int r;
2120 struct vfs_class *me;
2121 gboolean flush_directory_cache = (flags & OPT_FLUSH) != 0;
2122
2123 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
2124
2125 rpath = vfs_s_get_path (vpath, &super, 0);
2126 if (rpath == NULL)
2127 return (-1);
2128
2129 p = ftpfs_translate_path (me, super, rpath);
2130 r = ftpfs_command (me, super, WAIT_REPLY, cmd, p);
2131 g_free (p);
2132 vfs_stamp_create (vfs_ftpfs_ops, super);
2133 if ((flags & OPT_IGNORE_ERROR) != 0)
2134 r = COMPLETE;
2135 if (r != COMPLETE)
2136 {
2137 me->verrno = EPERM;
2138 return (-1);
2139 }
2140 if (flush_directory_cache)
2141 vfs_s_invalidate (me, super);
2142 return 0;
2143 }
2144
2145
2146
2147 static int
2148 ftpfs_stat (const vfs_path_t *vpath, struct stat *buf)
2149 {
2150 int ret;
2151
2152 ret = vfs_s_stat (vpath, buf);
2153 ftpfs_set_blksize (buf);
2154 return ret;
2155 }
2156
2157
2158
2159 static int
2160 ftpfs_lstat (const vfs_path_t *vpath, struct stat *buf)
2161 {
2162 int ret;
2163
2164 ret = vfs_s_lstat (vpath, buf);
2165 ftpfs_set_blksize (buf);
2166 return ret;
2167 }
2168
2169
2170
2171 static int
2172 ftpfs_fstat (void *vfs_info, struct stat *buf)
2173 {
2174 int ret;
2175
2176 ret = vfs_s_fstat (vfs_info, buf);
2177 ftpfs_set_blksize (buf);
2178 return ret;
2179 }
2180
2181
2182
2183 static int
2184 ftpfs_chmod (const vfs_path_t *vpath, mode_t mode)
2185 {
2186 char buf[BUF_SMALL];
2187 int ret;
2188
2189 g_snprintf (buf, sizeof (buf), "SITE CHMOD %4.4o /%%s", (unsigned int) (mode & 07777));
2190 ret = ftpfs_send_command (vpath, buf, OPT_FLUSH);
2191 return ftpfs_ignore_chattr_errors ? 0 : ret;
2192 }
2193
2194
2195
2196 static int
2197 ftpfs_chown (const vfs_path_t *vpath, uid_t owner, gid_t group)
2198 {
2199 #if 0
2200 (void) vpath;
2201 (void) owner;
2202 (void) group;
2203
2204 me->verrno = EPERM;
2205 return (-1);
2206 #else
2207
2208
2209 (void) vpath;
2210 (void) owner;
2211 (void) group;
2212 return 0;
2213 #endif
2214 }
2215
2216
2217
2218 static int
2219 ftpfs_unlink (const vfs_path_t *vpath)
2220 {
2221 return ftpfs_send_command (vpath, "DELE /%s", OPT_FLUSH);
2222 }
2223
2224
2225
2226
2227 static gboolean
2228 ftpfs_is_same_dir (struct vfs_class *me, struct vfs_s_super *super, const char *path)
2229 {
2230 (void) me;
2231
2232 return (FTP_SUPER (super)->current_dir != NULL
2233 && strcmp (path, FTP_SUPER (super)->current_dir) == 0);
2234 }
2235
2236
2237
2238 static int
2239 ftpfs_chdir_internal (struct vfs_class *me, struct vfs_s_super *super, const char *remote_path)
2240 {
2241 ftp_super_t *ftp_super = FTP_SUPER (super);
2242 int r;
2243 char *p;
2244
2245 if (!ftp_super->cwd_deferred && ftpfs_is_same_dir (me, super, remote_path))
2246 return COMPLETE;
2247
2248 p = ftpfs_translate_path (me, super, remote_path);
2249 r = ftpfs_command (me, super, WAIT_REPLY, "CWD /%s", p);
2250 g_free (p);
2251
2252 if (r != COMPLETE)
2253 me->verrno = EIO;
2254 else
2255 {
2256 g_free (ftp_super->current_dir);
2257 ftp_super->current_dir = g_strdup (remote_path);
2258 ftp_super->cwd_deferred = FALSE;
2259 }
2260 return r;
2261 }
2262
2263
2264
2265 static int
2266 ftpfs_rename (const vfs_path_t *vpath1, const vfs_path_t *vpath2)
2267 {
2268 ftpfs_send_command (vpath1, "RNFR /%s", OPT_FLUSH);
2269 return ftpfs_send_command (vpath2, "RNTO /%s", OPT_FLUSH);
2270 }
2271
2272
2273
2274 static int
2275 ftpfs_mkdir (const vfs_path_t *vpath, mode_t mode)
2276 {
2277 (void) mode;
2278
2279 return ftpfs_send_command (vpath, "MKD /%s", OPT_FLUSH);
2280 }
2281
2282
2283
2284 static int
2285 ftpfs_rmdir (const vfs_path_t *vpath)
2286 {
2287 return ftpfs_send_command (vpath, "RMD /%s", OPT_FLUSH);
2288 }
2289
2290
2291
2292 static vfs_file_handler_t *
2293 ftpfs_fh_new (struct vfs_s_inode *ino, gboolean changed)
2294 {
2295 ftp_file_handler_t *fh;
2296
2297 fh = g_new0 (ftp_file_handler_t, 1);
2298 vfs_s_init_fh (VFS_FILE_HANDLER (fh), ino, changed);
2299 fh->sock = -1;
2300
2301 return VFS_FILE_HANDLER (fh);
2302 }
2303
2304
2305
2306 static int
2307 ftpfs_fh_open (struct vfs_class *me, vfs_file_handler_t *fh, int flags, mode_t mode)
2308 {
2309 ftp_file_handler_t *ftp = FTP_FILE_HANDLER (fh);
2310
2311 (void) mode;
2312
2313
2314 if (((flags & O_WRONLY) == O_WRONLY) && ((flags & (O_RDONLY | O_RDWR)) == 0))
2315 {
2316 #ifdef HAVE_STRUCT_LINGER_L_LINGER
2317 struct linger li;
2318 #else
2319 int li = 1;
2320 #endif
2321 char *name;
2322
2323
2324
2325
2326
2327 if (FTP_SUPER (VFS_FILE_HANDLER_SUPER (fh))->ctl_connection_busy)
2328 {
2329 if (fh->ino->localname == NULL)
2330 {
2331 vfs_path_t *vpath;
2332 int handle;
2333
2334 handle = vfs_mkstemps (&vpath, me->name, fh->ino->ent->name);
2335 if (handle == -1)
2336 return (-1);
2337
2338 close (handle);
2339 fh->ino->localname = vfs_path_free (vpath, FALSE);
2340 ftp->append = (flags & O_APPEND) != 0;
2341 }
2342 return 0;
2343 }
2344 name = vfs_s_fullpath (me, fh->ino);
2345 if (name == NULL)
2346 return (-1);
2347
2348 fh->handle = ftpfs_open_data_connection (me, VFS_FILE_HANDLER_SUPER (fh),
2349 (flags & O_APPEND) != 0 ? "APPE" : "STOR", name,
2350 TYPE_BINARY, 0);
2351 g_free (name);
2352
2353 if (fh->handle < 0)
2354 return (-1);
2355
2356 #ifdef HAVE_STRUCT_LINGER_L_LINGER
2357 li.l_onoff = 1;
2358 li.l_linger = 120;
2359 #endif
2360 setsockopt (fh->handle, SOL_SOCKET, SO_LINGER, &li, sizeof (li));
2361
2362 if (fh->ino->localname != NULL)
2363 {
2364 unlink (fh->ino->localname);
2365 MC_PTR_FREE (fh->ino->localname);
2366 }
2367 return 0;
2368 }
2369
2370 if (fh->ino->localname == NULL && vfs_s_retrieve_file (me, fh->ino) == -1)
2371 return (-1);
2372
2373 if (fh->ino->localname == NULL)
2374 vfs_die ("retrieve_file failed to fill in localname");
2375 return 0;
2376 }
2377
2378
2379
2380 static int
2381 ftpfs_fh_close (struct vfs_class *me, vfs_file_handler_t *fh)
2382 {
2383 if (fh->handle != -1 && fh->ino->localname == NULL)
2384 {
2385 ftp_super_t *ftp = FTP_SUPER (VFS_FILE_HANDLER_SUPER (fh));
2386
2387 close (fh->handle);
2388 fh->handle = -1;
2389 ftp->ctl_connection_busy = FALSE;
2390
2391
2392
2393 fh->changed = FALSE;
2394 if (ftpfs_get_reply (me, ftp->sock, NULL, 0) != COMPLETE)
2395 ERRNOR (EIO, -1);
2396 vfs_s_invalidate (me, VFS_FILE_HANDLER_SUPER (fh));
2397 }
2398
2399 return 0;
2400 }
2401
2402
2403
2404 static void
2405 ftpfs_done (struct vfs_class *me)
2406 {
2407 (void) me;
2408
2409 g_slist_free_full (no_proxy, g_free);
2410
2411 g_free (ftpfs_anonymous_passwd);
2412 g_free (ftpfs_proxy_host);
2413 }
2414
2415
2416
2417 static void
2418 ftpfs_fill_names (struct vfs_class *me, fill_names_f func)
2419 {
2420 GList *iter;
2421
2422 for (iter = VFS_SUBCLASS (me)->supers; iter != NULL; iter = g_list_next (iter))
2423 {
2424 const struct vfs_s_super *super = (const struct vfs_s_super *) iter->data;
2425 GString *name;
2426
2427 name = vfs_path_element_build_pretty_path_str (super->path_element);
2428
2429 func (name->str);
2430 g_string_free (name, TRUE);
2431 }
2432 }
2433
2434
2435
2436 static keyword_t
2437 ftpfs_netrc_next (void)
2438 {
2439 char *p;
2440 keyword_t i;
2441 static const char *const keywords[] = {
2442 "default", "machine", "login", "password", "passwd", "account", "macdef", NULL,
2443 };
2444
2445 while (TRUE)
2446 {
2447 netrcp = skip_separators (netrcp);
2448 if (*netrcp != '\n')
2449 break;
2450 netrcp++;
2451 }
2452 if (*netrcp == '\0')
2453 return NETRC_NONE;
2454
2455 p = buffer;
2456 if (*netrcp == '"')
2457 {
2458 for (netrcp++; *netrcp != '"' && *netrcp != '\0'; netrcp++)
2459 {
2460 if (*netrcp == '\\')
2461 netrcp++;
2462 *p++ = *netrcp;
2463 }
2464 }
2465 else
2466 {
2467 for (; *netrcp != '\0' && !whiteness (*netrcp) && *netrcp != ','; netrcp++)
2468 {
2469 if (*netrcp == '\\')
2470 netrcp++;
2471 *p++ = *netrcp;
2472 }
2473 }
2474
2475 *p = '\0';
2476 if (*buffer == '\0')
2477 return NETRC_NONE;
2478
2479 for (i = NETRC_DEFAULT; keywords[i - 1] != NULL; i++)
2480 if (strcmp (keywords[i - 1], buffer) == 0)
2481 return i;
2482
2483 return NETRC_UNKNOWN;
2484 }
2485
2486
2487
2488 static gboolean
2489 ftpfs_netrc_bad_mode (const char *netrcname)
2490 {
2491 struct stat mystat;
2492
2493 if (stat (netrcname, &mystat) >= 0 && (mystat.st_mode & 077) != 0)
2494 {
2495 static gboolean be_angry = TRUE;
2496
2497 if (be_angry)
2498 {
2499 message (D_ERROR, MSG_ERROR,
2500 _ ("~/.netrc file has incorrect mode\nRemove password or correct mode"));
2501 be_angry = FALSE;
2502 }
2503 return TRUE;
2504 }
2505
2506 return FALSE;
2507 }
2508
2509
2510
2511
2512
2513
2514
2515 static gboolean
2516 ftpfs_find_machine (const char *host, const char *domain)
2517 {
2518 keyword_t keyword;
2519
2520 if (host == NULL)
2521 host = "";
2522 if (domain == NULL)
2523 domain = "";
2524
2525 while ((keyword = ftpfs_netrc_next ()) != NETRC_NONE)
2526 {
2527 if (keyword == NETRC_DEFAULT)
2528 return TRUE;
2529
2530 if (keyword == NETRC_MACDEF)
2531 {
2532
2533 do
2534 {
2535 while (*netrcp != '\0' && *netrcp != '\n')
2536 netrcp++;
2537 if (*netrcp != '\n')
2538 break;
2539 netrcp++;
2540 }
2541 while (*netrcp != '\0' && *netrcp != '\n');
2542
2543 continue;
2544 }
2545
2546 if (keyword != NETRC_MACHINE)
2547 continue;
2548
2549
2550 if (ftpfs_netrc_next () == NETRC_NONE)
2551 break;
2552
2553 if (g_ascii_strcasecmp (host, buffer) != 0)
2554 {
2555 const char *host_domain;
2556
2557
2558 host_domain = strchr (host, '.');
2559 if (host_domain == NULL)
2560 continue;
2561
2562
2563 if (g_ascii_strcasecmp (host_domain, domain) != 0)
2564 continue;
2565
2566
2567 if (g_ascii_strncasecmp (host, buffer, host_domain - host) != 0)
2568 continue;
2569 }
2570
2571 return TRUE;
2572 }
2573
2574
2575 return FALSE;
2576 }
2577
2578
2579
2580
2581
2582
2583 static gboolean
2584 ftpfs_netrc_lookup (const char *host, char **login, char **pass)
2585 {
2586 char *netrcname;
2587 char *tmp_pass = NULL;
2588 char hostname[MAXHOSTNAMELEN];
2589 const char *domain;
2590 static struct rupcache
2591 {
2592 struct rupcache *next;
2593 char *host;
2594 char *login;
2595 char *pass;
2596 } *rup_cache = NULL, *rupp;
2597
2598
2599 MC_PTR_FREE (*login);
2600 MC_PTR_FREE (*pass);
2601
2602
2603 for (rupp = rup_cache; rupp != NULL; rupp = rupp->next)
2604 if (strcmp (host, rupp->host) == 0)
2605 {
2606 *login = g_strdup (rupp->login);
2607 *pass = g_strdup (rupp->pass);
2608 return TRUE;
2609 }
2610
2611
2612 netrcname = g_build_filename (mc_config_get_home_dir (), ".netrc", (char *) NULL);
2613 if (!g_file_get_contents (netrcname, &netrc, NULL, NULL))
2614 {
2615 g_free (netrcname);
2616 return TRUE;
2617 }
2618
2619 netrcp = netrc;
2620
2621
2622 if (gethostname (hostname, sizeof (hostname)) < 0)
2623 *hostname = '\0';
2624
2625 domain = strchr (hostname, '.');
2626 if (domain == NULL)
2627 domain = "";
2628
2629
2630 ftpfs_find_machine (host, domain);
2631
2632
2633 while (TRUE)
2634 {
2635 keyword_t keyword;
2636
2637 gboolean need_break = FALSE;
2638 keyword = ftpfs_netrc_next ();
2639
2640 switch (keyword)
2641 {
2642 case NETRC_LOGIN:
2643 if (ftpfs_netrc_next () == NETRC_NONE)
2644 {
2645 need_break = TRUE;
2646 break;
2647 }
2648
2649
2650 if (*login != NULL)
2651 {
2652 need_break = TRUE;
2653 break;
2654 }
2655
2656
2657 *login = g_strdup (buffer);
2658 break;
2659
2660 case NETRC_PASSWORD:
2661 case NETRC_PASSWD:
2662 if (ftpfs_netrc_next () == NETRC_NONE)
2663 {
2664 need_break = TRUE;
2665 break;
2666 }
2667
2668
2669 if (*login != NULL && strcmp (*login, "anonymous") != 0 && strcmp (*login, "ftp") != 0
2670 && ftpfs_netrc_bad_mode (netrcname))
2671 {
2672 need_break = TRUE;
2673 break;
2674 }
2675
2676
2677 if (tmp_pass == NULL)
2678 tmp_pass = g_strdup (buffer);
2679 break;
2680
2681 case NETRC_ACCOUNT:
2682
2683 if (ftpfs_netrc_next () == NETRC_NONE)
2684 {
2685 need_break = TRUE;
2686 break;
2687 }
2688
2689
2690 ftpfs_netrc_bad_mode (netrcname);
2691 break;
2692
2693 default:
2694
2695 need_break = TRUE;
2696 break;
2697 }
2698
2699 if (need_break)
2700 break;
2701 }
2702
2703 MC_PTR_FREE (netrc);
2704 g_free (netrcname);
2705
2706 rupp = g_new (struct rupcache, 1);
2707 rupp->host = g_strdup (host);
2708 rupp->login = g_strdup (*login);
2709 rupp->pass = g_strdup (tmp_pass);
2710
2711 rupp->next = rup_cache;
2712 rup_cache = rupp;
2713
2714 *pass = tmp_pass;
2715
2716 return TRUE;
2717 }
2718
2719
2720
2721
2722
2723
2724 void
2725 ftpfs_init_passwd (void)
2726 {
2727 ftpfs_anonymous_passwd = load_anon_passwd ();
2728
2729 if (ftpfs_anonymous_passwd == NULL)
2730 {
2731
2732
2733
2734
2735
2736
2737
2738
2739 ftpfs_anonymous_passwd = g_strdup ("anonymous@");
2740 }
2741 }
2742
2743
2744
2745 void
2746 vfs_init_ftpfs (void)
2747 {
2748 tcp_init ();
2749
2750 vfs_init_subclass (&ftpfs_subclass, "ftpfs", VFSF_NOLINKS | VFSF_REMOTE | VFSF_USETMP, "ftp");
2751 vfs_ftpfs_ops->done = ftpfs_done;
2752 vfs_ftpfs_ops->fill_names = ftpfs_fill_names;
2753 vfs_ftpfs_ops->stat = ftpfs_stat;
2754 vfs_ftpfs_ops->lstat = ftpfs_lstat;
2755 vfs_ftpfs_ops->fstat = ftpfs_fstat;
2756 vfs_ftpfs_ops->chmod = ftpfs_chmod;
2757 vfs_ftpfs_ops->chown = ftpfs_chown;
2758 vfs_ftpfs_ops->unlink = ftpfs_unlink;
2759 vfs_ftpfs_ops->rename = ftpfs_rename;
2760 vfs_ftpfs_ops->mkdir = ftpfs_mkdir;
2761 vfs_ftpfs_ops->rmdir = ftpfs_rmdir;
2762 vfs_ftpfs_ops->ctl = ftpfs_ctl;
2763 ftpfs_subclass.archive_same = ftpfs_archive_same;
2764 ftpfs_subclass.new_archive = ftpfs_new_archive;
2765 ftpfs_subclass.open_archive = ftpfs_open_archive;
2766 ftpfs_subclass.free_archive = ftpfs_free_archive;
2767 ftpfs_subclass.fh_new = ftpfs_fh_new;
2768 ftpfs_subclass.fh_open = ftpfs_fh_open;
2769 ftpfs_subclass.fh_close = ftpfs_fh_close;
2770 ftpfs_subclass.dir_load = ftpfs_dir_load;
2771 ftpfs_subclass.file_store = ftpfs_file_store;
2772 ftpfs_subclass.linear_start = ftpfs_linear_start;
2773 ftpfs_subclass.linear_read = ftpfs_linear_read;
2774 ftpfs_subclass.linear_close = ftpfs_linear_close;
2775 vfs_register_class (vfs_ftpfs_ops);
2776 }
2777
2778