Mercurial > gftp.yaz
diff lib/protocols.c @ 58:c01d91c10f6c
2002-11-20 Brian Masney <masneyb@gftp.org>
* lib/protocols.c lib/gftp.h - added gftp_get_line(), gftp_read(),
gftp_write(), gftp_writefmt(), and gftp_set_sockblocking() functions.
Added struct_gftp_getline_buffer for gftp_get_line function()
* lib/cache.c lib/gftp.h lib/local.c lib/misc.c lib/protocols.c
lib/rfc2068.c lib/rfc959.c lib/ssh.c lib/sshv2.c - *_get_file() returns
off_t instead of long. *_{get,put}_next_file_chunk returns ssize_t
instead of size_t. Added *_set_config_options function to gftp_request
structure and protocol files. Use the new network functions
documented above. Convert usage of ANSI C IO (FILE *) to standard BSD
sockets so that I can use timeouts properly with select
* lib/misc.c (ssh_start_login_sequence) - use gftp_set_sockblock(),
gftp_read() and gftp_write() functions
* lib/protocols.c - move some protocol specific code to the protocol
specific files
* lib/local.c - log succesful messages to gftp_logging_misc instead
of gftp_logging_error
* lib/cache.c - log some more error conditions to the user
* lib/rfc959.c - added rfc959_getcwd(). In,
rfc959_accept_active_connection(), set set socket to blocking mode
before calling accept()
* src/text/gftk-text.c - If we get no files in gftp_text_ls(),
return instead of segfaulting
* src/gtk/gftp-gtk.c - expand the port field in the toolbar to be 45
pixels wide
* src/text/gftp-text.c src/gtk/misc-gtk.c src/gtk/transfer.c
src/gtk/view_dialog.c - changes for conversion of request->{sock,data}
from ANSI C IO (FILE *) to standard BSD sockets
author | masneyb |
---|---|
date | Thu, 21 Nov 2002 00:33:51 +0000 |
parents | a12bcbc2fce4 |
children | 8a9324fb63a4 |
line wrap: on
line diff
--- a/lib/protocols.c Tue Nov 12 00:04:44 2002 +0000 +++ b/lib/protocols.c Thu Nov 21 00:33:51 2002 +0000 @@ -26,8 +26,7 @@ gftp_request *request; request = g_malloc0 (sizeof (*request)); - request->sockfd = NULL; - request->datafd = NULL; + request->sockfd = -1; request->data_type = GFTP_TYPE_BINARY; return (request); } @@ -107,20 +106,6 @@ if (request->connect == NULL) return (-2); - if (request->sftpserv_path == NULL) - { - /* FIXME - move this to per protocol files */ - switch (request->protonum) - { - case GFTP_SSH_NUM: - request->sftpserv_path = g_strdup (ssh1_sftp_path); - break; - case GFTP_SSHV2_NUM: - request->sftpserv_path = g_strdup (ssh2_sftp_path); - break; - } - } - gftp_set_config_options (request); return (request->connect (request)); @@ -151,8 +136,8 @@ } -size_t -gftp_get_file (gftp_request * request, const char *filename, FILE * fd, +off_t +gftp_get_file (gftp_request * request, const char *filename, int fd, size_t startsize) { g_return_val_if_fail (request != NULL, -2); @@ -165,7 +150,7 @@ int -gftp_put_file (gftp_request * request, const char *filename, FILE * fd, +gftp_put_file (gftp_request * request, const char *filename, int fd, size_t startsize, size_t totalsize) { g_return_val_if_fail (request != NULL, -2); @@ -179,9 +164,9 @@ long gftp_transfer_file (gftp_request * fromreq, const char *fromfile, - FILE * fromfd, size_t fromsize, + int fromfd, size_t fromsize, gftp_request * toreq, const char *tofile, - FILE * tofd, size_t tosize) + int tofd, size_t tosize) { long size; @@ -215,150 +200,32 @@ } -size_t +ssize_t gftp_get_next_file_chunk (gftp_request * request, char *buf, size_t size) { - struct timeval tv; - fd_set fset; - size_t len; - int ret; - g_return_val_if_fail (request != NULL, -2); g_return_val_if_fail (buf != NULL, -2); if (request->get_next_file_chunk != NULL) return (request->get_next_file_chunk (request, buf, size)); - errno = 0; - len = 0; - do - { - FD_ZERO (&fset); - FD_SET (fileno (request->datafd), &fset); - tv.tv_sec = request->network_timeout; - tv.tv_usec = 0; - ret = select (fileno (request->datafd) + 1, &fset, NULL, NULL, &tv); - if (ret == -1 && errno == EINTR) - { - if (request->cancel) - break; - else - continue; - } - else if (ret <= 0) - { - request->logging_function (gftp_logging_error, request->user_data, - _("Connection to %s timed out\n"), - request->hostname); - gftp_disconnect (request); - return (-1); - } - - if ((len = read (fileno (request->datafd), buf, size)) == -1) - { - if (errno == EINTR) - { - if (request->cancel) - break; - else - continue; - } - - request->logging_function (gftp_logging_error, request->user_data, - _("Error reading from host %s: %s\n"), - request->hostname, - g_strerror (errno)); - gftp_disconnect (request); - return (-1); - } - } - while (errno == EINTR && !request->cancel); - - if (errno == EINTR && request->cancel) - { - gftp_disconnect (request); - return (-1); - } - - return (len); + return (gftp_read (request, buf, size, request->datafd)); } -size_t +ssize_t gftp_put_next_file_chunk (gftp_request * request, char *buf, size_t size) { - struct timeval tv; - size_t len, ret; - fd_set fset; - char *pos; - int sret; - g_return_val_if_fail (request != NULL, -2); + g_return_val_if_fail (buf != NULL, -2); - ret = size; if (request->put_next_file_chunk != NULL) return (request->put_next_file_chunk (request, buf, size)); if (size == 0) return (0); - pos = buf; - while (size > 0) - { - errno = 0; - do - { - FD_ZERO (&fset); - FD_SET (fileno (request->datafd), &fset); - tv.tv_sec = request->network_timeout; - tv.tv_usec = 0; - sret = select (fileno (request->datafd) + 1, NULL, &fset, NULL, &tv); - if (sret == -1 && errno == EINTR) - { - if (request->cancel) - break; - else - continue; - } - else if (sret <= 0) - { - request->logging_function (gftp_logging_error, request->user_data, - _("Connection to %s timed out\n"), - request->hostname); - gftp_disconnect (request); - return (-1); - } - - if ((len = write (fileno (request->datafd), pos, size)) < 0) - { - if (sret == -1 && errno == EINTR) - { - if (request->cancel) - break; - else - continue; - } - - request->logging_function (gftp_logging_error, request->user_data, - _("Error writing to host %s: %s\n"), - request->hostname, - g_strerror (errno)); - gftp_disconnect (request); - return (-1); - } - size -= len; - pos += len; - } - while (errno == EINTR && !request->cancel); - } - - if (errno == EINTR && request->cancel) - { - gftp_disconnect (request); - return (-1); - } - - return (ret); + return (gftp_write (request, buf, size, request->datafd)); } @@ -375,10 +242,10 @@ else ret = 0; - if (request->cachefd != NULL) + if (request->cachefd > 0) { - fclose (request->cachefd); - request->cachefd = NULL; + close (request->cachefd); + request->cachefd = -1; } if (request->last_dir_entry) @@ -407,12 +274,12 @@ int gftp_list_files (gftp_request * request) { - FILE * fd; + int fd; g_return_val_if_fail (request != NULL, -2); request->cached = 0; - if (request->use_cache && (fd = gftp_find_cache_entry (request)) != NULL) + if (request->use_cache && (fd = gftp_find_cache_entry (request)) > 0) { request->logging_function (gftp_logging_misc, request->user_data, _("Loading directory listing %s from cache\n"), @@ -437,8 +304,7 @@ int gftp_get_next_file (gftp_request * request, char *filespec, gftp_file * fle) { - FILE * fd; - int ret; + int fd, ret; #if GLIB_MAJOR_VERSION > 1 gsize bread, bwrite; char *tempstr; @@ -450,7 +316,7 @@ if (request->get_next_file == NULL) return (-2); - if (request->cached && request->cachefd != NULL) + if (request->cached && request->cachefd > 0) fd = request->cachefd; else fd = request->datafd; @@ -477,18 +343,15 @@ } #endif - if (ret >= 0 && !request->cached && request->cachefd != NULL && + if (ret >= 0 && !request->cached && request->cachefd > 0&& request->last_dir_entry != NULL) { - fwrite (request->last_dir_entry, 1, request->last_dir_entry_len, - request->cachefd); - if (ferror (request->cachefd)) + if (gftp_writefmt (request, request->cachefd, "%s\n", + request->last_dir_entry) < 0) { request->logging_function (gftp_logging_error, request->user_data, _("Error: Cannot write to cache: %s\n"), g_strerror (errno)); - fclose (request->cachefd); - request->cachefd = NULL; } } } while (ret > 0 && !gftp_match_filespec (fle->file, filespec)); @@ -678,7 +541,7 @@ g_return_val_if_fail (directory != NULL, -2); - if (request->sockfd == NULL) + if (request->sockfd <= 0 && !request->always_connected) { if (directory != request->directory) { @@ -871,7 +734,7 @@ } -long +off_t gftp_get_file_size (gftp_request * request, const char *filename) { g_return_val_if_fail (request != NULL, 0); @@ -1917,6 +1780,13 @@ request->logging_function (gftp_logging_misc, request->user_data, _("Connected to %s:%d\n"), connect_host, port); + + if (gftp_set_sockblocking (request, sock, 1) == -1) + { + close (sock); + return (-1); + } + return (sock); } @@ -1924,57 +1794,13 @@ void gftp_set_config_options (gftp_request * request) { - /* FIXME - move this to per protocol files */ - request->transfer_type = passive_transfer ? gftp_transfer_passive : gftp_transfer_active; request->network_timeout = network_timeout; request->retries = retries; request->sleep_time = sleep_time; request->maxkbs = maxkbs; - if (request->protonum == GFTP_SSHV2_NUM || - request->protonum == GFTP_SSH_NUM) - request->need_userpass = ssh_need_userpass; - - /* Set up the proxy server settings. If we are using a HTTP proxy for FTP, - then set up the HTTP proxy settings */ - if ((strcmp (request->protocol_name, "FTP") == 0 || - strcmp (request->protocol_name, "HTTP") == 0) && - proxy_config != NULL) - { - if (strcmp (request->protocol_name, "FTP") == 0 && - strcmp (proxy_config, "http") != 0) - { - gftp_set_proxy_hostname (request, firewall_host); - gftp_set_proxy_port (request, firewall_port); - gftp_set_proxy_username (request, firewall_username); - gftp_set_proxy_password (request, firewall_password); - gftp_set_proxy_account (request, firewall_account); - gftp_set_proxy_config (request, proxy_config); - } - else - { - gftp_set_proxy_hostname (request, http_proxy_host); - gftp_set_proxy_port (request, http_proxy_port); - gftp_set_proxy_username (request, http_proxy_username); - gftp_set_proxy_password (request, http_proxy_password); - - - if (request->proxy_config == NULL) - { - if (strcmp (GFTP_GET_PROTOCOL_NAME (request), "FTP") == 0) - { - gftp_protocols[GFTP_HTTP_NUM].init (request); - request->proxy_config = g_malloc (4); - strcpy (request->proxy_config, "ftp"); - } - else - { - request->proxy_config = g_malloc (5); - strcpy (request->proxy_config, "http"); - } - } - } - } + if (request->set_config_options != NULL) + request->set_config_options (request); } @@ -2037,99 +1863,169 @@ } -char * -gftp_fgets (gftp_request * request, char * str, size_t len, FILE * fd) +static void +gftp_free_getline_buffer (gftp_getline_buffer ** rbuf) { - char * ret = NULL; - - errno = 0; - do - { - ret = fgets (str, len, fd); - if (ferror (fd)) - { - if (errno == EINTR) - { - clearerr (fd); - if (request->cancel) - break; - else - continue; - } - - request->logging_function (gftp_logging_error, request->user_data, - _("Error: Could not read from socket: %s\n"), - g_strerror (errno)); - gftp_disconnect (request); - return (NULL); - } - } - while (errno == EINTR && !request->cancel); - - if (errno == EINTR && request->cancel) - { - gftp_disconnect (request); - return (NULL); - } - - return (ret); + g_free ((*rbuf)->buffer); + g_free (*rbuf); + *rbuf = NULL; } -size_t -gftp_fwrite (gftp_request * request, const void *ptr, size_t size, FILE * fd) +ssize_t +gftp_get_line (gftp_request * request, gftp_getline_buffer ** rbuf, + char * str, size_t len, int fd) { - size_t ret; + ssize_t ret, retval, rlen, copysize; + char *pos, *nextpos; + + if (*rbuf == NULL) + { + *rbuf = g_malloc0 (sizeof (**rbuf)); + (*rbuf)->max_bufsize = len; + (*rbuf)->buffer = g_malloc ((*rbuf)->max_bufsize); + if ((ret = gftp_read (request, (*rbuf)->buffer, (*rbuf)->max_bufsize, + fd)) <= 0) + { + gftp_free_getline_buffer (rbuf); + return (ret); + } + (*rbuf)->cur_bufsize = ret; + (*rbuf)->curpos = (*rbuf)->buffer; + } + + retval = -2; + + do + { + if ((*rbuf)->cur_bufsize > 0 && + ((pos = strchr ((*rbuf)->curpos, '\n')) != NULL || + ((*rbuf)->curpos == (*rbuf)->buffer && + (*rbuf)->max_bufsize == (*rbuf)->cur_bufsize))) + { + if (pos != NULL) + { + nextpos = pos + 1; + if (pos > (*rbuf)->curpos && *(pos - 1) == '\r') + pos--; + *pos = '\0'; + + if (len > pos - (*rbuf)->curpos + 1) + len = pos - (*rbuf)->curpos + 1; + } + else + { + nextpos = NULL; + if (len > (*rbuf)->cur_bufsize) + len = (*rbuf)->cur_bufsize; + } + + strncpy (str, (*rbuf)->curpos, len); + str[len] = '\0'; + retval = len; + + if (pos != NULL) + { + if (nextpos - (*rbuf)->buffer >= (*rbuf)->cur_bufsize) + (*rbuf)->cur_bufsize = 0; + else + (*rbuf)->curpos = nextpos; + } + + break; + } + else + { + if ((*rbuf)->cur_bufsize == 0 || *(*rbuf)->curpos == '\0') + { + rlen = (*rbuf)->max_bufsize; + pos = (*rbuf)->buffer; + copysize = 0; + } + else + { + copysize = (*rbuf)->cur_bufsize - ((*rbuf)->curpos - (*rbuf)->buffer); + memmove ((*rbuf)->buffer, (*rbuf)->curpos, copysize); + pos = (*rbuf)->buffer + copysize; + rlen = (*rbuf)->max_bufsize - copysize; + } + (*rbuf)->curpos = (*rbuf)->buffer; + + if ((ret = gftp_read (request, pos, rlen, fd)) <= 0) + { + gftp_free_getline_buffer (rbuf); + return (ret); + } + (*rbuf)->cur_bufsize = ret + copysize; + } + } + while (retval == -2); + + return (retval); +} + + +ssize_t +gftp_read (gftp_request * request, void *ptr, size_t size, int fd) +{ + struct timeval tv; + fd_set fset; + ssize_t ret; errno = 0; ret = 0; do { - ret = fwrite (ptr, size, 1, fd); - if (ferror (fd)) + FD_ZERO (&fset); + FD_SET (fd, &fset); + if (request != NULL) + tv.tv_sec = request->network_timeout; + else + tv.tv_sec = network_timeout; + tv.tv_usec = 0; + ret = select (fd + 1, &fset, NULL, NULL, &tv); + if (ret == -1 && errno == EINTR) { - if (errno == EINTR) + if (request && request->cancel) + break; + else + continue; + } + else if (ret <= 0) + { + if (request != NULL) { - if (request->cancel) - break; - else - { - clearerr (fd); - continue; - } - } - - request->logging_function (gftp_logging_error, request->user_data, - _("Error: Could not write to socket: %s\n"), - g_strerror (errno)); - gftp_disconnect (request); + request->logging_function (gftp_logging_error, request->user_data, + _("Connection to %s timed out\n"), + request->hostname); + gftp_disconnect (request); + } return (-1); } - fflush (request->sockfd_write); - if (ferror (fd)) + if ((ret = read (fd, ptr, size)) < 0) { if (errno == EINTR) { - if (request->cancel) + if (request != NULL && request->cancel) break; else - { - clearerr (fd); - continue; - } + continue; } - request->logging_function (gftp_logging_error, request->user_data, - _("Error: Could not write to socket: %s\n"), + if (request != NULL) + { + request->logging_function (gftp_logging_error, request->user_data, + _("Error: Could not read from socket: %s\n"), g_strerror (errno)); - gftp_disconnect (request); + gftp_disconnect (request); + } return (-1); } } - while (errno == EINTR && !request->cancel); + while (errno == EINTR && !(request != NULL && request->cancel)); - if (errno == EINTR && request->cancel) + if (errno == EINTR && request != NULL && request->cancel) { gftp_disconnect (request); return (-1); @@ -2138,3 +2034,127 @@ return (ret); } + +ssize_t +gftp_write (gftp_request * request, const char *ptr, size_t size, int fd) +{ + struct timeval tv; + size_t ret, w_ret; + fd_set fset; + + errno = 0; + ret = 0; + do + { + FD_ZERO (&fset); + FD_SET (fd, &fset); + if (request != NULL) + tv.tv_sec = request->network_timeout; + else + tv.tv_sec = network_timeout; + tv.tv_usec = 0; + ret = select (fd + 1, NULL, &fset, NULL, &tv); + if (ret == -1 && errno == EINTR) + { + if (request != NULL && request->cancel) + break; + else + continue; + } + else if (ret <= 0) + { + if (request != NULL) + { + request->logging_function (gftp_logging_error, request->user_data, + _("Connection to %s timed out\n"), + request->hostname); + gftp_disconnect (request); + } + return (-1); + } + + if ((w_ret = write (fd, ptr, size)) < 0) + { + if (errno == EINTR) + { + if (request != NULL && request->cancel) + break; + else + continue; + } + + if (request != NULL) + { + request->logging_function (gftp_logging_error, request->user_data, + _("Error: Could not write to socket: %s\n"), + g_strerror (errno)); + gftp_disconnect (request); + } + return (-1); + } + + ptr += w_ret; + size -= w_ret; + ret += w_ret; + } + while (size > 0); + + if (errno == EINTR && request != NULL && request->cancel) + { + gftp_disconnect (request); + return (-1); + } + + 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 = gftp_write (request, tempstr, strlen (tempstr), fd); + g_free (tempstr); + return (ret); +} + + +int +gftp_set_sockblocking (gftp_request * request, int fd, int non_blocking) +{ + int flags; + + if ((flags = fcntl (fd, F_GETFL, 0)) == -1) + { + request->logging_function (gftp_logging_error, request->user_data, + _("Cannot get socket flags: %s\n"), + g_strerror (errno)); + gftp_disconnect (request); + return (-1); + } + + if (non_blocking) + flags |= O_NONBLOCK; + else + flags &= ~O_NONBLOCK; + + if (fcntl (fd, F_SETFL, flags) == -1) + { + request->logging_function (gftp_logging_error, request->user_data, + _("Cannot set socket to non-blocking: %s\n"), + g_strerror (errno)); + gftp_disconnect (request); + return (-1); + } + + return (0); +} + +