gftp r958 - in trunk: . lib
- From: masneyb svn gnome org
- To: svn-commits-list gnome org
- Subject: gftp r958 - in trunk: . lib
- Date: Tue, 4 Mar 2008 12:28:41 +0000 (GMT)
Author: masneyb
Date: Tue Mar 4 12:28:40 2008
New Revision: 958
URL: http://svn.gnome.org/viewvc/gftp?rev=958&view=rev
Log:
2008-03-04 Brian Masney <masneyb gftp org>
* lib/gftp.h lib/socket-connect.c lib/sockutils.c lib/protocols.c
lib/Makefile.am lib/charset-conv.c lib/parse-dir-listing.c - split
protocols.c into smaller files. No changes were made to the moved
functions.
Added:
trunk/lib/charset-conv.c
trunk/lib/parse-dir-listing.c
trunk/lib/socket-connect.c
trunk/lib/sockutils.c
Modified:
trunk/ChangeLog
trunk/lib/Makefile.am
trunk/lib/gftp.h
trunk/lib/protocols.c
Modified: trunk/lib/Makefile.am
==============================================================================
--- trunk/lib/Makefile.am (original)
+++ trunk/lib/Makefile.am Tue Mar 4 12:28:40 2008
@@ -2,8 +2,9 @@
SUBDIRS=fsplib
noinst_LIBRARIES = libgftp.a
-libgftp_a_SOURCES=bookmark.c cache.c config_file.c fsp.c ftps.c https.c \
- local.c misc.c mkstemps.c protocols.c pty.c rfc959.c \
- rfc2068.c sshv2.c sslcommon.c
+libgftp_a_SOURCES=bookmark.c cache.c charset-conv.c config_file.c fsp.c ftps.c \
+ https.c local.c misc.c mkstemps.c parse-dir-listing.c \
+ protocols.c pty.c rfc959.c rfc2068.c sshv2.c sslcommon.c \
+ socket-connect.c sockutils.c
INCLUDES= GLIB_CFLAGS@ @PTHREAD_CFLAGS@ -I../intl -DSHARE_DIR=\"$(datadir)/gftp\" -DLOCALE_DIR=\"$(datadir)/locale\"
noinst_HEADERS=gftp.h ftpcommon.h httpcommon.h options.h
Added: trunk/lib/charset-conv.c
==============================================================================
--- (empty file)
+++ trunk/lib/charset-conv.c Tue Mar 4 12:28:40 2008
@@ -0,0 +1,263 @@
+/*****************************************************************************/
+/* charset-conv.c - contains functions for performing conversions between */
+/* character sets. */
+/* Copyright (C) 1998-2008 Brian Masney <masneyb gftp org> */
+/* */
+/* This program is free software; you can redistribute it and/or modify */
+/* it under the terms of the GNU General Public License as published by */
+/* the Free Software Foundation; either version 2 of the License, or */
+/* (at your option) any later version. */
+/* */
+/* 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 General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA */
+/*****************************************************************************/
+
+#include "gftp.h"
+static const char cvsid[] = "$Id: protocols.c 952 2008-01-24 23:31:26Z masneyb $";
+
+#if GLIB_MAJOR_VERSION > 1
+
+static /* null@*/ char *
+_gftp_get_next_charset (char **curpos)
+{
+ char *ret, *endpos;
+ size_t len, retlen;
+
+ if (**curpos == '\0')
+ return (NULL);
+
+ for (; **curpos == ' ' || **curpos == '\t'; (*curpos)++);
+
+ if ((endpos = strchr (*curpos, ',')) == NULL)
+ len = strlen (*curpos) - 1; /* the trailing ',' should be omitted */
+ else
+ len = endpos - *curpos;
+
+ for (retlen = len - 1;
+ (*curpos)[retlen - 1] == ' ' || (*curpos)[retlen - 1] == '\t';
+ retlen--);
+
+ retlen++; /* Needed due to the len - 1 above... */
+ ret = g_malloc0 (retlen + 1);
+ memcpy (ret, *curpos, retlen);
+
+ for (*curpos += len; **curpos == ','; (*curpos)++);
+
+ return (ret);
+}
+
+
+static void
+_do_show_iconv_error (const char *str, char *charset, int from_utf8,
+ GError * error)
+{
+ const char *fromset, *toset;
+
+ if (from_utf8)
+ {
+ fromset = "UTF-8";
+ toset = charset;
+ }
+ else
+ {
+ fromset = charset;
+ toset = "UTF-8";
+ }
+
+ printf (_("Error converting string '%s' from character set %s to character set %s: %s\n"),
+ str, fromset, toset, error->message);
+}
+
+
+/* null@*/ static char *
+_do_convert_string (gftp_request * request, int is_filename, int force_local,
+ const char *str, size_t *dest_len, int from_utf8)
+{
+ char *remote_charsets, *ret, *fromset, *toset, *stpos, *cur_charset;
+ GError * error;
+ gsize bread;
+
+ if (request == NULL)
+ return (NULL);
+
+ if (g_utf8_validate (str, -1, NULL) != from_utf8)
+ return (NULL);
+
+ error = NULL;
+ gftp_lookup_request_option (request, "remote_charsets", &remote_charsets);
+ if (*remote_charsets == '\0' || request->use_local_encoding ||
+ force_local == 1)
+ {
+ if (from_utf8)
+ {
+ if (is_filename)
+ ret = g_filename_from_utf8 (str, -1, &bread, dest_len, &error);
+ else
+ ret = g_locale_from_utf8 (str, -1, &bread, dest_len, &error);
+ }
+ else
+ {
+ if (is_filename)
+ ret = g_filename_to_utf8 (str, -1, &bread, dest_len, &error);
+ else
+ ret = g_locale_to_utf8 (str, -1, &bread, dest_len, &error);
+ }
+
+ if (ret == NULL)
+ _do_show_iconv_error (str, request->iconv_charset, from_utf8, error);
+
+ return (ret);
+ }
+
+ if (from_utf8)
+ {
+ if (request->iconv_from_initialized)
+ {
+ ret = g_convert_with_iconv (str, -1, request->iconv_from, &bread, dest_len,
+ &error);
+ if (ret == NULL)
+ _do_show_iconv_error (str, request->iconv_charset, from_utf8, error);
+
+ return (ret);
+ }
+ }
+ else
+ {
+ if (request->iconv_to_initialized)
+ {
+ ret = g_convert_with_iconv (str, -1, request->iconv_to, &bread, dest_len,
+ &error);
+ if (ret == NULL)
+ _do_show_iconv_error (str, request->iconv_charset, from_utf8, error);
+
+ return (ret);
+ }
+ }
+
+ stpos = remote_charsets;
+ while ((cur_charset = _gftp_get_next_charset (&stpos)) != NULL)
+ {
+ if (from_utf8)
+ {
+ fromset = "UTF-8";
+ toset = cur_charset;
+ if ((request->iconv_from = g_iconv_open (toset, fromset)) == (GIConv) -1)
+ {
+ g_free (cur_charset);
+ continue;
+ }
+
+ error = NULL;
+ if ((ret = g_convert_with_iconv (str, -1, request->iconv_from, &bread,
+ dest_len, &error)) == NULL)
+ {
+ g_iconv_close (request->iconv_from);
+ request->iconv_from = NULL;
+ _do_show_iconv_error (str, cur_charset, from_utf8, error);
+ g_free (cur_charset);
+ continue;
+ }
+
+ request->iconv_from_initialized = 1;
+ }
+ else
+ {
+ fromset = cur_charset;
+ toset = "UTF-8";
+ if ((request->iconv_to = g_iconv_open (toset, fromset)) == (GIConv) -1)
+ {
+ g_free (cur_charset);
+ continue;
+ }
+
+ error = NULL;
+ if ((ret = g_convert_with_iconv (str, -1, request->iconv_to, &bread,
+ dest_len, &error)) == NULL)
+ {
+ g_iconv_close (request->iconv_to);
+ request->iconv_to = NULL;
+ _do_show_iconv_error (str, cur_charset, from_utf8, error);
+ g_free (cur_charset);
+ continue;
+ }
+
+ request->iconv_to_initialized = 1;
+ }
+
+ request->iconv_charset = cur_charset;
+ return (ret);
+ }
+
+ return (NULL);
+}
+
+char *
+gftp_string_to_utf8 (gftp_request * request, const char *str, size_t *dest_len)
+{
+ return (_do_convert_string (request, 0, 0, str, dest_len, 0));
+}
+
+
+char *
+gftp_string_from_utf8 (gftp_request * request, int force_local, const char *str,
+ size_t *dest_len)
+{
+ return (_do_convert_string (request, 0, force_local, str, dest_len, 1));
+}
+
+
+char *
+gftp_filename_to_utf8 (gftp_request * request, const char *str,
+ size_t *dest_len)
+{
+ return (_do_convert_string (request, 1, 0, str, dest_len, 0));
+}
+
+
+char *
+gftp_filename_from_utf8 (gftp_request * request, const char *str,
+ size_t *dest_len)
+{
+ return (_do_convert_string (request, 1, 0, str, dest_len, 1));
+}
+
+#else
+
+char *
+gftp_string_to_utf8 (gftp_request * request, const char *str, size_t dest_len)
+{
+ return (NULL);
+}
+
+
+char *
+gftp_string_from_utf8 (gftp_request * request, int force_local, const char *str,
+ size_t dest_len)
+{
+ return (NULL);
+}
+
+
+char *
+gftp_filename_to_utf8 (gftp_request * request, const char *str, size_t dest_len)
+{
+ return (NULL);
+}
+
+
+char *
+gftp_filename_from_utf8 (gftp_request * request, int force_local,
+ const char *str, size_t dest_len)
+{
+ return (NULL);
+}
+
+#endif
+
+
Modified: trunk/lib/gftp.h
==============================================================================
--- trunk/lib/gftp.h (original)
+++ trunk/lib/gftp.h Tue Mar 4 12:28:40 2008
@@ -668,6 +668,24 @@
char *descr,
int ignore_directory );
+/* charset-conv.c */
+/* null@*/ char * gftp_string_to_utf8 ( gftp_request * request,
+ const char *str,
+ size_t *dest_len );
+
+/* null@*/ char * gftp_string_from_utf8 ( gftp_request * request,
+ int force_local,
+ const char *str,
+ size_t *dest_len );
+
+/* null@*/ char * gftp_filename_to_utf8 ( gftp_request * request,
+ const char *str,
+ size_t *dest_len );
+
+/* null@*/ char * gftp_filename_from_utf8 ( gftp_request * request,
+ const char *str,
+ size_t *dest_len );
+
/* config_file.c */
int gftp_config_parse_args ( char *str,
int numargs,
@@ -812,6 +830,15 @@
int mkstemps ( char *template,
int suffix_len );
+/* parse-dir-listing.c */
+time_t parse_time ( char *str,
+ char **endpos );
+
+int gftp_parse_ls ( gftp_request * request,
+ const char *lsoutput,
+ gftp_file *fle,
+ int fd );
+
/* protocols.c */
#define GFTP_FTP_NUM 0
#define GFTP_FTPS_NUM 1
@@ -909,23 +936,6 @@
int gftp_list_files ( gftp_request * request );
-/* null@*/ char * gftp_string_to_utf8 ( gftp_request * request,
- const char *str,
- size_t *dest_len );
-
-/* null@*/ char * gftp_string_from_utf8 ( gftp_request * request,
- int force_local,
- const char *str,
- size_t *dest_len );
-
-/* null@*/ char * gftp_filename_to_utf8 ( gftp_request * request,
- const char *str,
- size_t *dest_len );
-
-/* null@*/ char * gftp_filename_from_utf8 ( gftp_request * request,
- const char *str,
- size_t *dest_len );
-
int gftp_parse_bookmark ( gftp_request * request,
gftp_request * local_request,
const char * bookmark,
@@ -996,23 +1006,10 @@
void gftp_calc_kbs ( gftp_transfer * tdata,
ssize_t num_read );
-time_t parse_time ( char *str,
- char **endpos );
-
-int gftp_parse_ls ( gftp_request * request,
- const char *lsoutput,
- gftp_file *fle,
- int fd );
-
int gftp_get_all_subdirs ( gftp_transfer * transfer,
void (*update_func)
( gftp_transfer * transfer ));
-int gftp_connect_server ( gftp_request * request,
- char *service,
- char *proxy_hostname,
- unsigned int proxy_port );
-
struct hostent *r_gethostbyname ( const char *name,
struct hostent *result_buf,
int *h_errnop );
@@ -1026,33 +1023,6 @@
void print_file_list ( GList * list );
-void gftp_free_getline_buffer ( gftp_getline_buffer ** rbuf );
-
-ssize_t gftp_get_line ( gftp_request * request,
- /* out@*/ gftp_getline_buffer ** rbuf,
- /* out@*/ char * str,
- size_t len,
- int fd );
-
-ssize_t gftp_fd_read ( gftp_request * request,
- void *ptr,
- size_t size,
- int fd );
-
-ssize_t gftp_fd_write ( gftp_request * request,
- const char *ptr,
- size_t size,
- int fd );
-
-ssize_t gftp_writefmt ( gftp_request * request,
- int fd,
- const char *fmt,
- ... );
-
-int gftp_fd_set_sockblocking ( gftp_request * request,
- int fd,
- int non_blocking );
-
void gftp_swap_socks ( gftp_request * dest,
gftp_request * source );
@@ -1118,3 +1088,37 @@
#endif
+/* socket-connect.c */
+int gftp_connect_server ( gftp_request * request,
+ char *service,
+ char *proxy_hostname,
+ unsigned int proxy_port );
+
+/* sockutils.c */
+ssize_t gftp_get_line ( gftp_request * request,
+ /* out@*/ gftp_getline_buffer ** rbuf,
+ /* out@*/ char * str,
+ size_t len,
+ int fd );
+
+void gftp_free_getline_buffer ( gftp_getline_buffer ** rbuf );
+
+ssize_t gftp_fd_read ( gftp_request * request,
+ void *ptr,
+ size_t size,
+ int fd );
+
+ssize_t gftp_fd_write ( gftp_request * request,
+ const char *ptr,
+ size_t size,
+ int fd );
+
+ssize_t gftp_writefmt ( gftp_request * request,
+ int fd,
+ const char *fmt,
+ ... );
+
+int gftp_fd_set_sockblocking ( gftp_request * request,
+ int fd,
+ int non_blocking );
+
Added: trunk/lib/parse-dir-listing.c
==============================================================================
--- (empty file)
+++ trunk/lib/parse-dir-listing.c Tue Mar 4 12:28:40 2008
@@ -0,0 +1,655 @@
+/*****************************************************************************/
+/* parse-dir-listing.c - contains functions for parsing the different types */
+/* of directory listings. */
+/* Copyright (C) 1998-2008 Brian Masney <masneyb gftp org> */
+/* */
+/* This program is free software; you can redistribute it and/or modify */
+/* it under the terms of the GNU General Public License as published by */
+/* the Free Software Foundation; either version 2 of the License, or */
+/* (at your option) any later version. */
+/* */
+/* 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 General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA */
+/*****************************************************************************/
+
+#include "gftp.h"
+static const char cvsid[] = "$Id: protocols.c 952 2008-01-24 23:31:26Z masneyb $";
+
+static char *
+copy_token (/* out@*/ char **dest, char *source)
+{
+ char *endpos, savepos;
+
+ endpos = source;
+ while (*endpos != ' ' && *endpos != '\t' && *endpos != '\0')
+ endpos++;
+ if (*endpos == '\0')
+ {
+ *dest = NULL;
+ return (NULL);
+ }
+
+ savepos = *endpos;
+ *endpos = '\0';
+ *dest = g_malloc0 ((gulong) (endpos - source + 1));
+ strcpy (*dest, source);
+ *endpos = savepos;
+
+ /* Skip the blanks till we get to the next entry */
+ source = endpos + 1;
+ while ((*source == ' ' || *source == '\t') && *source != '\0')
+ source++;
+ return (source);
+}
+
+
+static char *
+goto_next_token (char *pos)
+{
+ while (*pos != ' ' && *pos != '\t' && *pos != '\0')
+ pos++;
+
+ while (*pos == ' ' || *pos == '\t')
+ pos++;
+
+ return (pos);
+}
+
+
+static time_t
+parse_vms_time (char *str, char **endpos)
+{
+ struct tm curtime;
+ time_t ret;
+
+ /* 8-JUN-2004 13:04:14 */
+ memset (&curtime, 0, sizeof (curtime));
+
+ *endpos = strptime (str, "%d-%b-%Y %H:%M:%S", &curtime);
+ if (*endpos == NULL)
+ *endpos = strptime (str, "%d-%b-%Y %H:%M", &curtime);
+
+ if (*endpos != NULL)
+ {
+ ret = mktime (&curtime);
+ for (; **endpos == ' ' || **endpos == '\t'; (*endpos)++);
+ }
+ else
+ {
+ ret = 0;
+ *endpos = goto_next_token (str);
+ if (*endpos != NULL)
+ *endpos = goto_next_token (*endpos);
+ }
+
+ return (ret);
+}
+
+
+time_t
+parse_time (char *str, char **endpos)
+{
+ struct tm curtime, *loctime;
+ time_t t, ret;
+ char *tmppos;
+ size_t slen;
+ int i, num;
+
+ slen = strlen (str);
+ memset (&curtime, 0, sizeof (curtime));
+ curtime.tm_isdst = -1;
+
+ if (slen > 4 && isdigit ((int) str[0]) && str[2] == '-' &&
+ isdigit ((int) str[3]))
+ {
+ /* This is how DOS will return the date/time */
+ /* 07-06-99 12:57PM */
+
+ tmppos = strptime (str, "%m-%d-%y %I:%M%p", &curtime);
+ }
+ else if (slen > 4 && isdigit ((int) str[0]) && str[2] == '-' &&
+ isalpha (str[3]))
+ {
+ /* 10-Jan-2003 09:14 */
+ tmppos = strptime (str, "%d-%h-%Y %H:%M", &curtime);
+ }
+ else if (slen > 4 && isdigit ((int) str[0]) && str[4] == '/')
+ {
+ /* 2003/12/25 */
+ tmppos = strptime (str, "%Y/%m/%d", &curtime);
+ }
+ else
+ {
+ /* This is how most UNIX, Novell, and MacOS ftp servers send their time */
+ /* Jul 06 12:57 or Jul 6 1999 */
+
+ if (strchr (str, ':') != NULL)
+ {
+ tmppos = strptime (str, "%h %d %H:%M", &curtime);
+ t = time (NULL);
+ loctime = localtime (&t);
+
+ if (curtime.tm_mon > loctime->tm_mon)
+ curtime.tm_year = loctime->tm_year - 1;
+ else
+ curtime.tm_year = loctime->tm_year;
+ }
+ else
+ tmppos = strptime (str, "%h %d %Y", &curtime);
+ }
+
+ if (tmppos != NULL)
+ ret = mktime (&curtime);
+ else
+ ret = 0;
+
+ if (endpos != NULL)
+ {
+ if (tmppos == NULL)
+ {
+ /* We cannot parse this date format. So, just skip this date field
+ and continue to the next token. This is mainly for the HTTP
+ support */
+
+ *endpos = str;
+ for (num = 0; num < 2 && **endpos != '\0'; num++)
+ {
+ for (i=0;
+ (*endpos)[i] != ' ' && (*endpos)[i] != '\t' &&
+ (*endpos)[i] != '\0';
+ i++);
+ *endpos += i;
+
+ for (i=0; (*endpos)[i] == ' ' || (*endpos)[i] == '\t'; i++);
+ *endpos += i;
+ }
+ }
+ else
+ *endpos = tmppos;
+ }
+
+ return (ret);
+}
+
+
+static mode_t
+gftp_parse_vms_attribs (char **src, mode_t mask)
+{
+ char *endpos;
+ mode_t ret;
+
+ if (*src == NULL)
+ return (0);
+
+ if ((endpos = strchr (*src, ',')) != NULL)
+ *endpos = '\0';
+
+ ret = 0;
+ if (strchr (*src, 'R') != NULL)
+ ret |= S_IRUSR | S_IRGRP | S_IROTH;
+ if (strchr (*src, 'W') != NULL)
+ ret |= S_IWUSR | S_IWGRP | S_IWOTH;
+ if (strchr (*src, 'E') != NULL)
+ ret |= S_IXUSR | S_IXGRP | S_IXOTH;
+
+ *src = endpos + 1;
+
+ return (ret & mask);
+}
+
+
+static int
+gftp_parse_ls_vms (gftp_request * request, int fd, char *str, gftp_file * fle)
+{
+ char *curpos, *endpos, tempstr[1024];
+ int multiline;
+ ssize_t len;
+
+ /* .PINE-DEBUG1;1 9 21-AUG-2002 20:06 [MYERSRG] (RWED,RWED,,) */
+ /* WWW.DIR;1 1 23-NOV-1999 05:47 [MYERSRG] (RWE,RWE,RE,E) */
+
+ /* Multiline VMS
+ $MAIN.TPU$JOURNAL;1
+ 1/18 8-JUN-2004 13:04:14 [NUCLEAR,FISSION] (RWED,RWED,RE,)
+ TCPIP$FTP_SERVER.LOG;29
+ 0/18 8-JUN-2004 14:42:04 [NUCLEAR,FISSION] (RWED,RWED,RE,)
+ TCPIP$FTP_SERVER.LOG;28
+ 5/18 8-JUN-2004 13:05:11 [NUCLEAR,FISSION] (RWED,RWED,RE,)
+ TCPIP$FTP_SERVER.LOG;27
+ 5/18 8-JUN-2004 13:03:51 [NUCLEAR,FISSION] (RWED,RWED,RE,) */
+
+ if ((curpos = strchr (str, ';')) == NULL)
+ return (GFTP_EFATAL);
+
+ multiline = strchr (str, ' ') == NULL;
+
+ *curpos = '\0';
+ if (strlen (str) > 4 && strcmp (curpos - 4, ".DIR") == 0)
+ {
+ fle->st_mode |= S_IFDIR;
+ *(curpos - 4) = '\0';
+ }
+
+ fle->file = g_strdup (str);
+
+ if (multiline)
+ {
+ if (request->get_next_dirlist_line == NULL)
+ return (GFTP_EFATAL);
+
+ len = request->get_next_dirlist_line (request, fd, tempstr,
+ sizeof (tempstr));
+ if (len <= 0)
+ return ((int) len);
+
+ for (curpos = tempstr; *curpos == ' ' || *curpos == '\t'; curpos++);
+ }
+ else
+ curpos = goto_next_token (curpos + 1);
+
+ fle->size = gftp_parse_file_size (curpos) * 512; /* Is this correct? */
+
+ curpos = goto_next_token (curpos);
+
+ fle->datetime = parse_vms_time (curpos, &curpos);
+
+ if (*curpos != '[')
+ return (GFTP_EFATAL);
+
+ if ((endpos = strchr (curpos, ']')) == NULL)
+ return (GFTP_EFATAL);
+
+ curpos = goto_next_token (endpos + 1);
+ if ((curpos = strchr (curpos, ',')) == NULL)
+ return (0);
+ curpos++;
+
+ fle->st_mode = gftp_parse_vms_attribs (&curpos, S_IRWXU);
+ fle->st_mode |= gftp_parse_vms_attribs (&curpos, S_IRWXG);
+ fle->st_mode |= gftp_parse_vms_attribs (&curpos, S_IRWXO);
+
+ fle->user = g_strdup ("");
+ fle->group = g_strdup ("");
+
+ return (0);
+}
+
+
+static int
+gftp_parse_ls_mvs (char *str, gftp_file * fle)
+{
+ char *curpos;
+
+ /* Volume Unit Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname */
+ /* SVI52A 3390 2003/12/10 8 216 FB 80 27920 PS CARDS.DELETES */
+ /* SVI528 3390 2003/12/12 1 5 FB 80 24000 PO CLIST */
+
+ curpos = goto_next_token (str + 1);
+ if (curpos == NULL)
+ return (GFTP_EFATAL);
+
+ curpos = goto_next_token (curpos + 1);
+ if (curpos == NULL)
+ return (GFTP_EFATAL);
+
+ fle->datetime = parse_time (curpos, &curpos);
+
+ curpos = goto_next_token (curpos);
+ if (curpos == NULL)
+ return (GFTP_EFATAL);
+
+ curpos = goto_next_token (curpos + 1);
+ if (curpos == NULL)
+ return (GFTP_EFATAL);
+
+ fle->size = gftp_parse_file_size (curpos) * 55996;
+ curpos = goto_next_token (curpos + 1);
+ if (curpos == NULL)
+ return (GFTP_EFATAL);
+
+ curpos = goto_next_token (curpos + 1);
+ if (curpos == NULL)
+ return (GFTP_EFATAL);
+
+ curpos = goto_next_token (curpos + 1);
+ if (curpos == NULL)
+ return (GFTP_EFATAL);
+
+ curpos = goto_next_token (curpos + 1);
+ if (curpos == NULL)
+ return (GFTP_EFATAL);
+
+ if (strncmp (curpos, "PS", 2) == 0)
+ fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+ else if (strncmp (curpos, "PO", 2) == 0)
+ fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+ else
+ return (GFTP_EFATAL);
+
+ curpos = goto_next_token (curpos + 1);
+
+ fle->user = g_strdup (_("unknown"));
+ fle->group = g_strdup (_("unknown"));
+ fle->file = g_strdup (curpos);
+
+ return (0);
+}
+
+
+static int
+gftp_parse_ls_eplf (char *str, gftp_file * fle)
+{
+ char *startpos;
+ int isdir = 0;
+
+ startpos = str;
+ while (startpos)
+ {
+ startpos++;
+ switch (*startpos)
+ {
+ case '/':
+ isdir = 1;
+ break;
+ case 's':
+ fle->size = gftp_parse_file_size (startpos + 1);
+ break;
+ case 'm':
+ fle->datetime = strtol (startpos + 1, NULL, 10);
+ break;
+ }
+ startpos = strchr (startpos, ',');
+ }
+
+ if ((startpos = strchr (str, 9)) == NULL)
+ return (GFTP_EFATAL);
+
+ if (isdir)
+ fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+ else
+ fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+
+ fle->file = g_strdup (startpos + 1);
+ fle->user = g_strdup (_("unknown"));
+ fle->group = g_strdup (_("unknown"));
+ return (0);
+}
+
+
+static int
+gftp_parse_ls_unix (gftp_request * request, char *str, size_t slen,
+ gftp_file * fle)
+{
+ char *endpos, *startpos, *pos, *attribs;
+ int cols;
+
+ /* If there is no space between the attribs and links field, just make one */
+ if (slen > 10)
+ str[10] = ' ';
+
+ /* Determine the number of columns */
+ cols = 0;
+ pos = str;
+ while (*pos != '\0')
+ {
+ while (*pos != '\0' && *pos != ' ' && *pos != '\t')
+ {
+ if (*pos == ':')
+ break;
+ pos++;
+ }
+
+ cols++;
+
+ if (*pos == ':')
+ {
+ cols++;
+ break;
+ }
+
+ while (*pos == ' ' || *pos == '\t')
+ pos++;
+ }
+
+ startpos = str;
+ /* Copy file attributes */
+ if ((startpos = copy_token (&attribs, startpos)) == NULL)
+ return (GFTP_EFATAL);
+
+ if (strlen (attribs) < 10)
+ return (GFTP_EFATAL);
+
+ fle->st_mode = gftp_convert_attributes_to_mode_t (attribs);
+ g_free (attribs);
+
+ if (cols >= 9)
+ {
+ /* Skip the number of links */
+ startpos = goto_next_token (startpos);
+
+ /* Copy the user that owns this file */
+ if ((startpos = copy_token (&fle->user, startpos)) == NULL)
+ return (GFTP_EFATAL);
+
+ /* Copy the group that owns this file */
+ if ((startpos = copy_token (&fle->group, startpos)) == NULL)
+ return (GFTP_EFATAL);
+ }
+ else
+ {
+ fle->group = g_strdup (_("unknown"));
+ if (cols == 8)
+ {
+ if ((startpos = copy_token (&fle->user, startpos)) == NULL)
+ return (GFTP_EFATAL);
+ }
+ else
+ fle->user = g_strdup (_("unknown"));
+ startpos = goto_next_token (startpos);
+ }
+
+ if (request->server_type == GFTP_DIRTYPE_CRAY)
+ {
+ /* See if this is a Cray directory listing. It has the following format:
+ drwx------ 2 feiliu g913 DK common 4096 Sep 24 2001 wv */
+ if (cols == 11 && strstr (str, "->") == NULL)
+ {
+ startpos = goto_next_token (startpos);
+ startpos = goto_next_token (startpos);
+ }
+ }
+
+ /* See if this is a block or character device. We will store the major number
+ in the high word and the minor number in the low word. */
+ if (GFTP_IS_SPECIAL_DEVICE (fle->st_mode) &&
+ (endpos = strchr (startpos, ',')) != NULL)
+ {
+ fle->size = (unsigned long) strtol (startpos, NULL, 10) << 16;
+
+ startpos = endpos + 1;
+ while (*startpos == ' ')
+ startpos++;
+
+ /* Get the minor number */
+ if ((endpos = strchr (startpos, ' ')) == NULL)
+ return (GFTP_EFATAL);
+ fle->size |= strtol (startpos, NULL, 10) & 0xFF;
+ }
+ else
+ {
+ /* This is a regular file */
+ if ((endpos = strchr (startpos, ' ')) == NULL)
+ return (GFTP_EFATAL);
+ fle->size = gftp_parse_file_size (startpos);
+ }
+
+ /* Skip the blanks till we get to the next entry */
+ startpos = endpos + 1;
+ while (*startpos == ' ')
+ startpos++;
+
+ fle->datetime = parse_time (startpos, &startpos);
+
+ /* Skip the blanks till we get to the next entry */
+ startpos = goto_next_token (startpos);
+
+ /* Parse the filename. If this file is a symbolic link, remove the -> part */
+ if (S_ISLNK (fle->st_mode) && ((endpos = strstr (startpos, "->")) != NULL))
+ *(endpos - 1) = '\0';
+
+ fle->file = g_strdup (startpos);
+
+ /* Uncomment this if you want to strip the spaces off of the end of the file.
+ I don't want to do this by default since there are valid filenames with
+ spaces at the end of them. Some broken FTP servers like the Paradyne IPC
+ DSLAMS append a bunch of spaces at the end of the file.
+ for (endpos = fle->file + strlen (fle->file) - 1;
+ *endpos == ' ';
+ *endpos-- = '\0');
+ */
+
+ return (0);
+}
+
+
+static int
+gftp_parse_ls_nt (char *str, gftp_file * fle)
+{
+ char *startpos;
+
+ startpos = str;
+ fle->datetime = parse_time (startpos, &startpos);
+
+ fle->user = g_strdup (_("unknown"));
+ fle->group = g_strdup (_("unknown"));
+
+ startpos = goto_next_token (startpos);
+
+ if (startpos[0] == '<')
+ fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+ else
+ {
+ fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+ fle->size = gftp_parse_file_size (startpos);
+ }
+
+ startpos = goto_next_token (startpos);
+ fle->file = g_strdup (startpos);
+ return (0);
+}
+
+
+static int
+gftp_parse_ls_novell (char *str, gftp_file * fle)
+{
+ char *startpos;
+
+ if (str[12] != ' ')
+ return (GFTP_EFATAL);
+
+ str[12] = '\0';
+ fle->st_mode = gftp_convert_attributes_to_mode_t (str);
+ startpos = str + 13;
+
+ while ((*startpos == ' ' || *startpos == '\t') && *startpos != '\0')
+ startpos++;
+
+ if ((startpos = copy_token (&fle->user, startpos)) == NULL)
+ return (GFTP_EFATAL);
+
+ fle->group = g_strdup (_("unknown"));
+
+ while (*startpos != '\0' && !isdigit (*startpos))
+ startpos++;
+
+ fle->size = gftp_parse_file_size (startpos);
+
+ startpos = goto_next_token (startpos);
+ fle->datetime = parse_time (startpos, &startpos);
+
+ startpos = goto_next_token (startpos);
+ fle->file = g_strdup (startpos);
+ return (0);
+}
+
+
+int
+gftp_parse_ls (gftp_request * request, const char *lsoutput, gftp_file * fle,
+ int fd)
+{
+ char *str, *endpos, tmpchar;
+ int result, is_vms;
+ size_t len;
+
+ g_return_val_if_fail (lsoutput != NULL, GFTP_EFATAL);
+ g_return_val_if_fail (fle != NULL, GFTP_EFATAL);
+
+ str = g_strdup (lsoutput);
+ memset (fle, 0, sizeof (*fle));
+
+ len = strlen (str);
+ if (len > 0 && str[len - 1] == '\n')
+ str[--len] = '\0';
+ if (len > 0 && str[len - 1] == '\r')
+ str[--len] = '\0';
+
+ switch (request->server_type)
+ {
+ case GFTP_DIRTYPE_CRAY:
+ case GFTP_DIRTYPE_UNIX:
+ result = gftp_parse_ls_unix (request, str, len, fle);
+ break;
+ case GFTP_DIRTYPE_EPLF:
+ result = gftp_parse_ls_eplf (str, fle);
+ break;
+ case GFTP_DIRTYPE_NOVELL:
+ result = gftp_parse_ls_novell (str, fle);
+ break;
+ case GFTP_DIRTYPE_DOS:
+ result = gftp_parse_ls_nt (str, fle);
+ break;
+ case GFTP_DIRTYPE_VMS:
+ result = gftp_parse_ls_vms (request, fd, str, fle);
+ break;
+ case GFTP_DIRTYPE_MVS:
+ result = gftp_parse_ls_mvs (str, fle);
+ break;
+ default: /* autodetect */
+ if (*lsoutput == '+')
+ result = gftp_parse_ls_eplf (str, fle);
+ else if (isdigit ((int) str[0]) && str[2] == '-')
+ result = gftp_parse_ls_nt (str, fle);
+ else if (str[1] == ' ' && str[2] == '[')
+ result = gftp_parse_ls_novell (str, fle);
+ else
+ {
+ if ((endpos = strchr (str, ' ')) != NULL)
+ {
+ /* If the first token in the string has a ; in it, then */
+ /* we'll assume that this is a VMS directory listing */
+ tmpchar = *endpos;
+ *endpos = '\0';
+ is_vms = strchr (str, ';') != NULL;
+ *endpos = tmpchar;
+ }
+ else
+ is_vms = 0;
+
+ if (is_vms)
+ result = gftp_parse_ls_vms (request, fd, str, fle);
+ else
+ result = gftp_parse_ls_unix (request, str, len, fle);
+ }
+ break;
+ }
+ g_free (str);
+
+ return (result);
+}
+
Modified: trunk/lib/protocols.c
==============================================================================
--- trunk/lib/protocols.c (original)
+++ trunk/lib/protocols.c Tue Mar 4 12:28:40 2008
@@ -413,246 +413,6 @@
}
-#if GLIB_MAJOR_VERSION > 1
-
-static /* null@*/ char *
-_gftp_get_next_charset (char **curpos)
-{
- char *ret, *endpos;
- size_t len, retlen;
-
- if (**curpos == '\0')
- return (NULL);
-
- for (; **curpos == ' ' || **curpos == '\t'; (*curpos)++);
-
- if ((endpos = strchr (*curpos, ',')) == NULL)
- len = strlen (*curpos) - 1; /* the trailing ',' should be omitted */
- else
- len = endpos - *curpos;
-
- for (retlen = len - 1;
- (*curpos)[retlen - 1] == ' ' || (*curpos)[retlen - 1] == '\t';
- retlen--);
-
- retlen++; /* Needed due to the len - 1 above... */
- ret = g_malloc0 (retlen + 1);
- memcpy (ret, *curpos, retlen);
-
- for (*curpos += len; **curpos == ','; (*curpos)++);
-
- return (ret);
-}
-
-
-static void
-_do_show_iconv_error (const char *str, char *charset, int from_utf8,
- GError * error)
-{
- const char *fromset, *toset;
-
- if (from_utf8)
- {
- fromset = "UTF-8";
- toset = charset;
- }
- else
- {
- fromset = charset;
- toset = "UTF-8";
- }
-
- printf (_("Error converting string '%s' from character set %s to character set %s: %s\n"),
- str, fromset, toset, error->message);
-}
-
-
-/* null@*/ char *
-_do_convert_string (gftp_request * request, int is_filename, int force_local,
- const char *str, size_t *dest_len, int from_utf8)
-{
- char *remote_charsets, *ret, *fromset, *toset, *stpos, *cur_charset;
- GError * error;
- gsize bread;
-
- if (request == NULL)
- return (NULL);
-
- if (g_utf8_validate (str, -1, NULL) != from_utf8)
- return (NULL);
-
- error = NULL;
- gftp_lookup_request_option (request, "remote_charsets", &remote_charsets);
- if (*remote_charsets == '\0' || request->use_local_encoding ||
- force_local == 1)
- {
- if (from_utf8)
- {
- if (is_filename)
- ret = g_filename_from_utf8 (str, -1, &bread, dest_len, &error);
- else
- ret = g_locale_from_utf8 (str, -1, &bread, dest_len, &error);
- }
- else
- {
- if (is_filename)
- ret = g_filename_to_utf8 (str, -1, &bread, dest_len, &error);
- else
- ret = g_locale_to_utf8 (str, -1, &bread, dest_len, &error);
- }
-
- if (ret == NULL)
- _do_show_iconv_error (str, request->iconv_charset, from_utf8, error);
-
- return (ret);
- }
-
- if (from_utf8)
- {
- if (request->iconv_from_initialized)
- {
- ret = g_convert_with_iconv (str, -1, request->iconv_from, &bread, dest_len,
- &error);
- if (ret == NULL)
- _do_show_iconv_error (str, request->iconv_charset, from_utf8, error);
-
- return (ret);
- }
- }
- else
- {
- if (request->iconv_to_initialized)
- {
- ret = g_convert_with_iconv (str, -1, request->iconv_to, &bread, dest_len,
- &error);
- if (ret == NULL)
- _do_show_iconv_error (str, request->iconv_charset, from_utf8, error);
-
- return (ret);
- }
- }
-
- stpos = remote_charsets;
- while ((cur_charset = _gftp_get_next_charset (&stpos)) != NULL)
- {
- if (from_utf8)
- {
- fromset = "UTF-8";
- toset = cur_charset;
- if ((request->iconv_from = g_iconv_open (toset, fromset)) == (GIConv) -1)
- {
- g_free (cur_charset);
- continue;
- }
-
- error = NULL;
- if ((ret = g_convert_with_iconv (str, -1, request->iconv_from, &bread,
- dest_len, &error)) == NULL)
- {
- g_iconv_close (request->iconv_from);
- request->iconv_from = NULL;
- _do_show_iconv_error (str, cur_charset, from_utf8, error);
- g_free (cur_charset);
- continue;
- }
-
- request->iconv_from_initialized = 1;
- }
- else
- {
- fromset = cur_charset;
- toset = "UTF-8";
- if ((request->iconv_to = g_iconv_open (toset, fromset)) == (GIConv) -1)
- {
- g_free (cur_charset);
- continue;
- }
-
- error = NULL;
- if ((ret = g_convert_with_iconv (str, -1, request->iconv_to, &bread,
- dest_len, &error)) == NULL)
- {
- g_iconv_close (request->iconv_to);
- request->iconv_to = NULL;
- _do_show_iconv_error (str, cur_charset, from_utf8, error);
- g_free (cur_charset);
- continue;
- }
-
- request->iconv_to_initialized = 1;
- }
-
- request->iconv_charset = cur_charset;
- return (ret);
- }
-
- return (NULL);
-}
-
-char *
-gftp_string_to_utf8 (gftp_request * request, const char *str, size_t *dest_len)
-{
- return (_do_convert_string (request, 0, 0, str, dest_len, 0));
-}
-
-
-char *
-gftp_string_from_utf8 (gftp_request * request, int force_local, const char *str,
- size_t *dest_len)
-{
- return (_do_convert_string (request, 0, force_local, str, dest_len, 1));
-}
-
-
-char *
-gftp_filename_to_utf8 (gftp_request * request, const char *str,
- size_t *dest_len)
-{
- return (_do_convert_string (request, 1, 0, str, dest_len, 0));
-}
-
-
-char *
-gftp_filename_from_utf8 (gftp_request * request, const char *str,
- size_t *dest_len)
-{
- return (_do_convert_string (request, 1, 0, str, dest_len, 1));
-}
-
-#else
-
-char *
-gftp_string_to_utf8 (gftp_request * request, const char *str, size_t dest_len)
-{
- return (NULL);
-}
-
-
-char *
-gftp_string_from_utf8 (gftp_request * request, int force_local, const char *str,
- size_t dest_len)
-{
- return (NULL);
-}
-
-
-char *
-gftp_filename_to_utf8 (gftp_request * request, const char *str, size_t dest_len)
-{
- return (NULL);
-}
-
-
-char *
-gftp_filename_from_utf8 (gftp_request * request, int force_local,
- const char *str, size_t dest_len)
-{
- return (NULL);
-}
-
-#endif
-
-
int
gftp_get_next_file (gftp_request * request, const char *filespec,
gftp_file * fle)
@@ -1157,847 +917,107 @@
}
-/* FIXME - clean up this function */
-static int
-gftp_need_proxy (gftp_request * request, char *service, char *proxy_hostname,
- unsigned int proxy_port)
+static GHashTable *
+gftp_gen_dir_hash (gftp_request * request, int *ret)
{
- gftp_config_list_vars * proxy_hosts;
- gftp_proxy_hosts * hostname;
- size_t hostlen, domlen;
- unsigned char addy[4];
- struct sockaddr *addr;
- GList * templist;
- gint32 netaddr;
- char *pos;
-#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
- struct addrinfo hints, *hostp;
- unsigned int port;
- int errnum;
- char serv[8];
-#else
- struct hostent host, *hostp;
-#endif
-
- gftp_lookup_global_option ("dont_use_proxy", &proxy_hosts);
-
- if (proxy_hostname == NULL || *proxy_hostname == '\0')
- return (0);
- else if (proxy_hosts->list == NULL)
- return (proxy_hostname != NULL &&
- *proxy_hostname != '\0');
-
- hostp = NULL;
-#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
- memset (&hints, 0, sizeof (hints));
- hints.ai_flags = AI_CANONNAME;
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
-
- port = request->use_proxy ? proxy_port : request->port;
- if (port == 0)
- strcpy (serv, service);
- else
- snprintf (serv, sizeof (serv), "%d", port);
-
- request->logging_function (gftp_logging_misc, request,
- _("Looking up %s\n"), request->hostname);
-
- if ((errnum = getaddrinfo (request->hostname, serv, &hints,
- &hostp)) != 0)
- {
- request->logging_function (gftp_logging_error, request,
- _("Cannot look up hostname %s: %s\n"),
- request->hostname, gai_strerror (errnum));
- return (GFTP_ERETRYABLE);
- }
-
- addr = hostp->ai_addr;
-
-#else /* !HAVE_GETADDRINFO */
- request->logging_function (gftp_logging_misc, request,
- _("Looking up %s\n"), request->hostname);
-
- if (!(hostp = r_gethostbyname (request->hostname, &host, NULL)))
- {
- request->logging_function (gftp_logging_error, request,
- _("Cannot look up hostname %s: %s\n"),
- request->hostname, g_strerror (errno));
- return (GFTP_ERETRYABLE);
- }
-
- addr = (struct sockaddr *) host.h_addr_list[0];
-
-#endif /* HAVE_GETADDRINFO */
+ GHashTable * dirhash;
+ gftp_file * fle;
+ off_t *newsize;
- templist = proxy_hosts->list;
- while (templist != NULL)
+ dirhash = g_hash_table_new (string_hash_function, string_hash_compare);
+ *ret = gftp_list_files (request);
+ if (*ret == 0)
{
- hostname = templist->data;
- if (hostname->domain != NULL)
- {
- hostlen = strlen (request->hostname);
- domlen = strlen (hostname->domain);
- if (hostlen > domlen)
- {
- pos = request->hostname + hostlen - domlen;
- if (strcmp (hostname->domain, pos) == 0)
- return (0);
- }
- }
-
- if (hostname->ipv4_network_address != 0)
+ fle = g_malloc0 (sizeof (*fle));
+ while (gftp_get_next_file (request, NULL, fle) > 0)
{
- memcpy (addy, addr, sizeof (*addy));
- netaddr =
- (((addy[0] & 0xff) << 24) | ((addy[1] & 0xff) << 16) |
- ((addy[2] & 0xff) << 8) | (addy[3] & 0xff)) &
- hostname->ipv4_netmask;
- if (netaddr == hostname->ipv4_network_address)
- return (0);
+ newsize = g_malloc0 (sizeof (*newsize));
+ *newsize = fle->size;
+ g_hash_table_insert (dirhash, fle->file, newsize);
+ fle->file = NULL;
+ gftp_file_destroy (fle, 0);
}
- templist = templist->next;
+ gftp_end_transfer (request);
+ g_free (fle);
}
-
- return (proxy_hostname != NULL && *proxy_hostname != '\0');
-}
-
-
-static char *
-copy_token (/* out@*/ char **dest, char *source)
-{
- /* This function is used internally by gftp_parse_ls () */
- char *endpos, savepos;
-
- endpos = source;
- while (*endpos != ' ' && *endpos != '\t' && *endpos != '\0')
- endpos++;
- if (*endpos == '\0')
+ else
{
- *dest = NULL;
- return (NULL);
+ g_hash_table_destroy (dirhash);
+ dirhash = NULL;
}
- savepos = *endpos;
- *endpos = '\0';
- *dest = g_malloc0 ((gulong) (endpos - source + 1));
- strcpy (*dest, source);
- *endpos = savepos;
-
- /* Skip the blanks till we get to the next entry */
- source = endpos + 1;
- while ((*source == ' ' || *source == '\t') && *source != '\0')
- source++;
- return (source);
+ return (dirhash);
}
-static char *
-goto_next_token (char *pos)
+static void
+destroy_hash_ent (gpointer key, gpointer value, gpointer user_data)
{
- while (*pos != ' ' && *pos != '\t' && *pos != '\0')
- pos++;
-
- while (*pos == ' ' || *pos == '\t')
- pos++;
- return (pos);
+ g_free (key);
+ g_free (value);
}
-static time_t
-parse_vms_time (char *str, char **endpos)
+static void
+gftp_destroy_dir_hash (GHashTable * dirhash)
{
- struct tm curtime;
- time_t ret;
-
- /* 8-JUN-2004 13:04:14 */
- memset (&curtime, 0, sizeof (curtime));
-
- *endpos = strptime (str, "%d-%b-%Y %H:%M:%S", &curtime);
- if (*endpos == NULL)
- *endpos = strptime (str, "%d-%b-%Y %H:%M", &curtime);
-
- if (*endpos != NULL)
- {
- ret = mktime (&curtime);
- for (; **endpos == ' ' || **endpos == '\t'; (*endpos)++);
- }
- else
- {
- ret = 0;
- *endpos = goto_next_token (str);
- if (*endpos != NULL)
- *endpos = goto_next_token (*endpos);
- }
+ if (dirhash == NULL)
+ return;
- return (ret);
+ g_hash_table_foreach (dirhash, destroy_hash_ent, NULL);
+ g_hash_table_destroy (dirhash);
}
-time_t
-parse_time (char *str, char **endpos)
+static GList *
+gftp_get_dir_listing (gftp_transfer * transfer, int getothdir, int *ret)
{
- struct tm curtime, *loctime;
- time_t t, ret;
- char *tmppos;
- size_t slen;
- int i, num;
-
- slen = strlen (str);
- memset (&curtime, 0, sizeof (curtime));
- curtime.tm_isdst = -1;
-
- if (slen > 4 && isdigit ((int) str[0]) && str[2] == '-' &&
- isdigit ((int) str[3]))
- {
- /* This is how DOS will return the date/time */
- /* 07-06-99 12:57PM */
+ GHashTable * dirhash;
+ GList * templist;
+ gftp_file * fle;
+ off_t *newsize;
+ char *newname;
- tmppos = strptime (str, "%m-%d-%y %I:%M%p", &curtime);
- }
- else if (slen > 4 && isdigit ((int) str[0]) && str[2] == '-' &&
- isalpha (str[3]))
+ if (getothdir && transfer->toreq != NULL)
{
- /* 10-Jan-2003 09:14 */
- tmppos = strptime (str, "%d-%h-%Y %H:%M", &curtime);
+ dirhash = gftp_gen_dir_hash (transfer->toreq, ret);
+ if (*ret == GFTP_EFATAL)
+ return (NULL);
}
- else if (slen > 4 && isdigit ((int) str[0]) && str[4] == '/')
+ else
+ dirhash = NULL;
+
+ *ret = gftp_list_files (transfer->fromreq);
+ if (*ret < 0)
{
- /* 2003/12/25 */
- tmppos = strptime (str, "%Y/%m/%d", &curtime);
+ gftp_destroy_dir_hash (dirhash);
+ return (NULL);
}
- else
- {
- /* This is how most UNIX, Novell, and MacOS ftp servers send their time */
- /* Jul 06 12:57 or Jul 6 1999 */
- if (strchr (str, ':') != NULL)
+ fle = g_malloc0 (sizeof (*fle));
+ templist = NULL;
+ while (gftp_get_next_file (transfer->fromreq, NULL, fle) > 0)
+ {
+ if (strcmp (fle->file, ".") == 0 || strcmp (fle->file, "..") == 0)
{
- tmppos = strptime (str, "%h %d %H:%M", &curtime);
- t = time (NULL);
- loctime = localtime (&t);
-
- if (curtime.tm_mon > loctime->tm_mon)
- curtime.tm_year = loctime->tm_year - 1;
- else
- curtime.tm_year = loctime->tm_year;
+ gftp_file_destroy (fle, 0);
+ continue;
}
- else
- tmppos = strptime (str, "%h %d %Y", &curtime);
- }
-
- if (tmppos != NULL)
- ret = mktime (&curtime);
- else
- ret = 0;
- if (endpos != NULL)
- {
- if (tmppos == NULL)
+ if (dirhash &&
+ (newsize = g_hash_table_lookup (dirhash, fle->file)) != NULL)
{
- /* We cannot parse this date format. So, just skip this date field
- and continue to the next token. This is mainly for the HTTP
- support */
-
- *endpos = str;
- for (num = 0; num < 2 && **endpos != '\0'; num++)
- {
- for (i=0;
- (*endpos)[i] != ' ' && (*endpos)[i] != '\t' &&
- (*endpos)[i] != '\0';
- i++);
- *endpos += i;
-
- for (i=0; (*endpos)[i] == ' ' || (*endpos)[i] == '\t'; i++);
- *endpos += i;
- }
+ fle->exists_other_side = 1;
+ fle->startsize = *newsize;
}
else
- *endpos = tmppos;
- }
+ fle->exists_other_side = 0;
- return (ret);
-}
-
-
-static mode_t
-gftp_parse_vms_attribs (char **src, mode_t mask)
-{
- char *endpos;
- mode_t ret;
-
- if (*src == NULL)
- return (0);
-
- if ((endpos = strchr (*src, ',')) != NULL)
- *endpos = '\0';
-
- ret = 0;
- if (strchr (*src, 'R') != NULL)
- ret |= S_IRUSR | S_IRGRP | S_IROTH;
- if (strchr (*src, 'W') != NULL)
- ret |= S_IWUSR | S_IWGRP | S_IWOTH;
- if (strchr (*src, 'E') != NULL)
- ret |= S_IXUSR | S_IXGRP | S_IXOTH;
-
- *src = endpos + 1;
-
- return (ret & mask);
-}
-
-
-static int
-gftp_parse_ls_vms (gftp_request * request, int fd, char *str, gftp_file * fle)
-{
- char *curpos, *endpos, tempstr[1024];
- int multiline;
- ssize_t len;
-
- /* .PINE-DEBUG1;1 9 21-AUG-2002 20:06 [MYERSRG] (RWED,RWED,,) */
- /* WWW.DIR;1 1 23-NOV-1999 05:47 [MYERSRG] (RWE,RWE,RE,E) */
-
- /* Multiline VMS
- $MAIN.TPU$JOURNAL;1
- 1/18 8-JUN-2004 13:04:14 [NUCLEAR,FISSION] (RWED,RWED,RE,)
- TCPIP$FTP_SERVER.LOG;29
- 0/18 8-JUN-2004 14:42:04 [NUCLEAR,FISSION] (RWED,RWED,RE,)
- TCPIP$FTP_SERVER.LOG;28
- 5/18 8-JUN-2004 13:05:11 [NUCLEAR,FISSION] (RWED,RWED,RE,)
- TCPIP$FTP_SERVER.LOG;27
- 5/18 8-JUN-2004 13:03:51 [NUCLEAR,FISSION] (RWED,RWED,RE,) */
-
- if ((curpos = strchr (str, ';')) == NULL)
- return (GFTP_EFATAL);
-
- multiline = strchr (str, ' ') == NULL;
-
- *curpos = '\0';
- if (strlen (str) > 4 && strcmp (curpos - 4, ".DIR") == 0)
- {
- fle->st_mode |= S_IFDIR;
- *(curpos - 4) = '\0';
- }
-
- fle->file = g_strdup (str);
-
- if (multiline)
- {
- if (request->get_next_dirlist_line == NULL)
- return (GFTP_EFATAL);
-
- len = request->get_next_dirlist_line (request, fd, tempstr,
- sizeof (tempstr));
- if (len <= 0)
- return ((int) len);
-
- for (curpos = tempstr; *curpos == ' ' || *curpos == '\t'; curpos++);
- }
- else
- curpos = goto_next_token (curpos + 1);
-
- fle->size = gftp_parse_file_size (curpos) * 512; /* Is this correct? */
-
- curpos = goto_next_token (curpos);
-
- fle->datetime = parse_vms_time (curpos, &curpos);
-
- if (*curpos != '[')
- return (GFTP_EFATAL);
-
- if ((endpos = strchr (curpos, ']')) == NULL)
- return (GFTP_EFATAL);
-
- curpos = goto_next_token (endpos + 1);
- if ((curpos = strchr (curpos, ',')) == NULL)
- return (0);
- curpos++;
-
- fle->st_mode = gftp_parse_vms_attribs (&curpos, S_IRWXU);
- fle->st_mode |= gftp_parse_vms_attribs (&curpos, S_IRWXG);
- fle->st_mode |= gftp_parse_vms_attribs (&curpos, S_IRWXO);
-
- fle->user = g_strdup ("");
- fle->group = g_strdup ("");
-
- return (0);
-}
-
-
-static int
-gftp_parse_ls_mvs (char *str, gftp_file * fle)
-{
- char *curpos;
-
- /* Volume Unit Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname */
- /* SVI52A 3390 2003/12/10 8 216 FB 80 27920 PS CARDS.DELETES */
- /* SVI528 3390 2003/12/12 1 5 FB 80 24000 PO CLIST */
-
- curpos = goto_next_token (str + 1);
- if (curpos == NULL)
- return (GFTP_EFATAL);
-
- curpos = goto_next_token (curpos + 1);
- if (curpos == NULL)
- return (GFTP_EFATAL);
-
- fle->datetime = parse_time (curpos, &curpos);
-
- curpos = goto_next_token (curpos);
- if (curpos == NULL)
- return (GFTP_EFATAL);
-
- curpos = goto_next_token (curpos + 1);
- if (curpos == NULL)
- return (GFTP_EFATAL);
-
- fle->size = gftp_parse_file_size (curpos) * 55996;
- curpos = goto_next_token (curpos + 1);
- if (curpos == NULL)
- return (GFTP_EFATAL);
-
- curpos = goto_next_token (curpos + 1);
- if (curpos == NULL)
- return (GFTP_EFATAL);
-
- curpos = goto_next_token (curpos + 1);
- if (curpos == NULL)
- return (GFTP_EFATAL);
-
- curpos = goto_next_token (curpos + 1);
- if (curpos == NULL)
- return (GFTP_EFATAL);
-
- if (strncmp (curpos, "PS", 2) == 0)
- fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
- else if (strncmp (curpos, "PO", 2) == 0)
- fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
- else
- return (GFTP_EFATAL);
-
- curpos = goto_next_token (curpos + 1);
-
- fle->user = g_strdup (_("unknown"));
- fle->group = g_strdup (_("unknown"));
- fle->file = g_strdup (curpos);
-
- return (0);
-}
-
-
-static int
-gftp_parse_ls_eplf (char *str, gftp_file * fle)
-{
- char *startpos;
- int isdir = 0;
-
- startpos = str;
- while (startpos)
- {
- startpos++;
- switch (*startpos)
- {
- case '/':
- isdir = 1;
- break;
- case 's':
- fle->size = gftp_parse_file_size (startpos + 1);
- break;
- case 'm':
- fle->datetime = strtol (startpos + 1, NULL, 10);
- break;
- }
- startpos = strchr (startpos, ',');
- }
-
- if ((startpos = strchr (str, 9)) == NULL)
- return (GFTP_EFATAL);
-
- if (isdir)
- fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
- else
- fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
-
- fle->file = g_strdup (startpos + 1);
- fle->user = g_strdup (_("unknown"));
- fle->group = g_strdup (_("unknown"));
- return (0);
-}
-
-
-static int
-gftp_parse_ls_unix (gftp_request * request, char *str, size_t slen,
- gftp_file * fle)
-{
- char *endpos, *startpos, *pos, *attribs;
- int cols;
-
- /* If there is no space between the attribs and links field, just make one */
- if (slen > 10)
- str[10] = ' ';
-
- /* Determine the number of columns */
- cols = 0;
- pos = str;
- while (*pos != '\0')
- {
- while (*pos != '\0' && *pos != ' ' && *pos != '\t')
- {
- if (*pos == ':')
- break;
- pos++;
- }
-
- cols++;
-
- if (*pos == ':')
- {
- cols++;
- break;
- }
-
- while (*pos == ' ' || *pos == '\t')
- pos++;
- }
-
- startpos = str;
- /* Copy file attributes */
- if ((startpos = copy_token (&attribs, startpos)) == NULL)
- return (GFTP_EFATAL);
-
- if (strlen (attribs) < 10)
- return (GFTP_EFATAL);
-
- fle->st_mode = gftp_convert_attributes_to_mode_t (attribs);
- g_free (attribs);
-
- if (cols >= 9)
- {
- /* Skip the number of links */
- startpos = goto_next_token (startpos);
-
- /* Copy the user that owns this file */
- if ((startpos = copy_token (&fle->user, startpos)) == NULL)
- return (GFTP_EFATAL);
-
- /* Copy the group that owns this file */
- if ((startpos = copy_token (&fle->group, startpos)) == NULL)
- return (GFTP_EFATAL);
- }
- else
- {
- fle->group = g_strdup (_("unknown"));
- if (cols == 8)
- {
- if ((startpos = copy_token (&fle->user, startpos)) == NULL)
- return (GFTP_EFATAL);
- }
- else
- fle->user = g_strdup (_("unknown"));
- startpos = goto_next_token (startpos);
- }
-
- if (request->server_type == GFTP_DIRTYPE_CRAY)
- {
- /* See if this is a Cray directory listing. It has the following format:
- drwx------ 2 feiliu g913 DK common 4096 Sep 24 2001 wv */
- if (cols == 11 && strstr (str, "->") == NULL)
- {
- startpos = goto_next_token (startpos);
- startpos = goto_next_token (startpos);
- }
- }
-
- /* See if this is a block or character device. We will store the major number
- in the high word and the minor number in the low word. */
- if (GFTP_IS_SPECIAL_DEVICE (fle->st_mode) &&
- (endpos = strchr (startpos, ',')) != NULL)
- {
- fle->size = (unsigned long) strtol (startpos, NULL, 10) << 16;
-
- startpos = endpos + 1;
- while (*startpos == ' ')
- startpos++;
-
- /* Get the minor number */
- if ((endpos = strchr (startpos, ' ')) == NULL)
- return (GFTP_EFATAL);
- fle->size |= strtol (startpos, NULL, 10) & 0xFF;
- }
- else
- {
- /* This is a regular file */
- if ((endpos = strchr (startpos, ' ')) == NULL)
- return (GFTP_EFATAL);
- fle->size = gftp_parse_file_size (startpos);
- }
-
- /* Skip the blanks till we get to the next entry */
- startpos = endpos + 1;
- while (*startpos == ' ')
- startpos++;
-
- fle->datetime = parse_time (startpos, &startpos);
-
- /* Skip the blanks till we get to the next entry */
- startpos = goto_next_token (startpos);
-
- /* Parse the filename. If this file is a symbolic link, remove the -> part */
- if (S_ISLNK (fle->st_mode) && ((endpos = strstr (startpos, "->")) != NULL))
- *(endpos - 1) = '\0';
-
- fle->file = g_strdup (startpos);
-
- /* Uncomment this if you want to strip the spaces off of the end of the file.
- I don't want to do this by default since there are valid filenames with
- spaces at the end of them. Some broken FTP servers like the Paradyne IPC
- DSLAMS append a bunch of spaces at the end of the file.
- for (endpos = fle->file + strlen (fle->file) - 1;
- *endpos == ' ';
- *endpos-- = '\0');
- */
-
- return (0);
-}
-
-
-static int
-gftp_parse_ls_nt (char *str, gftp_file * fle)
-{
- char *startpos;
-
- startpos = str;
- fle->datetime = parse_time (startpos, &startpos);
-
- fle->user = g_strdup (_("unknown"));
- fle->group = g_strdup (_("unknown"));
-
- startpos = goto_next_token (startpos);
-
- if (startpos[0] == '<')
- fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
- else
- {
- fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
- fle->size = gftp_parse_file_size (startpos);
- }
-
- startpos = goto_next_token (startpos);
- fle->file = g_strdup (startpos);
- return (0);
-}
-
-
-static int
-gftp_parse_ls_novell (char *str, gftp_file * fle)
-{
- char *startpos;
-
- if (str[12] != ' ')
- return (GFTP_EFATAL);
-
- str[12] = '\0';
- fle->st_mode = gftp_convert_attributes_to_mode_t (str);
- startpos = str + 13;
-
- while ((*startpos == ' ' || *startpos == '\t') && *startpos != '\0')
- startpos++;
-
- if ((startpos = copy_token (&fle->user, startpos)) == NULL)
- return (GFTP_EFATAL);
-
- fle->group = g_strdup (_("unknown"));
-
- while (*startpos != '\0' && !isdigit (*startpos))
- startpos++;
-
- fle->size = gftp_parse_file_size (startpos);
-
- startpos = goto_next_token (startpos);
- fle->datetime = parse_time (startpos, &startpos);
-
- startpos = goto_next_token (startpos);
- fle->file = g_strdup (startpos);
- return (0);
-}
-
-
-int
-gftp_parse_ls (gftp_request * request, const char *lsoutput, gftp_file * fle,
- int fd)
-{
- char *str, *endpos, tmpchar;
- int result, is_vms;
- size_t len;
-
- g_return_val_if_fail (lsoutput != NULL, GFTP_EFATAL);
- g_return_val_if_fail (fle != NULL, GFTP_EFATAL);
-
- str = g_strdup (lsoutput);
- memset (fle, 0, sizeof (*fle));
-
- len = strlen (str);
- if (len > 0 && str[len - 1] == '\n')
- str[--len] = '\0';
- if (len > 0 && str[len - 1] == '\r')
- str[--len] = '\0';
-
- switch (request->server_type)
- {
- case GFTP_DIRTYPE_CRAY:
- case GFTP_DIRTYPE_UNIX:
- result = gftp_parse_ls_unix (request, str, len, fle);
- break;
- case GFTP_DIRTYPE_EPLF:
- result = gftp_parse_ls_eplf (str, fle);
- break;
- case GFTP_DIRTYPE_NOVELL:
- result = gftp_parse_ls_novell (str, fle);
- break;
- case GFTP_DIRTYPE_DOS:
- result = gftp_parse_ls_nt (str, fle);
- break;
- case GFTP_DIRTYPE_VMS:
- result = gftp_parse_ls_vms (request, fd, str, fle);
- break;
- case GFTP_DIRTYPE_MVS:
- result = gftp_parse_ls_mvs (str, fle);
- break;
- default: /* autodetect */
- if (*lsoutput == '+')
- result = gftp_parse_ls_eplf (str, fle);
- else if (isdigit ((int) str[0]) && str[2] == '-')
- result = gftp_parse_ls_nt (str, fle);
- else if (str[1] == ' ' && str[2] == '[')
- result = gftp_parse_ls_novell (str, fle);
- else
- {
- if ((endpos = strchr (str, ' ')) != NULL)
- {
- /* If the first token in the string has a ; in it, then */
- /* we'll assume that this is a VMS directory listing */
- tmpchar = *endpos;
- *endpos = '\0';
- is_vms = strchr (str, ';') != NULL;
- *endpos = tmpchar;
- }
- else
- is_vms = 0;
-
- if (is_vms)
- result = gftp_parse_ls_vms (request, fd, str, fle);
- else
- result = gftp_parse_ls_unix (request, str, len, fle);
- }
- break;
- }
- g_free (str);
-
- return (result);
-}
-
-
-static GHashTable *
-gftp_gen_dir_hash (gftp_request * request, int *ret)
-{
- GHashTable * dirhash;
- gftp_file * fle;
- off_t *newsize;
-
- dirhash = g_hash_table_new (string_hash_function, string_hash_compare);
- *ret = gftp_list_files (request);
- if (*ret == 0)
- {
- fle = g_malloc0 (sizeof (*fle));
- while (gftp_get_next_file (request, NULL, fle) > 0)
- {
- newsize = g_malloc0 (sizeof (*newsize));
- *newsize = fle->size;
- g_hash_table_insert (dirhash, fle->file, newsize);
- fle->file = NULL;
- gftp_file_destroy (fle, 0);
- }
- gftp_end_transfer (request);
- g_free (fle);
- }
- else
- {
- g_hash_table_destroy (dirhash);
- dirhash = NULL;
- }
-
- return (dirhash);
-}
-
-
-static void
-destroy_hash_ent (gpointer key, gpointer value, gpointer user_data)
-{
-
- g_free (key);
- g_free (value);
-}
-
-
-static void
-gftp_destroy_dir_hash (GHashTable * dirhash)
-{
- if (dirhash == NULL)
- return;
-
- g_hash_table_foreach (dirhash, destroy_hash_ent, NULL);
- g_hash_table_destroy (dirhash);
-}
-
-
-static GList *
-gftp_get_dir_listing (gftp_transfer * transfer, int getothdir, int *ret)
-{
- GHashTable * dirhash;
- GList * templist;
- gftp_file * fle;
- off_t *newsize;
- char *newname;
-
- if (getothdir && transfer->toreq != NULL)
- {
- dirhash = gftp_gen_dir_hash (transfer->toreq, ret);
- if (*ret == GFTP_EFATAL)
- return (NULL);
- }
- else
- dirhash = NULL;
-
- *ret = gftp_list_files (transfer->fromreq);
- if (*ret < 0)
- {
- gftp_destroy_dir_hash (dirhash);
- return (NULL);
- }
-
- fle = g_malloc0 (sizeof (*fle));
- templist = NULL;
- while (gftp_get_next_file (transfer->fromreq, NULL, fle) > 0)
- {
- if (strcmp (fle->file, ".") == 0 || strcmp (fle->file, "..") == 0)
- {
- gftp_file_destroy (fle, 0);
- continue;
- }
-
- if (dirhash &&
- (newsize = g_hash_table_lookup (dirhash, fle->file)) != NULL)
- {
- fle->exists_other_side = 1;
- fle->startsize = *newsize;
- }
- else
- fle->exists_other_side = 0;
-
- if (transfer->toreq && fle->destfile == NULL)
- fle->destfile = gftp_build_path (transfer->toreq,
- transfer->toreq->directory,
- fle->file, NULL);
+ if (transfer->toreq && fle->destfile == NULL)
+ fle->destfile = gftp_build_path (transfer->toreq,
+ transfer->toreq->directory,
+ fle->file, NULL);
if (transfer->fromreq->directory != NULL &&
*transfer->fromreq->directory != '\0' &&
@@ -2239,358 +1259,84 @@
ret = gftp_set_directory (transfer->fromreq, curfle->file);
if (ret < 0)
- {
- _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
- update_func);
- _free_device_hash (device_hash);
- return (ret);
- }
-
- if (transfer->toreq != NULL)
- {
- if (oldtodir == NULL)
- oldtodir = g_strdup (transfer->toreq->directory);
-
- if (curfle->exists_other_side)
- {
- ret = gftp_set_directory (transfer->toreq, curfle->destfile);
- if (ret == GFTP_EFATAL)
- {
- _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
- update_func);
- _free_device_hash (device_hash);
- return (ret);
- }
- }
- else
- {
- if (transfer->toreq->directory != NULL)
- g_free (transfer->toreq->directory);
-
- transfer->toreq->directory = g_strdup (curfle->destfile);
- }
- }
-
- ret = 0;
- lastlist->next = gftp_get_dir_listing (transfer,
- curfle->exists_other_side, &ret);
- if (ret < 0)
- {
- _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
- update_func);
- _free_device_hash (device_hash);
- return (ret);
- }
-
- if (lastlist->next != NULL)
- {
- lastlist->next->prev = lastlist;
- for (; lastlist->next != NULL; lastlist = lastlist->next);
- }
-
- if (update_func != NULL)
- update_func (transfer);
- }
-
- _free_device_hash (device_hash);
-
- if (oldfromdir != NULL)
- {
- ret = gftp_set_directory (transfer->fromreq, oldfromdir);
- if (ret == GFTP_EFATAL)
- {
- _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
- update_func);
- return (ret);
- }
- }
-
- if (oldtodir != NULL)
- {
- ret = gftp_set_directory (transfer->toreq, oldtodir);
- if (ret == GFTP_EFATAL)
- {
- _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
- update_func);
- return (ret);
- }
- }
-
- _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir, update_func);
-
- return (0);
-}
-
-
-#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
-static int
-get_port (struct addrinfo *addr)
-{
- struct sockaddr_in * saddr;
- int port;
-
- if (addr->ai_family == AF_INET)
- {
- saddr = (struct sockaddr_in *) addr->ai_addr;
- port = ntohs (saddr->sin_port);
- }
- else
- port = 0;
-
- return (port);
-}
-
-
-int
-gftp_connect_server_with_getaddr (gftp_request * request, char *service,
- char *proxy_hostname, unsigned int proxy_port)
-{
- struct addrinfo *hostp, *current_hostp;
- char *connect_host, *disphost;
- struct addrinfo hints, *res;
- intptr_t enable_ipv6;
- unsigned int port;
- int ret, sock = -1;
- char serv[8];
-
- if ((ret = gftp_need_proxy (request, service, proxy_hostname,
- proxy_port)) < 0)
- return (ret);
- else
- request->use_proxy = ret;
-
- gftp_lookup_request_option (request, "enable_ipv6", &enable_ipv6);
-
- memset (&hints, 0, sizeof (hints));
- hints.ai_flags = AI_CANONNAME;
-
- hints.ai_family = enable_ipv6 ? PF_UNSPEC : AF_INET;
- hints.ai_socktype = SOCK_STREAM;
-
- if (request->use_proxy)
- {
- connect_host = proxy_hostname;
- port = proxy_port;
- }
- else
- {
- connect_host = request->hostname;
- port = request->port;
- }
-
- if (port == 0)
- strcpy (serv, service);
- else
- snprintf (serv, sizeof (serv), "%d", port);
-
- request->logging_function (gftp_logging_misc, request,
- _("Looking up %s\n"), connect_host);
- if ((ret = getaddrinfo (connect_host, serv, &hints,
- &hostp)) != 0)
- {
- request->logging_function (gftp_logging_error, request,
- _("Cannot look up hostname %s: %s\n"),
- connect_host, gai_strerror (ret));
- return (GFTP_ERETRYABLE);
- }
-
- disphost = connect_host;
- for (res = hostp; res != NULL; res = res->ai_next)
- {
- disphost = res->ai_canonname ? res->ai_canonname : connect_host;
- port = get_port (res);
- if (!request->use_proxy)
- request->port = port;
-
- if ((sock = socket (res->ai_family, res->ai_socktype,
- res->ai_protocol)) < 0)
- {
- request->logging_function (gftp_logging_error, request,
- _("Failed to create a socket: %s\n"),
- g_strerror (errno));
- continue;
- }
-
- request->logging_function (gftp_logging_misc, request,
- _("Trying %s:%d\n"), disphost, port);
-
- if (connect (sock, res->ai_addr, res->ai_addrlen) == -1)
- {
- request->logging_function (gftp_logging_error, request,
- _("Cannot connect to %s: %s\n"),
- disphost, g_strerror (errno));
- close (sock);
- continue;
- }
-
- current_hostp = res;
- request->ai_family = res->ai_family;
- break;
- }
-
- if (res == NULL)
- {
- if (hostp != NULL)
- freeaddrinfo (hostp);
-
- return (GFTP_ERETRYABLE);
- }
-
- request->remote_addr_len = current_hostp->ai_addrlen;
- request->remote_addr = g_malloc0 (request->remote_addr_len);
- memcpy (request->remote_addr, &((struct sockaddr_in *) current_hostp->ai_addr)->sin_addr,
- request->remote_addr_len);
-
- request->logging_function (gftp_logging_misc, request,
- _("Connected to %s:%d\n"), connect_host, port);
-
- return (sock);
-}
-#endif
-
-
-int
-gftp_connect_server_legacy (gftp_request * request, char *service,
- char *proxy_hostname, unsigned int proxy_port)
-{
- struct sockaddr_in remote_address;
- char *connect_host, *disphost;
- struct hostent host, *hostp;
- struct servent serv_struct;
- int ret, sock, curhost;
- unsigned int port;
-
- if ((ret = gftp_need_proxy (request, service, proxy_hostname,
- proxy_port)) < 0)
- return (ret);
-
- request->use_proxy = ret;
- if (request->use_proxy == 1)
- hostp = NULL;
-
- request->ai_family = AF_INET;
- if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
- {
- request->logging_function (gftp_logging_error, request,
- _("Failed to create a IPv4 socket: %s\n"),
- g_strerror (errno));
- return (GFTP_ERETRYABLE);
- }
-
- memset (&remote_address, 0, sizeof (remote_address));
- remote_address.sin_family = AF_INET;
-
- if (request->use_proxy)
- {
- connect_host = proxy_hostname;
- port = proxy_port;
- }
- else
- {
- connect_host = request->hostname;
- port = request->port;
- }
-
- if (port == 0)
- {
- if (!r_getservbyname (service, "tcp", &serv_struct, NULL))
- {
- request->logging_function (gftp_logging_error, request,
- _("Cannot look up service name %s/tcp. Please check your services file\n"),
- service);
- close (sock);
- return (GFTP_EFATAL);
+ {
+ _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
+ update_func);
+ _free_device_hash (device_hash);
+ return (ret);
}
- port = ntohs (serv_struct.s_port);
-
- if (!request->use_proxy)
- request->port = port;
- }
-
- remote_address.sin_port = htons (port);
+ if (transfer->toreq != NULL)
+ {
+ if (oldtodir == NULL)
+ oldtodir = g_strdup (transfer->toreq->directory);
- request->logging_function (gftp_logging_misc, request,
- _("Looking up %s\n"), connect_host);
+ if (curfle->exists_other_side)
+ {
+ ret = gftp_set_directory (transfer->toreq, curfle->destfile);
+ if (ret == GFTP_EFATAL)
+ {
+ _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
+ update_func);
+ _free_device_hash (device_hash);
+ return (ret);
+ }
+ }
+ else
+ {
+ if (transfer->toreq->directory != NULL)
+ g_free (transfer->toreq->directory);
- if (!(hostp = r_gethostbyname (connect_host, &host, NULL)))
- {
- request->logging_function (gftp_logging_error, request,
- _("Cannot look up hostname %s: %s\n"),
- connect_host, g_strerror (errno));
- close (sock);
- return (GFTP_ERETRYABLE);
- }
+ transfer->toreq->directory = g_strdup (curfle->destfile);
+ }
+ }
- disphost = NULL;
- for (curhost = 0;
- host.h_addr_list[curhost] != NULL;
- curhost++)
- {
- disphost = host.h_name;
- memcpy (&remote_address.sin_addr,
- host.h_addr_list[curhost],
- host.h_length);
- request->logging_function (gftp_logging_misc, request,
- _("Trying %s:%d\n"),
- host.h_name, port);
+ ret = 0;
+ lastlist->next = gftp_get_dir_listing (transfer,
+ curfle->exists_other_side, &ret);
+ if (ret < 0)
+ {
+ _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
+ update_func);
+ _free_device_hash (device_hash);
+ return (ret);
+ }
- if (connect (sock, (struct sockaddr *) &remote_address,
- sizeof (remote_address)) == -1)
+ if (lastlist->next != NULL)
{
- request->logging_function (gftp_logging_error, request,
- _("Cannot connect to %s: %s\n"),
- connect_host, g_strerror (errno));
+ lastlist->next->prev = lastlist;
+ for (; lastlist->next != NULL; lastlist = lastlist->next);
}
- break;
- }
- if (host.h_addr_list[curhost] == NULL)
- {
- close (sock);
- return (GFTP_ERETRYABLE);
+ if (update_func != NULL)
+ update_func (transfer);
}
- return (sock);
-}
-
-
-int
-gftp_connect_server (gftp_request * request, char *service,
- char *proxy_hostname, unsigned int proxy_port)
-{
- int sock;
-
-#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
- sock = gftp_connect_server_with_getaddr (request, service, proxy_hostname,
- proxy_port);
-#else
- sock = gftp_connect_server_legacy (request, service, proxy_hostname,
- proxy_port);
-#endif
-
- if (sock < 0)
- return (sock);
+ _free_device_hash (device_hash);
- if (fcntl (sock, F_SETFD, 1) == -1)
+ if (oldfromdir != NULL)
{
- request->logging_function (gftp_logging_error, request,
- _("Error: Cannot set close on exec flag: %s\n"),
- g_strerror (errno));
- close (sock);
- return (GFTP_ERETRYABLE);
+ ret = gftp_set_directory (transfer->fromreq, oldfromdir);
+ if (ret == GFTP_EFATAL)
+ {
+ _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
+ update_func);
+ return (ret);
+ }
}
- if (gftp_fd_set_sockblocking (request, sock, 1) < 0)
+ if (oldtodir != NULL)
{
- close (sock);
- return (GFTP_ERETRYABLE);
+ ret = gftp_set_directory (transfer->toreq, oldtodir);
+ if (ret == GFTP_EFATAL)
+ {
+ _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
+ update_func);
+ return (ret);
+ }
}
- request->datafd = sock;
-
- if (request->post_connect != NULL)
- return (request->post_connect (request));
+ _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir, update_func);
return (0);
}
@@ -2649,345 +1395,6 @@
void
-gftp_free_getline_buffer (gftp_getline_buffer ** rbuf)
-{
- g_free ((*rbuf)->buffer);
- g_free (*rbuf);
- *rbuf = NULL;
-}
-
-
-ssize_t
-gftp_get_line (gftp_request * request, gftp_getline_buffer ** rbuf,
- char * str, size_t len, int fd)
-{
- ssize_t (*read_function) (gftp_request * request, void *ptr, size_t size,
- int fd);
- char *pos, *nextpos;
- size_t rlen, nslen;
- int end_of_buffer;
- ssize_t ret;
-
- if (request == NULL || request->read_function == NULL)
- read_function = gftp_fd_read;
- else
- read_function = request->read_function;
-
- if (*rbuf == NULL)
- {
- *rbuf = g_malloc0 (sizeof (**rbuf));
- (*rbuf)->max_bufsize = len;
- (*rbuf)->buffer = g_malloc0 ((gulong) ((*rbuf)->max_bufsize + 1));
-
- if ((ret = read_function (request, (*rbuf)->buffer,
- (*rbuf)->max_bufsize, fd)) <= 0)
- {
- gftp_free_getline_buffer (rbuf);
- return (ret);
- }
- (*rbuf)->buffer[ret] = '\0';
- (*rbuf)->cur_bufsize = ret;
- (*rbuf)->curpos = (*rbuf)->buffer;
- }
-
- ret = 0;
- while (1)
- {
- pos = strchr ((*rbuf)->curpos, '\n');
- end_of_buffer = (*rbuf)->curpos == (*rbuf)->buffer &&
- ((*rbuf)->max_bufsize == (*rbuf)->cur_bufsize || (*rbuf)->eof);
-
- if ((*rbuf)->cur_bufsize > 0 && (pos != NULL || end_of_buffer))
- {
- if (pos != NULL)
- {
- nslen = pos - (*rbuf)->curpos + 1;
- nextpos = pos + 1;
- if (pos > (*rbuf)->curpos && *(pos - 1) == '\r')
- pos--;
- *pos = '\0';
- }
- else
- {
- nslen = (*rbuf)->cur_bufsize;
- nextpos = NULL;
-
- /* This is not an overflow since we allocated one extra byte to
- buffer above */
- ((*rbuf)->buffer)[nslen] = '\0';
- }
-
- strncpy (str, (*rbuf)->curpos, len);
- str[len - 1] = '\0';
- (*rbuf)->cur_bufsize -= nslen;
-
- if (nextpos != NULL)
- (*rbuf)->curpos = nextpos;
- else
- (*rbuf)->cur_bufsize = 0;
-
- ret = nslen;
- break;
- }
- else
- {
- if ((*rbuf)->cur_bufsize == 0 || *(*rbuf)->curpos == '\0')
- {
- rlen = (*rbuf)->max_bufsize;
- pos = (*rbuf)->buffer;
- }
- else
- {
- memmove ((*rbuf)->buffer, (*rbuf)->curpos, (*rbuf)->cur_bufsize);
- pos = (*rbuf)->buffer + (*rbuf)->cur_bufsize;
- rlen = (*rbuf)->max_bufsize - (*rbuf)->cur_bufsize;
- }
-
- (*rbuf)->curpos = (*rbuf)->buffer;
-
- if ((*rbuf)->eof)
- ret = 0;
- else
- {
- ret = read_function (request, pos, rlen, fd);
- if (ret < 0)
- {
- gftp_free_getline_buffer (rbuf);
- return (ret);
- }
- }
-
- if (ret == 0)
- {
- if ((*rbuf)->cur_bufsize == 0)
- {
- gftp_free_getline_buffer (rbuf);
- return (ret);
- }
-
- (*rbuf)->eof = 1;
- }
-
- (*rbuf)->cur_bufsize += ret;
- (*rbuf)->buffer[(*rbuf)->cur_bufsize] = '\0';
- }
- }
-
- return (ret);
-}
-
-
-ssize_t
-gftp_fd_read (gftp_request * request, void *ptr, size_t size, int fd)
-{
- intptr_t network_timeout;
- struct timeval tv;
- fd_set fset;
- ssize_t ret;
- int s_ret;
-
- g_return_val_if_fail (fd >= 0, GFTP_EFATAL);
-
- gftp_lookup_request_option (request, "network_timeout", &network_timeout);
-
- errno = 0;
- ret = 0;
- FD_ZERO (&fset);
-
- do
- {
- FD_SET (fd, &fset);
- tv.tv_sec = network_timeout;
- tv.tv_usec = 0;
- s_ret = select (fd + 1, &fset, NULL, NULL, &tv);
- if (s_ret == -1 && (errno == EINTR || errno == EAGAIN))
- {
- if (request != NULL && request->cancel)
- {
- gftp_disconnect (request);
- return (GFTP_ERETRYABLE);
- }
-
- continue;
- }
- else if (s_ret <= 0)
- {
- if (request != NULL)
- {
- request->logging_function (gftp_logging_error, request,
- _("Connection to %s timed out\n"),
- request->hostname);
- gftp_disconnect (request);
- }
-
- return (GFTP_ERETRYABLE);
- }
-
- if ((ret = read (fd, ptr, size)) < 0)
- {
- if (errno == EINTR || errno == EAGAIN)
- {
- if (request != NULL && request->cancel)
- {
- gftp_disconnect (request);
- return (GFTP_ERETRYABLE);
- }
-
- continue;
- }
-
- if (request != NULL)
- {
- request->logging_function (gftp_logging_error, request,
- _("Error: Could not read from socket: %s\n"),
- g_strerror (errno));
- gftp_disconnect (request);
- }
-
- return (GFTP_ERETRYABLE);
- }
-
- break;
- }
- while (1);
-
- return (ret);
-}
-
-
-ssize_t
-gftp_fd_write (gftp_request * request, const char *ptr, size_t size, int fd)
-{
- intptr_t network_timeout;
- struct timeval tv;
- int ret, s_ret;
- ssize_t w_ret;
- fd_set fset;
-
- g_return_val_if_fail (fd >= 0, GFTP_EFATAL);
-
- gftp_lookup_request_option (request, "network_timeout", &network_timeout);
-
- errno = 0;
- ret = 0;
- FD_ZERO (&fset);
-
- do
- {
- FD_SET (fd, &fset);
- tv.tv_sec = network_timeout;
- tv.tv_usec = 0;
- s_ret = select (fd + 1, NULL, &fset, NULL, &tv);
- if (s_ret == -1 && (errno == EINTR || errno == EAGAIN))
- {
- if (request != NULL && request->cancel)
- {
- gftp_disconnect (request);
- return (GFTP_ERETRYABLE);
- }
-
- continue;
- }
- else if (s_ret <= 0)
- {
- if (request != NULL)
- {
- request->logging_function (gftp_logging_error, request,
- _("Connection to %s timed out\n"),
- request->hostname);
- gftp_disconnect (request);
- }
-
- return (GFTP_ERETRYABLE);
- }
-
- w_ret = write (fd, ptr, size);
- if (w_ret < 0)
- {
- if (errno == EINTR || errno == EAGAIN)
- {
- if (request != NULL && request->cancel)
- {
- gftp_disconnect (request);
- return (GFTP_ERETRYABLE);
- }
-
- continue;
- }
-
- if (request != NULL)
- {
- request->logging_function (gftp_logging_error, request,
- _("Error: Could not write to socket: %s\n"),
- g_strerror (errno));
- gftp_disconnect (request);
- }
-
- return (GFTP_ERETRYABLE);
- }
-
- ptr += w_ret;
- size -= w_ret;
- ret += w_ret;
- }
- while (size > 0);
-
- return (ret);
-}
-
-
-ssize_t
-gftp_writefmt (gftp_request * request, int fd, const char *fmt, ...)
-{
- char *tempstr;
- va_list argp;
- ssize_t ret;
-
- va_start (argp, fmt);
- tempstr = g_strdup_vprintf (fmt, argp);
- va_end (argp);
-
- ret = request->write_function (request, tempstr, strlen (tempstr), fd);
- g_free (tempstr);
- return (ret);
-}
-
-
-int
-gftp_fd_set_sockblocking (gftp_request * request, int fd, int non_blocking)
-{
- int flags;
-
- g_return_val_if_fail (fd >= 0, GFTP_EFATAL);
-
- if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
- {
- request->logging_function (gftp_logging_error, request,
- _("Cannot get socket flags: %s\n"),
- g_strerror (errno));
- gftp_disconnect (request);
- return (GFTP_ERETRYABLE);
- }
-
- if (non_blocking)
- flags |= O_NONBLOCK;
- else
- flags &= ~O_NONBLOCK;
-
- if (fcntl (fd, F_SETFL, flags) < 0)
- {
- request->logging_function (gftp_logging_error, request,
- _("Cannot set socket to non-blocking: %s\n"),
- g_strerror (errno));
- gftp_disconnect (request);
- return (GFTP_ERETRYABLE);
- }
-
- return (0);
-}
-
-
-void
gftp_swap_socks (gftp_request * dest, gftp_request * source)
{
g_return_if_fail (dest != NULL);
Added: trunk/lib/socket-connect.c
==============================================================================
--- (empty file)
+++ trunk/lib/socket-connect.c Tue Mar 4 12:28:40 2008
@@ -0,0 +1,401 @@
+/*****************************************************************************/
+/* socket-connect.c - contains functions for connecting to a server */
+/* Copyright (C) 1998-2008 Brian Masney <masneyb gftp org> */
+/* */
+/* This program is free software; you can redistribute it and/or modify */
+/* it under the terms of the GNU General Public License as published by */
+/* the Free Software Foundation; either version 2 of the License, or */
+/* (at your option) any later version. */
+/* */
+/* 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 General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA */
+/*****************************************************************************/
+
+#include "gftp.h"
+static const char cvsid[] = "$Id: protocols.c 952 2008-01-24 23:31:26Z masneyb $";
+
+/* FIXME - clean up this function */
+static int
+gftp_need_proxy (gftp_request * request, char *service, char *proxy_hostname,
+ unsigned int proxy_port)
+{
+ gftp_config_list_vars * proxy_hosts;
+ gftp_proxy_hosts * hostname;
+ size_t hostlen, domlen;
+ unsigned char addy[4];
+ struct sockaddr *addr;
+ GList * templist;
+ gint32 netaddr;
+ char *pos;
+#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
+ struct addrinfo hints, *hostp;
+ unsigned int port;
+ int errnum;
+ char serv[8];
+#else
+ struct hostent host, *hostp;
+#endif
+
+ gftp_lookup_global_option ("dont_use_proxy", &proxy_hosts);
+
+ if (proxy_hostname == NULL || *proxy_hostname == '\0')
+ return (0);
+ else if (proxy_hosts->list == NULL)
+ return (proxy_hostname != NULL &&
+ *proxy_hostname != '\0');
+
+ hostp = NULL;
+#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ port = request->use_proxy ? proxy_port : request->port;
+ if (port == 0)
+ strcpy (serv, service);
+ else
+ snprintf (serv, sizeof (serv), "%d", port);
+
+ request->logging_function (gftp_logging_misc, request,
+ _("Looking up %s\n"), request->hostname);
+
+ if ((errnum = getaddrinfo (request->hostname, serv, &hints,
+ &hostp)) != 0)
+ {
+ request->logging_function (gftp_logging_error, request,
+ _("Cannot look up hostname %s: %s\n"),
+ request->hostname, gai_strerror (errnum));
+ return (GFTP_ERETRYABLE);
+ }
+
+ addr = hostp->ai_addr;
+
+#else /* !HAVE_GETADDRINFO */
+ request->logging_function (gftp_logging_misc, request,
+ _("Looking up %s\n"), request->hostname);
+
+ if (!(hostp = r_gethostbyname (request->hostname, &host, NULL)))
+ {
+ request->logging_function (gftp_logging_error, request,
+ _("Cannot look up hostname %s: %s\n"),
+ request->hostname, g_strerror (errno));
+ return (GFTP_ERETRYABLE);
+ }
+
+ addr = (struct sockaddr *) host.h_addr_list[0];
+
+#endif /* HAVE_GETADDRINFO */
+
+ templist = proxy_hosts->list;
+ while (templist != NULL)
+ {
+ hostname = templist->data;
+ if (hostname->domain != NULL)
+ {
+ hostlen = strlen (request->hostname);
+ domlen = strlen (hostname->domain);
+ if (hostlen > domlen)
+ {
+ pos = request->hostname + hostlen - domlen;
+ if (strcmp (hostname->domain, pos) == 0)
+ return (0);
+ }
+ }
+
+ if (hostname->ipv4_network_address != 0)
+ {
+ memcpy (addy, addr, sizeof (*addy));
+ netaddr =
+ (((addy[0] & 0xff) << 24) | ((addy[1] & 0xff) << 16) |
+ ((addy[2] & 0xff) << 8) | (addy[3] & 0xff)) &
+ hostname->ipv4_netmask;
+ if (netaddr == hostname->ipv4_network_address)
+ return (0);
+ }
+ templist = templist->next;
+ }
+
+ return (proxy_hostname != NULL && *proxy_hostname != '\0');
+}
+
+
+#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
+static int
+get_port (struct addrinfo *addr)
+{
+ struct sockaddr_in * saddr;
+ int port;
+
+ if (addr->ai_family == AF_INET)
+ {
+ saddr = (struct sockaddr_in *) addr->ai_addr;
+ port = ntohs (saddr->sin_port);
+ }
+ else
+ port = 0;
+
+ return (port);
+}
+
+
+static int
+gftp_connect_server_with_getaddr (gftp_request * request, char *service,
+ char *proxy_hostname, unsigned int proxy_port)
+{
+ struct addrinfo *hostp, *current_hostp;
+ char *connect_host, *disphost;
+ struct addrinfo hints, *res;
+ intptr_t enable_ipv6;
+ unsigned int port;
+ int ret, sock = -1;
+ char serv[8];
+
+ if ((ret = gftp_need_proxy (request, service, proxy_hostname,
+ proxy_port)) < 0)
+ return (ret);
+ else
+ request->use_proxy = ret;
+
+ gftp_lookup_request_option (request, "enable_ipv6", &enable_ipv6);
+
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_flags = AI_CANONNAME;
+
+ hints.ai_family = enable_ipv6 ? PF_UNSPEC : AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+
+ if (request->use_proxy)
+ {
+ connect_host = proxy_hostname;
+ port = proxy_port;
+ }
+ else
+ {
+ connect_host = request->hostname;
+ port = request->port;
+ }
+
+ if (port == 0)
+ strcpy (serv, service);
+ else
+ snprintf (serv, sizeof (serv), "%d", port);
+
+ request->logging_function (gftp_logging_misc, request,
+ _("Looking up %s\n"), connect_host);
+ if ((ret = getaddrinfo (connect_host, serv, &hints,
+ &hostp)) != 0)
+ {
+ request->logging_function (gftp_logging_error, request,
+ _("Cannot look up hostname %s: %s\n"),
+ connect_host, gai_strerror (ret));
+ return (GFTP_ERETRYABLE);
+ }
+
+ disphost = connect_host;
+ for (res = hostp; res != NULL; res = res->ai_next)
+ {
+ disphost = res->ai_canonname ? res->ai_canonname : connect_host;
+ port = get_port (res);
+ if (!request->use_proxy)
+ request->port = port;
+
+ if ((sock = socket (res->ai_family, res->ai_socktype,
+ res->ai_protocol)) < 0)
+ {
+ request->logging_function (gftp_logging_error, request,
+ _("Failed to create a socket: %s\n"),
+ g_strerror (errno));
+ continue;
+ }
+
+ request->logging_function (gftp_logging_misc, request,
+ _("Trying %s:%d\n"), disphost, port);
+
+ if (connect (sock, res->ai_addr, res->ai_addrlen) == -1)
+ {
+ request->logging_function (gftp_logging_error, request,
+ _("Cannot connect to %s: %s\n"),
+ disphost, g_strerror (errno));
+ close (sock);
+ continue;
+ }
+
+ current_hostp = res;
+ request->ai_family = res->ai_family;
+ break;
+ }
+
+ if (res == NULL)
+ {
+ if (hostp != NULL)
+ freeaddrinfo (hostp);
+
+ return (GFTP_ERETRYABLE);
+ }
+
+ request->remote_addr_len = current_hostp->ai_addrlen;
+ request->remote_addr = g_malloc0 (request->remote_addr_len);
+ memcpy (request->remote_addr, &((struct sockaddr_in *) current_hostp->ai_addr)->sin_addr,
+ request->remote_addr_len);
+
+ request->logging_function (gftp_logging_misc, request,
+ _("Connected to %s:%d\n"), connect_host, port);
+
+ return (sock);
+}
+#endif
+
+
+static int
+gftp_connect_server_legacy (gftp_request * request, char *service,
+ char *proxy_hostname, unsigned int proxy_port)
+{
+ struct sockaddr_in remote_address;
+ char *connect_host, *disphost;
+ struct hostent host, *hostp;
+ struct servent serv_struct;
+ int ret, sock, curhost;
+ unsigned int port;
+
+ if ((ret = gftp_need_proxy (request, service, proxy_hostname,
+ proxy_port)) < 0)
+ return (ret);
+
+ request->use_proxy = ret;
+ if (request->use_proxy == 1)
+ hostp = NULL;
+
+ request->ai_family = AF_INET;
+ if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+ {
+ request->logging_function (gftp_logging_error, request,
+ _("Failed to create a IPv4 socket: %s\n"),
+ g_strerror (errno));
+ return (GFTP_ERETRYABLE);
+ }
+
+ memset (&remote_address, 0, sizeof (remote_address));
+ remote_address.sin_family = AF_INET;
+
+ if (request->use_proxy)
+ {
+ connect_host = proxy_hostname;
+ port = proxy_port;
+ }
+ else
+ {
+ connect_host = request->hostname;
+ port = request->port;
+ }
+
+ if (port == 0)
+ {
+ if (!r_getservbyname (service, "tcp", &serv_struct, NULL))
+ {
+ request->logging_function (gftp_logging_error, request,
+ _("Cannot look up service name %s/tcp. Please check your services file\n"),
+ service);
+ close (sock);
+ return (GFTP_EFATAL);
+ }
+
+ port = ntohs (serv_struct.s_port);
+
+ if (!request->use_proxy)
+ request->port = port;
+ }
+
+ remote_address.sin_port = htons (port);
+
+ request->logging_function (gftp_logging_misc, request,
+ _("Looking up %s\n"), connect_host);
+
+ if (!(hostp = r_gethostbyname (connect_host, &host, NULL)))
+ {
+ request->logging_function (gftp_logging_error, request,
+ _("Cannot look up hostname %s: %s\n"),
+ connect_host, g_strerror (errno));
+ close (sock);
+ return (GFTP_ERETRYABLE);
+ }
+
+ disphost = NULL;
+ for (curhost = 0;
+ host.h_addr_list[curhost] != NULL;
+ curhost++)
+ {
+ disphost = host.h_name;
+ memcpy (&remote_address.sin_addr,
+ host.h_addr_list[curhost],
+ host.h_length);
+ request->logging_function (gftp_logging_misc, request,
+ _("Trying %s:%d\n"),
+ host.h_name, port);
+
+ if (connect (sock, (struct sockaddr *) &remote_address,
+ sizeof (remote_address)) == -1)
+ {
+ request->logging_function (gftp_logging_error, request,
+ _("Cannot connect to %s: %s\n"),
+ connect_host, g_strerror (errno));
+ }
+ break;
+ }
+
+ if (host.h_addr_list[curhost] == NULL)
+ {
+ close (sock);
+ return (GFTP_ERETRYABLE);
+ }
+
+ return (sock);
+}
+
+
+int
+gftp_connect_server (gftp_request * request, char *service,
+ char *proxy_hostname, unsigned int proxy_port)
+{
+ int sock;
+
+#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
+ sock = gftp_connect_server_with_getaddr (request, service, proxy_hostname,
+ proxy_port);
+#else
+ sock = gftp_connect_server_legacy (request, service, proxy_hostname,
+ proxy_port);
+#endif
+
+ if (sock < 0)
+ return (sock);
+
+ if (fcntl (sock, F_SETFD, 1) == -1)
+ {
+ request->logging_function (gftp_logging_error, request,
+ _("Error: Cannot set close on exec flag: %s\n"),
+ g_strerror (errno));
+ close (sock);
+ return (GFTP_ERETRYABLE);
+ }
+
+ if (gftp_fd_set_sockblocking (request, sock, 1) < 0)
+ {
+ close (sock);
+ return (GFTP_ERETRYABLE);
+ }
+
+ request->datafd = sock;
+
+ if (request->post_connect != NULL)
+ return (request->post_connect (request));
+
+ return (0);
+}
+
Added: trunk/lib/sockutils.c
==============================================================================
--- (empty file)
+++ trunk/lib/sockutils.c Tue Mar 4 12:28:40 2008
@@ -0,0 +1,360 @@
+/*****************************************************************************/
+/* sockutils.c - various utilities for dealing with sockets */
+/* Copyright (C) 1998-2008 Brian Masney <masneyb gftp org> */
+/* */
+/* This program is free software; you can redistribute it and/or modify */
+/* it under the terms of the GNU General Public License as published by */
+/* the Free Software Foundation; either version 2 of the License, or */
+/* (at your option) any later version. */
+/* */
+/* 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 General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA */
+/*****************************************************************************/
+
+#include "gftp.h"
+static const char cvsid[] = "$Id: protocols.c 952 2008-01-24 23:31:26Z masneyb $";
+
+ssize_t
+gftp_get_line (gftp_request * request, gftp_getline_buffer ** rbuf,
+ char * str, size_t len, int fd)
+{
+ ssize_t (*read_function) (gftp_request * request, void *ptr, size_t size,
+ int fd);
+ char *pos, *nextpos;
+ size_t rlen, nslen;
+ int end_of_buffer;
+ ssize_t ret;
+
+ if (request == NULL || request->read_function == NULL)
+ read_function = gftp_fd_read;
+ else
+ read_function = request->read_function;
+
+ if (*rbuf == NULL)
+ {
+ *rbuf = g_malloc0 (sizeof (**rbuf));
+ (*rbuf)->max_bufsize = len;
+ (*rbuf)->buffer = g_malloc0 ((gulong) ((*rbuf)->max_bufsize + 1));
+
+ if ((ret = read_function (request, (*rbuf)->buffer,
+ (*rbuf)->max_bufsize, fd)) <= 0)
+ {
+ gftp_free_getline_buffer (rbuf);
+ return (ret);
+ }
+ (*rbuf)->buffer[ret] = '\0';
+ (*rbuf)->cur_bufsize = ret;
+ (*rbuf)->curpos = (*rbuf)->buffer;
+ }
+
+ ret = 0;
+ while (1)
+ {
+ pos = strchr ((*rbuf)->curpos, '\n');
+ end_of_buffer = (*rbuf)->curpos == (*rbuf)->buffer &&
+ ((*rbuf)->max_bufsize == (*rbuf)->cur_bufsize || (*rbuf)->eof);
+
+ if ((*rbuf)->cur_bufsize > 0 && (pos != NULL || end_of_buffer))
+ {
+ if (pos != NULL)
+ {
+ nslen = pos - (*rbuf)->curpos + 1;
+ nextpos = pos + 1;
+ if (pos > (*rbuf)->curpos && *(pos - 1) == '\r')
+ pos--;
+ *pos = '\0';
+ }
+ else
+ {
+ nslen = (*rbuf)->cur_bufsize;
+ nextpos = NULL;
+
+ /* This is not an overflow since we allocated one extra byte to
+ buffer above */
+ ((*rbuf)->buffer)[nslen] = '\0';
+ }
+
+ strncpy (str, (*rbuf)->curpos, len);
+ str[len - 1] = '\0';
+ (*rbuf)->cur_bufsize -= nslen;
+
+ if (nextpos != NULL)
+ (*rbuf)->curpos = nextpos;
+ else
+ (*rbuf)->cur_bufsize = 0;
+
+ ret = nslen;
+ break;
+ }
+ else
+ {
+ if ((*rbuf)->cur_bufsize == 0 || *(*rbuf)->curpos == '\0')
+ {
+ rlen = (*rbuf)->max_bufsize;
+ pos = (*rbuf)->buffer;
+ }
+ else
+ {
+ memmove ((*rbuf)->buffer, (*rbuf)->curpos, (*rbuf)->cur_bufsize);
+ pos = (*rbuf)->buffer + (*rbuf)->cur_bufsize;
+ rlen = (*rbuf)->max_bufsize - (*rbuf)->cur_bufsize;
+ }
+
+ (*rbuf)->curpos = (*rbuf)->buffer;
+
+ if ((*rbuf)->eof)
+ ret = 0;
+ else
+ {
+ ret = read_function (request, pos, rlen, fd);
+ if (ret < 0)
+ {
+ gftp_free_getline_buffer (rbuf);
+ return (ret);
+ }
+ }
+
+ if (ret == 0)
+ {
+ if ((*rbuf)->cur_bufsize == 0)
+ {
+ gftp_free_getline_buffer (rbuf);
+ return (ret);
+ }
+
+ (*rbuf)->eof = 1;
+ }
+
+ (*rbuf)->cur_bufsize += ret;
+ (*rbuf)->buffer[(*rbuf)->cur_bufsize] = '\0';
+ }
+ }
+
+ return (ret);
+}
+
+
+void
+gftp_free_getline_buffer (gftp_getline_buffer ** rbuf)
+{
+ g_free ((*rbuf)->buffer);
+ g_free (*rbuf);
+ *rbuf = NULL;
+}
+
+
+ssize_t
+gftp_fd_read (gftp_request * request, void *ptr, size_t size, int fd)
+{
+ intptr_t network_timeout;
+ struct timeval tv;
+ fd_set fset;
+ ssize_t ret;
+ int s_ret;
+
+ g_return_val_if_fail (fd >= 0, GFTP_EFATAL);
+
+ gftp_lookup_request_option (request, "network_timeout", &network_timeout);
+
+ errno = 0;
+ ret = 0;
+ FD_ZERO (&fset);
+
+ do
+ {
+ FD_SET (fd, &fset);
+ tv.tv_sec = network_timeout;
+ tv.tv_usec = 0;
+ s_ret = select (fd + 1, &fset, NULL, NULL, &tv);
+ if (s_ret == -1 && (errno == EINTR || errno == EAGAIN))
+ {
+ if (request != NULL && request->cancel)
+ {
+ gftp_disconnect (request);
+ return (GFTP_ERETRYABLE);
+ }
+
+ continue;
+ }
+ else if (s_ret <= 0)
+ {
+ if (request != NULL)
+ {
+ request->logging_function (gftp_logging_error, request,
+ _("Connection to %s timed out\n"),
+ request->hostname);
+ gftp_disconnect (request);
+ }
+
+ return (GFTP_ERETRYABLE);
+ }
+
+ if ((ret = read (fd, ptr, size)) < 0)
+ {
+ if (errno == EINTR || errno == EAGAIN)
+ {
+ if (request != NULL && request->cancel)
+ {
+ gftp_disconnect (request);
+ return (GFTP_ERETRYABLE);
+ }
+
+ continue;
+ }
+
+ if (request != NULL)
+ {
+ request->logging_function (gftp_logging_error, request,
+ _("Error: Could not read from socket: %s\n"),
+ g_strerror (errno));
+ gftp_disconnect (request);
+ }
+
+ return (GFTP_ERETRYABLE);
+ }
+
+ break;
+ }
+ while (1);
+
+ return (ret);
+}
+
+
+ssize_t
+gftp_fd_write (gftp_request * request, const char *ptr, size_t size, int fd)
+{
+ intptr_t network_timeout;
+ struct timeval tv;
+ int ret, s_ret;
+ ssize_t w_ret;
+ fd_set fset;
+
+ g_return_val_if_fail (fd >= 0, GFTP_EFATAL);
+
+ gftp_lookup_request_option (request, "network_timeout", &network_timeout);
+
+ errno = 0;
+ ret = 0;
+ FD_ZERO (&fset);
+
+ do
+ {
+ FD_SET (fd, &fset);
+ tv.tv_sec = network_timeout;
+ tv.tv_usec = 0;
+ s_ret = select (fd + 1, NULL, &fset, NULL, &tv);
+ if (s_ret == -1 && (errno == EINTR || errno == EAGAIN))
+ {
+ if (request != NULL && request->cancel)
+ {
+ gftp_disconnect (request);
+ return (GFTP_ERETRYABLE);
+ }
+
+ continue;
+ }
+ else if (s_ret <= 0)
+ {
+ if (request != NULL)
+ {
+ request->logging_function (gftp_logging_error, request,
+ _("Connection to %s timed out\n"),
+ request->hostname);
+ gftp_disconnect (request);
+ }
+
+ return (GFTP_ERETRYABLE);
+ }
+
+ w_ret = write (fd, ptr, size);
+ if (w_ret < 0)
+ {
+ if (errno == EINTR || errno == EAGAIN)
+ {
+ if (request != NULL && request->cancel)
+ {
+ gftp_disconnect (request);
+ return (GFTP_ERETRYABLE);
+ }
+
+ continue;
+ }
+
+ if (request != NULL)
+ {
+ request->logging_function (gftp_logging_error, request,
+ _("Error: Could not write to socket: %s\n"),
+ g_strerror (errno));
+ gftp_disconnect (request);
+ }
+
+ return (GFTP_ERETRYABLE);
+ }
+
+ ptr += w_ret;
+ size -= w_ret;
+ ret += w_ret;
+ }
+ while (size > 0);
+
+ return (ret);
+}
+
+
+ssize_t
+gftp_writefmt (gftp_request * request, int fd, const char *fmt, ...)
+{
+ char *tempstr;
+ va_list argp;
+ ssize_t ret;
+
+ va_start (argp, fmt);
+ tempstr = g_strdup_vprintf (fmt, argp);
+ va_end (argp);
+
+ ret = request->write_function (request, tempstr, strlen (tempstr), fd);
+ g_free (tempstr);
+ return (ret);
+}
+
+
+int
+gftp_fd_set_sockblocking (gftp_request * request, int fd, int non_blocking)
+{
+ int flags;
+
+ g_return_val_if_fail (fd >= 0, GFTP_EFATAL);
+
+ if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
+ {
+ request->logging_function (gftp_logging_error, request,
+ _("Cannot get socket flags: %s\n"),
+ g_strerror (errno));
+ gftp_disconnect (request);
+ return (GFTP_ERETRYABLE);
+ }
+
+ if (non_blocking)
+ flags |= O_NONBLOCK;
+ else
+ flags &= ~O_NONBLOCK;
+
+ if (fcntl (fd, F_SETFL, flags) < 0)
+ {
+ request->logging_function (gftp_logging_error, request,
+ _("Cannot set socket to non-blocking: %s\n"),
+ g_strerror (errno));
+ gftp_disconnect (request);
+ return (GFTP_ERETRYABLE);
+ }
+
+ return (0);
+}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]