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