mc/vfs/ftpfs.c

2086 lines
50 KiB
C
Raw Normal View History

1998-02-27 07:54:42 +03:00
/* Virtual File System: FTP file system.
Copyright (C) 1995 The Free Software Foundation
Written by: 1995 Ching Hui
1995 Jakub Jelinek
1995, 1996, 1997 Miguel de Icaza
1997 Norbert Warmuth
1998 Pavel Machek
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License
as published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
1998-02-27 07:54:42 +03:00
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
1998-02-27 07:54:42 +03:00
You should have received a copy of the GNU Library General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
1998-02-27 07:54:42 +03:00
/* FTPfs TODO:
- make it more robust - all the connects etc. should handle EADDRINUSE and
ERETRY (have I spelled these names correctly?)
- make the user able to flush a connection - all the caches will get empty
etc., (tarfs as well), we should give there a user selectable timeout
and assign a key sequence.
- use hash table instead of linklist to cache ftpfs directory.
What to do with this?
* NOTE: Usage of tildes is deprecated, consider:
* cd /#ftp:pavel@hobit
* cd ~
* And now: what do I want to do? Do I want to go to /home/pavel or to
* /#ftp:hobit/home/pavel? I think first has better sense...
*
{
int f = !strcmp( remote_path, "/~" );
if (f || !strncmp( remote_path, "/~/", 3 )) {
char *s;
s = concat_dir_and_file( qhome (*bucket), remote_path +3-f );
g_free (remote_path);
remote_path = s;
}
}
1998-02-27 07:54:42 +03:00
*/
1998-10-13 02:07:53 +04:00
/* Namespace pollution: horrible */
#include <config.h>
2000-03-20 04:57:58 +03:00
#include <sys/types.h> /* POSIX-required by sys/socket.h and netdb.h */
1998-02-27 07:54:42 +03:00
#include <netdb.h> /* struct hostent */
#include <sys/socket.h> /* AF_INET */
#include <netinet/in.h> /* struct in_addr */
#ifdef HAVE_SETSOCKOPT
# include <netinet/ip.h> /* IP options */
#endif
#ifdef HAVE_ARPA_INET_H
1998-02-27 07:54:42 +03:00
#include <arpa/inet.h>
#endif
1998-02-27 07:54:42 +03:00
#include <arpa/ftp.h>
#include <arpa/telnet.h>
#include <sys/param.h>
#include "utilvfs.h"
#include "xdirentry.h"
1998-02-27 07:54:42 +03:00
#include "vfs.h"
#include "tcputil.h"
#include "../src/dialog.h"
#include "../src/setup.h" /* for load_anon_passwd */
1998-02-27 07:54:42 +03:00
#include "ftpfs.h"
#ifndef MAXHOSTNAMELEN
# define MAXHOSTNAMELEN 64
#endif
#define UPLOAD_ZERO_LENGTH_FILE
#define SUP super->u.ftp
#define FH_SOCK fh->u.ftp.sock
1998-02-27 07:54:42 +03:00
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
static int my_errno;
1998-02-27 07:54:42 +03:00
static int code;
/* Delay to retry a connection */
int ftpfs_retry_seconds = 30;
/* Method to use to connect to ftp sites */
int ftpfs_use_passive_connections = 1;
Tue Sep 15 20:51:42 1998 Norbert Warmuth <k3190@fh-sw.de> * setup.c: save and restore new global variable/option ftp_use_unix_list_options Tue Sep 15 20:31:32 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.c (ftp_use_unix_list_options): New global variable/option. If true we try to use 'LIST -la <path>'. When it fails we use the two commands 'CWD <path>' and 'LIST' instead. (resolve_symlink): rewritten. Don't get a second directory listing with `LIST -lLa'. Instead use the cache to get the file stat of symbolic links. If the directory the symlink points to isn't already in the cache the directory listing will be fetched and stored in the directory cache (without resolving symlinks recursively). The new method to resolve symlinks is faster if symlinks the same directory or the directory the symlink points to is already in the cache. This function was small and nice until I discovered that it was broken for symlinks to symlinks. Now it looks ugly and perhaps I will revert it to use "LIST -lLa" again. With a fast connection it doesn't matter which methode we use but with a slow connection I wouldn't hesitate to burn more cpu cycles on the client side. (retrieve_dir): Added parameter to tell whether to resolve symlinks (don't resolve symlinks in directory listings retrieved while resolving symlinks). When we don't get a directory listing with 'LIST -la <path>' then try to get it with `CWD <path>; LIST'. Tue Sep 15 20:27:29 1998 Norbert Warmuth <k3190@fh-sw.de * ftpfs.c (login_server): s/ftpfs_get_host/my_get_host/ (retrieve_file_start2): Don't create target file O_EXCL, in copy_file_file we check existance of the target file and know that we want to truncate it (this change was already done a while back but it was reverted with the vfs-split). Tue Sep 15 20:15:42 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.h (struct connection): added boolean which indicates that the ftp server doesn't unterstand Unix ls options * ftpfs.h (struct dir): added enum to store symlink status of the in memory directory cache (directory has no symbolic links; symbolic links but not yet resolved; symbolic links which are resolved) Tue Sep 15 20:02:08 1998 Norbert Warmuth <k3190@fh-sw.de> * shared_ftp_fish.c, fish.c: updated references to retrieve_dir to honour the additional boolean parameter
1998-09-15 23:41:22 +04:00
/* Method used to get directory listings:
* 1: try 'LIST -la <path>', if it fails
* fall back to CWD <path>; LIST
* 0: always use CWD <path>; LIST
Tue Sep 15 20:51:42 1998 Norbert Warmuth <k3190@fh-sw.de> * setup.c: save and restore new global variable/option ftp_use_unix_list_options Tue Sep 15 20:31:32 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.c (ftp_use_unix_list_options): New global variable/option. If true we try to use 'LIST -la <path>'. When it fails we use the two commands 'CWD <path>' and 'LIST' instead. (resolve_symlink): rewritten. Don't get a second directory listing with `LIST -lLa'. Instead use the cache to get the file stat of symbolic links. If the directory the symlink points to isn't already in the cache the directory listing will be fetched and stored in the directory cache (without resolving symlinks recursively). The new method to resolve symlinks is faster if symlinks the same directory or the directory the symlink points to is already in the cache. This function was small and nice until I discovered that it was broken for symlinks to symlinks. Now it looks ugly and perhaps I will revert it to use "LIST -lLa" again. With a fast connection it doesn't matter which methode we use but with a slow connection I wouldn't hesitate to burn more cpu cycles on the client side. (retrieve_dir): Added parameter to tell whether to resolve symlinks (don't resolve symlinks in directory listings retrieved while resolving symlinks). When we don't get a directory listing with 'LIST -la <path>' then try to get it with `CWD <path>; LIST'. Tue Sep 15 20:27:29 1998 Norbert Warmuth <k3190@fh-sw.de * ftpfs.c (login_server): s/ftpfs_get_host/my_get_host/ (retrieve_file_start2): Don't create target file O_EXCL, in copy_file_file we check existance of the target file and know that we want to truncate it (this change was already done a while back but it was reverted with the vfs-split). Tue Sep 15 20:15:42 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.h (struct connection): added boolean which indicates that the ftp server doesn't unterstand Unix ls options * ftpfs.h (struct dir): added enum to store symlink status of the in memory directory cache (directory has no symbolic links; symbolic links but not yet resolved; symbolic links which are resolved) Tue Sep 15 20:02:08 1998 Norbert Warmuth <k3190@fh-sw.de> * shared_ftp_fish.c, fish.c: updated references to retrieve_dir to honour the additional boolean parameter
1998-09-15 23:41:22 +04:00
*/
int ftpfs_use_unix_list_options = 1;
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
/* First "CWD <path>", then "LIST -la ." */
int ftpfs_first_cd_then_ls;
1998-02-27 07:54:42 +03:00
/* Use the ~/.netrc */
int use_netrc = 1;
/* Anonymous setup */
char *ftpfs_anonymous_passwd = NULL;
int ftpfs_directory_timeout = 900;
1998-02-27 07:54:42 +03:00
/* Proxy host */
char *ftpfs_proxy_host = NULL;
1998-02-27 07:54:42 +03:00
/* wether we have to use proxy by default? */
int ftpfs_always_use_proxy;
/* source routing host */
extern int source_route;
/* Where we store the transactions */
static FILE *logfile = NULL;
1998-02-27 07:54:42 +03:00
/* If true, the directory cache is forced to reload */
static int force_expiration = 0;
2001-05-15 03:34:43 +04:00
#ifdef FIXME_LATER_ALIGATOR
static struct linklist *connections_list;
2001-05-15 03:34:43 +04:00
#endif
1998-02-27 07:54:42 +03:00
/* command wait_flag: */
#define NONE 0x00
#define WAIT_REPLY 0x01
#define WANT_STRING 0x02
static char reply_str [80];
1998-02-27 07:54:42 +03:00
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
/* char *translate_path (struct ftpfs_connection *bucket, char *remote_path)
Translate a Unix path, i.e. MC's internal path representation (e.g.
/somedir/somefile) to a path valid for the remote server. Every path
transfered to the remote server has to be mangled by this function
right prior to sending it.
Currently only Amiga ftp servers are handled in a special manner.
When the remote server is an amiga:
a) strip leading slash if necesarry
b) replace first occurance of ":/" with ":"
c) strip trailing "/."
*/
static char *ftpfs_get_current_directory (vfs *me, vfs_s_super *super);
static int ftpfs_chdir_internal (vfs *me, vfs_s_super *super, char *remote_path);
2002-11-15 09:38:55 +03:00
static int command (vfs *me, vfs_s_super *super, int wait_reply, const char *fmt, ...)
__attribute__ ((format (printf, 4, 5)));
static int ftpfs_open_socket (vfs *me, vfs_s_super *super);
static int login_server (vfs *me, vfs_s_super *super, const char *netrcpass);
static int lookup_netrc (const char *host, char **login, char **pass);
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
static char *
translate_path (vfs *me, vfs_s_super *super, const char *remote_path)
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
{
if (!SUP.remote_is_amiga)
return g_strdup (remote_path);
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
else {
char *ret, *p;
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
if (logfile) {
fprintf (logfile, "MC -- translate_path: %s\n", remote_path);
fflush (logfile);
}
/* strip leading slash(es) */
while (*remote_path == '/')
remote_path++;
/*
* Don't change "/" into "", e.g. "CWD " would be
* invalid.
*/
if (*remote_path == '\0')
return g_strdup (".");
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
ret = g_strdup (remote_path);
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
/* replace first occurance of ":/" with ":" */
if ((p = strchr (ret, ':')) && *(p + 1) == '/')
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
strcpy (p + 1, p + 2);
/* strip trailing "/." */
if ((p = strrchr (ret, '/')) && *(p + 1) == '.' && *(p + 2) == '\0')
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
*p = '\0';
return ret;
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
}
}
1998-02-27 07:54:42 +03:00
/* Extract the hostname and username from the path */
/*
* path is in the form: [user@]hostname:port/remote-dir, e.g.:
1998-02-27 07:54:42 +03:00
* ftp://sunsite.unc.edu/pub/linux
* ftp://miguel@sphinx.nuclecu.unam.mx/c/nc
* ftp://tsx-11.mit.edu:8192/
* ftp://joe@foo.edu:11321/private
* If the user is empty, e.g. ftp://@roxanne/private, then your login name
* is supplied.
*
*/
1998-02-27 07:54:42 +03:00
#define FTP_COMMAND_PORT 21
static void
ftp_split_url(char *path, char **host, char **user, int *port, char **pass)
{
char *p;
p = vfs_split_url (path, host, user, port, pass, FTP_COMMAND_PORT,
URL_ALLOW_ANON);
if (!*user) {
/* Look up user and password in netrc */
if (use_netrc)
lookup_netrc (*host, user, pass);
if (!*user)
*user = g_strdup ("anonymous");
}
/* Look up password in netrc for known user */
if (use_netrc && *user && pass && !*pass) {
char *new_user;
lookup_netrc (*host, &new_user, pass);
/* If user is different, remove password */
if (new_user && strcmp (*user, new_user)) {
g_free (*pass);
*pass = NULL;
}
g_free (new_user);
}
if (p)
g_free (p);
}
1998-02-27 07:54:42 +03:00
/* Returns a reply code, check /usr/include/arpa/ftp.h for possible values */
static int
get_reply (vfs *me, int sock, char *string_buf, int string_len)
1998-02-27 07:54:42 +03:00
{
char answer[BUF_1K];
1998-02-27 07:54:42 +03:00
int i;
for (;;) {
if (!vfs_s_get_line (me, sock, answer, sizeof (answer), '\n')){
1998-02-27 07:54:42 +03:00
if (string_buf)
*string_buf = 0;
code = 421;
return 4;
}
switch (sscanf(answer, "%d", &code)){
1998-02-27 07:54:42 +03:00
case 0:
if (string_buf) {
strncpy (string_buf, answer, string_len - 1);
1998-02-27 07:54:42 +03:00
*(string_buf + string_len - 1) = 0;
}
code = 500;
return 5;
case 1:
if (answer[3] == '-') {
while (1) {
if (!vfs_s_get_line (me, sock, answer, sizeof(answer), '\n')){
1998-02-27 07:54:42 +03:00
if (string_buf)
*string_buf = 0;
code = 421;
return 4;
}
if ((sscanf (answer, "%d", &i) > 0) &&
1998-02-27 07:54:42 +03:00
(code == i) && (answer[3] == ' '))
break;
}
}
if (string_buf){
strncpy (string_buf, answer, string_len - 1);
1998-02-27 07:54:42 +03:00
*(string_buf + string_len - 1) = 0;
}
return code / 100;
}
}
}
static int
reconnect (vfs *me, vfs_s_super *super)
{
int sock = ftpfs_open_socket (me, super);
if (sock != -1){
char *cwdir = SUP.cwdir;
close (SUP.sock);
SUP.sock = sock;
SUP.cwdir = NULL;
if (login_server (me, super, SUP.password)){
if (!cwdir)
return 1;
sock = ftpfs_chdir_internal (me, super, cwdir);
g_free (cwdir);
return sock == COMPLETE;
}
SUP.cwdir = cwdir;
}
return 0;
}
static int
2002-11-15 09:38:55 +03:00
command (vfs *me, vfs_s_super *super, int wait_reply, const char *fmt, ...)
1998-02-27 07:54:42 +03:00
{
va_list ap;
char *cmdstr;
int status, cmdlen;
1998-02-27 07:54:42 +03:00
va_start (ap, fmt);
cmdstr = g_strdup_vprintf (fmt, ap);
1998-02-27 07:54:42 +03:00
va_end (ap);
cmdlen = strlen (cmdstr);
cmdstr = g_realloc (cmdstr, cmdlen + 3);
strcpy (cmdstr + cmdlen, "\r\n");
cmdlen += 2;
1998-02-27 07:54:42 +03:00
if (logfile) {
if (strncmp (cmdstr, "PASS ", 5) == 0) {
fputs ("PASS <Password not logged>\r\n", logfile);
} else
fwrite (cmdstr, cmdlen, 1, logfile);
1998-10-30 20:51:28 +03:00
fflush (logfile);
1998-02-27 07:54:42 +03:00
}
1998-02-27 07:54:42 +03:00
got_sigpipe = 0;
enable_interrupt_key ();
status = write (SUP.sock, cmdstr, cmdlen);
if (status < 0) {
1998-02-27 07:54:42 +03:00
code = 421;
if (errno == EPIPE) { /* Remote server has closed connection */
static int level = 0; /* login_server() use command() */
if (level == 0) {
level = 1;
status = reconnect (me, super);
level = 0;
if (status && (write (SUP.sock, cmdstr, cmdlen) > 0)) {
goto ok;
}
}
1998-02-27 07:54:42 +03:00
got_sigpipe = 1;
}
g_free (cmdstr);
disable_interrupt_key ();
1998-02-27 07:54:42 +03:00
return TRANSIENT;
}
ok:
g_free (cmdstr);
disable_interrupt_key ();
1998-02-27 07:54:42 +03:00
if (wait_reply)
return get_reply (me, SUP.sock,
(wait_reply & WANT_STRING) ? reply_str : NULL,
sizeof (reply_str) - 1);
1998-02-27 07:54:42 +03:00
return COMPLETE;
}
static void
free_archive (vfs *me, vfs_s_super *super)
1998-02-27 07:54:42 +03:00
{
if (SUP.sock != -1){
print_vfs_message (_("ftpfs: Disconnecting from %s"), SUP.host);
command(me, super, NONE, "QUIT");
close(SUP.sock);
1998-02-27 07:54:42 +03:00
}
g_free (SUP.host);
g_free (SUP.user);
g_free (SUP.cwdir);
g_free (SUP.password);
1998-02-27 07:54:42 +03:00
}
/* some defines only used by changetype */
/* These two are valid values for the second parameter */
#define TYPE_ASCII 0
#define TYPE_BINARY 1
/* This one is only used to initialize bucket->isbinary, don't use it as
second parameter to changetype. */
#define TYPE_UNKNOWN -1
1998-02-27 07:54:42 +03:00
static int
changetype (vfs *me, vfs_s_super *super, int binary)
1998-02-27 07:54:42 +03:00
{
if (binary != SUP.isbinary) {
if (command (me, super, WAIT_REPLY, "TYPE %c", binary ? 'I' : 'A') != COMPLETE)
ERRNOR (EIO, -1);
SUP.isbinary = binary;
1998-02-27 07:54:42 +03:00
}
return binary;
}
/* This routine logs the user in */
static int
login_server (vfs *me, vfs_s_super *super, const char *netrcpass)
1998-02-27 07:54:42 +03:00
{
char *pass;
char *op;
char *name; /* login user name */
int anon = 0;
char reply_string[BUF_MEDIUM];
SUP.isbinary = TYPE_UNKNOWN;
1998-02-27 07:54:42 +03:00
if (netrcpass)
op = g_strdup (netrcpass);
1998-02-27 07:54:42 +03:00
else {
if (!strcmp (SUP.user, "anonymous") || !strcmp (SUP.user, "ftp")) {
if (!ftpfs_anonymous_passwd)
ftpfs_init_passwd ();
op = g_strdup (ftpfs_anonymous_passwd);
1998-02-27 07:54:42 +03:00
anon = 1;
} else {
char *p;
1998-02-27 07:54:42 +03:00
if (!SUP.password) {
p = g_strconcat (_(" FTP: Password required for "),
SUP.user, " ", NULL);
op = vfs_get_password (p);
g_free (p);
if (op == NULL)
ERRNOR (EPERM, 0);
SUP.password = g_strdup (op);
1998-02-27 07:54:42 +03:00
} else
op = g_strdup (SUP.password);
}
1998-02-27 07:54:42 +03:00
}
if (!anon || logfile)
pass = op;
else {
pass = g_strconcat ("-", op, NULL);
wipe_password (op);
}
/* Proxy server accepts: username@host-we-want-to-connect */
if (SUP.proxy) {
name =
g_strconcat (SUP.user, "@",
SUP.host[0] == '!' ? SUP.host + 1 : SUP.host,
NULL);
} else
name = g_strdup (SUP.user);
if (get_reply (me, SUP.sock, reply_string, sizeof (reply_string) - 1)
== COMPLETE) {
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
g_strup (reply_string);
SUP.remote_is_amiga = strstr (reply_string, "AMIGA") != 0;
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
if (logfile) {
fprintf (logfile, "MC -- remote_is_amiga = %d\n",
SUP.remote_is_amiga);
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
fflush (logfile);
}
print_vfs_message (_("ftpfs: sending login name"));
code = command (me, super, WAIT_REPLY, "USER %s", name);
1998-02-27 07:54:42 +03:00
switch (code) {
1998-02-27 07:54:42 +03:00
case CONTINUE:
print_vfs_message (_("ftpfs: sending user password"));
code = command (me, super, WAIT_REPLY, "PASS %s", pass);
if (code == CONTINUE) {
char *p;
p = g_strdup_printf (_
("FTP: Account required for user %s"),
SUP.user);
op = input_dialog (p, _("Account:"), "");
g_free (p);
if (op == NULL)
ERRNOR (EPERM, 0);
print_vfs_message (_("ftpfs: sending user account"));
code = command (me, super, WAIT_REPLY, "ACCT %s", op);
g_free (op);
}
if (code != COMPLETE)
1998-02-27 07:54:42 +03:00
break;
/* fall through */
1998-02-27 07:54:42 +03:00
case COMPLETE:
print_vfs_message (_("ftpfs: logged in"));
1998-02-27 07:54:42 +03:00
wipe_password (pass);
g_free (name);
1998-02-27 07:54:42 +03:00
return 1;
default:
SUP.failed_on_login = 1;
/* my_errno = E; */
if (SUP.password)
wipe_password (SUP.password);
SUP.password = 0;
goto login_fail;
1998-02-27 07:54:42 +03:00
}
}
message_2s (1, MSG_ERROR, _("ftpfs: Login incorrect for user %s "),
SUP.user);
login_fail:
1998-02-27 07:54:42 +03:00
wipe_password (pass);
g_free (name);
ERRNOR (EPERM, 0);
1998-02-27 07:54:42 +03:00
}
#ifdef HAVE_SETSOCKOPT
static void
setup_source_route (int socket, int dest)
{
char buffer [20];
char *ptr = buffer;
if (!source_route)
return;
memset (buffer, 0, sizeof (buffer));
1998-02-27 07:54:42 +03:00
*ptr++ = IPOPT_LSRR;
*ptr++ = 3 + 8;
*ptr++ = 4; /* pointer */
/* First hop */
memcpy (ptr, (char *) &source_route, sizeof (int));
1998-02-27 07:54:42 +03:00
ptr += 4;
/* Second hop (ie, final destination) */
memcpy (ptr, (char *) &dest, sizeof (int));
1998-02-27 07:54:42 +03:00
ptr += 4;
while ((ptr - buffer) & 3)
ptr++;
if (setsockopt (socket, IPPROTO_IP, IP_OPTIONS,
buffer, ptr - buffer) < 0)
2002-12-08 04:12:18 +03:00
message_2s (1, MSG_ERROR, _(" Cannot set source routing (%s)"), unix_error_string (errno));
1998-02-27 07:54:42 +03:00
}
#else
#define setup_source_route(x,y)
#endif
static struct no_proxy_entry {
char *domain;
void *next;
} *no_proxy;
static void
load_no_proxy_list (void)
1998-02-27 07:54:42 +03:00
{
/* FixMe: shouldn't be hardcoded!!! */
char s[BUF_LARGE]; /* provide for BUF_LARGE characters */
struct no_proxy_entry *np, *current = 0;
1998-02-27 07:54:42 +03:00
FILE *npf;
int c;
2000-12-04 22:14:52 +03:00
char *p;
static char *mc_file;
1998-02-27 07:54:42 +03:00
2000-12-04 22:14:52 +03:00
if (mc_file)
1998-02-27 07:54:42 +03:00
return;
mc_file = concat_dir_and_file (mc_home, "mc.no_proxy");
if (exist_file (mc_file) &&
(npf = fopen (mc_file, "r"))) {
while (fgets (s, sizeof(s), npf) || !(feof (npf) || ferror (npf))) {
1998-02-27 07:54:42 +03:00
if (!(p = strchr (s, '\n'))) { /* skip bogus entries */
while ((c = fgetc (npf)) != EOF && c != '\n')
1998-02-27 07:54:42 +03:00
;
continue;
}
if (p == s)
continue;
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
*p = '\0';
np = g_new (struct no_proxy_entry, 1);
np->domain = g_strdup (s);
np->next = NULL;
1998-02-27 07:54:42 +03:00
if (no_proxy)
current->next = np;
else
no_proxy = np;
current = np;
}
fclose (npf);
}
g_free (mc_file);
1998-02-27 07:54:42 +03:00
}
2002-11-02 19:58:18 +03:00
/* Return 1 if FTP proxy should be used for this host, 0 otherwise */
1998-02-27 07:54:42 +03:00
static int
ftpfs_check_proxy (const char *host)
1998-02-27 07:54:42 +03:00
{
struct no_proxy_entry *npe;
if (!ftpfs_proxy_host || !*ftpfs_proxy_host || !host || !*host)
return 0; /* sanity check */
if (*host == '!')
return 1;
if (!ftpfs_always_use_proxy)
return 0;
if (!strchr (host, '.'))
return 0;
load_no_proxy_list ();
for (npe = no_proxy; npe; npe=npe->next) {
char *domain = npe->domain;
if (domain[0] == '.') {
int ld = strlen (domain);
int lh = strlen (host);
while (ld && lh && host[lh - 1] == domain[ld - 1]) {
ld--;
lh--;
}
if (!ld)
return 0;
} else
if (!g_strcasecmp (host, domain))
1998-02-27 07:54:42 +03:00
return 0;
}
return 1;
}
static void
ftpfs_get_proxy_host_and_port (char *proxy, char **host, int *port)
{
char *user, *dir;
1998-02-27 07:54:42 +03:00
dir =
vfs_split_url (proxy, host, &user, port, 0, FTP_COMMAND_PORT,
URL_ALLOW_ANON);
g_free (user);
g_free (dir);
1998-02-27 07:54:42 +03:00
}
static int
ftpfs_open_socket (vfs *me, vfs_s_super *super)
1998-02-27 07:54:42 +03:00
{
struct sockaddr_in server_address;
struct hostent *hp;
int my_socket;
char *host;
int port = SUP.port;
1998-02-27 07:54:42 +03:00
int free_host = 0;
/* Use a proxy host? */
host = SUP.host;
1998-02-27 07:54:42 +03:00
if (!host || !*host){
print_vfs_message (_("ftpfs: Invalid host name."));
my_errno = EINVAL;
1998-02-27 07:54:42 +03:00
return -1;
}
/* Hosts to connect to that start with a ! should use proxy */
if (SUP.proxy){
1998-02-27 07:54:42 +03:00
ftpfs_get_proxy_host_and_port (ftpfs_proxy_host, &host, &port);
free_host = 1;
}
/* Get host address */
memset ((char *) &server_address, 0, sizeof (server_address));
1998-02-27 07:54:42 +03:00
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr (host);
if (server_address.sin_addr.s_addr == INADDR_NONE) {
hp = gethostbyname (host);
1998-02-27 07:54:42 +03:00
if (hp == NULL){
print_vfs_message (_("ftpfs: Invalid host address."));
my_errno = EINVAL;
1998-02-27 07:54:42 +03:00
if (free_host)
g_free (host);
1998-02-27 07:54:42 +03:00
return -1;
}
server_address.sin_family = hp->h_addrtype;
2002-12-26 05:21:37 +03:00
/* We copy only 4 bytes, we cannot trust hp->h_length, as it comes from the DNS */
memcpy ((char *) &server_address.sin_addr, (char *) hp->h_addr, 4);
1998-02-27 07:54:42 +03:00
}
server_address.sin_port = htons (port);
1998-02-27 07:54:42 +03:00
/* Connect */
if ((my_socket = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
my_errno = errno;
1998-02-27 07:54:42 +03:00
if (free_host)
g_free (host);
1998-02-27 07:54:42 +03:00
return -1;
}
setup_source_route (my_socket, server_address.sin_addr.s_addr);
print_vfs_message (_("ftpfs: making connection to %s"), host);
1998-02-27 07:54:42 +03:00
if (free_host)
g_free (host);
1998-02-27 07:54:42 +03:00
enable_interrupt_key (); /* clear the interrupt flag */
1998-02-27 07:54:42 +03:00
if (connect (my_socket, (struct sockaddr *) &server_address,
sizeof (server_address)) < 0){
my_errno = errno;
if (errno == EINTR && got_interrupt ())
print_vfs_message (_("ftpfs: connection interrupted by user"));
1998-02-27 07:54:42 +03:00
else
print_vfs_message (_("ftpfs: connection to server failed: %s"),
unix_error_string(errno));
1998-02-27 07:54:42 +03:00
disable_interrupt_key();
close (my_socket);
return -1;
}
disable_interrupt_key();
return my_socket;
}
static int
open_archive_int (vfs *me, vfs_s_super *super)
1998-02-27 07:54:42 +03:00
{
int retry_seconds, count_down;
/* We do not want to use the passive if we are using proxies */
if (SUP.proxy)
SUP.use_passive_connection = 0;
1998-02-27 07:54:42 +03:00
retry_seconds = 0;
do {
SUP.failed_on_login = 0;
1998-02-27 07:54:42 +03:00
SUP.sock = ftpfs_open_socket (me, super);
if (SUP.sock == -1)
return -1;
1998-02-27 07:54:42 +03:00
if (login_server (me, super, NULL)) {
1998-02-27 07:54:42 +03:00
/* Logged in, no need to retry the connection */
break;
} else {
if (SUP.failed_on_login){
1998-02-27 07:54:42 +03:00
/* Close only the socket descriptor */
close (SUP.sock);
1998-02-27 07:54:42 +03:00
} else {
return -1;
1998-02-27 07:54:42 +03:00
}
if (ftpfs_retry_seconds){
retry_seconds = ftpfs_retry_seconds;
enable_interrupt_key ();
for (count_down = retry_seconds; count_down; count_down--){
print_vfs_message (_("Waiting to retry... %d (Control-C to cancel)"), count_down);
1998-02-27 07:54:42 +03:00
sleep (1);
if (got_interrupt ()){
/* my_errno = E; */
1998-02-27 07:54:42 +03:00
disable_interrupt_key ();
return 0;
1998-02-27 07:54:42 +03:00
}
}
disable_interrupt_key ();
}
}
} while (retry_seconds);
SUP.cwdir = ftpfs_get_current_directory (me, super);
if (!SUP.cwdir)
SUP.cwdir = g_strdup (PATH_SEP_STR);
return 0;
1998-02-27 07:54:42 +03:00
}
static int
open_archive (vfs *me, vfs_s_super *super, char *archive_name, char *op)
1998-02-27 07:54:42 +03:00
{
char *host, *user, *password;
int port;
1998-02-27 07:54:42 +03:00
ftp_split_url (strchr (op, ':') + 1, &host, &user, &port, &password);
SUP.host = host;
SUP.user = user;
SUP.port = port;
SUP.cwdir = NULL;
SUP.proxy = 0;
if (ftpfs_check_proxy (host))
SUP.proxy = ftpfs_proxy_host;
SUP.password = password;
SUP.use_passive_connection = ftpfs_use_passive_connections | source_route;
SUP.use_source_route = source_route;
SUP.strict = ftpfs_use_unix_list_options ? RFC_AUTODETECT : RFC_STRICT;
SUP.isbinary = TYPE_UNKNOWN;
SUP.remote_is_amiga = 0;
super->name = g_strdup("/");
super->root = vfs_s_new_inode (me, super, vfs_s_default_stat(me, S_IFDIR | 0755));
return open_archive_int (me, super);
}
static int
archive_same(vfs *me, vfs_s_super *super, char *archive_name, char *op, void *cookie)
{
char *host, *user;
int port;
ftp_split_url (strchr(op, ':') + 1, &host, &user, &port, 0);
port = ((strcmp (host, SUP.host) == 0) &&
(strcmp (user, SUP.user) == 0) &&
(port == SUP.port));
g_free (host);
g_free (user);
return port;
1998-02-27 07:54:42 +03:00
}
void
ftpfs_flushdir (void)
{
force_expiration = 1;
}
static int
dir_uptodate(vfs *me, vfs_s_inode *ino)
1998-02-27 07:54:42 +03:00
{
struct timeval tim;
if (force_expiration) {
force_expiration = 0;
return 0;
1998-02-27 07:54:42 +03:00
}
gettimeofday(&tim, NULL);
if (tim.tv_sec < ino->u.ftp.timestamp.tv_sec)
return 1;
return 0;
1998-02-27 07:54:42 +03:00
}
/* The returned directory should always contain a trailing slash */
static char *
ftpfs_get_current_directory (vfs *me, vfs_s_super *super)
1998-02-27 07:54:42 +03:00
{
char buf[BUF_8K], *bufp, *bufq;
1998-02-27 07:54:42 +03:00
if (command (me, super, NONE, "PWD") == COMPLETE &&
get_reply(me, SUP.sock, buf, sizeof(buf)) == COMPLETE) {
1998-02-27 07:54:42 +03:00
bufp = NULL;
for (bufq = buf; *bufq; bufq++)
if (*bufq == '"') {
if (!bufp) {
bufp = bufq + 1;
} else {
*bufq = 0;
if (*bufp) {
if (*(bufq - 1) != '/') {
*bufq++ = '/';
*bufq = 0;
}
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
if (*bufp == '/')
return g_strdup (bufp);
else {
/* If the remote server is an Amiga a leading slash
might be missing. MC needs it because it is used
2003-06-02 23:47:30 +04:00
as separator between hostname and path internally. */
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
return g_strconcat( "/", bufp, 0);
}
} else {
my_errno = EIO;
return NULL;
}
1998-02-27 07:54:42 +03:00
}
}
}
my_errno = EIO;
1998-02-27 07:54:42 +03:00
return NULL;
}
/* Setup Passive ftp connection, we use it for source routed connections */
static int
setup_passive (vfs *me, vfs_s_super *super, int my_socket, struct sockaddr_in *sa)
1998-02-27 07:54:42 +03:00
{
int xa, xb, xc, xd, xe, xf;
char n [6];
char *c = reply_str;
if (command (me, super, WAIT_REPLY | WANT_STRING, "PASV") != COMPLETE)
1998-02-27 07:54:42 +03:00
return 0;
/* Parse remote parameters */
for (c = reply_str + 4; (*c) && (!isdigit ((unsigned char) *c)); c++)
1998-02-27 07:54:42 +03:00
;
if (!*c)
return 0;
if (!isdigit ((unsigned char) *c))
1998-02-27 07:54:42 +03:00
return 0;
if (sscanf (c, "%d,%d,%d,%d,%d,%d", &xa, &xb, &xc, &xd, &xe, &xf) != 6)
return 0;
n [0] = (unsigned char) xa;
n [1] = (unsigned char) xb;
n [2] = (unsigned char) xc;
n [3] = (unsigned char) xd;
n [4] = (unsigned char) xe;
n [5] = (unsigned char) xf;
memcpy (&(sa->sin_addr.s_addr), (void *)n, 4);
memcpy (&(sa->sin_port), (void *)&n[4], 2);
1998-02-27 07:54:42 +03:00
setup_source_route (my_socket, sa->sin_addr.s_addr);
if (connect (my_socket, (struct sockaddr *) sa, sizeof (struct sockaddr_in)) < 0)
return 0;
return 1;
}
static int
initconn (vfs *me, vfs_s_super *super)
1998-02-27 07:54:42 +03:00
{
struct sockaddr_in data_addr;
int data, len = sizeof(data_addr);
struct protoent *pe;
getsockname(SUP.sock, (struct sockaddr *) &data_addr, &len);
1998-02-27 07:54:42 +03:00
data_addr.sin_port = 0;
pe = getprotobyname("tcp");
if (pe == NULL)
ERRNOR (EIO, -1);
1998-02-27 07:54:42 +03:00
data = socket (AF_INET, SOCK_STREAM, pe->p_proto);
if (data < 0)
ERRNOR (EIO, -1);
1998-02-27 07:54:42 +03:00
if (SUP.use_passive_connection){
if ((SUP.use_passive_connection = setup_passive (me, super, data, &data_addr)))
1998-02-27 07:54:42 +03:00
return data;
SUP.use_source_route = 0;
SUP.use_passive_connection = 0;
print_vfs_message (_("ftpfs: could not setup passive mode"));
1998-02-27 07:54:42 +03:00
}
1998-02-27 07:54:42 +03:00
/* If passive setup fails, fallback to active connections */
/* Active FTP connection */
if ((bind (data, (struct sockaddr *)&data_addr, len) == 0) &&
(getsockname (data, (struct sockaddr *) &data_addr, &len) == 0) &&
(listen (data, 1) == 0))
1998-02-27 07:54:42 +03:00
{
unsigned char *a = (unsigned char *)&data_addr.sin_addr;
unsigned char *p = (unsigned char *)&data_addr.sin_port;
if (command (me, super, WAIT_REPLY, "PORT %d,%d,%d,%d,%d,%d", a[0], a[1],
a[2], a[3], p[0], p[1]) == COMPLETE)
return data;
1998-02-27 07:54:42 +03:00
}
close(data);
my_errno = EIO;
1998-02-27 07:54:42 +03:00
return -1;
}
static int
open_data_connection (vfs *me, vfs_s_super *super, char *cmd, char *remote,
1998-10-13 02:07:53 +04:00
int isbinary, int reget)
1998-02-27 07:54:42 +03:00
{
struct sockaddr_in from;
int s, j, data, fromlen = sizeof(from);
if ((s = initconn (me, super)) == -1)
1998-02-27 07:54:42 +03:00
return -1;
if (changetype (me, super, isbinary) == -1)
1998-02-27 07:54:42 +03:00
return -1;
1998-10-13 02:07:53 +04:00
if (reget > 0){
j = command (me, super, WAIT_REPLY, "REST %d", reget);
1998-02-27 07:54:42 +03:00
if (j != CONTINUE)
return -1;
}
if (remote) {
char * remote_path = translate_path (me, super, remote);
j = command (me, super, WAIT_REPLY, "%s /%s", cmd,
/* WarFtpD can't STORE //filename */
(*remote_path == '/') ? remote_path + 1 : remote_path);
g_free (remote_path);
} else
j = command (me, super, WAIT_REPLY, "%s", cmd);
if (j != PRELIM)
ERRNOR (EPERM, -1);
1998-02-27 07:54:42 +03:00
enable_interrupt_key();
if (SUP.use_passive_connection)
1998-02-27 07:54:42 +03:00
data = s;
else {
data = accept (s, (struct sockaddr *)&from, &fromlen);
close(s);
1998-02-27 07:54:42 +03:00
if (data < 0) {
my_errno = errno;
1998-02-27 07:54:42 +03:00
return -1;
}
}
disable_interrupt_key();
return data;
}
#define ABORT_TIMEOUT 5
1998-02-27 07:54:42 +03:00
static void
linear_abort (vfs *me, vfs_s_fh *fh)
1998-02-27 07:54:42 +03:00
{
vfs_s_super *super = FH_SUPER;
static unsigned char const ipbuf[3] = { IAC, IP, IAC };
1998-02-27 07:54:42 +03:00
fd_set mask;
char buf[1024];
int dsock = FH_SOCK;
FH_SOCK = -1;
SUP.control_connection_buzy = 0;
1998-02-27 07:54:42 +03:00
print_vfs_message (_("ftpfs: aborting transfer."));
if (send (SUP.sock, ipbuf, sizeof (ipbuf), MSG_OOB) != sizeof (ipbuf)) {
print_vfs_message (_("ftpfs: abort error: %s"),
unix_error_string (errno));
if (dsock != -1)
close (dsock);
1998-02-27 07:54:42 +03:00
return;
}
if (command (me, super, NONE, "%cABOR", DM) != COMPLETE) {
print_vfs_message (_("ftpfs: abort failed"));
if (dsock != -1)
close (dsock);
1998-02-27 07:54:42 +03:00
return;
}
if (dsock != -1) {
FD_ZERO (&mask);
FD_SET (dsock, &mask);
if (select (dsock + 1, &mask, NULL, NULL, NULL) > 0) {
struct timeval start_tim, tim;
gettimeofday (&start_tim, NULL);
/* flush the remaining data */
while (read (dsock, buf, sizeof (buf)) > 0) {
gettimeofday (&tim, NULL);
if (tim.tv_sec > start_tim.tv_sec + ABORT_TIMEOUT) {
/* server keeps sending, drop the connection and reconnect */
reconnect (me, super);
return;
}
}
}
close (dsock);
}
if ((get_reply (me, SUP.sock, NULL, 0) == TRANSIENT) && (code == 426))
get_reply (me, SUP.sock, NULL, 0);
1998-02-27 07:54:42 +03:00
}
#if 0
1998-02-27 07:54:42 +03:00
static void
resolve_symlink_without_ls_options(vfs *me, vfs_s_super *super, vfs_s_inode *dir)
1998-02-27 07:54:42 +03:00
{
struct linklist *flist;
Tue Sep 15 20:51:42 1998 Norbert Warmuth <k3190@fh-sw.de> * setup.c: save and restore new global variable/option ftp_use_unix_list_options Tue Sep 15 20:31:32 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.c (ftp_use_unix_list_options): New global variable/option. If true we try to use 'LIST -la <path>'. When it fails we use the two commands 'CWD <path>' and 'LIST' instead. (resolve_symlink): rewritten. Don't get a second directory listing with `LIST -lLa'. Instead use the cache to get the file stat of symbolic links. If the directory the symlink points to isn't already in the cache the directory listing will be fetched and stored in the directory cache (without resolving symlinks recursively). The new method to resolve symlinks is faster if symlinks the same directory or the directory the symlink points to is already in the cache. This function was small and nice until I discovered that it was broken for symlinks to symlinks. Now it looks ugly and perhaps I will revert it to use "LIST -lLa" again. With a fast connection it doesn't matter which methode we use but with a slow connection I wouldn't hesitate to burn more cpu cycles on the client side. (retrieve_dir): Added parameter to tell whether to resolve symlinks (don't resolve symlinks in directory listings retrieved while resolving symlinks). When we don't get a directory listing with 'LIST -la <path>' then try to get it with `CWD <path>; LIST'. Tue Sep 15 20:27:29 1998 Norbert Warmuth <k3190@fh-sw.de * ftpfs.c (login_server): s/ftpfs_get_host/my_get_host/ (retrieve_file_start2): Don't create target file O_EXCL, in copy_file_file we check existance of the target file and know that we want to truncate it (this change was already done a while back but it was reverted with the vfs-split). Tue Sep 15 20:15:42 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.h (struct connection): added boolean which indicates that the ftp server doesn't unterstand Unix ls options * ftpfs.h (struct dir): added enum to store symlink status of the in memory directory cache (directory has no symbolic links; symbolic links but not yet resolved; symbolic links which are resolved) Tue Sep 15 20:02:08 1998 Norbert Warmuth <k3190@fh-sw.de> * shared_ftp_fish.c, fish.c: updated references to retrieve_dir to honour the additional boolean parameter
1998-09-15 23:41:22 +04:00
struct direntry *fe, *fel;
char tmp[MC_MAXPATHLEN];
int depth;
1998-02-27 07:54:42 +03:00
dir->symlink_status = FTPFS_RESOLVING_SYMLINKS;
Tue Sep 15 20:51:42 1998 Norbert Warmuth <k3190@fh-sw.de> * setup.c: save and restore new global variable/option ftp_use_unix_list_options Tue Sep 15 20:31:32 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.c (ftp_use_unix_list_options): New global variable/option. If true we try to use 'LIST -la <path>'. When it fails we use the two commands 'CWD <path>' and 'LIST' instead. (resolve_symlink): rewritten. Don't get a second directory listing with `LIST -lLa'. Instead use the cache to get the file stat of symbolic links. If the directory the symlink points to isn't already in the cache the directory listing will be fetched and stored in the directory cache (without resolving symlinks recursively). The new method to resolve symlinks is faster if symlinks the same directory or the directory the symlink points to is already in the cache. This function was small and nice until I discovered that it was broken for symlinks to symlinks. Now it looks ugly and perhaps I will revert it to use "LIST -lLa" again. With a fast connection it doesn't matter which methode we use but with a slow connection I wouldn't hesitate to burn more cpu cycles on the client side. (retrieve_dir): Added parameter to tell whether to resolve symlinks (don't resolve symlinks in directory listings retrieved while resolving symlinks). When we don't get a directory listing with 'LIST -la <path>' then try to get it with `CWD <path>; LIST'. Tue Sep 15 20:27:29 1998 Norbert Warmuth <k3190@fh-sw.de * ftpfs.c (login_server): s/ftpfs_get_host/my_get_host/ (retrieve_file_start2): Don't create target file O_EXCL, in copy_file_file we check existance of the target file and know that we want to truncate it (this change was already done a while back but it was reverted with the vfs-split). Tue Sep 15 20:15:42 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.h (struct connection): added boolean which indicates that the ftp server doesn't unterstand Unix ls options * ftpfs.h (struct dir): added enum to store symlink status of the in memory directory cache (directory has no symbolic links; symbolic links but not yet resolved; symbolic links which are resolved) Tue Sep 15 20:02:08 1998 Norbert Warmuth <k3190@fh-sw.de> * shared_ftp_fish.c, fish.c: updated references to retrieve_dir to honour the additional boolean parameter
1998-09-15 23:41:22 +04:00
for (flist = dir->file_list->next; flist != dir->file_list; flist = flist->next) {
/* flist->data->l_stat is alread initialized with 0 */
fel = flist->data;
if (S_ISLNK(fel->s.st_mode) && fel->linkname) {
Tue Sep 15 20:51:42 1998 Norbert Warmuth <k3190@fh-sw.de> * setup.c: save and restore new global variable/option ftp_use_unix_list_options Tue Sep 15 20:31:32 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.c (ftp_use_unix_list_options): New global variable/option. If true we try to use 'LIST -la <path>'. When it fails we use the two commands 'CWD <path>' and 'LIST' instead. (resolve_symlink): rewritten. Don't get a second directory listing with `LIST -lLa'. Instead use the cache to get the file stat of symbolic links. If the directory the symlink points to isn't already in the cache the directory listing will be fetched and stored in the directory cache (without resolving symlinks recursively). The new method to resolve symlinks is faster if symlinks the same directory or the directory the symlink points to is already in the cache. This function was small and nice until I discovered that it was broken for symlinks to symlinks. Now it looks ugly and perhaps I will revert it to use "LIST -lLa" again. With a fast connection it doesn't matter which methode we use but with a slow connection I wouldn't hesitate to burn more cpu cycles on the client side. (retrieve_dir): Added parameter to tell whether to resolve symlinks (don't resolve symlinks in directory listings retrieved while resolving symlinks). When we don't get a directory listing with 'LIST -la <path>' then try to get it with `CWD <path>; LIST'. Tue Sep 15 20:27:29 1998 Norbert Warmuth <k3190@fh-sw.de * ftpfs.c (login_server): s/ftpfs_get_host/my_get_host/ (retrieve_file_start2): Don't create target file O_EXCL, in copy_file_file we check existance of the target file and know that we want to truncate it (this change was already done a while back but it was reverted with the vfs-split). Tue Sep 15 20:15:42 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.h (struct connection): added boolean which indicates that the ftp server doesn't unterstand Unix ls options * ftpfs.h (struct dir): added enum to store symlink status of the in memory directory cache (directory has no symbolic links; symbolic links but not yet resolved; symbolic links which are resolved) Tue Sep 15 20:02:08 1998 Norbert Warmuth <k3190@fh-sw.de> * shared_ftp_fish.c, fish.c: updated references to retrieve_dir to honour the additional boolean parameter
1998-09-15 23:41:22 +04:00
if (fel->linkname[0] == '/') {
if (strlen (fel->linkname) >= MC_MAXPATHLEN)
continue;
strcpy (tmp, fel->linkname);
} else {
if ((strlen (dir->remote_path) + strlen (fel->linkname)) >= MC_MAXPATHLEN)
continue;
strcpy (tmp, dir->remote_path);
if (tmp[1] != '\0')
strcat (tmp, "/");
strcat (tmp + 1, fel->linkname);
Sun May 10 13:21:45 1998 Norbert Warmuth <k3190@fh-sw.de> * edit/syntax.c: Disable debug messages on stderr. * edit/edit.h: Added missing _() Sun May 10 14:51:03 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.c (__ftpfs_chdir): CWD command wasn't sent at all. This optimation is wrong because for directories containing spaces we have to "CWD <pathname>" and "LIST -la" instead of "LIST -la <pathname>". I implemented a different optimation. Now ftpfs_chdir only stores the new working directory and sets a flag. __ftpfs_chdir is called when we really want to change the directory on the ftp server. (resolve_symlink): Log the directory listing to the logfile. * ftpfs.h (struct ftpfs_connection): Added a (per connection) cwd_defered flag. Sun May 10 13:27:50 1998 Norbert Warmuth <k3190@fh-sw.de> * widget.c (handle_char): Don't try to to delete default text in input widget more than once. Right after MC's start copy_filename (ESC Enter) failed because a flag wasn't cleared while characters were stuffed into the commandline (Andrej reported this bug). * main.c (copy_readlink): usr mc_readlink instead of readlink * file.c: Changed default for the copy/move option "dive into subdir if exists" to off (note: this was only possible after the change in setup.c). (copy_dir_dir): Activated the previously uncommented code which implements "Dive into subdirs". Even when there's no case where we actually would like that behaviour it is a documented feature. Though I don't wanted to change the default behavour. Hence the option change. (file_mask_defaults): set dive_into_subdirs (file_mask_dialog): Fix for debian Bug #20727: Move operation with "[ ] Dive into subdir if exists" and destination filename not wildcarded. If destination is an existing directory then files will be moved into this directory. If destination is not an existing directory then src file will be renamed (one file selected) or an error will be displayed (more than one file selected). (file_mask_dialog): made the option "Using shell patterns" local to the current copy/move operation, i.e. this option is always initialized with the global options's value. Previously it affected the global Options/Configuration/shell Patterns. Another possiblilty would be to make the global option a default option on startup and keep changes in the copy/move dialog (without saving these changes with save setup). * setup.c: Don't save and load options which can be changed outside the options menu. For example I don't like that preserve_uid_gid and dive_into_subdirs from the copy/move dialog are saved and restored (strange, what about the other options from this dialog?). It would be much cleaner to make these option read-only. This way one could edit ~/.mc/ini to provide default option setting on startup and "Save setup" wouldn't have side effects outside the option's menu. Sun May 10 13:24:20 1998 Norbert Warmuth <k3190@fh-sw.de> * doc/mc.1.in, doc/mc.sgml, mc.hlp: Updated to reflect new default for dive into subdirs.
1998-05-10 17:41:43 +04:00
}
for ( depth = 0; depth < 100; depth++) { /* depth protects against recursive symbolic links */
canonicalize_pathname (tmp);
Tue Sep 15 20:51:42 1998 Norbert Warmuth <k3190@fh-sw.de> * setup.c: save and restore new global variable/option ftp_use_unix_list_options Tue Sep 15 20:31:32 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.c (ftp_use_unix_list_options): New global variable/option. If true we try to use 'LIST -la <path>'. When it fails we use the two commands 'CWD <path>' and 'LIST' instead. (resolve_symlink): rewritten. Don't get a second directory listing with `LIST -lLa'. Instead use the cache to get the file stat of symbolic links. If the directory the symlink points to isn't already in the cache the directory listing will be fetched and stored in the directory cache (without resolving symlinks recursively). The new method to resolve symlinks is faster if symlinks the same directory or the directory the symlink points to is already in the cache. This function was small and nice until I discovered that it was broken for symlinks to symlinks. Now it looks ugly and perhaps I will revert it to use "LIST -lLa" again. With a fast connection it doesn't matter which methode we use but with a slow connection I wouldn't hesitate to burn more cpu cycles on the client side. (retrieve_dir): Added parameter to tell whether to resolve symlinks (don't resolve symlinks in directory listings retrieved while resolving symlinks). When we don't get a directory listing with 'LIST -la <path>' then try to get it with `CWD <path>; LIST'. Tue Sep 15 20:27:29 1998 Norbert Warmuth <k3190@fh-sw.de * ftpfs.c (login_server): s/ftpfs_get_host/my_get_host/ (retrieve_file_start2): Don't create target file O_EXCL, in copy_file_file we check existance of the target file and know that we want to truncate it (this change was already done a while back but it was reverted with the vfs-split). Tue Sep 15 20:15:42 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.h (struct connection): added boolean which indicates that the ftp server doesn't unterstand Unix ls options * ftpfs.h (struct dir): added enum to store symlink status of the in memory directory cache (directory has no symbolic links; symbolic links but not yet resolved; symbolic links which are resolved) Tue Sep 15 20:02:08 1998 Norbert Warmuth <k3190@fh-sw.de> * shared_ftp_fish.c, fish.c: updated references to retrieve_dir to honour the additional boolean parameter
1998-09-15 23:41:22 +04:00
fe = _get_file_entry(bucket, tmp, 0, 0);
if (fe) {
if (S_ISLNK (fe->s.st_mode) && fe->l_stat == 0) {
/* Symlink points to link which isn't resolved, yet. */
if (fe->linkname[0] == '/') {
if (strlen (fe->linkname) >= MC_MAXPATHLEN)
break;
strcpy (tmp, fe->linkname);
} else {
/* at this point tmp looks always like this
/directory/filename, i.e. no need to check
strrchr's return value */
*(strrchr (tmp, '/') + 1) = '\0'; /* dirname */
if ((strlen (tmp) + strlen (fe->linkname)) >= MC_MAXPATHLEN)
break;
strcat (tmp, fe->linkname);
}
continue;
} else {
fel->l_stat = g_new (struct stat, 1);
Tue Sep 15 20:51:42 1998 Norbert Warmuth <k3190@fh-sw.de> * setup.c: save and restore new global variable/option ftp_use_unix_list_options Tue Sep 15 20:31:32 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.c (ftp_use_unix_list_options): New global variable/option. If true we try to use 'LIST -la <path>'. When it fails we use the two commands 'CWD <path>' and 'LIST' instead. (resolve_symlink): rewritten. Don't get a second directory listing with `LIST -lLa'. Instead use the cache to get the file stat of symbolic links. If the directory the symlink points to isn't already in the cache the directory listing will be fetched and stored in the directory cache (without resolving symlinks recursively). The new method to resolve symlinks is faster if symlinks the same directory or the directory the symlink points to is already in the cache. This function was small and nice until I discovered that it was broken for symlinks to symlinks. Now it looks ugly and perhaps I will revert it to use "LIST -lLa" again. With a fast connection it doesn't matter which methode we use but with a slow connection I wouldn't hesitate to burn more cpu cycles on the client side. (retrieve_dir): Added parameter to tell whether to resolve symlinks (don't resolve symlinks in directory listings retrieved while resolving symlinks). When we don't get a directory listing with 'LIST -la <path>' then try to get it with `CWD <path>; LIST'. Tue Sep 15 20:27:29 1998 Norbert Warmuth <k3190@fh-sw.de * ftpfs.c (login_server): s/ftpfs_get_host/my_get_host/ (retrieve_file_start2): Don't create target file O_EXCL, in copy_file_file we check existance of the target file and know that we want to truncate it (this change was already done a while back but it was reverted with the vfs-split). Tue Sep 15 20:15:42 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.h (struct connection): added boolean which indicates that the ftp server doesn't unterstand Unix ls options * ftpfs.h (struct dir): added enum to store symlink status of the in memory directory cache (directory has no symbolic links; symbolic links but not yet resolved; symbolic links which are resolved) Tue Sep 15 20:02:08 1998 Norbert Warmuth <k3190@fh-sw.de> * shared_ftp_fish.c, fish.c: updated references to retrieve_dir to honour the additional boolean parameter
1998-09-15 23:41:22 +04:00
if ( S_ISLNK (fe->s.st_mode))
*fel->l_stat = *fe->l_stat;
else
*fel->l_stat = fe->s;
(*fel->l_stat).st_ino = bucket->__inode_counter++;
}
}
break;
1998-02-27 07:54:42 +03:00
}
Tue Sep 15 20:51:42 1998 Norbert Warmuth <k3190@fh-sw.de> * setup.c: save and restore new global variable/option ftp_use_unix_list_options Tue Sep 15 20:31:32 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.c (ftp_use_unix_list_options): New global variable/option. If true we try to use 'LIST -la <path>'. When it fails we use the two commands 'CWD <path>' and 'LIST' instead. (resolve_symlink): rewritten. Don't get a second directory listing with `LIST -lLa'. Instead use the cache to get the file stat of symbolic links. If the directory the symlink points to isn't already in the cache the directory listing will be fetched and stored in the directory cache (without resolving symlinks recursively). The new method to resolve symlinks is faster if symlinks the same directory or the directory the symlink points to is already in the cache. This function was small and nice until I discovered that it was broken for symlinks to symlinks. Now it looks ugly and perhaps I will revert it to use "LIST -lLa" again. With a fast connection it doesn't matter which methode we use but with a slow connection I wouldn't hesitate to burn more cpu cycles on the client side. (retrieve_dir): Added parameter to tell whether to resolve symlinks (don't resolve symlinks in directory listings retrieved while resolving symlinks). When we don't get a directory listing with 'LIST -la <path>' then try to get it with `CWD <path>; LIST'. Tue Sep 15 20:27:29 1998 Norbert Warmuth <k3190@fh-sw.de * ftpfs.c (login_server): s/ftpfs_get_host/my_get_host/ (retrieve_file_start2): Don't create target file O_EXCL, in copy_file_file we check existance of the target file and know that we want to truncate it (this change was already done a while back but it was reverted with the vfs-split). Tue Sep 15 20:15:42 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.h (struct connection): added boolean which indicates that the ftp server doesn't unterstand Unix ls options * ftpfs.h (struct dir): added enum to store symlink status of the in memory directory cache (directory has no symbolic links; symbolic links but not yet resolved; symbolic links which are resolved) Tue Sep 15 20:02:08 1998 Norbert Warmuth <k3190@fh-sw.de> * shared_ftp_fish.c, fish.c: updated references to retrieve_dir to honour the additional boolean parameter
1998-09-15 23:41:22 +04:00
}
1998-02-27 07:54:42 +03:00
}
dir->symlink_status = FTPFS_RESOLVED_SYMLINKS;
}
static void
resolve_symlink_with_ls_options(vfs *me, vfs_s_super *super, vfs_s_inode *dir)
{
char buffer[2048] = "", *filename;
int sock;
FILE *fp;
struct stat s;
struct linklist *flist;
struct direntry *fe;
int switch_method = 0;
dir->symlink_status = FTPFS_RESOLVED_SYMLINKS;
if (strchr (dir->remote_path, ' ')) {
if (ftpfs_chdir_internal (bucket, dir->remote_path) != COMPLETE) {
print_vfs_message(_("ftpfs: CWD failed."));
return;
}
sock = open_data_connection (bucket, "LIST -lLa", ".", TYPE_ASCII, 0);
}
else
sock = open_data_connection (bucket, "LIST -lLa",
dir->remote_path, TYPE_ASCII, 0);
if (sock == -1) {
print_vfs_message(_("ftpfs: couldn't resolve symlink"));
return;
}
fp = fdopen(sock, "r");
if (fp == NULL) {
close(sock);
print_vfs_message(_("ftpfs: couldn't resolve symlink"));
return;
}
enable_interrupt_key();
flist = dir->file_list->next;
while (1) {
do {
if (flist == dir->file_list)
goto done;
fe = flist->data;
flist = flist->next;
} while (!S_ISLNK(fe->s.st_mode));
while (1) {
if (fgets (buffer, sizeof (buffer), fp) == NULL)
goto done;
if (logfile){
fputs (buffer, logfile);
fflush (logfile);
}
vfs_die("This code should be commented out\n");
if (vfs_parse_ls_lga (buffer, &s, &filename, NULL)) {
int r = strcmp(fe->name, filename);
g_free(filename);
if (r == 0) {
if (S_ISLNK (s.st_mode)) {
/* This server doesn't understand LIST -lLa */
switch_method = 1;
goto done;
}
fe->l_stat = g_new (struct stat, 1);
if (fe->l_stat == NULL)
goto done;
*fe->l_stat = s;
(*fe->l_stat).st_ino = bucket->__inode_counter++;
break;
}
if (r < 0)
break;
}
}
}
done:
while (fgets(buffer, sizeof(buffer), fp) != NULL);
disable_interrupt_key();
fclose(fp);
get_reply(me, SUP.sock, NULL, 0);
}
static void
resolve_symlink(vfs *me, vfs_s_super *super, vfs_s_inode *dir)
{
print_vfs_message(_("Resolving symlink..."));
if (SUP.strict_rfc959_list_cmd)
resolve_symlink_without_ls_options(me, super, dir);
else
resolve_symlink_with_ls_options(me, super, dir);
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
}
#endif
static int
dir_load(vfs *me, vfs_s_inode *dir, char *remote_path)
1998-02-27 07:54:42 +03:00
{
vfs_s_entry *ent;
vfs_s_super *super = dir->super;
2001-05-15 03:34:43 +04:00
int sock, num_entries = 0;
#ifdef FIXME_LATER
int has_symlinks = 0;
#endif
char buffer[BUF_8K];
int cd_first;
cd_first = ftpfs_first_cd_then_ls || (strchr (remote_path, ' ') != NULL)
|| (SUP.strict == RFC_STRICT);
again:
2000-12-04 22:14:52 +03:00
print_vfs_message(_("ftpfs: Reading FTP directory %s... %s%s"), remote_path,
SUP.strict == RFC_STRICT ? _("(strict rfc959)") : "",
cd_first ? _("(chdir first)") : "");
if (cd_first) {
char *p;
p = translate_path (me, super, remote_path);
if (ftpfs_chdir_internal (me, super, p) != COMPLETE) {
g_free (p);
my_errno = ENOENT;
print_vfs_message(_("ftpfs: CWD failed."));
return -1;
1998-02-27 07:54:42 +03:00
}
g_free (p);
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
}
1998-02-27 07:54:42 +03:00
gettimeofday(&dir->u.ftp.timestamp, NULL);
dir->u.ftp.timestamp.tv_sec += ftpfs_directory_timeout;
if (SUP.strict == RFC_STRICT)
sock = open_data_connection (me, super, "LIST", 0, TYPE_ASCII, 0);
else if (cd_first)
/* Dirty hack to avoid autoprepending / to . */
/* Wu-ftpd produces strange output for '/' if 'LIST -la .' used */
sock = open_data_connection (me, super, "LIST -la", 0, TYPE_ASCII, 0);
1998-02-27 07:54:42 +03:00
else {
/* Trailing "/." is necessary if remote_path is a symlink */
char *path = concat_dir_and_file (remote_path, ".");
sock = open_data_connection (me, super, "LIST -la", path, TYPE_ASCII, 0);
g_free (path);
1998-02-27 07:54:42 +03:00
}
if (sock == -1)
1998-10-28 19:39:53 +03:00
goto fallback;
1998-02-27 07:54:42 +03:00
/* Clear the interrupt flag */
enable_interrupt_key ();
#if 1
{
/* added 20001006 by gisburn
* add dots '.' and '..'. This must be _executed_ before scanning the dir as the
* code below may jump directly into error handling code (without executing
* remaining code). And C doesn't have try {...} finally {}; :-)
*/
vfs_s_inode *parent = dir->ent->dir;
if( parent==NULL )
parent = dir;
ent = vfs_s_generate_entry(me, ".", dir, 0);
ent->ino->st=dir->st;
num_entries++;
vfs_s_insert_entry(me, dir, ent);
ent = vfs_s_generate_entry(me, "..", parent, 0);
ent->ino->st=parent->st;
num_entries++;
vfs_s_insert_entry(me, dir, ent);
}
#endif
while (1) {
int i;
int res = vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), sock);
if (!res)
1998-02-27 07:54:42 +03:00
break;
if (res == EINTR) {
me->verrno = ECONNRESET;
close (sock);
disable_interrupt_key();
get_reply(me, SUP.sock, NULL, 0);
print_vfs_message (_("%s: failure"), me->name);
return -1;
}
if (logfile){
fputs (buffer, logfile);
fputs ("\n", logfile);
fflush (logfile);
1998-02-27 07:54:42 +03:00
}
ent = vfs_s_generate_entry(me, NULL, dir, 0);
i = ent->ino->st.st_nlink;
if (!vfs_parse_ls_lga (buffer, &ent->ino->st, &ent->name, &ent->ino->linkname)) {
vfs_s_free_entry (me, ent);
continue;
1998-02-27 07:54:42 +03:00
}
ent->ino->st.st_nlink = i; /* Ouch, we need to preserve our counts :-( */
num_entries++;
if ((!strcmp(ent->name, ".")) || (!strcmp (ent->name, ".."))) {
g_free (ent->name);
ent->name = NULL; /* Ouch, vfs_s_free_entry "knows" about . and .. being special :-( */
vfs_s_free_entry (me, ent);
continue;
1998-02-27 07:54:42 +03:00
}
vfs_s_insert_entry(me, dir, ent);
1998-02-27 07:54:42 +03:00
}
/* vfs_s_add_dots(me, dir, NULL);
FIXME This really should be here; but we need to provide correct parent.
Disabled for now, please fix it. Pavel
*/
close(sock);
me->verrno = E_REMOTE;
if ((get_reply (me, SUP.sock, NULL, 0) != COMPLETE) || !num_entries)
1998-10-28 19:39:53 +03:00
goto fallback;
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
if (SUP.strict == RFC_AUTODETECT)
SUP.strict = RFC_DARING;
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
#ifdef FIXME_LATER
Tue Sep 15 20:51:42 1998 Norbert Warmuth <k3190@fh-sw.de> * setup.c: save and restore new global variable/option ftp_use_unix_list_options Tue Sep 15 20:31:32 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.c (ftp_use_unix_list_options): New global variable/option. If true we try to use 'LIST -la <path>'. When it fails we use the two commands 'CWD <path>' and 'LIST' instead. (resolve_symlink): rewritten. Don't get a second directory listing with `LIST -lLa'. Instead use the cache to get the file stat of symbolic links. If the directory the symlink points to isn't already in the cache the directory listing will be fetched and stored in the directory cache (without resolving symlinks recursively). The new method to resolve symlinks is faster if symlinks the same directory or the directory the symlink points to is already in the cache. This function was small and nice until I discovered that it was broken for symlinks to symlinks. Now it looks ugly and perhaps I will revert it to use "LIST -lLa" again. With a fast connection it doesn't matter which methode we use but with a slow connection I wouldn't hesitate to burn more cpu cycles on the client side. (retrieve_dir): Added parameter to tell whether to resolve symlinks (don't resolve symlinks in directory listings retrieved while resolving symlinks). When we don't get a directory listing with 'LIST -la <path>' then try to get it with `CWD <path>; LIST'. Tue Sep 15 20:27:29 1998 Norbert Warmuth <k3190@fh-sw.de * ftpfs.c (login_server): s/ftpfs_get_host/my_get_host/ (retrieve_file_start2): Don't create target file O_EXCL, in copy_file_file we check existance of the target file and know that we want to truncate it (this change was already done a while back but it was reverted with the vfs-split). Tue Sep 15 20:15:42 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.h (struct connection): added boolean which indicates that the ftp server doesn't unterstand Unix ls options * ftpfs.h (struct dir): added enum to store symlink status of the in memory directory cache (directory has no symbolic links; symbolic links but not yet resolved; symbolic links which are resolved) Tue Sep 15 20:02:08 1998 Norbert Warmuth <k3190@fh-sw.de> * shared_ftp_fish.c, fish.c: updated references to retrieve_dir to honour the additional boolean parameter
1998-09-15 23:41:22 +04:00
if (has_symlinks) {
if (resolve_symlinks)
resolve_symlink(me, super, dcache);
Tue Sep 15 20:51:42 1998 Norbert Warmuth <k3190@fh-sw.de> * setup.c: save and restore new global variable/option ftp_use_unix_list_options Tue Sep 15 20:31:32 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.c (ftp_use_unix_list_options): New global variable/option. If true we try to use 'LIST -la <path>'. When it fails we use the two commands 'CWD <path>' and 'LIST' instead. (resolve_symlink): rewritten. Don't get a second directory listing with `LIST -lLa'. Instead use the cache to get the file stat of symbolic links. If the directory the symlink points to isn't already in the cache the directory listing will be fetched and stored in the directory cache (without resolving symlinks recursively). The new method to resolve symlinks is faster if symlinks the same directory or the directory the symlink points to is already in the cache. This function was small and nice until I discovered that it was broken for symlinks to symlinks. Now it looks ugly and perhaps I will revert it to use "LIST -lLa" again. With a fast connection it doesn't matter which methode we use but with a slow connection I wouldn't hesitate to burn more cpu cycles on the client side. (retrieve_dir): Added parameter to tell whether to resolve symlinks (don't resolve symlinks in directory listings retrieved while resolving symlinks). When we don't get a directory listing with 'LIST -la <path>' then try to get it with `CWD <path>; LIST'. Tue Sep 15 20:27:29 1998 Norbert Warmuth <k3190@fh-sw.de * ftpfs.c (login_server): s/ftpfs_get_host/my_get_host/ (retrieve_file_start2): Don't create target file O_EXCL, in copy_file_file we check existance of the target file and know that we want to truncate it (this change was already done a while back but it was reverted with the vfs-split). Tue Sep 15 20:15:42 1998 Norbert Warmuth <k3190@fh-sw.de> * ftpfs.h (struct connection): added boolean which indicates that the ftp server doesn't unterstand Unix ls options * ftpfs.h (struct dir): added enum to store symlink status of the in memory directory cache (directory has no symbolic links; symbolic links but not yet resolved; symbolic links which are resolved) Tue Sep 15 20:02:08 1998 Norbert Warmuth <k3190@fh-sw.de> * shared_ftp_fish.c, fish.c: updated references to retrieve_dir to honour the additional boolean parameter
1998-09-15 23:41:22 +04:00
else
dcache->symlink_status = FTPFS_UNRESOLVED_SYMLINKS;
}
1998-02-27 07:54:42 +03:00
#endif
print_vfs_message (_("%s: done."), me->name);
return 0;
1998-10-28 19:39:53 +03:00
fallback:
if (SUP.strict == RFC_AUTODETECT) {
1998-10-28 19:39:53 +03:00
/* It's our first attempt to get a directory listing from this
server (UNIX style LIST command) */
SUP.strict = RFC_STRICT;
/* I hate goto, but recursive call needs another 8K on stack */
/* return dir_load (me, dir, remote_path); */
cd_first = 1;
goto again;
1998-10-28 19:39:53 +03:00
}
print_vfs_message(_("ftpfs: failed; nowhere to fallback to"));
ERRNOR(-1, EACCES);
1998-02-27 07:54:42 +03:00
}
static int
file_store(vfs *me, vfs_s_fh *fh, char *name, char *localname)
1998-02-27 07:54:42 +03:00
{
int h, sock, n;
off_t total;
1998-02-27 07:54:42 +03:00
#ifdef HAVE_STRUCT_LINGER
struct linger li;
#else
int flag_one = 1;
#endif
char buffer[8192];
struct stat s;
vfs_s_super *super = FH_SUPER;
1998-02-27 07:54:42 +03:00
h = open(localname, O_RDONLY);
if (h == -1)
ERRNOR (EIO, -1);
fstat(h, &s);
sock = open_data_connection(me, super, fh->u.ftp.append ? "APPE" : "STOR", name, TYPE_BINARY, 0);
1998-02-27 07:54:42 +03:00
if (sock < 0) {
close(h);
return -1;
1998-02-27 07:54:42 +03:00
}
#ifdef HAVE_STRUCT_LINGER
li.l_onoff = 1;
li.l_linger = 120;
setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(li));
#else
setsockopt(sock, SOL_SOCKET, SO_LINGER, &flag_one, sizeof (flag_one));
#endif
total = 0;
enable_interrupt_key();
while (1) {
while ((n = read(h, buffer, sizeof(buffer))) < 0) {
1998-02-27 07:54:42 +03:00
if (errno == EINTR) {
if (got_interrupt()) {
my_errno = EINTR;
1998-02-27 07:54:42 +03:00
goto error_return;
}
else
continue;
}
my_errno = errno;
1998-02-27 07:54:42 +03:00
goto error_return;
}
if (n == 0)
break;
while (write(sock, buffer, n) < 0) {
if (errno == EINTR) {
if (got_interrupt()) {
my_errno = EINTR;
1998-02-27 07:54:42 +03:00
goto error_return;
}
else
continue;
}
my_errno = errno;
1998-02-27 07:54:42 +03:00
goto error_return;
}
total += n;
print_vfs_message(_("ftpfs: storing file %lu (%lu)"),
(unsigned long) total, (unsigned long) s.st_size);
1998-02-27 07:54:42 +03:00
}
disable_interrupt_key();
close(sock);
close(h);
if (get_reply (me, SUP.sock, NULL, 0) != COMPLETE)
ERRNOR (EIO, -1);
return 0;
1998-02-27 07:54:42 +03:00
error_return:
disable_interrupt_key();
close(sock);
close(h);
get_reply(me, SUP.sock, NULL, 0);
return -1;
1998-02-27 07:54:42 +03:00
}
static int
linear_start(vfs *me, vfs_s_fh *fh, int offset)
1998-02-27 07:54:42 +03:00
{
char *name = vfs_s_fullpath (me, fh->ino);
if (!name)
return 0;
FH_SOCK = open_data_connection(me, FH_SUPER, "RETR", name, TYPE_BINARY, offset);
g_free (name);
if (FH_SOCK == -1)
ERRNOR (EACCES, 0);
fh->linear = LS_LINEAR_OPEN;
FH_SUPER->u.ftp.control_connection_buzy = 1;
fh->u.ftp.append = 0;
1998-02-27 07:54:42 +03:00
return 1;
}
static int
linear_read (vfs *me, vfs_s_fh *fh, void *buf, int len)
1998-02-27 07:54:42 +03:00
{
int n;
vfs_s_super *super = FH_SUPER;
while ((n = read (FH_SOCK, buf, len))<0) {
if ((errno == EINTR) && !got_interrupt())
continue;
break;
}
1998-02-27 07:54:42 +03:00
if (n<0)
linear_abort(me, fh);
if (!n) {
SUP.control_connection_buzy = 0;
close (FH_SOCK);
FH_SOCK = -1;
if ((get_reply (me, SUP.sock, NULL, 0) != COMPLETE))
ERRNOR (E_REMOTE, -1);
return 0;
1998-02-27 07:54:42 +03:00
}
ERRNOR (errno, n);
1998-02-27 07:54:42 +03:00
}
static void
linear_close (vfs *me, vfs_s_fh *fh)
1998-02-27 07:54:42 +03:00
{
if (FH_SOCK != -1)
linear_abort(me, fh);
}
1998-02-27 07:54:42 +03:00
static int ftpfs_ctl (void *fh, int ctlop, int arg)
{
switch (ctlop) {
case MCCTL_IS_NOTREADY:
{
1998-10-13 02:07:53 +04:00
int v;
if (!FH->linear)
1998-10-13 02:07:53 +04:00
vfs_die ("You may not do this");
if (FH->linear == LS_LINEAR_CLOSED)
1998-10-13 02:07:53 +04:00
return 0;
v = vfs_s_select_on_two (FH->u.ftp.sock, 0);
if (((v < 0) && (errno == EINTR)) || v == 0)
return 1;
return 0;
1998-02-27 07:54:42 +03:00
}
default:
return 0;
1998-02-27 07:54:42 +03:00
}
}
/* Warning: filename passed to this command is damaged */
1998-02-27 07:54:42 +03:00
static int
send_ftp_command(vfs *me, char *filename, char *cmd, int flags)
1998-02-27 07:54:42 +03:00
{
char *rpath, *p;
vfs_s_super *super;
1998-02-27 07:54:42 +03:00
int r;
int flush_directory_cache = (flags & OPT_FLUSH);
1998-02-27 07:54:42 +03:00
if (!(rpath = vfs_s_get_path_mangle(me, filename, &super, 0)))
1998-02-27 07:54:42 +03:00
return -1;
p = translate_path (me, super, rpath);
r = command (me, super, WAIT_REPLY, cmd, p);
g_free (p);
vfs_add_noncurrent_stamps (&vfs_ftpfs_ops, (vfsid) super, NULL);
1998-02-27 07:54:42 +03:00
if (flags & OPT_IGNORE_ERROR)
r = COMPLETE;
if (r != COMPLETE)
ERRNOR (EPERM, -1);
1998-02-27 07:54:42 +03:00
if (flush_directory_cache)
vfs_s_invalidate(me, super);
1998-02-27 07:54:42 +03:00
return 0;
}
/* This routine is called as the last step in load_setup */
void
ftpfs_init_passwd(void)
{
ftpfs_anonymous_passwd = load_anon_passwd ();
if (ftpfs_anonymous_passwd)
return;
/* If there is no anonymous ftp password specified
* then we'll just use anonymous@
* We don't send any other thing because:
* - We want to remain anonymous
* - We want to stop SPAM
* - We don't want to let ftp sites to discriminate by the user,
* host or country.
*/
ftpfs_anonymous_passwd = g_strdup ("anonymous@");
1998-02-27 07:54:42 +03:00
}
1998-10-13 02:07:53 +04:00
static int ftpfs_chmod (vfs *me, char *path, int mode)
1998-02-27 07:54:42 +03:00
{
char buf[BUF_SMALL];
2002-02-06 15:32:52 +03:00
g_snprintf(buf, sizeof(buf), "SITE CHMOD %4.4o /%%s", mode & 07777);
2002-02-06 15:32:52 +03:00
return send_ftp_command(me, path, buf, OPT_FLUSH);
1998-02-27 07:54:42 +03:00
}
1998-10-13 02:07:53 +04:00
static int ftpfs_chown (vfs *me, char *path, int owner, int group)
1998-02-27 07:54:42 +03:00
{
#if 0
my_errno = EPERM;
1998-02-27 07:54:42 +03:00
return -1;
#else
/* Everyone knows it is not possible to chown remotely, so why bother them.
If someone's root, then copy/move will always try to chown it... */
return 0;
#endif
}
static int ftpfs_unlink (vfs *me, char *path)
1998-02-27 07:54:42 +03:00
{
return send_ftp_command(me, path, "DELE /%s", OPT_FLUSH);
1998-02-27 07:54:42 +03:00
}
/* Return 1 if path is the same directory as the one we are in now */
static int
is_same_dir (vfs *me, vfs_s_super *super, const char *path)
1998-02-27 07:54:42 +03:00
{
if (!SUP.cwdir)
return 0;
if (strcmp (path, SUP.cwdir) == 0)
return 1;
return 0;
1998-02-27 07:54:42 +03:00
}
static int
ftpfs_chdir_internal (vfs *me, vfs_s_super *super, char *remote_path)
1998-02-27 07:54:42 +03:00
{
int r;
Rerun configure when you have problems with missing slang.h. Sun Jan 31 20:04:13 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/vfs.c (vfs_strip_suffix_from_filename): Whoever replaces every occurance of 0 with NULL should stop this stupidy. And replacing '\0' with NULL is plain wrong!!. Reverted this replacement. * vfs/ftpfs.c (load_no_proxy_list): ditto Fri Jan 29 22:55:56 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * slang/slang.h: renamed to slang-mc.h * slang/Makefile.in: delete slang.h on "make clean" * configure.in: link slang/slang-mc.h to slang/slang.h when the included slang is used. Problem was that MC's slang.h was used when we compiled with an already installed SLang and the systems header file were included with <slang/slang.h>. Unfortunatly I can't use AC_LINK_FILES to make the links because if we needn't make any links AC_LINK_FILES makes a link from srcdir to top_builddir (builddir != srcdir). Temporary add $LGPM to $LIBS when checking for the resizeterm and keyok functions (ncurses might be linked against GPM). Substitude PACKAGE (intl/Makefile makes use of it) Sun Jan 31 19:42:47 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * gnome/Makefile.in (install_mx): make it work with srcdir != builddir (gmc.gnorba is located in $srcdir) * src/hotlist.c (add_new_entry_input, add_new_group_input): Make the quick_widget arrays static and various changes needed because they are now static. add_widgets_i18n recalculates button positions which get lost when the quick_widget arrays are non static. * src/screen.c (to_buffer): nul terminate string when using strncpy * src/setup.c: Save and restore new option ftpfs_first_cd_then_ls. Sun Jan 31 19:57:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * vfs/ftpfs.c (insert_dot): New function. Insert a "." into the linked list. Stat'ing the root directory of a ftpfs fails if the dot is missing. (retrieve_dir): insert "." into the linked list if the ftp server haven't send it. Sun Jan 31 19:50:24 1999 Norbert Warmuth <nwarmuth@privat.circular.de> * The following changes make ftpfs work with a remote AmiTCP server are the result of somehow longish EMail debugging session. I don't know any public server of this kind but I was told the combination Unix/Amiga boxes are often used in intranets. * vfs/ftpfs.c (translate_path): New function. Translate a Unix path, i.e. MC's internal path representation (e.g. /somedir/somefile) to a path valid for the remote server. Every path transfered to the remote server has to be mangled by this function right prior to sending it. Currently only Amiga ftp servers are handled in a special manner. * vfs/ftpfs.c (various places): use translate_path * vfs/ftpfs.c (login_server): Assume we have to mangle pathnames if the greatings string from the server contains the word Amiga. If this assumption is wrong I have to find another way to turn on path translation. * vfs/ftpfs.c (ftpfs_get_current_directory): Prepend a leading slash if it is missing. MC needs it as seperator between hostname and path in its internal url representation.
1999-01-31 23:28:13 +03:00
char *p;
1998-02-27 07:54:42 +03:00
if (!SUP.cwd_defered && is_same_dir (me, super, remote_path))
1998-02-27 07:54:42 +03:00
return COMPLETE;
p = translate_path (me, super, remote_path);
r = command (me, super, WAIT_REPLY, "CWD /%s", p);
g_free (p);
1998-02-27 07:54:42 +03:00
if (r != COMPLETE) {
my_errno = EIO;
1998-02-27 07:54:42 +03:00
} else {
g_free(SUP.cwdir);
SUP.cwdir = g_strdup (remote_path);
SUP.cwd_defered = 0;
1998-02-27 07:54:42 +03:00
}
return r;
}
static int ftpfs_rename (vfs *me, char *path1, char *path2)
1998-02-27 07:54:42 +03:00
{
send_ftp_command(me, path1, "RNFR /%s", OPT_FLUSH);
return send_ftp_command(me, path2, "RNTO /%s", OPT_FLUSH);
1998-02-27 07:54:42 +03:00
}
static int ftpfs_mkdir (vfs *me, char *path, mode_t mode)
1998-02-27 07:54:42 +03:00
{
return send_ftp_command(me, path, "MKD /%s", OPT_FLUSH);
1998-02-27 07:54:42 +03:00
}
static int ftpfs_rmdir (vfs *me, char *path)
1998-02-27 07:54:42 +03:00
{
return send_ftp_command(me, path, "RMD /%s", OPT_FLUSH);
1998-02-27 07:54:42 +03:00
}
static int ftpfs_fh_open (vfs *me, vfs_s_fh *fh, int flags, int mode)
{
fh->u.ftp.append = 0;
/* File will be written only, so no need to retrieve it from ftp server */
if (((flags & O_WRONLY) == O_WRONLY) && !(flags & (O_RDONLY|O_RDWR))){
#ifdef HAVE_STRUCT_LINGER
struct linger li;
#else
int li = 1;
#endif
char * name;
/* linear_start() called, so data will be written
* to local temporary file and stored to ftp server
* by vfs_s_close later
*/
if (FH_SUPER->u.ftp.control_connection_buzy){
if (!fh->ino->localname){
int handle = mc_mkstemps (&fh->ino->localname, me->name, NULL);
if (handle == -1)
return -1;
close (handle);
fh->u.ftp.append = flags & O_APPEND;
}
return 0;
}
name = vfs_s_fullpath (me, fh->ino);
if (!name)
return -1;
fh->handle = open_data_connection(me, fh->ino->super,
(flags & O_APPEND) ? "APPE" : "STOR", name, TYPE_BINARY, 0);
g_free (name);
if (fh->handle < 0)
return -1;
#ifdef HAVE_STRUCT_LINGER
li.l_onoff = 1;
li.l_linger = 120;
#endif
setsockopt(fh->handle, SOL_SOCKET, SO_LINGER, &li, sizeof(li));
if (fh->ino->localname){
unlink (fh->ino->localname);
g_free (fh->ino->localname);
fh->ino->localname = NULL;
}
return 0;
}
if (!fh->ino->localname)
if (vfs_s_retrieve_file (me, fh->ino)==-1)
return -1;
if (!fh->ino->localname)
vfs_die( "retrieve_file failed to fill in localname" );
return 0;
}
static int ftpfs_fh_close (vfs *me, vfs_s_fh *fh)
{
if (fh->handle != -1 && !fh->ino->localname){
close (fh->handle);
fh->handle = -1;
/* File is stored to destination already, so
* we prevent MEDATA->file_store() call from vfs_s_close ()
*/
fh->changed = 0;
if (get_reply (me, fh->ino->SUP.sock, NULL, 0) != COMPLETE)
ERRNOR (EIO, -1);
vfs_s_invalidate (me, FH_SUPER);
}
return 0;
}
static struct vfs_s_data ftp_data = {
NULL,
0,
0,
NULL, /* logfile */
NULL, /* init_inode */
NULL, /* free_inode */
NULL, /* init_entry */
NULL, /* archive_check */
archive_same,
open_archive,
free_archive,
ftpfs_fh_open, /* fh_open */
ftpfs_fh_close, /* fh_close */
vfs_s_find_entry_linear,
dir_load,
dir_uptodate,
file_store,
linear_start,
linear_read,
linear_close
};
1998-02-27 07:54:42 +03:00
static void
ftpfs_done (vfs *me)
{
g_free (ftpfs_anonymous_passwd);
g_free (ftpfs_proxy_host);
}
static void
ftpfs_fill_names (vfs *me, void (*func)(char *))
{
struct vfs_s_super * super = ftp_data.supers;
char *name;
while (super){
name = g_strconcat ("/#ftp:", SUP.user, "@", SUP.host, "/", SUP.cwdir, NULL);
(*func)(name);
g_free (name);
super = super->next;
}
}
1998-10-13 02:07:53 +04:00
vfs vfs_ftpfs_ops = {
NULL, /* This is place of next pointer */
"ftpfs",
F_NET, /* flags */
"ftp:", /* prefix */
&ftp_data, /* data */
0, /* errno */
NULL, /* init */
ftpfs_done, /* done */
ftpfs_fill_names,
NULL,
vfs_s_open,
vfs_s_close,
vfs_s_read,
vfs_s_write,
1998-02-27 07:54:42 +03:00
vfs_s_opendir,
vfs_s_readdir,
vfs_s_closedir,
vfs_s_telldir,
vfs_s_seekdir,
1998-02-27 07:54:42 +03:00
vfs_s_stat,
vfs_s_lstat,
vfs_s_fstat,
1998-02-27 07:54:42 +03:00
ftpfs_chmod,
1998-08-31 14:05:42 +04:00
ftpfs_chown, /* not really implemented but returns success */
1998-02-27 07:54:42 +03:00
NULL,
vfs_s_readlink,
1998-08-31 14:05:42 +04:00
NULL,
NULL,
1998-02-27 07:54:42 +03:00
ftpfs_unlink,
ftpfs_rename,
vfs_s_chdir,
vfs_s_ferrno,
vfs_s_lseek,
1998-08-31 14:05:42 +04:00
NULL,
1998-02-27 07:54:42 +03:00
vfs_s_getid,
vfs_s_nothingisopen,
vfs_s_free,
1998-02-27 07:54:42 +03:00
NULL,
NULL,
1998-02-27 07:54:42 +03:00
ftpfs_mkdir,
ftpfs_rmdir,
ftpfs_ctl,
vfs_s_setctl
1998-10-13 02:07:53 +04:00
MMAPNULL
1998-02-27 07:54:42 +03:00
};
void ftpfs_set_debug (const char *file)
{
logfile = fopen (file, "w+");
if (logfile)
ftp_data.logfile = logfile;
}
static char buffer[BUF_MEDIUM];
1998-02-27 07:54:42 +03:00
static char *netrc, *netrcp;
/* This should match the keywords[] array below */
typedef enum {
NETRC_NONE = 0,
NETRC_DEFAULT,
NETRC_MACHINE,
NETRC_LOGIN,
NETRC_PASSWORD,
NETRC_PASSWD,
NETRC_ACCOUNT,
NETRC_MACDEF,
NETRC_UNKNOWN
} keyword_t;
static keyword_t netrc_next (void)
1998-02-27 07:54:42 +03:00
{
char *p;
keyword_t i;
static const char *const keywords[] = { "default", "machine",
"login", "password", "passwd", "account", "macdef", NULL
};
1998-02-27 07:54:42 +03:00
while (1) {
netrcp = skip_separators (netrcp);
if (*netrcp != '\n')
break;
netrcp++;
1998-02-27 07:54:42 +03:00
}
if (!*netrcp)
return NETRC_NONE;
1998-02-27 07:54:42 +03:00
p = buffer;
if (*netrcp == '"') {
for (netrcp++; *netrcp != '"' && *netrcp; netrcp++) {
1998-02-27 07:54:42 +03:00
if (*netrcp == '\\')
netrcp++;
*p++ = *netrcp;
}
} else {
for (; *netrcp != '\n' && *netrcp != '\t' && *netrcp != ' ' &&
*netrcp != ',' && *netrcp; netrcp++) {
1998-02-27 07:54:42 +03:00
if (*netrcp == '\\')
netrcp++;
*p++ = *netrcp;
}
}
*p = 0;
if (!*buffer)
return 0;
i = NETRC_DEFAULT;
while (keywords[i - 1]) {
if (!strcmp (keywords[i - 1], buffer))
return i;
i++;
}
return NETRC_UNKNOWN;
1998-02-27 07:54:42 +03:00
}
static int netrc_has_incorrect_mode (char *netrcname, char *netrc)
{
static int be_angry = 1;
struct stat mystat;
if (stat (netrcname, &mystat) >= 0 && (mystat.st_mode & 077)) {
if (be_angry) {
message_1s (1, MSG_ERROR,
_("~/.netrc file has not correct mode.\n"
"Remove password or correct mode."));
be_angry = 0;
}
return 1;
}
return 0;
}
/* Scan .netrc until we find matching "machine" or "default"
* domain is used for additional matching
* No search is done after "default" in compliance with "man netrc"
* Return 0 if found, -1 otherwise */
static int find_machine (const char *host, const char *domain)
{
keyword_t keyword;
while ((keyword = netrc_next ()) != NETRC_NONE) {
if (keyword == NETRC_DEFAULT)
return 0;
if (keyword == NETRC_MACDEF) {
/* Scan for an empty line, which concludes "macdef" */
do {
while (*netrcp && *netrcp != '\n')
netrcp++;
if (*netrcp != '\n')
break;
netrcp++;
} while (*netrcp && *netrcp != '\n');
continue;
}
if (keyword != NETRC_MACHINE)
continue;
/* Take machine name */
if (netrc_next () == NETRC_NONE)
break;
if (g_strcasecmp (host, buffer)) {
/* Try adding our domain to short names in .netrc */
char *host_domain = strchr (host, '.');
if (!host_domain)
continue;
/* Compare domain part */
if (g_strcasecmp (host_domain, domain))
continue;
/* Compare local part */
if (g_strncasecmp (host, buffer, host_domain - host))
continue;
}
return 0;
}
/* end of .netrc */
return -1;
}
/* Extract login and password from .netrc for the host.
* pass may be NULL.
* Returns 0 for success, -1 for error */
static int lookup_netrc (const char *host, char **login, char **pass)
1998-02-27 07:54:42 +03:00
{
char *netrcname;
char *tmp_pass = NULL;
1998-02-27 07:54:42 +03:00
char hostname[MAXHOSTNAMELEN], *domain;
keyword_t keyword;
1998-02-27 07:54:42 +03:00
static struct rupcache {
struct rupcache *next;
char *host;
char *login;
char *pass;
1998-02-27 07:54:42 +03:00
} *rup_cache = NULL, *rupp;
/* Initialize *login and *pass */
if (!login)
return 0;
*login = NULL;
if (pass)
*pass = NULL;
/* Look up in the cache first */
for (rupp = rup_cache; rupp != NULL; rupp = rupp->next) {
if (!strcmp (host, rupp->host)) {
if (rupp->login)
*login = g_strdup (rupp->login);
if (pass && rupp->pass)
*pass = g_strdup (rupp->pass);
return 0;
}
}
/* Load current .netrc */
netrcname = concat_dir_and_file (home_dir, ".netrc");
1998-02-27 07:54:42 +03:00
netrcp = netrc = load_file (netrcname);
if (netrc == NULL) {
g_free (netrcname);
1998-02-27 07:54:42 +03:00
return 0;
}
/* Find our own domain name */
1998-02-27 07:54:42 +03:00
if (gethostname (hostname, sizeof (hostname)) < 0)
*hostname = 0;
if (!(domain = strchr (hostname, '.')))
domain = "";
/* Scan for "default" and matching "machine" keywords */
find_machine (host, domain);
/* Scan for keywords following "default" and "machine" */
while (1) {
int need_break = 0;
keyword = netrc_next ();
switch (keyword) {
case NETRC_LOGIN:
if (netrc_next () == NETRC_NONE) {
need_break = 1;
break;
}
/* We have another name already - should not happen */
if (*login) {
need_break = 1;
break;
}
/* We have login name now */
*login = g_strdup (buffer);
break;
case NETRC_PASSWORD:
case NETRC_PASSWD:
if (netrc_next () == NETRC_NONE) {
need_break = 1;
break;
}
/* Ignore unsafe passwords */
if (strcmp (*login, "anonymous") && strcmp (*login, "ftp")
&& netrc_has_incorrect_mode (netrcname, netrc)) {
need_break = 1;
break;
}
/* Remember password. pass may be NULL, so use tmp_pass */
if (tmp_pass == NULL)
tmp_pass = g_strdup (buffer);
break;
case NETRC_ACCOUNT:
/* "account" is followed by a token which we ignore */
if (netrc_next () == NETRC_NONE) {
need_break = 1;
break;
1998-02-27 07:54:42 +03:00
}
/* Ignore account, but warn user anyways */
netrc_has_incorrect_mode (netrcname, netrc);
break;
default:
/* Unexpected keyword or end of file */
need_break = 1;
break;
1998-02-27 07:54:42 +03:00
}
if (need_break)
1998-02-27 07:54:42 +03:00
break;
}
g_free (netrc);
g_free (netrcname);
rupp = g_new (struct rupcache, 1);
rupp->host = g_strdup (host);
1998-02-27 07:54:42 +03:00
rupp->login = rupp->pass = 0;
if (*login != NULL) {
rupp->login = g_strdup (*login);
}
if (tmp_pass != NULL)
rupp->pass = g_strdup (tmp_pass);
1998-02-27 07:54:42 +03:00
rupp->next = rup_cache;
rup_cache = rupp;
if (pass)
*pass = tmp_pass;
1998-02-27 07:54:42 +03:00
return 0;
}