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