Mercurial > gftp.yaz
annotate lib/protocols.c @ 303:3b9d5797050f
2003-11-2 Brian Masney <masneyb@gftp.org>
* lib/rfc2068.c (rfc2068_chunked_read) - more improvements to this
function so that it will parse more chunked file transfers correctly.
* lib/misc.c lib/gftp.h lib/rfc2068.c src/gtk/bookmarks.c
src/gtk/dnd.c - removed remove_double_slashes(). Call gftp_build_path()
to build the paths. This now allows Novell directory listings with
//server
* lib/protocols.c src/gtk/transfer.c lib/gftp.h - added variable
conn_error_no_timeout to gftp_transfer structure. If this is enabled,
if the remote connection to the server timed out, don't wait and
immediately reconnect. So far, the only time this is used is when the
user was editing a file and it is to be uploaded back to the server.
* src/gtk/gftp-gtk.h src/gtk/transfer.c - add_file_transfer() now
returns the struct gftp_transfer that was just added.
* src/gtk/misc-gtk.c (update_directory_download_progress) - don't
make the window a popup and remove the window decorations
* src/text/gftp-text.c - don't populate the transfer_direction variable
in struct gftp_transfer. This is only needed by the GTK+ port and will
hopefully be taken out soon.
* lib/gftp.h - remove gftp_transfer_type enum. It wasn't used anymore.
author | masneyb |
---|---|
date | Mon, 03 Nov 2003 02:14:05 +0000 |
parents | 4747f621b79b |
children | cc2eeb30b793 |
rev | line source |
---|---|
1 | 1 /*****************************************************************************/ |
2 /* protocols.c - Skeleton functions for the protocols gftp supports */ | |
122 | 3 /* Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org> */ |
1 | 4 /* */ |
5 /* This program is free software; you can redistribute it and/or modify */ | |
6 /* it under the terms of the GNU General Public License as published by */ | |
7 /* the Free Software Foundation; either version 2 of the License, or */ | |
8 /* (at your option) any later version. */ | |
9 /* */ | |
10 /* This program is distributed in the hope that it will be useful, */ | |
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ | |
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ | |
13 /* GNU General Public License for more details. */ | |
14 /* */ | |
15 /* You should have received a copy of the GNU General Public License */ | |
16 /* along with this program; if not, write to the Free Software */ | |
17 /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA */ | |
18 /*****************************************************************************/ | |
19 | |
20 #include "gftp.h" | |
33 | 21 static const char cvsid[] = "$Id$"; |
1 | 22 |
23 gftp_request * | |
24 gftp_request_new (void) | |
25 { | |
26 gftp_request *request; | |
27 | |
28 request = g_malloc0 (sizeof (*request)); | |
66 | 29 request->datafd = -1; |
30 request->cachefd = -1; | |
122 | 31 request->server_type = GFTP_DIRTYPE_OTHER; |
1 | 32 return (request); |
33 } | |
136 | 34 |
1 | 35 |
36 void | |
67 | 37 gftp_request_destroy (gftp_request * request, int free_request) |
1 | 38 { |
39 g_return_if_fail (request != NULL); | |
40 | |
41 gftp_disconnect (request); | |
42 | |
43 if (request->destroy != NULL) | |
44 request->destroy (request); | |
45 | |
46 if (request->hostname) | |
47 g_free (request->hostname); | |
48 if (request->username) | |
49 g_free (request->username); | |
50 if (request->password) | |
51 { | |
52 memset (request->password, 0, strlen (request->password)); | |
53 g_free (request->password); | |
54 } | |
55 if (request->account) | |
56 { | |
57 memset (request->account, 0, strlen (request->account)); | |
58 g_free (request->account); | |
59 } | |
60 if (request->directory) | |
61 g_free (request->directory); | |
62 if (request->last_ftp_response) | |
63 g_free (request->last_ftp_response); | |
64 if (request->protocol_data) | |
65 g_free (request->protocol_data); | |
67 | 66 |
198 | 67 if (request->local_options_vars != NULL) |
68 { | |
201 | 69 gftp_config_free_options (request->local_options_vars, |
70 request->local_options_hash, | |
71 request->num_local_options_vars); | |
198 | 72 } |
73 | |
1 | 74 memset (request, 0, sizeof (*request)); |
67 | 75 |
76 if (free_request) | |
77 g_free (request); | |
78 else | |
79 { | |
80 request->datafd = -1; | |
81 request->cachefd = -1; | |
82 } | |
1 | 83 } |
84 | |
85 | |
86 void | |
87 gftp_file_destroy (gftp_file * file) | |
88 { | |
89 g_return_if_fail (file != NULL); | |
90 | |
91 if (file->file) | |
92 g_free (file->file); | |
93 if (file->user) | |
94 g_free (file->user); | |
95 if (file->group) | |
96 g_free (file->group); | |
97 if (file->attribs) | |
98 g_free (file->attribs); | |
99 if (file->destfile) | |
100 g_free (file->destfile); | |
101 memset (file, 0, sizeof (*file)); | |
102 } | |
103 | |
104 | |
105 int | |
106 gftp_connect (gftp_request * request) | |
107 { | |
177 | 108 int ret; |
109 | |
84 | 110 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1 | 111 |
112 if (request->connect == NULL) | |
84 | 113 return (GFTP_EFATAL); |
1 | 114 |
177 | 115 if ((ret = gftp_set_config_options (request)) < 0) |
116 return (ret); | |
1 | 117 |
118 return (request->connect (request)); | |
119 } | |
120 | |
121 | |
122 void | |
123 gftp_disconnect (gftp_request * request) | |
124 { | |
125 g_return_if_fail (request != NULL); | |
126 | |
127 #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR) | |
151 | 128 if (request->free_hostp && request->hostp != NULL) |
1 | 129 freeaddrinfo (request->hostp); |
130 #endif | |
131 request->hostp = NULL; | |
132 | |
168 | 133 #ifdef USE_SSL |
134 if (request->ssl != NULL) | |
135 { | |
136 SSL_free (request->ssl); | |
137 request->ssl = NULL; | |
138 } | |
139 #endif | |
140 | |
187 | 141 #if GLIB_MAJOR_VERSION > 1 |
142 if (request->iconv_initialized) | |
143 { | |
144 g_iconv_close (request->iconv); | |
145 request->iconv_initialized = 0; | |
146 } | |
147 #endif | |
148 | |
1 | 149 request->cached = 0; |
150 if (request->disconnect == NULL) | |
151 return; | |
152 request->disconnect (request); | |
153 } | |
154 | |
155 | |
58 | 156 off_t |
157 gftp_get_file (gftp_request * request, const char *filename, int fd, | |
244 | 158 off_t startsize) |
1 | 159 { |
84 | 160 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1 | 161 |
162 request->cached = 0; | |
163 if (request->get_file == NULL) | |
84 | 164 return (GFTP_EFATAL); |
244 | 165 |
1 | 166 return (request->get_file (request, filename, fd, startsize)); |
167 } | |
168 | |
169 | |
170 int | |
58 | 171 gftp_put_file (gftp_request * request, const char *filename, int fd, |
244 | 172 off_t startsize, off_t totalsize) |
1 | 173 { |
84 | 174 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1 | 175 |
176 request->cached = 0; | |
177 if (request->put_file == NULL) | |
84 | 178 return (GFTP_EFATAL); |
1 | 179 return (request->put_file (request, filename, fd, startsize, totalsize)); |
180 } | |
181 | |
182 | |
261 | 183 off_t |
1 | 184 gftp_transfer_file (gftp_request * fromreq, const char *fromfile, |
244 | 185 int fromfd, off_t fromsize, |
1 | 186 gftp_request * toreq, const char *tofile, |
244 | 187 int tofd, off_t tosize) |
1 | 188 { |
294 | 189 float maxkbs; |
261 | 190 off_t size; |
84 | 191 int ret; |
1 | 192 |
84 | 193 g_return_val_if_fail (fromreq != NULL, GFTP_EFATAL); |
194 g_return_val_if_fail (fromfile != NULL, GFTP_EFATAL); | |
195 g_return_val_if_fail (toreq != NULL, GFTP_EFATAL); | |
196 g_return_val_if_fail (tofile != NULL, GFTP_EFATAL); | |
197 | |
294 | 198 gftp_lookup_request_option (toreq, "maxkbs", &maxkbs); |
199 if (maxkbs > 0) | |
200 { | |
201 toreq->logging_function (gftp_logging_misc, toreq, | |
202 _("File transfer will be throttled to %.2f KB/s\n"), | |
203 maxkbs); | |
204 } | |
205 | |
87 | 206 if (fromreq->protonum == toreq->protonum && |
84 | 207 fromreq->transfer_file != NULL) |
208 return (fromreq->transfer_file (fromreq, fromfile, fromsize, toreq, | |
209 tofile, tosize)); | |
1 | 210 |
211 fromreq->cached = 0; | |
212 toreq->cached = 0; | |
213 if ((size = gftp_get_file (fromreq, fromfile, fromfd, tosize)) < 0) | |
84 | 214 return (size); |
1 | 215 |
84 | 216 if ((ret = gftp_put_file (toreq, tofile, tofd, tosize, size)) != 0) |
1 | 217 { |
40 | 218 if (gftp_abort_transfer (fromreq) != 0) |
219 gftp_end_transfer (fromreq); | |
220 | |
84 | 221 return (ret); |
1 | 222 } |
223 | |
224 return (size); | |
225 } | |
226 | |
227 | |
58 | 228 ssize_t |
1 | 229 gftp_get_next_file_chunk (gftp_request * request, char *buf, size_t size) |
230 { | |
84 | 231 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
232 g_return_val_if_fail (buf != NULL, GFTP_EFATAL); | |
1 | 233 |
234 if (request->get_next_file_chunk != NULL) | |
235 return (request->get_next_file_chunk (request, buf, size)); | |
236 | |
168 | 237 return (request->read_function (request, buf, size, request->datafd)); |
1 | 238 } |
239 | |
240 | |
58 | 241 ssize_t |
1 | 242 gftp_put_next_file_chunk (gftp_request * request, char *buf, size_t size) |
243 { | |
84 | 244 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
245 g_return_val_if_fail (buf != NULL, GFTP_EFATAL); | |
1 | 246 |
247 if (request->put_next_file_chunk != NULL) | |
248 return (request->put_next_file_chunk (request, buf, size)); | |
249 | |
250 if (size == 0) | |
251 return (0); | |
252 | |
168 | 253 return (request->write_function (request, buf, size, request->datafd)); |
1 | 254 } |
255 | |
256 | |
257 int | |
258 gftp_end_transfer (gftp_request * request) | |
259 { | |
260 int ret; | |
261 | |
84 | 262 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1 | 263 |
40 | 264 if (!request->cached && |
265 request->end_transfer != NULL) | |
266 ret = request->end_transfer (request); | |
267 else | |
268 ret = 0; | |
1 | 269 |
58 | 270 if (request->cachefd > 0) |
1 | 271 { |
58 | 272 close (request->cachefd); |
273 request->cachefd = -1; | |
1 | 274 } |
275 | |
276 if (request->last_dir_entry) | |
277 { | |
278 g_free (request->last_dir_entry); | |
279 request->last_dir_entry = NULL; | |
280 request->last_dir_entry_len = 0; | |
281 } | |
282 | |
283 return (ret); | |
284 } | |
285 | |
286 | |
287 int | |
40 | 288 gftp_abort_transfer (gftp_request * request) |
289 { | |
84 | 290 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
40 | 291 |
292 if (request->abort_transfer == NULL) | |
84 | 293 return (GFTP_EFATAL); |
40 | 294 |
295 return (request->abort_transfer (request)); | |
296 } | |
297 | |
298 | |
299 int | |
1 | 300 gftp_list_files (gftp_request * request) |
301 { | |
58 | 302 int fd; |
1 | 303 |
84 | 304 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1 | 305 |
306 request->cached = 0; | |
58 | 307 if (request->use_cache && (fd = gftp_find_cache_entry (request)) > 0) |
1 | 308 { |
186 | 309 request->logging_function (gftp_logging_misc, request, |
1 | 310 _("Loading directory listing %s from cache\n"), |
311 request->directory); | |
312 | |
313 request->cachefd = fd; | |
314 request->cached = 1; | |
315 return (0); | |
316 } | |
317 else if (request->use_cache) | |
318 { | |
319 request->cachefd = gftp_new_cache_entry (request); | |
320 request->cached = 0; | |
321 } | |
322 | |
323 if (request->list_files == NULL) | |
84 | 324 return (GFTP_EFATAL); |
1 | 325 return (request->list_files (request)); |
326 } | |
327 | |
328 | |
184 | 329 #if GLIB_MAJOR_VERSION > 1 |
291 | 330 |
184 | 331 static char * |
207 | 332 _gftp_get_next_charset (char *remote_charsets, char *orig_str, char **curpos) |
184 | 333 { |
334 char *ret, *endpos; | |
335 | |
336 if (**curpos == '\0') | |
337 return (NULL); | |
338 | |
339 ret = *curpos; | |
340 if (*curpos != remote_charsets) | |
207 | 341 { |
342 *orig_str = *(*curpos - 1); | |
343 *(*curpos - 1) = ','; | |
344 } | |
185 | 345 |
346 if ((endpos = strchr (*curpos, ',')) == NULL) | |
184 | 347 *curpos += strlen (*curpos); |
348 else | |
349 { | |
350 *endpos = '\0'; | |
207 | 351 |
352 if (*orig_str != '\0') | |
353 *curpos = endpos + 1; | |
354 else | |
355 *curpos = endpos; | |
184 | 356 } |
357 | |
358 return (ret); | |
359 } | |
360 | |
361 | |
207 | 362 static void |
363 _gftp_restore_charset_string (char **remote_charsets, char orig_str, char **curpos) | |
364 { | |
365 if (*curpos != *remote_charsets) | |
366 *(*curpos - 1) = orig_str; | |
367 } | |
368 | |
369 | |
186 | 370 char * |
291 | 371 gftp_string_to_utf8 (gftp_request * request, const char *str) |
184 | 372 { |
207 | 373 char *ret, *remote_charsets, *stpos, *cur_charset, orig_str; |
184 | 374 gsize bread, bwrite; |
375 GError * error; | |
376 | |
188 | 377 if (request == NULL) |
378 return (NULL); | |
379 | |
184 | 380 if (request->iconv_initialized) |
381 return (g_convert_with_iconv (str, -1, request->iconv, &bread, &bwrite, | |
382 &error)); | |
291 | 383 else if (g_utf8_validate (str, -1, NULL)) |
384 return (NULL); | |
184 | 385 |
386 gftp_lookup_request_option (request, "remote_charsets", &remote_charsets); | |
387 if (*remote_charsets == '\0') | |
388 { | |
389 error = NULL; | |
390 if ((ret = g_locale_to_utf8 (str, -1, &bread, &bwrite, &error)) != NULL) | |
391 return (ret); | |
392 | |
393 return (NULL); | |
394 } | |
395 | |
396 ret = NULL; | |
397 stpos = remote_charsets; | |
207 | 398 while ((cur_charset = _gftp_get_next_charset (remote_charsets, &orig_str, |
184 | 399 &stpos)) != NULL) |
400 { | |
401 if ((request->iconv = g_iconv_open ("UTF-8", cur_charset)) == (GIConv) -1) | |
402 continue; | |
403 | |
404 error = NULL; | |
405 if ((ret = g_convert_with_iconv (str, -1, request->iconv, &bread, &bwrite, | |
406 &error)) == NULL) | |
407 { | |
408 g_iconv_close (request->iconv); | |
409 request->iconv = NULL; | |
410 continue; | |
411 } | |
412 else | |
413 { | |
414 request->iconv_initialized = 1; | |
207 | 415 _gftp_restore_charset_string (&remote_charsets, *cur_charset, &stpos); |
184 | 416 break; |
417 } | |
418 } | |
419 | |
420 return (ret); | |
421 } | |
291 | 422 |
423 | |
424 char * | |
425 gftp_string_from_utf8 (gftp_request * request, const char *str) | |
426 { | |
427 char *ret, *remote_charsets, *stpos, *cur_charset, orig_str; | |
428 gsize bread, bwrite; | |
429 GError * error; | |
430 | |
431 if (request == NULL) | |
432 return (NULL); | |
433 | |
434 if (request->iconv_initialized) | |
435 return (g_convert_with_iconv (str, -1, request->iconv, &bread, &bwrite, | |
436 &error)); | |
437 else if (g_utf8_validate (str, -1, NULL)) | |
438 return (NULL); | |
439 | |
440 gftp_lookup_request_option (request, "remote_charsets", &remote_charsets); | |
441 if (*remote_charsets == '\0') | |
442 { | |
443 error = NULL; | |
444 if ((ret = g_locale_from_utf8 (str, -1, &bread, &bwrite, &error)) != NULL) | |
445 return (ret); | |
446 | |
447 return (NULL); | |
448 } | |
449 | |
450 ret = NULL; | |
451 stpos = remote_charsets; | |
452 while ((cur_charset = _gftp_get_next_charset (remote_charsets, &orig_str, | |
453 &stpos)) != NULL) | |
454 { | |
455 if ((request->iconv = g_iconv_open (cur_charset, "UTF-8")) == (GIConv) -1) | |
456 continue; | |
457 | |
458 error = NULL; | |
459 if ((ret = g_convert_with_iconv (str, -1, request->iconv, &bread, &bwrite, | |
460 &error)) == NULL) | |
461 { | |
462 g_iconv_close (request->iconv); | |
463 request->iconv = NULL; | |
464 continue; | |
465 } | |
466 else | |
467 { | |
468 request->iconv_initialized = 1; | |
469 _gftp_restore_charset_string (&remote_charsets, *cur_charset, &stpos); | |
470 break; | |
471 } | |
472 } | |
473 | |
474 return (ret); | |
475 } | |
476 | |
477 #else | |
478 | |
479 char * | |
480 gftp_string_to_utf8 (gftp_request * request, const char *str) | |
481 { | |
482 return (NULL); | |
483 } | |
484 | |
485 | |
486 char * | |
487 gftp_string_from_utf8 (gftp_request * request, const char *str) | |
488 { | |
489 return (NULL); | |
490 } | |
491 | |
184 | 492 #endif |
493 | |
494 | |
1 | 495 int |
496 gftp_get_next_file (gftp_request * request, char *filespec, gftp_file * fle) | |
497 { | |
58 | 498 int fd, ret; |
1 | 499 |
84 | 500 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1 | 501 |
502 if (request->get_next_file == NULL) | |
84 | 503 return (GFTP_EFATAL); |
1 | 504 |
58 | 505 if (request->cached && request->cachefd > 0) |
1 | 506 fd = request->cachefd; |
507 else | |
508 fd = request->datafd; | |
509 | |
510 memset (fle, 0, sizeof (*fle)); | |
511 do | |
512 { | |
513 gftp_file_destroy (fle); | |
514 ret = request->get_next_file (request, fle, fd); | |
515 | |
291 | 516 if (ret >= 0 && fle->file != NULL) |
184 | 517 fle->utf8_file = gftp_string_to_utf8 (request, fle->file); |
45 | 518 |
60 | 519 if (ret >= 0 && !request->cached && request->cachefd > 0 && |
1 | 520 request->last_dir_entry != NULL) |
521 { | |
168 | 522 if (gftp_fd_write (request, request->last_dir_entry, |
60 | 523 request->last_dir_entry_len, request->cachefd) < 0) |
1 | 524 { |
186 | 525 request->logging_function (gftp_logging_error, request, |
1 | 526 _("Error: Cannot write to cache: %s\n"), |
527 g_strerror (errno)); | |
60 | 528 close (request->cachefd); |
529 request->cachefd = -1; | |
1 | 530 } |
531 } | |
532 } while (ret > 0 && !gftp_match_filespec (fle->file, filespec)); | |
533 | |
534 return (ret); | |
535 } | |
536 | |
537 | |
538 int | |
243 | 539 gftp_parse_bookmark (gftp_request * request, gftp_request * local_request, |
275 | 540 const char * bookmark, int *refresh_local) |
87 | 541 { |
542 gftp_logging_func logging_function; | |
122 | 543 gftp_bookmarks_var * tempentry; |
544 char *default_protocol; | |
173 | 545 int i, init_ret; |
87 | 546 |
547 g_return_val_if_fail (request != NULL, GFTP_EFATAL); | |
548 g_return_val_if_fail (bookmark != NULL, GFTP_EFATAL); | |
549 | |
550 logging_function = request->logging_function; | |
551 gftp_request_destroy (request, 0); | |
552 request->logging_function = logging_function; | |
553 | |
122 | 554 if ((tempentry = g_hash_table_lookup (gftp_bookmarks_htable, |
555 bookmark)) == NULL) | |
87 | 556 { |
186 | 557 request->logging_function (gftp_logging_error, request, |
87 | 558 _("Error: Could not find bookmark %s\n"), |
559 bookmark); | |
560 return (GFTP_EFATAL); | |
561 } | |
562 else if (tempentry->hostname == NULL || *tempentry->hostname == '\0') | |
563 { | |
186 | 564 request->logging_function (gftp_logging_error, request, |
87 | 565 _("Bookmarks Error: The bookmark entry %s does not have a hostname\n"), bookmark); |
566 return (GFTP_EFATAL); | |
567 } | |
568 | |
569 if (tempentry->user != NULL) | |
570 gftp_set_username (request, tempentry->user); | |
571 | |
572 if (tempentry->pass != NULL) | |
122 | 573 gftp_set_password (request, tempentry->pass); |
87 | 574 |
575 if (tempentry->acct != NULL) | |
576 gftp_set_account (request, tempentry->acct); | |
577 | |
578 gftp_set_hostname (request, tempentry->hostname); | |
579 gftp_set_directory (request, tempentry->remote_dir); | |
580 gftp_set_port (request, tempentry->port); | |
581 | |
243 | 582 if (local_request != NULL && |
583 tempentry->local_dir != NULL && | |
584 *tempentry->local_dir != '\0') | |
275 | 585 { |
586 gftp_set_directory (local_request, tempentry->local_dir); | |
587 *refresh_local = 1; | |
588 } | |
589 else | |
590 *refresh_local = 0; | |
243 | 591 |
87 | 592 for (i = 0; gftp_protocols[i].name; i++) |
593 { | |
594 if (strcmp (gftp_protocols[i].name, tempentry->protocol) == 0) | |
595 { | |
173 | 596 if ((init_ret = gftp_protocols[i].init (request)) < 0) |
597 { | |
598 gftp_request_destroy (request, 0); | |
599 return (init_ret); | |
600 } | |
87 | 601 break; |
602 } | |
603 } | |
604 | |
122 | 605 if (gftp_protocols[i].name == NULL) |
87 | 606 { |
122 | 607 gftp_lookup_request_option (request, "default_protocol", |
608 &default_protocol); | |
609 | |
125 | 610 if (default_protocol != NULL && *default_protocol != '\0') |
87 | 611 { |
122 | 612 for (i = 0; gftp_protocols[i].url_prefix; i++) |
613 { | |
614 if (strcmp (gftp_protocols[i].name, default_protocol) == 0) | |
615 break; | |
616 } | |
87 | 617 } |
618 | |
619 if (gftp_protocols[i].url_prefix == NULL) | |
620 i = GFTP_FTP_NUM; | |
621 } | |
622 | |
199 | 623 gftp_copy_local_options (&request->local_options_vars, |
624 &request->local_options_hash, | |
625 tempentry->local_options_vars, | |
626 tempentry->num_local_options_vars); | |
627 | |
173 | 628 if ((init_ret = gftp_protocols[i].init (request)) < 0) |
629 { | |
630 gftp_request_destroy (request, 0); | |
631 return (init_ret); | |
632 } | |
633 | |
87 | 634 return (0); |
635 } | |
636 | |
637 | |
638 int | |
1 | 639 gftp_parse_url (gftp_request * request, const char *url) |
640 { | |
168 | 641 char *pos, *endpos, *endhostpos, tempchar, *default_protocol, *stpos; |
67 | 642 gftp_logging_func logging_function; |
173 | 643 int len, i, init_ret; |
168 | 644 const char *cpos; |
1 | 645 |
84 | 646 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
647 g_return_val_if_fail (url != NULL, GFTP_EFATAL); | |
1 | 648 |
67 | 649 logging_function = request->logging_function; |
650 gftp_request_destroy (request, 0); | |
651 request->logging_function = logging_function; | |
652 | |
168 | 653 for (cpos = url; *cpos == ' '; cpos++); |
654 stpos = g_strdup (cpos); | |
655 for (pos = stpos + strlen (stpos) - 1; *pos == ' '; pos--) | |
656 *pos = '\0'; | |
1 | 657 |
122 | 658 i = GFTP_FTP_NUM; |
659 | |
1 | 660 if ((pos = strstr (stpos, "://")) != NULL) |
661 { | |
662 *pos = '\0'; | |
663 | |
664 for (i = 0; gftp_protocols[i].url_prefix; i++) | |
665 { | |
666 if (strcmp (gftp_protocols[i].url_prefix, stpos) == 0) | |
667 break; | |
668 } | |
669 | |
670 if (gftp_protocols[i].url_prefix == NULL) | |
168 | 671 { |
173 | 672 request->logging_function (gftp_logging_misc, NULL, |
673 _("The protocol '%s' is currently not supported.\n"), | |
674 stpos); | |
168 | 675 g_free (stpos); |
676 return (GFTP_EFATAL); | |
677 } | |
173 | 678 |
679 *pos = ':'; | |
1 | 680 } |
681 else | |
682 { | |
122 | 683 gftp_lookup_request_option (request, "default_protocol", |
684 &default_protocol); | |
685 | |
125 | 686 if (default_protocol != NULL && *default_protocol != '\0') |
1 | 687 { |
122 | 688 for (i = 0; gftp_protocols[i].url_prefix; i++) |
689 { | |
690 if (strcmp (gftp_protocols[i].name, default_protocol) == 0) | |
691 break; | |
692 } | |
1 | 693 } |
122 | 694 } |
1 | 695 |
122 | 696 if (gftp_protocols[i].url_prefix == NULL) |
697 i = GFTP_FTP_NUM; | |
1 | 698 |
173 | 699 if ((init_ret = gftp_protocols[i].init (request)) < 0) |
700 { | |
701 gftp_request_destroy (request, 0); | |
702 return (init_ret); | |
703 } | |
1 | 704 |
705 if (request->parse_url != NULL) | |
168 | 706 { |
707 g_free (stpos); | |
708 return (request->parse_url (request, url)); | |
709 } | |
710 | |
711 pos = stpos; | |
712 len = strlen (request->url_prefix); | |
713 if (strncmp (pos, request->url_prefix, len) == 0 && | |
714 strncmp (pos + len, "://", 3) == 0) | |
715 pos += len + 3; | |
1 | 716 |
717 if (i == GFTP_LOCAL_NUM) | |
718 { | |
168 | 719 request->directory = g_strdup (pos); |
720 g_free (stpos); | |
1 | 721 return (0); |
722 } | |
723 | |
182 | 724 if ((endhostpos = strrchr (pos, '@')) != NULL) |
1 | 725 { |
726 /* A user/password was entered */ | |
727 if ((endpos = strchr (pos, ':')) == NULL || endhostpos < endpos) | |
168 | 728 { |
729 /* No password was entered */ | |
730 gftp_set_password (request, ""); | |
731 endpos = endhostpos; | |
732 } | |
1 | 733 |
734 *endpos = '\0'; | |
735 gftp_set_username (request, pos); | |
736 | |
737 pos = endpos + 1; | |
738 if ((endpos = strchr (pos, '@')) != NULL) | |
168 | 739 { |
740 if (strchr (endpos + 1, '@') != NULL) | |
741 endpos = strchr (endpos + 1, '@'); | |
742 *endpos = '\0'; | |
743 gftp_set_password (request, pos); | |
1 | 744 |
168 | 745 pos = endpos + 1; |
746 } | |
1 | 747 } |
748 | |
749 /* Now get the hostname and an optional port and optional directory */ | |
750 endhostpos = pos + strlen (pos); | |
751 if ((endpos = strchr (pos, ':')) != NULL) | |
752 endhostpos = endpos; | |
753 else if ((endpos = strchr (pos, '/')) != NULL) | |
754 endhostpos = endpos; | |
755 tempchar = *endhostpos; | |
756 *endhostpos = '\0'; | |
757 gftp_set_hostname (request, pos); | |
758 *endhostpos = tempchar; | |
759 | |
760 if ((endpos = strchr (pos, ':')) != NULL) | |
761 { | |
762 /* A port was entered */ | |
763 pos = endpos + 1; | |
764 gftp_set_port (request, strtol (pos, NULL, 10)); | |
765 } | |
766 if ((endpos = strchr (pos, '/')) != NULL) | |
767 gftp_set_directory (request, endpos); | |
168 | 768 g_free (stpos); |
1 | 769 return (0); |
770 } | |
771 | |
772 | |
773 void | |
774 gftp_set_hostname (gftp_request * request, const char *hostname) | |
775 { | |
776 g_return_if_fail (request != NULL); | |
777 g_return_if_fail (hostname != NULL); | |
778 | |
779 if (request->hostname) | |
780 g_free (request->hostname); | |
124 | 781 request->hostname = g_strdup (hostname); |
1 | 782 } |
783 | |
784 | |
785 void | |
786 gftp_set_username (gftp_request * request, const char *username) | |
787 { | |
788 g_return_if_fail (request != NULL); | |
789 g_return_if_fail (username != NULL); | |
790 | |
791 if (request->username) | |
792 g_free (request->username); | |
169 | 793 |
794 if (username != NULL) | |
795 request->username = g_strdup (username); | |
796 else | |
797 request->username = NULL; | |
1 | 798 } |
799 | |
800 | |
801 void | |
802 gftp_set_password (gftp_request * request, const char *password) | |
803 { | |
804 g_return_if_fail (request != NULL); | |
805 g_return_if_fail (password != NULL); | |
806 | |
807 if (request->password) | |
808 g_free (request->password); | |
169 | 809 |
810 if (password != NULL) | |
811 request->password = g_strdup (password); | |
812 else | |
813 request->password = NULL; | |
1 | 814 } |
815 | |
816 | |
817 void | |
818 gftp_set_account (gftp_request * request, const char *account) | |
819 { | |
820 g_return_if_fail (request != NULL); | |
821 g_return_if_fail (account != NULL); | |
822 | |
823 if (request->account) | |
824 g_free (request->account); | |
124 | 825 request->account = g_strdup (account); |
1 | 826 } |
827 | |
828 | |
829 int | |
830 gftp_set_directory (gftp_request * request, const char *directory) | |
831 { | |
84 | 832 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
833 g_return_val_if_fail (directory != NULL, GFTP_EFATAL); | |
1 | 834 |
835 | |
169 | 836 if (request->datafd <= 0 && !request->always_connected) |
1 | 837 { |
838 if (directory != request->directory) | |
168 | 839 { |
840 if (request->directory) | |
841 g_free (request->directory); | |
842 request->directory = g_strdup (directory); | |
843 } | |
1 | 844 return (0); |
845 } | |
846 else if (request->chdir == NULL) | |
84 | 847 return (GFTP_EFATAL); |
1 | 848 return (request->chdir (request, directory)); |
849 } | |
850 | |
851 | |
852 void | |
853 gftp_set_port (gftp_request * request, unsigned int port) | |
854 { | |
855 g_return_if_fail (request != NULL); | |
856 | |
857 request->port = port; | |
858 } | |
859 | |
860 | |
861 int | |
862 gftp_remove_directory (gftp_request * request, const char *directory) | |
863 { | |
84 | 864 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1 | 865 |
866 if (request->rmdir == NULL) | |
84 | 867 return (GFTP_EFATAL); |
1 | 868 return (request->rmdir (request, directory)); |
869 } | |
870 | |
871 | |
872 int | |
873 gftp_remove_file (gftp_request * request, const char *file) | |
874 { | |
84 | 875 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1 | 876 |
877 if (request->rmfile == NULL) | |
84 | 878 return (GFTP_EFATAL); |
1 | 879 return (request->rmfile (request, file)); |
880 } | |
881 | |
882 | |
883 int | |
884 gftp_make_directory (gftp_request * request, const char *directory) | |
885 { | |
291 | 886 char *utf8; |
887 int ret; | |
888 | |
84 | 889 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1 | 890 |
891 if (request->mkdir == NULL) | |
84 | 892 return (GFTP_EFATAL); |
291 | 893 |
894 utf8 = gftp_string_from_utf8 (request, directory); | |
895 if (utf8 != NULL) | |
896 { | |
897 ret = request->mkdir (request, utf8); | |
898 g_free (utf8); | |
899 } | |
900 else | |
901 ret = request->mkdir (request, directory); | |
902 | |
903 return (ret); | |
1 | 904 } |
905 | |
906 | |
907 int | |
908 gftp_rename_file (gftp_request * request, const char *oldname, | |
168 | 909 const char *newname) |
1 | 910 { |
291 | 911 char *utf8; |
912 int ret; | |
913 | |
84 | 914 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1 | 915 |
916 if (request->rename == NULL) | |
84 | 917 return (GFTP_EFATAL); |
291 | 918 |
919 utf8 = gftp_string_from_utf8 (request, newname); | |
920 if (utf8 != NULL) | |
921 { | |
922 ret = request->rename (request, oldname, utf8); | |
923 g_free (utf8); | |
924 } | |
925 else | |
926 ret = request->rename (request, oldname, newname); | |
927 | |
928 return (ret); | |
1 | 929 } |
930 | |
931 | |
932 int | |
933 gftp_chmod (gftp_request * request, const char *file, int mode) | |
934 { | |
84 | 935 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1 | 936 |
937 if (request->chmod == NULL) | |
84 | 938 return (GFTP_EFATAL); |
1 | 939 return (request->chmod (request, file, mode)); |
940 } | |
941 | |
942 | |
943 int | |
944 gftp_set_file_time (gftp_request * request, const char *file, time_t datetime) | |
945 { | |
84 | 946 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1 | 947 |
948 if (request->set_file_time == NULL) | |
84 | 949 return (GFTP_EFATAL); |
1 | 950 return (request->set_file_time (request, file, datetime)); |
951 } | |
952 | |
953 | |
954 char | |
955 gftp_site_cmd (gftp_request * request, const char *command) | |
956 { | |
84 | 957 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1 | 958 |
959 if (request->site == NULL) | |
84 | 960 return (GFTP_EFATAL); |
1 | 961 return (request->site (request, command)); |
962 } | |
963 | |
964 | |
58 | 965 off_t |
1 | 966 gftp_get_file_size (gftp_request * request, const char *filename) |
967 { | |
968 g_return_val_if_fail (request != NULL, 0); | |
969 | |
970 if (request->get_file_size == NULL) | |
971 return (0); | |
972 return (request->get_file_size (request, filename)); | |
973 } | |
974 | |
975 | |
122 | 976 static int |
977 gftp_need_proxy (gftp_request * request, char *service, char *proxy_hostname, | |
978 int proxy_port) | |
1 | 979 { |
122 | 980 gftp_config_list_vars * proxy_hosts; |
1 | 981 gftp_proxy_hosts * hostname; |
982 unsigned char addy[4]; | |
983 struct sockaddr *addr; | |
984 GList * templist; | |
985 gint32 netaddr; | |
986 char *pos; | |
987 #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR) | |
988 struct addrinfo hints; | |
989 int port, errnum; | |
990 char serv[8]; | |
122 | 991 #endif |
992 | |
218 | 993 gftp_lookup_global_option ("dont_use_proxy", &proxy_hosts); |
122 | 994 |
995 if (proxy_hostname == NULL || *proxy_hostname == '\0') | |
996 return (0); | |
997 else if (proxy_hosts->list == NULL) | |
998 return (proxy_hostname != NULL && | |
999 *proxy_hostname != '\0'); | |
1 | 1000 |
1001 request->hostp = NULL; | |
122 | 1002 #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR) |
151 | 1003 request->free_hostp = 1; |
1 | 1004 memset (&hints, 0, sizeof (hints)); |
1005 hints.ai_flags = AI_CANONNAME; | |
146 | 1006 hints.ai_family = PF_UNSPEC; |
1 | 1007 hints.ai_socktype = SOCK_STREAM; |
1008 | |
122 | 1009 port = request->use_proxy ? proxy_port : request->port; |
1 | 1010 if (port == 0) |
1011 strcpy (serv, service); | |
1012 else | |
1013 snprintf (serv, sizeof (serv), "%d", port); | |
1014 | |
186 | 1015 request->logging_function (gftp_logging_misc, request, |
1 | 1016 _("Looking up %s\n"), request->hostname); |
1017 | |
1018 if ((errnum = getaddrinfo (request->hostname, serv, &hints, | |
1019 &request->hostp)) != 0) | |
1020 { | |
186 | 1021 request->logging_function (gftp_logging_error, request, |
1 | 1022 _("Cannot look up hostname %s: %s\n"), |
1023 request->hostname, gai_strerror (errnum)); | |
84 | 1024 return (GFTP_ERETRYABLE); |
1 | 1025 } |
1026 | |
1027 addr = request->hostp->ai_addr; | |
1028 | |
1029 #else /* !HAVE_GETADDRINFO */ | |
186 | 1030 request->logging_function (gftp_logging_misc, request, |
1 | 1031 _("Looking up %s\n"), request->hostname); |
1032 | |
1033 if (!(request->hostp = r_gethostbyname (request->hostname, &request->host, | |
1034 NULL))) | |
1035 { | |
186 | 1036 request->logging_function (gftp_logging_error, request, |
1 | 1037 _("Cannot look up hostname %s: %s\n"), |
1038 request->hostname, g_strerror (errno)); | |
84 | 1039 return (GFTP_ERETRYABLE); |
1 | 1040 } |
1041 | |
1042 addr = (struct sockaddr *) request->host.h_addr_list[0]; | |
1043 | |
1044 #endif /* HAVE_GETADDRINFO */ | |
1045 | |
122 | 1046 templist = proxy_hosts->list; |
1 | 1047 while (templist != NULL) |
1048 { | |
1049 hostname = templist->data; | |
1050 if (hostname->domain && | |
1051 strlen (request->hostname) > strlen (hostname->domain)) | |
168 | 1052 { |
1053 pos = request->hostname + strlen (request->hostname) - | |
1054 strlen (hostname->domain); | |
1055 if (strcmp (hostname->domain, pos) == 0) | |
1056 return (0); | |
1057 } | |
1 | 1058 |
1059 if (hostname->ipv4_network_address != 0) | |
168 | 1060 { |
1061 memcpy (addy, addr, sizeof (addy)); | |
1062 netaddr = | |
1063 (((addy[0] & 0xff) << 24) | ((addy[1] & 0xff) << 16) | | |
1064 ((addy[2] & 0xff) << 8) | (addy[3] & 0xff)) & | |
1 | 1065 hostname->ipv4_netmask; |
168 | 1066 if (netaddr == hostname->ipv4_network_address) |
1067 return (0); | |
1068 } | |
1 | 1069 templist = templist->next; |
1070 } | |
1071 | |
122 | 1072 return (proxy_hostname != NULL && *proxy_hostname != '\0'); |
1 | 1073 } |
1074 | |
1075 | |
48 | 1076 static char * |
1077 copy_token (char **dest, char *source) | |
1 | 1078 { |
48 | 1079 /* This function is used internally by gftp_parse_ls () */ |
1080 char *endpos, savepos; | |
1 | 1081 |
48 | 1082 endpos = source; |
1083 while (*endpos != ' ' && *endpos != '\t' && *endpos != '\0') | |
1084 endpos++; | |
1085 if (*endpos == '\0') | |
1086 return (NULL); | |
1 | 1087 |
48 | 1088 savepos = *endpos; |
1089 *endpos = '\0'; | |
1090 *dest = g_malloc (endpos - source + 1); | |
1091 strcpy (*dest, source); | |
1092 *endpos = savepos; | |
1 | 1093 |
48 | 1094 /* Skip the blanks till we get to the next entry */ |
1095 source = endpos + 1; | |
1096 while ((*source == ' ' || *source == '\t') && *source != '\0') | |
1097 source++; | |
1098 return (source); | |
1099 } | |
1 | 1100 |
1101 | |
48 | 1102 static char * |
1103 goto_next_token (char *pos) | |
1104 { | |
1105 while (*pos != ' ' && *pos != '\t' && *pos != '\0') | |
1106 pos++; | |
1 | 1107 |
48 | 1108 if (pos == '\0') |
1109 return (pos); | |
1 | 1110 |
48 | 1111 while ((*pos == ' ' || *pos == '\t') && *pos != '\0') |
1112 pos++; | |
1113 | |
1114 return (pos); | |
1 | 1115 } |
1116 | |
1117 | |
102 | 1118 time_t |
1119 parse_time (char *str, char **endpos) | |
1 | 1120 { |
102 | 1121 struct tm curtime, *loctime; |
105 | 1122 time_t t, ret; |
102 | 1123 char *tmppos; |
260 | 1124 int i, num; |
1 | 1125 |
102 | 1126 memset (&curtime, 0, sizeof (curtime)); |
1127 curtime.tm_isdst = -1; | |
260 | 1128 if (strlen (str) > 4 && isdigit ((int) str[0]) && str[2] == '-' && |
1129 isdigit ((int) str[3])) | |
1 | 1130 { |
1131 /* This is how DOS will return the date/time */ | |
1132 /* 07-06-99 12:57PM */ | |
1133 | |
102 | 1134 tmppos = strptime (str, "%m-%d-%y %I:%M%p", &curtime); |
1 | 1135 } |
260 | 1136 else if (strlen (str) > 4 && isdigit ((int) str[0]) && str[2] == '-' && |
1137 isalpha (str[3])) | |
105 | 1138 { |
1139 /* 10-Jan-2003 09:14 */ | |
1140 tmppos = strptime (str, "%d-%h-%Y %H:%M", &curtime); | |
1141 } | |
1 | 1142 else |
1143 { | |
1144 /* This is how most UNIX, Novell, and MacOS ftp servers send their time */ | |
102 | 1145 /* Jul 06 12:57 or Jul 6 1999 */ |
1 | 1146 |
102 | 1147 if (strchr (str, ':') != NULL) |
1148 { | |
1149 tmppos = strptime (str, "%h %d %H:%M", &curtime); | |
1150 t = time (NULL); | |
1151 loctime = localtime (&t); | |
1152 curtime.tm_year = loctime->tm_year; | |
1153 } | |
1154 else | |
1155 tmppos = strptime (str, "%h %d %Y", &curtime); | |
1156 } | |
1 | 1157 |
105 | 1158 if (tmppos != NULL) |
1159 ret = mktime (&curtime); | |
1160 else | |
1161 ret = 0; | |
1162 | |
102 | 1163 if (endpos != NULL) |
105 | 1164 { |
1165 if (tmppos == NULL) | |
1166 { | |
260 | 1167 /* We cannot parse this date format. So, just skip this date field |
1168 and continue to the next token. This is mainly for the HTTP | |
1169 support */ | |
1170 | |
1171 *endpos = str; | |
1172 for (num = 0; num < 2 && **endpos != '\0'; num++) | |
1173 { | |
1174 for (i=0; | |
1175 (*endpos)[i] != ' ' && (*endpos)[i] != '\t' && | |
1176 (*endpos)[i] != '\0'; | |
1177 i++); | |
1178 *endpos += i; | |
1179 | |
1180 for (i=0; (*endpos)[i] == ' ' || (*endpos)[i] == '\t'; i++); | |
1181 *endpos += i; | |
1182 } | |
105 | 1183 } |
1184 else | |
1185 *endpos = tmppos; | |
1186 } | |
1 | 1187 |
281 | 1188 return (ret); |
1 | 1189 } |
1190 | |
1191 | |
107 | 1192 static void |
1193 gftp_parse_vms_attribs (char *dest, char **src) | |
1194 { | |
1195 char *endpos; | |
1196 | |
1197 if (*src == NULL) | |
1198 return; | |
1199 | |
1200 if ((endpos = strchr (*src, ',')) != NULL) | |
1201 *endpos = '\0'; | |
1202 | |
1203 if (strchr (*src, 'R') != NULL) | |
1204 *dest = 'r'; | |
1205 if (strchr (*src, 'W') != NULL) | |
1206 *(dest + 1) = 'w'; | |
1207 if (strchr (*src, 'E') != NULL) | |
1208 *(dest + 2) = 'x'; | |
1209 | |
1210 *src = endpos + 1; | |
1211 } | |
1212 | |
1213 | |
1214 static int | |
1215 gftp_parse_ls_vms (char *str, gftp_file * fle) | |
1216 { | |
1217 char *curpos, *endpos; | |
1218 | |
1219 /* .PINE-DEBUG1;1 9 21-AUG-2002 20:06 [MYERSRG] (RWED,RWED,,) */ | |
1220 /* WWW.DIR;1 1 23-NOV-1999 05:47 [MYERSRG] (RWE,RWE,RE,E) */ | |
1221 | |
1222 if ((curpos = strchr (str, ';')) == NULL) | |
1223 return (GFTP_EFATAL); | |
1224 | |
1225 *curpos = '\0'; | |
1226 fle->attribs = g_strdup ("----------"); | |
1227 if (strlen (str) > 4 && strcmp (curpos - 4, ".DIR") == 0) | |
1228 { | |
1229 fle->isdir = 1; | |
1230 *fle->attribs = 'd'; | |
1231 *(curpos - 4) = '\0'; | |
1232 } | |
1233 | |
1234 fle->file = g_strdup (str); | |
1235 | |
1236 curpos = goto_next_token (curpos + 1); | |
244 | 1237 fle->size = gftp_parse_file_size (curpos) * 512; /* Is this correct? */ |
107 | 1238 curpos = goto_next_token (curpos); |
1239 | |
1240 if ((fle->datetime = parse_time (curpos, &curpos)) == 0) | |
1241 return (GFTP_EFATAL); | |
1242 | |
1243 curpos = goto_next_token (curpos); | |
1244 | |
1245 if (*curpos != '[') | |
1246 return (GFTP_EFATAL); | |
1247 curpos++; | |
1248 if ((endpos = strchr (curpos, ']')) == NULL) | |
1249 return (GFTP_EFATAL); | |
1250 *endpos = '\0'; | |
1251 fle->user = g_strdup (curpos); | |
1252 fle->group = g_strdup (""); | |
1253 | |
1254 curpos = goto_next_token (endpos + 1); | |
1255 if ((curpos = strchr (curpos, ',')) == NULL) | |
1256 return (0); | |
1257 curpos++; | |
1258 | |
1259 gftp_parse_vms_attribs (fle->attribs + 1, &curpos); | |
1260 gftp_parse_vms_attribs (fle->attribs + 4, &curpos); | |
1261 gftp_parse_vms_attribs (fle->attribs + 7, &curpos); | |
1262 | |
1263 return (0); | |
1264 } | |
1265 | |
1266 | |
1 | 1267 static int |
1268 gftp_parse_ls_eplf (char *str, gftp_file * fle) | |
1269 { | |
1270 char *startpos; | |
1271 | |
1272 startpos = str; | |
124 | 1273 fle->attribs = g_strdup ("----------"); |
1 | 1274 while (startpos) |
1275 { | |
1276 startpos++; | |
1277 switch (*startpos) | |
168 | 1278 { |
1279 case '/': | |
1280 *fle->attribs = 'd'; | |
1281 break; | |
1282 case 's': | |
244 | 1283 fle->size = gftp_parse_file_size (startpos + 1); |
168 | 1284 break; |
1285 case 'm': | |
1286 fle->datetime = strtol (startpos + 1, NULL, 10); | |
1287 break; | |
1288 } | |
1 | 1289 startpos = strchr (startpos, ','); |
1290 } | |
1291 if ((startpos = strchr (str, 9)) == NULL) | |
84 | 1292 return (GFTP_EFATAL); |
124 | 1293 fle->file = g_strdup (startpos + 1); |
1294 fle->user = g_strdup (_("unknown")); | |
1295 fle->group = g_strdup (_("unknown")); | |
1 | 1296 return (0); |
1297 } | |
1298 | |
1299 | |
1300 static int | |
91 | 1301 gftp_parse_ls_unix (gftp_request * request, char *str, gftp_file * fle) |
1 | 1302 { |
91 | 1303 char *endpos, *startpos, *pos; |
1304 int cols; | |
1305 | |
1306 /* If there is no space between the attribs and links field, just make one */ | |
1307 if (strlen (str) > 10) | |
1308 str[10] = ' '; | |
1309 | |
1310 /* Determine the number of columns */ | |
1311 cols = 0; | |
1312 pos = str; | |
1313 while (*pos != '\0') | |
1314 { | |
1315 while (*pos != '\0' && *pos != ' ' && *pos != '\t') | |
1316 { | |
1317 if (*pos == ':') | |
1318 break; | |
1319 pos++; | |
1320 } | |
1321 | |
1322 cols++; | |
1323 | |
1324 if (*pos == ':') | |
1325 { | |
1326 cols++; | |
1327 break; | |
1328 } | |
1329 | |
1330 while (*pos == ' ' || *pos == '\t') | |
1331 pos++; | |
1332 } | |
1 | 1333 |
1334 startpos = str; | |
1335 /* Copy file attributes */ | |
1336 if ((startpos = copy_token (&fle->attribs, startpos)) == NULL) | |
84 | 1337 return (GFTP_EFATAL); |
1 | 1338 |
1339 if (cols >= 9) | |
1340 { | |
1341 /* Skip the number of links */ | |
1342 startpos = goto_next_token (startpos); | |
1343 | |
1344 /* Copy the user that owns this file */ | |
1345 if ((startpos = copy_token (&fle->user, startpos)) == NULL) | |
168 | 1346 return (GFTP_EFATAL); |
1 | 1347 |
1348 /* Copy the group that owns this file */ | |
1349 if ((startpos = copy_token (&fle->group, startpos)) == NULL) | |
168 | 1350 return (GFTP_EFATAL); |
1 | 1351 } |
1352 else | |
1353 { | |
124 | 1354 fle->group = g_strdup (_("unknown")); |
1 | 1355 if (cols == 8) |
168 | 1356 { |
1357 if ((startpos = copy_token (&fle->user, startpos)) == NULL) | |
1358 return (GFTP_EFATAL); | |
1359 } | |
1 | 1360 else |
124 | 1361 fle->user = g_strdup (_("unknown")); |
1 | 1362 startpos = goto_next_token (startpos); |
1363 } | |
1364 | |
281 | 1365 if (request->server_type == GFTP_DIRTYPE_CRAY) |
1 | 1366 { |
91 | 1367 /* See if this is a Cray directory listing. It has the following format: |
1368 drwx------ 2 feiliu g913 DK common 4096 Sep 24 2001 wv */ | |
1369 if (cols == 11 && strstr (str, "->") == NULL) | |
1370 { | |
1371 startpos = goto_next_token (startpos); | |
1372 startpos = goto_next_token (startpos); | |
1373 } | |
1 | 1374 } |
1375 | |
1376 /* See if this is a block or character device. We will store the major number | |
1377 in the high word and the minor number in the low word. */ | |
1378 if ((fle->attribs[0] == 'b' || fle->attribs[0] == 'u' || | |
14
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
1379 fle->attribs[0] == 'c') && |
1 | 1380 ((endpos = strchr (startpos, ',')) != NULL)) |
1381 { | |
1382 fle->size = strtol (startpos, NULL, 10) << 16; | |
1383 | |
1384 startpos = endpos + 1; | |
1385 while (*startpos == ' ') | |
168 | 1386 startpos++; |
1 | 1387 |
1388 /* Get the minor number */ | |
1389 if ((endpos = strchr (startpos, ' ')) == NULL) | |
168 | 1390 return (GFTP_EFATAL); |
14
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
1391 fle->size |= strtol (startpos, NULL, 10) & 0xFF; |
1 | 1392 } |
1393 else | |
1394 { | |
1395 /* This is a regular file */ | |
1396 if ((endpos = strchr (startpos, ' ')) == NULL) | |
168 | 1397 return (GFTP_EFATAL); |
244 | 1398 fle->size = gftp_parse_file_size (startpos); |
1 | 1399 } |
1400 | |
1401 /* Skip the blanks till we get to the next entry */ | |
1402 startpos = endpos + 1; | |
1403 while (*startpos == ' ') | |
1404 startpos++; | |
1405 | |
102 | 1406 if ((fle->datetime = parse_time (startpos, &startpos)) == 0) |
84 | 1407 return (GFTP_EFATAL); |
1 | 1408 |
1409 /* Skip the blanks till we get to the next entry */ | |
1410 startpos = goto_next_token (startpos); | |
1411 | |
1412 /* Parse the filename. If this file is a symbolic link, remove the -> part */ | |
1413 if (fle->attribs[0] == 'l' && ((endpos = strstr (startpos, "->")) != NULL)) | |
1414 *(endpos - 1) = '\0'; | |
1415 | |
124 | 1416 fle->file = g_strdup (startpos); |
1 | 1417 |
1418 /* Uncomment this if you want to strip the spaces off of the end of the file. | |
1419 I don't want to do this by default since there are valid filenames with | |
1420 spaces at the end of them. Some broken FTP servers like the Paradyne IPC | |
1421 DSLAMS append a bunch of spaces at the end of the file. | |
1422 for (endpos = fle->file + strlen (fle->file) - 1; | |
1423 *endpos == ' '; | |
1424 *endpos-- = '\0'); | |
1425 */ | |
1426 | |
1427 return (0); | |
1428 } | |
1429 | |
1430 | |
1431 static int | |
1432 gftp_parse_ls_nt (char *str, gftp_file * fle) | |
1433 { | |
1434 char *startpos; | |
1435 | |
1436 startpos = str; | |
102 | 1437 if ((fle->datetime = parse_time (startpos, &startpos)) == 0) |
84 | 1438 return (GFTP_EFATAL); |
1 | 1439 |
124 | 1440 fle->user = g_strdup (_("unknown")); |
1441 fle->group = g_strdup (_("unknown")); | |
1 | 1442 |
1443 startpos = goto_next_token (startpos); | |
1444 if (startpos[0] == '<') | |
124 | 1445 fle->attribs = g_strdup ("drwxrwxrwx"); |
1 | 1446 else |
1447 { | |
124 | 1448 fle->attribs = g_strdup ("-rw-rw-rw-"); |
244 | 1449 fle->size = gftp_parse_file_size (startpos); |
1 | 1450 } |
124 | 1451 |
1 | 1452 startpos = goto_next_token (startpos); |
124 | 1453 fle->file = g_strdup (startpos); |
1 | 1454 return (0); |
1455 } | |
1456 | |
1457 | |
1458 static int | |
1459 gftp_parse_ls_novell (char *str, gftp_file * fle) | |
1460 { | |
1461 char *startpos; | |
1462 | |
1463 if (str[12] != ' ') | |
84 | 1464 return (GFTP_EFATAL); |
1 | 1465 str[12] = '\0'; |
124 | 1466 fle->attribs = g_strdup (str); |
1 | 1467 startpos = str + 13; |
1468 | |
1469 while ((*startpos == ' ' || *startpos == '\t') && *startpos != '\0') | |
1470 startpos++; | |
1471 | |
1472 if ((startpos = copy_token (&fle->user, startpos)) == NULL) | |
84 | 1473 return (GFTP_EFATAL); |
1 | 1474 |
124 | 1475 fle->group = g_strdup (_("unknown")); |
1 | 1476 |
244 | 1477 fle->size = gftp_parse_file_size (startpos); |
1 | 1478 |
1479 startpos = goto_next_token (startpos); | |
102 | 1480 if ((fle->datetime = parse_time (startpos, &startpos)) == 0) |
84 | 1481 return (GFTP_EFATAL); |
1 | 1482 |
1483 startpos = goto_next_token (startpos); | |
124 | 1484 fle->file = g_strdup (startpos); |
1 | 1485 return (0); |
1486 } | |
1487 | |
1488 | |
48 | 1489 int |
91 | 1490 gftp_parse_ls (gftp_request * request, const char *lsoutput, gftp_file * fle) |
1 | 1491 { |
107 | 1492 char *str, *endpos, tmpchar; |
1493 int result, is_vms; | |
91 | 1494 size_t len; |
48 | 1495 |
84 | 1496 g_return_val_if_fail (lsoutput != NULL, GFTP_EFATAL); |
1497 g_return_val_if_fail (fle != NULL, GFTP_EFATAL); | |
48 | 1498 |
124 | 1499 str = g_strdup (lsoutput); |
48 | 1500 memset (fle, 0, sizeof (*fle)); |
1 | 1501 |
91 | 1502 len = strlen (str); |
107 | 1503 if (len > 0 && str[len - 1] == '\n') |
91 | 1504 str[--len] = '\0'; |
1505 if (len > 0 && str[len - 1] == '\r') | |
1506 str[--len] = '\0'; | |
39 | 1507 |
91 | 1508 switch (request->server_type) |
1509 { | |
122 | 1510 case GFTP_DIRTYPE_CRAY: |
1511 case GFTP_DIRTYPE_UNIX: | |
1512 result = gftp_parse_ls_unix (request, str, fle); | |
91 | 1513 break; |
122 | 1514 case GFTP_DIRTYPE_EPLF: |
91 | 1515 result = gftp_parse_ls_eplf (str, fle); |
1516 break; | |
122 | 1517 case GFTP_DIRTYPE_NOVELL: |
91 | 1518 result = gftp_parse_ls_novell (str, fle); |
1519 break; | |
122 | 1520 case GFTP_DIRTYPE_DOS: |
91 | 1521 result = gftp_parse_ls_nt (str, fle); |
1522 break; | |
122 | 1523 case GFTP_DIRTYPE_VMS: |
107 | 1524 result = gftp_parse_ls_vms (str, fle); |
1525 break; | |
91 | 1526 default: /* autodetect */ |
1527 if (*lsoutput == '+') | |
1528 result = gftp_parse_ls_eplf (str, fle); | |
1529 else if (isdigit ((int) str[0]) && str[2] == '-') | |
1530 result = gftp_parse_ls_nt (str, fle); | |
1531 else if (str[1] == ' ' && str[2] == '[') | |
1532 result = gftp_parse_ls_novell (str, fle); | |
1533 else | |
107 | 1534 { |
1535 if ((endpos = strchr (str, ' ')) != NULL) | |
1536 { | |
1537 /* If the first token in the string has a ; in it, then */ | |
1538 /* we'll assume that this is a VMS directory listing */ | |
1539 tmpchar = *endpos; | |
1540 *endpos = '\0'; | |
1541 is_vms = strchr (str, ';') != NULL; | |
1542 *endpos = tmpchar; | |
1543 } | |
1544 else | |
1545 is_vms = 0; | |
48 | 1546 |
107 | 1547 if (is_vms) |
1548 result = gftp_parse_ls_vms (str, fle); | |
1549 else | |
1550 result = gftp_parse_ls_unix (request, str, fle); | |
1551 } | |
91 | 1552 break; |
48 | 1553 } |
1554 g_free (str); | |
1555 | |
1556 if (fle->attribs == NULL) | |
1557 return (result); | |
1558 | |
1559 if (*fle->attribs == 'd') | |
1560 fle->isdir = 1; | |
1561 if (*fle->attribs == 'l') | |
1562 fle->islink = 1; | |
1563 if (strchr (fle->attribs, 'x') != NULL && !fle->isdir && !fle->islink) | |
1564 fle->isexe = 1; | |
1565 | |
1566 return (result); | |
1 | 1567 } |
1568 | |
1569 | |
48 | 1570 static GHashTable * |
1571 gftp_gen_dir_hash (gftp_request * request) | |
1 | 1572 { |
48 | 1573 unsigned long *newsize; |
1574 GHashTable * dirhash; | |
1575 gftp_file * fle; | |
1576 char * newname; | |
1577 | |
39 | 1578 |
48 | 1579 dirhash = g_hash_table_new (string_hash_function, string_hash_compare); |
1580 if (gftp_list_files (request) == 0) | |
1581 { | |
1582 fle = g_malloc0 (sizeof (*fle)); | |
1583 while (gftp_get_next_file (request, NULL, fle) > 0) | |
1584 { | |
1585 newname = fle->file; | |
1586 newsize = g_malloc (sizeof (unsigned long)); | |
1587 *newsize = fle->size; | |
1588 g_hash_table_insert (dirhash, newname, newsize); | |
1589 fle->file = NULL; | |
1590 gftp_file_destroy (fle); | |
1591 } | |
1592 gftp_end_transfer (request); | |
1593 g_free (fle); | |
1594 } | |
1595 else | |
1596 { | |
1597 g_hash_table_destroy (dirhash); | |
1598 dirhash = NULL; | |
1599 } | |
1600 return (dirhash); | |
1601 } | |
39 | 1602 |
48 | 1603 |
1604 static void | |
1605 destroy_hash_ent (gpointer key, gpointer value, gpointer user_data) | |
1606 { | |
39 | 1607 |
48 | 1608 g_free (key); |
1609 g_free (value); | |
1610 } | |
1611 | |
1612 | |
1613 static void | |
1614 gftp_destroy_dir_hash (GHashTable * dirhash) | |
1615 { | |
1616 g_hash_table_foreach (dirhash, destroy_hash_ent, NULL); | |
1617 g_hash_table_destroy (dirhash); | |
1 | 1618 } |
1619 | |
1620 | |
1621 static GList * | |
1622 gftp_get_dir_listing (gftp_transfer * transfer, int getothdir) | |
1623 { | |
1624 unsigned long *newsize; | |
1625 GHashTable * dirhash; | |
1626 GList * templist; | |
1627 gftp_file * fle; | |
1628 char *newname; | |
1629 | |
1630 if (getothdir && transfer->toreq) | |
1631 dirhash = gftp_gen_dir_hash (transfer->toreq); | |
1632 else | |
1633 dirhash = NULL; | |
1634 | |
1635 if (gftp_list_files (transfer->fromreq) != 0) | |
1636 return (NULL); | |
1637 | |
1638 fle = g_malloc (sizeof (*fle)); | |
1639 templist = NULL; | |
1640 while (gftp_get_next_file (transfer->fromreq, NULL, fle) > 0) | |
1641 { | |
1642 if (strcmp (fle->file, ".") == 0 || strcmp (fle->file, "..") == 0) | |
1643 { | |
1644 gftp_file_destroy (fle); | |
1645 continue; | |
1646 } | |
1647 | |
1648 if (dirhash && | |
1649 (newsize = g_hash_table_lookup (dirhash, fle->file)) != NULL) | |
1650 fle->startsize = *newsize; | |
1651 | |
1652 if (transfer->toreq) | |
245 | 1653 fle->destfile = gftp_build_path (transfer->toreq->directory, |
1654 fle->file, NULL); | |
1655 | |
1656 newname = gftp_build_path (transfer->fromreq->directory, | |
1657 fle->file, NULL); | |
211 | 1658 |
1 | 1659 g_free (fle->file); |
1660 fle->file = newname; | |
1661 | |
1662 templist = g_list_append (templist, fle); | |
1663 | |
1664 fle = g_malloc (sizeof (*fle)); | |
1665 } | |
1666 gftp_end_transfer (transfer->fromreq); | |
1667 | |
1668 gftp_file_destroy (fle); | |
1669 g_free (fle); | |
1670 | |
1671 if (dirhash) | |
1672 gftp_destroy_dir_hash (dirhash); | |
1673 | |
1674 | |
1675 return (templist); | |
1676 } | |
1677 | |
1678 | |
1679 int | |
1680 gftp_get_all_subdirs (gftp_transfer * transfer, | |
1681 void (*update_func) (gftp_transfer * transfer)) | |
1682 { | |
1683 char *oldfromdir, *oldtodir, *newname; | |
1684 GList * templist, * lastlist; | |
1685 int forcecd, remotechanged; | |
1686 unsigned long *newsize; | |
1687 GHashTable * dirhash; | |
1688 gftp_file * curfle; | |
1689 | |
84 | 1690 g_return_val_if_fail (transfer != NULL, GFTP_EFATAL); |
1691 g_return_val_if_fail (transfer->fromreq != NULL, GFTP_EFATAL); | |
1692 g_return_val_if_fail (transfer->files != NULL, GFTP_EFATAL); | |
1 | 1693 |
1694 if (transfer->toreq != NULL) | |
1695 dirhash = gftp_gen_dir_hash (transfer->toreq); | |
1696 else | |
1697 dirhash = NULL; | |
1698 | |
1699 for (lastlist = transfer->files; ; lastlist = lastlist->next) | |
1700 { | |
1701 curfle = lastlist->data; | |
1702 if (dirhash && | |
1703 (newsize = g_hash_table_lookup (dirhash, curfle->file)) != NULL) | |
1704 curfle->startsize = *newsize; | |
1705 | |
1706 if (transfer->toreq) | |
1707 curfle->destfile = g_strconcat (transfer->toreq->directory, "/", | |
1708 curfle->file, NULL); | |
1709 newname = g_strconcat (transfer->fromreq->directory, transfer->fromreq->directory[strlen (transfer->fromreq->directory) - 1] == '/' ? "" : "/", curfle->file, NULL); | |
1710 g_free (curfle->file); | |
1711 curfle->file = newname; | |
1712 | |
1713 if (lastlist->next == NULL) | |
1714 break; | |
1715 } | |
1716 | |
1717 if (dirhash) | |
1718 gftp_destroy_dir_hash (dirhash); | |
1719 | |
1720 oldfromdir = oldtodir = NULL; | |
1721 remotechanged = 0; | |
1722 forcecd = 0; | |
1723 for (templist = transfer->files; templist != NULL; templist = templist->next) | |
1724 { | |
1725 curfle = templist->data; | |
1726 | |
1727 if (curfle->isdir) | |
1728 { | |
1729 oldfromdir = transfer->fromreq->directory; | |
1730 transfer->fromreq->directory = curfle->file; | |
1731 | |
1732 if (transfer->toreq) | |
1733 { | |
1734 oldtodir = transfer->toreq->directory; | |
1735 transfer->toreq->directory = curfle->destfile; | |
1736 } | |
1737 forcecd = 1; | |
1738 if (gftp_set_directory (transfer->fromreq, | |
1739 transfer->fromreq->directory) == 0) | |
1740 { | |
1741 if (curfle->startsize > 0 && transfer->toreq) | |
1742 { | |
1743 remotechanged = 1; | |
1744 if (gftp_set_directory (transfer->toreq, | |
1745 transfer->toreq->directory) != 0) | |
1746 curfle->startsize = 0; | |
1747 } | |
1748 | |
1749 lastlist->next = gftp_get_dir_listing (transfer, | |
1750 curfle->startsize > 0); | |
1751 if (lastlist->next != NULL) | |
1752 { | |
1753 lastlist->next->prev = lastlist; | |
1754 for (; lastlist->next != NULL; lastlist = lastlist->next); | |
1755 } | |
1756 transfer->numdirs++; | |
1757 if (update_func) | |
1758 update_func (transfer); | |
1759 } | |
1760 else | |
1761 curfle->transfer_action = GFTP_TRANS_ACTION_SKIP; | |
1762 | |
1763 transfer->fromreq->directory = oldfromdir; | |
1764 if (transfer->toreq) | |
1765 transfer->toreq->directory = oldtodir; | |
1766 } | |
1767 else | |
122 | 1768 transfer->numfiles++; |
1 | 1769 } |
1770 | |
1771 if (forcecd) | |
1772 gftp_set_directory (transfer->fromreq, transfer->fromreq->directory); | |
1773 if (remotechanged && transfer->toreq) | |
1774 gftp_set_directory (transfer->toreq, transfer->toreq->directory); | |
1775 | |
1776 if (update_func) | |
1777 { | |
1778 transfer->numfiles = transfer->numdirs = -1; | |
1779 update_func (transfer); | |
1780 } | |
1781 return (0); | |
1782 } | |
1783 | |
1784 | |
1785 #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR) | |
122 | 1786 static int |
1 | 1787 get_port (struct addrinfo *addr) |
1788 { | |
1789 struct sockaddr_in * saddr; | |
1790 int port; | |
1791 | |
1792 if (addr->ai_family == AF_INET) | |
1793 { | |
1794 saddr = (struct sockaddr_in *) addr->ai_addr; | |
1795 port = ntohs (saddr->sin_port); | |
1796 } | |
1797 else | |
1798 port = 0; | |
1799 | |
1800 return (port); | |
1801 } | |
1802 #endif | |
1803 | |
1804 | |
1805 int | |
122 | 1806 gftp_connect_server (gftp_request * request, char *service, |
1807 char *proxy_hostname, int proxy_port) | |
1 | 1808 { |
1809 char *connect_host, *disphost; | |
1810 int port, sock; | |
1811 #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR) | |
1812 struct addrinfo hints, *res; | |
1813 char serv[8]; | |
1814 int errnum; | |
1815 | |
122 | 1816 if ((request->use_proxy = gftp_need_proxy (request, service, |
1817 proxy_hostname, proxy_port)) < 0) | |
84 | 1818 return (request->use_proxy); |
1 | 1819 else if (request->use_proxy == 1) |
1820 request->hostp = NULL; | |
1821 | |
151 | 1822 request->free_hostp = 1; |
1 | 1823 memset (&hints, 0, sizeof (hints)); |
1824 hints.ai_flags = AI_CANONNAME; | |
146 | 1825 hints.ai_family = PF_UNSPEC; |
1 | 1826 hints.ai_socktype = SOCK_STREAM; |
1827 | |
122 | 1828 if (request->use_proxy) |
1829 { | |
1830 connect_host = proxy_hostname; | |
1831 port = proxy_port; | |
1832 } | |
1833 else | |
1834 { | |
1835 connect_host = request->hostname; | |
1836 port = request->port; | |
1837 } | |
1 | 1838 |
1839 if (request->hostp == NULL) | |
1840 { | |
1841 if (port == 0) | |
1842 strcpy (serv, service); | |
1843 else | |
1844 snprintf (serv, sizeof (serv), "%d", port); | |
1845 | |
186 | 1846 request->logging_function (gftp_logging_misc, request, |
168 | 1847 _("Looking up %s\n"), connect_host); |
1 | 1848 if ((errnum = getaddrinfo (connect_host, serv, &hints, |
1849 &request->hostp)) != 0) | |
168 | 1850 { |
186 | 1851 request->logging_function (gftp_logging_error, request, |
168 | 1852 _("Cannot look up hostname %s: %s\n"), |
1853 connect_host, gai_strerror (errnum)); | |
1854 return (GFTP_ERETRYABLE); | |
1855 } | |
1 | 1856 } |
1857 | |
1858 disphost = connect_host; | |
1859 for (res = request->hostp; res != NULL; res = res->ai_next) | |
1860 { | |
1861 disphost = res->ai_canonname ? res->ai_canonname : connect_host; | |
1862 port = get_port (res); | |
56 | 1863 if (!request->use_proxy) |
1864 request->port = port; | |
1865 | |
1 | 1866 if ((sock = socket (res->ai_family, res->ai_socktype, |
1867 res->ai_protocol)) < 0) | |
1868 { | |
186 | 1869 request->logging_function (gftp_logging_error, request, |
1 | 1870 _("Failed to create a socket: %s\n"), |
1871 g_strerror (errno)); | |
1872 continue; | |
66 | 1873 } |
1 | 1874 |
186 | 1875 request->logging_function (gftp_logging_misc, request, |
168 | 1876 _("Trying %s:%d\n"), disphost, port); |
1 | 1877 |
1878 if (connect (sock, res->ai_addr, res->ai_addrlen) == -1) | |
168 | 1879 { |
186 | 1880 request->logging_function (gftp_logging_error, request, |
168 | 1881 _("Cannot connect to %s: %s\n"), |
1882 disphost, g_strerror (errno)); | |
1 | 1883 close (sock); |
1884 continue; | |
168 | 1885 } |
1 | 1886 break; |
1887 } | |
1888 | |
1889 if (res == NULL) | |
1890 { | |
1891 if (request->hostp != NULL) | |
1892 { | |
1893 freeaddrinfo (request->hostp); | |
1894 request->hostp = NULL; | |
1895 } | |
84 | 1896 return (GFTP_ERETRYABLE); |
1 | 1897 } |
1898 | |
1899 #else /* !HAVE_GETADDRINFO */ | |
1900 struct sockaddr_in remote_address; | |
1901 struct servent serv_struct; | |
1902 int curhost; | |
1903 | |
122 | 1904 if ((request->use_proxy = gftp_need_proxy (request, service, |
1905 proxy_hostname, proxy_port)) < 0) | |
84 | 1906 return (request->use_proxy); |
1 | 1907 else if (request->use_proxy == 1) |
1908 request->hostp = NULL; | |
1909 | |
1910 if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) | |
1911 { | |
186 | 1912 request->logging_function (gftp_logging_error, request, |
1 | 1913 _("Failed to create a socket: %s\n"), |
1914 g_strerror (errno)); | |
84 | 1915 return (GFTP_ERETRYABLE); |
1 | 1916 } |
1917 | |
1918 memset (&remote_address, 0, sizeof (remote_address)); | |
1919 remote_address.sin_family = AF_INET; | |
1920 | |
122 | 1921 if (request->use_proxy) |
1922 { | |
1923 connect_host = proxy_hostname; | |
1924 port = proxy_port; | |
1925 } | |
1926 else | |
1927 { | |
1928 connect_host = request->hostname; | |
1929 port = request->port; | |
1930 } | |
1 | 1931 |
1932 if (port == 0) | |
1933 { | |
1934 if (!r_getservbyname (service, "tcp", &serv_struct, NULL)) | |
1935 { | |
186 | 1936 request->logging_function (gftp_logging_error, request, |
122 | 1937 _("Cannot look up service name %s/tcp. Please check your services file\n"), |
1938 service); | |
1939 close (sock); | |
1940 return (GFTP_EFATAL); | |
1 | 1941 } |
1942 else | |
1943 { | |
1944 port = serv_struct.s_port; | |
1945 request->port = ntohs (serv_struct.s_port); | |
1946 } | |
56 | 1947 |
1948 if (!request->use_proxy) | |
1949 request->port = ntohs (port); | |
1 | 1950 } |
1951 remote_address.sin_port = port; | |
1952 | |
1953 if (request->hostp == NULL) | |
1954 { | |
186 | 1955 request->logging_function (gftp_logging_misc, request, |
168 | 1956 _("Looking up %s\n"), connect_host); |
1 | 1957 if (!(request->hostp = r_gethostbyname (connect_host, &request->host, |
1958 NULL))) | |
1959 { | |
186 | 1960 request->logging_function (gftp_logging_error, request, |
1 | 1961 _("Cannot look up hostname %s: %s\n"), |
1962 connect_host, g_strerror (errno)); | |
1963 close (sock); | |
84 | 1964 return (GFTP_ERETRYABLE); |
1 | 1965 } |
1966 } | |
1967 | |
1968 disphost = NULL; | |
1969 for (curhost = 0; request->host.h_addr_list[curhost] != NULL; curhost++) | |
1970 { | |
1971 disphost = request->host.h_name; | |
1972 memcpy (&remote_address.sin_addr, request->host.h_addr_list[curhost], | |
1973 request->host.h_length); | |
186 | 1974 request->logging_function (gftp_logging_misc, request, |
1 | 1975 _("Trying %s:%d\n"), |
1976 request->host.h_name, ntohs (port)); | |
1977 | |
1978 if (connect (sock, (struct sockaddr *) &remote_address, | |
1979 sizeof (remote_address)) == -1) | |
1980 { | |
186 | 1981 request->logging_function (gftp_logging_error, request, |
1 | 1982 _("Cannot connect to %s: %s\n"), |
1983 connect_host, g_strerror (errno)); | |
1984 } | |
1985 break; | |
1986 } | |
1987 | |
1988 if (request->host.h_addr_list[curhost] == NULL) | |
1989 { | |
1990 close (sock); | |
84 | 1991 return (GFTP_ERETRYABLE); |
1 | 1992 } |
1993 port = ntohs (port); | |
1994 #endif /* HAVE_GETADDRINFO */ | |
1995 | |
182 | 1996 if (fcntl (sock, F_SETFD, 1) == -1) |
1997 { | |
186 | 1998 request->logging_function (gftp_logging_error, request, |
182 | 1999 _("Error: Cannot set close on exec flag: %s\n"), |
2000 g_strerror (errno)); | |
2001 | |
2002 return (GFTP_ERETRYABLE); | |
2003 } | |
2004 | |
186 | 2005 request->logging_function (gftp_logging_misc, request, |
168 | 2006 _("Connected to %s:%d\n"), connect_host, port); |
58 | 2007 |
168 | 2008 if (gftp_fd_set_sockblocking (request, sock, 1) < 0) |
58 | 2009 { |
2010 close (sock); | |
84 | 2011 return (GFTP_ERETRYABLE); |
58 | 2012 } |
2013 | |
169 | 2014 request->datafd = sock; |
168 | 2015 |
2016 if (request->post_connect != NULL) | |
2017 return (request->post_connect (request)); | |
2018 | |
2019 return (0); | |
1 | 2020 } |
2021 | |
2022 | |
177 | 2023 int |
1 | 2024 gftp_set_config_options (gftp_request * request) |
2025 { | |
58 | 2026 if (request->set_config_options != NULL) |
177 | 2027 return (request->set_config_options (request)); |
2028 else | |
2029 return (0); | |
1 | 2030 } |
2031 | |
2032 | |
2033 void | |
2034 print_file_list (GList * list) | |
2035 { | |
2036 gftp_file * tempfle; | |
2037 GList * templist; | |
2038 | |
2039 printf ("--START OF FILE LISTING - TOP TO BOTTOM--\n"); | |
2040 for (templist = list; ; templist = templist->next) | |
2041 { | |
2042 tempfle = templist->data; | |
14
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
2043 #if defined (_LARGEFILE_SOURCE) |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
2044 printf ("%s:%s:%lld:%lld:%s:%s:%s\n", |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
2045 #else |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
2046 printf ("%s:%s:%ld:%ld:%s:%s:%s\n", |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
2047 #endif |
16 | 2048 tempfle->file, tempfle->destfile, |
2049 tempfle->size, tempfle->startsize, | |
2050 tempfle->user, tempfle->group, tempfle->attribs); | |
1 | 2051 if (templist->next == NULL) |
2052 break; | |
2053 } | |
2054 | |
2055 printf ("--START OF FILE LISTING - BOTTOM TO TOP--\n"); | |
2056 for (; ; templist = templist->prev) | |
2057 { | |
2058 tempfle = templist->data; | |
14
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
2059 #if defined (_LARGEFILE_SOURCE) |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
2060 printf ("%s:%s:%lld:%lld:%s:%s:%s\n", |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
2061 #else |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
2062 printf ("%s:%s:%ld:%ld:%s:%s:%s\n", |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
2063 #endif |
16 | 2064 tempfle->file, tempfle->destfile, |
2065 tempfle->size, tempfle->startsize, | |
2066 tempfle->user, tempfle->group, tempfle->attribs); | |
1 | 2067 if (templist == list) |
2068 break; | |
2069 } | |
2070 printf ("--END OF FILE LISTING--\n"); | |
2071 } | |
2072 | |
41 | 2073 |
201 | 2074 void |
58 | 2075 gftp_free_getline_buffer (gftp_getline_buffer ** rbuf) |
41 | 2076 { |
58 | 2077 g_free ((*rbuf)->buffer); |
2078 g_free (*rbuf); | |
2079 *rbuf = NULL; | |
41 | 2080 } |
2081 | |
2082 | |
58 | 2083 ssize_t |
2084 gftp_get_line (gftp_request * request, gftp_getline_buffer ** rbuf, | |
2085 char * str, size_t len, int fd) | |
41 | 2086 { |
168 | 2087 ssize_t ret, retval, rlen; |
58 | 2088 char *pos, *nextpos; |
168 | 2089 ssize_t (*read_function) (gftp_request * request, void *ptr, size_t size, |
2090 int fd); | |
179 | 2091 int end_of_buffer; |
168 | 2092 |
2093 if (request == NULL || request->read_function == NULL) | |
2094 read_function = gftp_fd_read; | |
2095 else | |
2096 read_function = request->read_function; | |
58 | 2097 |
2098 if (*rbuf == NULL) | |
2099 { | |
2100 *rbuf = g_malloc0 (sizeof (**rbuf)); | |
2101 (*rbuf)->max_bufsize = len; | |
249 | 2102 (*rbuf)->buffer = g_malloc0 ((*rbuf)->max_bufsize + 1); |
168 | 2103 |
2104 if ((ret = read_function (request, (*rbuf)->buffer, | |
2105 (*rbuf)->max_bufsize, fd)) <= 0) | |
58 | 2106 { |
2107 gftp_free_getline_buffer (rbuf); | |
2108 return (ret); | |
2109 } | |
60 | 2110 (*rbuf)->buffer[ret] = '\0'; |
58 | 2111 (*rbuf)->cur_bufsize = ret; |
2112 (*rbuf)->curpos = (*rbuf)->buffer; | |
2113 } | |
2114 | |
84 | 2115 retval = GFTP_ERETRYABLE; |
58 | 2116 do |
2117 { | |
179 | 2118 pos = strchr ((*rbuf)->curpos, '\n'); |
2119 end_of_buffer = (*rbuf)->curpos == (*rbuf)->buffer && | |
2120 ((*rbuf)->max_bufsize == (*rbuf)->cur_bufsize || (*rbuf)->eof); | |
2121 | |
2122 if ((*rbuf)->cur_bufsize > 0 && (pos != NULL || end_of_buffer)) | |
58 | 2123 { |
2124 if (pos != NULL) | |
2125 { | |
249 | 2126 retval = pos - (*rbuf)->curpos + 1; |
58 | 2127 nextpos = pos + 1; |
2128 if (pos > (*rbuf)->curpos && *(pos - 1) == '\r') | |
2129 pos--; | |
2130 *pos = '\0'; | |
2131 } | |
2132 else | |
249 | 2133 { |
2134 retval = (*rbuf)->cur_bufsize; | |
2135 nextpos = NULL; | |
2136 | |
2137 /* This is not an overflow since we allocated one extra byte to | |
2138 buffer above */ | |
2139 ((*rbuf)->curpos)[retval] = '\0'; | |
2140 } | |
58 | 2141 |
2142 strncpy (str, (*rbuf)->curpos, len); | |
249 | 2143 str[len - 1] = '\0'; |
168 | 2144 (*rbuf)->cur_bufsize -= retval; |
58 | 2145 |
168 | 2146 if (nextpos != NULL) |
2147 (*rbuf)->curpos = nextpos; | |
2148 else | |
2149 (*rbuf)->cur_bufsize = 0; | |
58 | 2150 break; |
2151 } | |
2152 else | |
2153 { | |
2154 if ((*rbuf)->cur_bufsize == 0 || *(*rbuf)->curpos == '\0') | |
2155 { | |
2156 rlen = (*rbuf)->max_bufsize; | |
2157 pos = (*rbuf)->buffer; | |
2158 } | |
2159 else | |
2160 { | |
168 | 2161 memmove ((*rbuf)->buffer, (*rbuf)->curpos, (*rbuf)->cur_bufsize); |
2162 pos = (*rbuf)->buffer + (*rbuf)->cur_bufsize; | |
2163 rlen = (*rbuf)->max_bufsize - (*rbuf)->cur_bufsize; | |
58 | 2164 } |
168 | 2165 |
58 | 2166 (*rbuf)->curpos = (*rbuf)->buffer; |
2167 | |
209 | 2168 if ((*rbuf)->eof) |
2169 ret = 0; | |
2170 else | |
2171 ret = read_function (request, pos, rlen, fd); | |
2172 | |
2173 if (ret < 0) | |
58 | 2174 { |
2175 gftp_free_getline_buffer (rbuf); | |
2176 return (ret); | |
2177 } | |
179 | 2178 else if (ret == 0) |
168 | 2179 { |
179 | 2180 if ((*rbuf)->cur_bufsize == 0) |
2181 { | |
2182 gftp_free_getline_buffer (rbuf); | |
2183 return (ret); | |
2184 } | |
2185 | |
2186 (*rbuf)->eof = 1; | |
168 | 2187 } |
2188 | |
2189 (*rbuf)->cur_bufsize += ret; | |
215 | 2190 (*rbuf)->curpos[(*rbuf)->cur_bufsize] = '\0'; |
58 | 2191 } |
2192 } | |
84 | 2193 while (retval == GFTP_ERETRYABLE); |
58 | 2194 |
2195 return (retval); | |
2196 } | |
2197 | |
2198 | |
2199 ssize_t | |
168 | 2200 gftp_fd_read (gftp_request * request, void *ptr, size_t size, int fd) |
58 | 2201 { |
122 | 2202 long network_timeout; |
58 | 2203 struct timeval tv; |
2204 fd_set fset; | |
2205 ssize_t ret; | |
41 | 2206 |
122 | 2207 gftp_lookup_request_option (request, "network_timeout", &network_timeout); |
2208 | |
41 | 2209 errno = 0; |
2210 ret = 0; | |
2211 do | |
2212 { | |
58 | 2213 FD_ZERO (&fset); |
2214 FD_SET (fd, &fset); | |
122 | 2215 tv.tv_sec = network_timeout; |
58 | 2216 tv.tv_usec = 0; |
2217 ret = select (fd + 1, &fset, NULL, NULL, &tv); | |
2218 if (ret == -1 && errno == EINTR) | |
41 | 2219 { |
58 | 2220 if (request && request->cancel) |
2221 break; | |
2222 else | |
2223 continue; | |
2224 } | |
2225 else if (ret <= 0) | |
2226 { | |
2227 if (request != NULL) | |
41 | 2228 { |
186 | 2229 request->logging_function (gftp_logging_error, request, |
58 | 2230 _("Connection to %s timed out\n"), |
2231 request->hostname); | |
2232 gftp_disconnect (request); | |
2233 } | |
84 | 2234 return (GFTP_ERETRYABLE); |
41 | 2235 } |
2236 | |
58 | 2237 if ((ret = read (fd, ptr, size)) < 0) |
41 | 2238 { |
2239 if (errno == EINTR) | |
2240 { | |
58 | 2241 if (request != NULL && request->cancel) |
41 | 2242 break; |
2243 else | |
58 | 2244 continue; |
41 | 2245 } |
2246 | |
58 | 2247 if (request != NULL) |
2248 { | |
186 | 2249 request->logging_function (gftp_logging_error, request, |
58 | 2250 _("Error: Could not read from socket: %s\n"), |
41 | 2251 g_strerror (errno)); |
58 | 2252 gftp_disconnect (request); |
2253 } | |
84 | 2254 return (GFTP_ERETRYABLE); |
41 | 2255 } |
2256 } | |
58 | 2257 while (errno == EINTR && !(request != NULL && request->cancel)); |
41 | 2258 |
58 | 2259 if (errno == EINTR && request != NULL && request->cancel) |
41 | 2260 { |
2261 gftp_disconnect (request); | |
84 | 2262 return (GFTP_ERETRYABLE); |
41 | 2263 } |
2264 | |
2265 return (ret); | |
2266 } | |
2267 | |
58 | 2268 |
2269 ssize_t | |
168 | 2270 gftp_fd_write (gftp_request * request, const char *ptr, size_t size, int fd) |
58 | 2271 { |
122 | 2272 long network_timeout; |
58 | 2273 struct timeval tv; |
248 | 2274 ssize_t w_ret; |
58 | 2275 fd_set fset; |
248 | 2276 size_t ret; |
58 | 2277 |
122 | 2278 gftp_lookup_request_option (request, "network_timeout", &network_timeout); |
2279 | |
58 | 2280 errno = 0; |
2281 ret = 0; | |
2282 do | |
2283 { | |
2284 FD_ZERO (&fset); | |
2285 FD_SET (fd, &fset); | |
122 | 2286 tv.tv_sec = network_timeout; |
58 | 2287 tv.tv_usec = 0; |
2288 ret = select (fd + 1, NULL, &fset, NULL, &tv); | |
2289 if (ret == -1 && errno == EINTR) | |
2290 { | |
2291 if (request != NULL && request->cancel) | |
2292 break; | |
2293 else | |
2294 continue; | |
2295 } | |
2296 else if (ret <= 0) | |
2297 { | |
2298 if (request != NULL) | |
2299 { | |
186 | 2300 request->logging_function (gftp_logging_error, request, |
58 | 2301 _("Connection to %s timed out\n"), |
2302 request->hostname); | |
2303 gftp_disconnect (request); | |
2304 } | |
84 | 2305 return (GFTP_ERETRYABLE); |
58 | 2306 } |
2307 | |
248 | 2308 w_ret = write (fd, ptr, size); |
2309 if (w_ret < 0) | |
58 | 2310 { |
2311 if (errno == EINTR) | |
2312 { | |
2313 if (request != NULL && request->cancel) | |
2314 break; | |
2315 else | |
2316 continue; | |
2317 } | |
2318 | |
2319 if (request != NULL) | |
2320 { | |
186 | 2321 request->logging_function (gftp_logging_error, request, |
58 | 2322 _("Error: Could not write to socket: %s\n"), |
2323 g_strerror (errno)); | |
2324 gftp_disconnect (request); | |
2325 } | |
84 | 2326 return (GFTP_ERETRYABLE); |
58 | 2327 } |
2328 | |
2329 ptr += w_ret; | |
2330 size -= w_ret; | |
2331 ret += w_ret; | |
2332 } | |
2333 while (size > 0); | |
2334 | |
2335 if (errno == EINTR && request != NULL && request->cancel) | |
2336 { | |
2337 gftp_disconnect (request); | |
84 | 2338 return (GFTP_ERETRYABLE); |
58 | 2339 } |
2340 | |
2341 return (ret); | |
2342 } | |
2343 | |
2344 | |
2345 ssize_t | |
2346 gftp_writefmt (gftp_request * request, int fd, const char *fmt, ...) | |
2347 { | |
2348 char *tempstr; | |
2349 va_list argp; | |
2350 ssize_t ret; | |
2351 | |
2352 va_start (argp, fmt); | |
2353 tempstr = g_strdup_vprintf (fmt, argp); | |
2354 va_end (argp); | |
2355 | |
168 | 2356 ret = request->write_function (request, tempstr, strlen (tempstr), fd); |
58 | 2357 g_free (tempstr); |
2358 return (ret); | |
2359 } | |
2360 | |
2361 | |
2362 int | |
168 | 2363 gftp_fd_set_sockblocking (gftp_request * request, int fd, int non_blocking) |
58 | 2364 { |
2365 int flags; | |
2366 | |
84 | 2367 if ((flags = fcntl (fd, F_GETFL, 0)) < 0) |
58 | 2368 { |
186 | 2369 request->logging_function (gftp_logging_error, request, |
58 | 2370 _("Cannot get socket flags: %s\n"), |
2371 g_strerror (errno)); | |
2372 gftp_disconnect (request); | |
84 | 2373 return (GFTP_ERETRYABLE); |
58 | 2374 } |
2375 | |
2376 if (non_blocking) | |
2377 flags |= O_NONBLOCK; | |
2378 else | |
2379 flags &= ~O_NONBLOCK; | |
2380 | |
84 | 2381 if (fcntl (fd, F_SETFL, flags) < 0) |
58 | 2382 { |
186 | 2383 request->logging_function (gftp_logging_error, request, |
58 | 2384 _("Cannot set socket to non-blocking: %s\n"), |
2385 g_strerror (errno)); | |
2386 gftp_disconnect (request); | |
84 | 2387 return (GFTP_ERETRYABLE); |
58 | 2388 } |
2389 | |
2390 return (0); | |
2391 } | |
2392 | |
2393 | |
63 | 2394 void |
2395 gftp_swap_socks (gftp_request * dest, gftp_request * source) | |
2396 { | |
2397 g_return_if_fail (dest != NULL); | |
2398 g_return_if_fail (source != NULL); | |
2399 g_return_if_fail (dest->protonum == source->protonum); | |
2400 | |
2401 dest->datafd = source->datafd; | |
2402 dest->cached = 0; | |
2403 if (!source->always_connected) | |
2404 { | |
2405 source->datafd = -1; | |
2406 source->cached = 1; | |
2407 } | |
2408 | |
2409 if (dest->swap_socks) | |
2410 dest->swap_socks (dest, source); | |
2411 } | |
2412 | |
122 | 2413 |
2414 void | |
2415 gftp_calc_kbs (gftp_transfer * tdata, ssize_t num_read) | |
2416 { | |
2417 unsigned long waitusecs; | |
220 | 2418 double start_difftime; |
122 | 2419 gftp_file * tempfle; |
2420 struct timeval tv; | |
2421 float maxkbs; | |
222 | 2422 int waited; |
122 | 2423 |
2424 gftp_lookup_request_option (tdata->fromreq, "maxkbs", &maxkbs); | |
2425 | |
2426 if (g_thread_supported ()) | |
2427 g_static_mutex_lock (&tdata->statmutex); | |
2428 | |
220 | 2429 gettimeofday (&tv, NULL); |
2430 | |
122 | 2431 tempfle = tdata->curfle->data; |
2432 tdata->trans_bytes += num_read; | |
2433 tdata->curtrans += num_read; | |
2434 tdata->stalled = 0; | |
2435 | |
220 | 2436 start_difftime = (tv.tv_sec - tdata->starttime.tv_sec) + ((double) (tv.tv_usec - tdata->starttime.tv_usec) / 1000000.0); |
2437 | |
2438 if (start_difftime <= 0) | |
2439 tdata->kbs = tdata->trans_bytes / 1024.0; | |
122 | 2440 else |
220 | 2441 tdata->kbs = tdata->trans_bytes / 1024.0 / start_difftime; |
2442 | |
222 | 2443 waited = 0; |
220 | 2444 if (maxkbs > 0 && tdata->kbs > maxkbs) |
122 | 2445 { |
220 | 2446 waitusecs = num_read / 1024.0 / maxkbs * 1000000.0 - start_difftime; |
122 | 2447 |
2448 if (waitusecs > 0) | |
2449 { | |
2450 if (g_thread_supported ()) | |
2451 g_static_mutex_unlock (&tdata->statmutex); | |
2452 | |
222 | 2453 waited = 1; |
122 | 2454 usleep (waitusecs); |
2455 | |
2456 if (g_thread_supported ()) | |
2457 g_static_mutex_lock (&tdata->statmutex); | |
2458 } | |
222 | 2459 |
122 | 2460 } |
2461 | |
222 | 2462 if (waited) |
2463 gettimeofday (&tdata->lasttime, NULL); | |
2464 else | |
2465 memcpy (&tdata->lasttime, &tv, sizeof (tdata->lasttime)); | |
122 | 2466 |
2467 if (g_thread_supported ()) | |
2468 g_static_mutex_unlock (&tdata->statmutex); | |
2469 } | |
2470 | |
125 | 2471 |
2472 int | |
2473 gftp_get_transfer_status (gftp_transfer * tdata, ssize_t num_read) | |
2474 { | |
2475 int ret1, ret2, retries, sleep_time; | |
2476 gftp_file * tempfle; | |
2477 struct timeval tv; | |
2478 | |
2479 ret1 = ret2 = 0; | |
2480 gftp_lookup_request_option (tdata->fromreq, "retries", &retries); | |
2481 gftp_lookup_request_option (tdata->fromreq, "sleep_time", &sleep_time); | |
2482 | |
2483 if (g_thread_supported ()) | |
2484 g_static_mutex_lock (&tdata->structmutex); | |
2485 | |
2486 if (tdata->curfle == NULL) | |
2487 { | |
2488 if (g_thread_supported ()) | |
2489 g_static_mutex_unlock (&tdata->structmutex); | |
2490 | |
2491 return (GFTP_EFATAL); | |
2492 } | |
2493 | |
2494 tempfle = tdata->curfle->data; | |
2495 | |
2496 if (g_thread_supported ()) | |
2497 g_static_mutex_unlock (&tdata->structmutex); | |
2498 | |
2499 gftp_disconnect (tdata->fromreq); | |
2500 gftp_disconnect (tdata->toreq); | |
2501 | |
2502 if (num_read < 0 || tdata->skip_file) | |
2503 { | |
2504 if (num_read == GFTP_EFATAL) | |
2505 return (GFTP_EFATAL); | |
303 | 2506 else if (!tdata->conn_error_no_timeout) |
125 | 2507 { |
303 | 2508 if (retries != 0 && |
2509 tdata->current_file_retries >= retries) | |
2510 { | |
2511 tdata->fromreq->logging_function (gftp_logging_error, tdata->fromreq, | |
2512 _("Error: Remote site %s disconnected. Max retries reached...giving up\n"), | |
2513 tdata->fromreq->hostname != NULL ? | |
2514 tdata->fromreq->hostname : tdata->toreq->hostname); | |
2515 return (GFTP_EFATAL); | |
2516 } | |
2517 else | |
2518 { | |
2519 tdata->fromreq->logging_function (gftp_logging_error, tdata->fromreq, | |
2520 _("Error: Remote site %s disconnected. Will reconnect in %d seconds\n"), | |
2521 tdata->fromreq->hostname != NULL ? | |
2522 tdata->fromreq->hostname : tdata->toreq->hostname, | |
2523 sleep_time); | |
2524 } | |
125 | 2525 } |
2526 | |
2527 while (retries == 0 || | |
2528 tdata->current_file_retries <= retries) | |
2529 { | |
303 | 2530 if (!tdata->conn_error_no_timeout && !tdata->skip_file) |
125 | 2531 { |
2532 tv.tv_sec = sleep_time; | |
2533 tv.tv_usec = 0; | |
2534 select (0, NULL, NULL, NULL, &tv); | |
2535 } | |
303 | 2536 else |
2537 tdata->conn_error_no_timeout = 0; | |
125 | 2538 |
2539 if ((ret1 = gftp_connect (tdata->fromreq)) == 0 && | |
2540 (ret2 = gftp_connect (tdata->toreq)) == 0) | |
2541 { | |
2542 if (g_thread_supported ()) | |
2543 g_static_mutex_lock (&tdata->structmutex); | |
2544 | |
2545 tdata->resumed_bytes = tdata->resumed_bytes + tdata->trans_bytes - tdata->curresumed - tdata->curtrans; | |
2546 tdata->trans_bytes = 0; | |
2547 if (tdata->skip_file) | |
2548 { | |
2549 tdata->total_bytes -= tempfle->size; | |
2550 tdata->curtrans = 0; | |
2551 | |
2552 tdata->curfle = tdata->curfle->next; | |
2553 tdata->next_file = 1; | |
2554 tdata->skip_file = 0; | |
2555 tdata->cancel = 0; | |
2556 tdata->fromreq->cancel = 0; | |
2557 tdata->toreq->cancel = 0; | |
2558 } | |
2559 else | |
2560 { | |
2561 tempfle->transfer_action = GFTP_TRANS_ACTION_RESUME; | |
2562 tempfle->startsize = tdata->curtrans + tdata->curresumed; | |
2563 /* We decrement this here because it will be incremented in | |
2564 the loop again */ | |
2565 tdata->curresumed = 0; | |
2566 tdata->current_file_number--; /* Decrement this because it | |
2567 will be incremented when we | |
2568 continue in the loop */ | |
2569 } | |
2570 | |
2571 gettimeofday (&tdata->starttime, NULL); | |
2572 | |
2573 if (g_thread_supported ()) | |
2574 g_static_mutex_unlock (&tdata->structmutex); | |
2575 | |
2576 return (GFTP_ERETRYABLE); | |
2577 } | |
2578 else if (ret1 == GFTP_EFATAL || ret2 == GFTP_EFATAL) | |
2579 { | |
2580 gftp_disconnect (tdata->fromreq); | |
2581 gftp_disconnect (tdata->toreq); | |
2582 return (GFTP_EFATAL); | |
2583 } | |
2584 else | |
2585 tdata->current_file_retries++; | |
2586 } | |
2587 } | |
2588 else if (tdata->cancel) | |
2589 return (GFTP_EFATAL); | |
2590 | |
2591 return (0); | |
2592 } | |
2593 | |
182 | 2594 |
2595 int | |
2596 gftp_fd_open (gftp_request * request, const char *pathname, int flags, mode_t mode) | |
2597 { | |
2598 int fd; | |
2599 | |
227 | 2600 if (mode == 0) |
2601 fd = open (pathname, flags); | |
2602 else | |
2603 fd = open (pathname, flags, mode); | |
2604 | |
2605 if (fd < 0) | |
182 | 2606 { |
2607 if (request != NULL) | |
186 | 2608 request->logging_function (gftp_logging_error, request, |
182 | 2609 _("Error: Cannot open local file %s: %s\n"), |
2610 pathname, g_strerror (errno)); | |
2611 return (GFTP_ERETRYABLE); | |
2612 } | |
2613 | |
2614 if (fcntl (fd, F_SETFD, 1) == -1) | |
2615 { | |
2616 if (request != NULL) | |
186 | 2617 request->logging_function (gftp_logging_error, request, |
182 | 2618 _("Error: Cannot set close on exec flag: %s\n"), |
2619 g_strerror (errno)); | |
2620 | |
2621 return (-1); | |
2622 } | |
2623 | |
2624 return (fd); | |
2625 } |