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