1
|
1 /*****************************************************************************/
|
|
2 /* protocols.c - Skeleton functions for the protocols gftp supports */
|
885
|
3 /* Copyright (C) 1998-2007 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)
|
944
|
51 g_free (request->password);
|
1
|
52 if (request->account)
|
944
|
53 g_free (request->account);
|
1
|
54 if (request->directory)
|
|
55 g_free (request->directory);
|
|
56 if (request->last_ftp_response)
|
|
57 g_free (request->last_ftp_response);
|
|
58 if (request->protocol_data)
|
|
59 g_free (request->protocol_data);
|
67
|
60
|
944
|
61 #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
|
|
62 if (request->remote_addr != NULL)
|
|
63 g_free (request->remote_addr);
|
|
64 #endif
|
|
65
|
198
|
66 if (request->local_options_vars != NULL)
|
|
67 {
|
201
|
68 gftp_config_free_options (request->local_options_vars,
|
|
69 request->local_options_hash,
|
|
70 request->num_local_options_vars);
|
198
|
71 }
|
|
72
|
1
|
73 memset (request, 0, sizeof (*request));
|
67
|
74
|
|
75 if (free_request)
|
|
76 g_free (request);
|
|
77 else
|
|
78 {
|
|
79 request->datafd = -1;
|
|
80 request->cachefd = -1;
|
924
|
81 request->server_type = GFTP_DIRTYPE_OTHER;
|
67
|
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
|
598
|
103 gftp_file_destroy (gftp_file * file, int free_it)
|
1
|
104 {
|
|
105 g_return_if_fail (file != NULL);
|
|
106
|
|
107 if (file->file)
|
|
108 g_free (file->file);
|
|
109 if (file->user)
|
|
110 g_free (file->user);
|
|
111 if (file->group)
|
|
112 g_free (file->group);
|
|
113 if (file->destfile)
|
|
114 g_free (file->destfile);
|
598
|
115
|
|
116 if (free_it)
|
|
117 g_free (file);
|
|
118 else
|
|
119 memset (file, 0, sizeof (*file));
|
1
|
120 }
|
|
121
|
|
122
|
|
123 int
|
|
124 gftp_connect (gftp_request * request)
|
|
125 {
|
177
|
126 int ret;
|
|
127
|
84
|
128 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
1
|
129
|
|
130 if (request->connect == NULL)
|
84
|
131 return (GFTP_EFATAL);
|
1
|
132
|
177
|
133 if ((ret = gftp_set_config_options (request)) < 0)
|
|
134 return (ret);
|
1
|
135
|
|
136 return (request->connect (request));
|
|
137 }
|
|
138
|
|
139
|
|
140 void
|
|
141 gftp_disconnect (gftp_request * request)
|
|
142 {
|
|
143 g_return_if_fail (request != NULL);
|
|
144
|
168
|
145 #ifdef USE_SSL
|
|
146 if (request->ssl != NULL)
|
|
147 {
|
|
148 SSL_free (request->ssl);
|
|
149 request->ssl = NULL;
|
|
150 }
|
|
151 #endif
|
|
152
|
187
|
153 #if GLIB_MAJOR_VERSION > 1
|
899
|
154 if (request->iconv_from_initialized)
|
|
155 {
|
|
156 g_iconv_close (request->iconv_from);
|
|
157 request->iconv_from_initialized = 0;
|
|
158 }
|
|
159
|
|
160 if (request->iconv_to_initialized)
|
187
|
161 {
|
899
|
162 g_iconv_close (request->iconv_to);
|
|
163 request->iconv_to_initialized = 0;
|
187
|
164 }
|
899
|
165
|
|
166 if (request->iconv_charset)
|
|
167 {
|
|
168 g_free (request->iconv_charset);
|
|
169 request->iconv_charset = NULL;
|
|
170 }
|
187
|
171 #endif
|
|
172
|
1
|
173 request->cached = 0;
|
|
174 if (request->disconnect == NULL)
|
|
175 return;
|
|
176 request->disconnect (request);
|
|
177 }
|
|
178
|
|
179
|
58
|
180 off_t
|
895
|
181 gftp_get_file (gftp_request * request, const char *filename,
|
244
|
182 off_t startsize)
|
1
|
183 {
|
84
|
184 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
1
|
185
|
|
186 request->cached = 0;
|
|
187 if (request->get_file == NULL)
|
84
|
188 return (GFTP_EFATAL);
|
244
|
189
|
895
|
190 return (request->get_file (request, filename, startsize));
|
1
|
191 }
|
|
192
|
|
193
|
|
194 int
|
895
|
195 gftp_put_file (gftp_request * request, const char *filename,
|
244
|
196 off_t startsize, off_t totalsize)
|
1
|
197 {
|
84
|
198 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
1
|
199
|
|
200 request->cached = 0;
|
|
201 if (request->put_file == NULL)
|
84
|
202 return (GFTP_EFATAL);
|
566
|
203
|
895
|
204 return (request->put_file (request, filename, startsize, totalsize));
|
1
|
205 }
|
|
206
|
|
207
|
261
|
208 off_t
|
1
|
209 gftp_transfer_file (gftp_request * fromreq, const char *fromfile,
|
895
|
210 off_t fromsize, gftp_request * toreq, const char *tofile,
|
|
211 off_t tosize)
|
1
|
212 {
|
469
|
213 /* Needed for systems that size(float) < size(void *) */
|
|
214 union { intptr_t i; float f; } maxkbs;
|
261
|
215 off_t size;
|
84
|
216 int ret;
|
1
|
217
|
84
|
218 g_return_val_if_fail (fromreq != NULL, GFTP_EFATAL);
|
|
219 g_return_val_if_fail (fromfile != NULL, GFTP_EFATAL);
|
|
220 g_return_val_if_fail (toreq != NULL, GFTP_EFATAL);
|
|
221 g_return_val_if_fail (tofile != NULL, GFTP_EFATAL);
|
|
222
|
469
|
223 gftp_lookup_request_option (toreq, "maxkbs", &maxkbs.f);
|
|
224
|
|
225 if (maxkbs.f > 0)
|
294
|
226 {
|
|
227 toreq->logging_function (gftp_logging_misc, toreq,
|
|
228 _("File transfer will be throttled to %.2f KB/s\n"),
|
469
|
229 maxkbs.f);
|
294
|
230 }
|
|
231
|
87
|
232 if (fromreq->protonum == toreq->protonum &&
|
84
|
233 fromreq->transfer_file != NULL)
|
|
234 return (fromreq->transfer_file (fromreq, fromfile, fromsize, toreq,
|
|
235 tofile, tosize));
|
1
|
236
|
|
237 fromreq->cached = 0;
|
|
238 toreq->cached = 0;
|
443
|
239
|
|
240 get_file:
|
895
|
241 size = gftp_get_file (fromreq, fromfile, tosize);
|
443
|
242 if (size < 0)
|
1
|
243 {
|
443
|
244 if (size == GFTP_ETIMEDOUT)
|
|
245 {
|
|
246 ret = gftp_connect (fromreq);
|
|
247 if (ret < 0)
|
|
248 return (ret);
|
|
249
|
|
250 goto get_file;
|
|
251 }
|
|
252
|
|
253 return (size);
|
|
254 }
|
|
255
|
|
256 put_file:
|
895
|
257 ret = gftp_put_file (toreq, tofile, tosize, size);
|
443
|
258 if (ret != 0)
|
|
259 {
|
|
260 if (size == GFTP_ETIMEDOUT)
|
|
261 {
|
|
262 ret = gftp_connect (fromreq);
|
|
263 if (ret < 0)
|
|
264 return (ret);
|
|
265
|
|
266 goto put_file;
|
|
267 }
|
|
268
|
40
|
269 if (gftp_abort_transfer (fromreq) != 0)
|
|
270 gftp_end_transfer (fromreq);
|
|
271
|
84
|
272 return (ret);
|
1
|
273 }
|
|
274
|
|
275 return (size);
|
|
276 }
|
|
277
|
|
278
|
58
|
279 ssize_t
|
1
|
280 gftp_get_next_file_chunk (gftp_request * request, char *buf, size_t size)
|
|
281 {
|
84
|
282 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
283 g_return_val_if_fail (buf != NULL, GFTP_EFATAL);
|
1
|
284
|
|
285 if (request->get_next_file_chunk != NULL)
|
|
286 return (request->get_next_file_chunk (request, buf, size));
|
|
287
|
168
|
288 return (request->read_function (request, buf, size, request->datafd));
|
1
|
289 }
|
|
290
|
|
291
|
58
|
292 ssize_t
|
1
|
293 gftp_put_next_file_chunk (gftp_request * request, char *buf, size_t size)
|
|
294 {
|
84
|
295 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
296 g_return_val_if_fail (buf != NULL, GFTP_EFATAL);
|
1
|
297
|
|
298 if (request->put_next_file_chunk != NULL)
|
|
299 return (request->put_next_file_chunk (request, buf, size));
|
|
300
|
168
|
301 return (request->write_function (request, buf, size, request->datafd));
|
1
|
302 }
|
|
303
|
|
304
|
|
305 int
|
|
306 gftp_end_transfer (gftp_request * request)
|
|
307 {
|
|
308 int ret;
|
|
309
|
84
|
310 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
1
|
311
|
40
|
312 if (!request->cached &&
|
|
313 request->end_transfer != NULL)
|
|
314 ret = request->end_transfer (request);
|
|
315 else
|
|
316 ret = 0;
|
1
|
317
|
58
|
318 if (request->cachefd > 0)
|
1
|
319 {
|
58
|
320 close (request->cachefd);
|
|
321 request->cachefd = -1;
|
1
|
322 }
|
|
323
|
|
324 if (request->last_dir_entry)
|
|
325 {
|
|
326 g_free (request->last_dir_entry);
|
|
327 request->last_dir_entry = NULL;
|
|
328 request->last_dir_entry_len = 0;
|
|
329 }
|
|
330
|
|
331 return (ret);
|
|
332 }
|
|
333
|
|
334
|
|
335 int
|
40
|
336 gftp_abort_transfer (gftp_request * request)
|
|
337 {
|
84
|
338 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
40
|
339
|
|
340 if (request->abort_transfer == NULL)
|
84
|
341 return (GFTP_EFATAL);
|
40
|
342
|
813
|
343 /* FIXME - end the transfer if it is not successful */
|
40
|
344 return (request->abort_transfer (request));
|
|
345 }
|
|
346
|
|
347
|
520
|
348 int
|
787
|
349 gftp_stat_filename (gftp_request * request, const char *filename, mode_t * mode,
|
|
350 off_t * filesize)
|
500
|
351 {
|
|
352 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
520
|
353 g_return_val_if_fail (filename != NULL, GFTP_EFATAL);
|
500
|
354
|
|
355 if (request->stat_filename != NULL)
|
787
|
356 return (request->stat_filename (request, filename, mode, filesize));
|
500
|
357 else
|
520
|
358 return (0);
|
500
|
359 }
|
|
360
|
|
361
|
40
|
362 int
|
1
|
363 gftp_list_files (gftp_request * request)
|
|
364 {
|
473
|
365 char *remote_lc_time, *locret;
|
58
|
366 int fd;
|
1
|
367
|
84
|
368 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
1
|
369
|
623
|
370 #if ENABLE_NLS
|
473
|
371 gftp_lookup_request_option (request, "remote_lc_time", &remote_lc_time);
|
|
372 if (remote_lc_time != NULL && *remote_lc_time != '\0')
|
|
373 locret = setlocale (LC_TIME, remote_lc_time);
|
|
374 else
|
|
375 locret = setlocale (LC_TIME, NULL);
|
|
376
|
|
377 if (locret == NULL)
|
|
378 {
|
|
379 locret = setlocale (LC_TIME, NULL);
|
677
|
380 request->logging_function (gftp_logging_error, request,
|
473
|
381 _("Error setting LC_TIME to '%s'. Falling back to '%s'\n"),
|
|
382 remote_lc_time, locret);
|
|
383 }
|
623
|
384 #else
|
|
385 locret = _("<unknown>");
|
|
386 #endif
|
473
|
387
|
1
|
388 request->cached = 0;
|
58
|
389 if (request->use_cache && (fd = gftp_find_cache_entry (request)) > 0)
|
1
|
390 {
|
186
|
391 request->logging_function (gftp_logging_misc, request,
|
473
|
392 _("Loading directory listing %s from cache (LC_TIME=%s)\n"),
|
|
393 request->directory, locret);
|
1
|
394
|
|
395 request->cachefd = fd;
|
|
396 request->cached = 1;
|
|
397 return (0);
|
|
398 }
|
|
399 else if (request->use_cache)
|
|
400 {
|
473
|
401 request->logging_function (gftp_logging_misc, request,
|
|
402 _("Loading directory listing %s from server (LC_TIME=%s)\n"),
|
|
403 request->directory, locret);
|
|
404
|
1
|
405 request->cachefd = gftp_new_cache_entry (request);
|
|
406 request->cached = 0;
|
|
407 }
|
|
408
|
|
409 if (request->list_files == NULL)
|
84
|
410 return (GFTP_EFATAL);
|
473
|
411
|
1
|
412 return (request->list_files (request));
|
|
413 }
|
|
414
|
|
415
|
|
416 int
|
377
|
417 gftp_get_next_file (gftp_request * request, const char *filespec,
|
|
418 gftp_file * fle)
|
1
|
419 {
|
830
|
420 char *slashpos, *tmpfile, *utf8;
|
838
|
421 size_t destlen;
|
58
|
422 int fd, ret;
|
1
|
423
|
84
|
424 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
1
|
425
|
|
426 if (request->get_next_file == NULL)
|
84
|
427 return (GFTP_EFATAL);
|
1
|
428
|
58
|
429 if (request->cached && request->cachefd > 0)
|
1
|
430 fd = request->cachefd;
|
|
431 else
|
|
432 fd = request->datafd;
|
|
433
|
|
434 memset (fle, 0, sizeof (*fle));
|
|
435 do
|
|
436 {
|
598
|
437 gftp_file_destroy (fle, 0);
|
1
|
438 ret = request->get_next_file (request, fle, fd);
|
666
|
439 if (fle->file != NULL && (slashpos = strrchr (fle->file, '/')) != NULL)
|
|
440 {
|
|
441 if (*(slashpos + 1) == '\0')
|
|
442 {
|
|
443 gftp_file_destroy (fle, 0);
|
|
444 continue;
|
|
445 }
|
|
446
|
|
447 *slashpos = '\0';
|
830
|
448 tmpfile = g_strdup (slashpos + 1);
|
666
|
449
|
|
450 if (strcmp (fle->file, request->directory) != 0)
|
|
451 request->logging_function (gftp_logging_error, request,
|
|
452 _("Warning: Stripping path off of file '%s'. The stripped path (%s) doesn't match the current directory (%s)\n"),
|
830
|
453 tmpfile, fle->file, request->directory,
|
666
|
454 g_strerror (errno));
|
|
455
|
|
456 g_free (fle->file);
|
830
|
457 fle->file = tmpfile;
|
666
|
458 }
|
1
|
459
|
291
|
460 if (ret >= 0 && fle->file != NULL)
|
830
|
461 {
|
916
|
462 if (g_utf8_validate (fle->file, -1, NULL))
|
|
463 fle->filename_utf8_encoded = 1;
|
|
464 else
|
830
|
465 {
|
916
|
466 utf8 = gftp_filename_to_utf8 (request, fle->file, &destlen);
|
|
467 if (utf8 != NULL)
|
|
468 {
|
|
469 g_free (fle->file);
|
|
470 fle->file = utf8;
|
|
471 fle->filename_utf8_encoded = 1;
|
|
472 }
|
830
|
473 }
|
|
474 }
|
45
|
475
|
60
|
476 if (ret >= 0 && !request->cached && request->cachefd > 0 &&
|
1
|
477 request->last_dir_entry != NULL)
|
|
478 {
|
168
|
479 if (gftp_fd_write (request, request->last_dir_entry,
|
60
|
480 request->last_dir_entry_len, request->cachefd) < 0)
|
1
|
481 {
|
186
|
482 request->logging_function (gftp_logging_error, request,
|
1
|
483 _("Error: Cannot write to cache: %s\n"),
|
|
484 g_strerror (errno));
|
60
|
485 close (request->cachefd);
|
|
486 request->cachefd = -1;
|
1
|
487 }
|
|
488 }
|
821
|
489 } while (ret > 0 && !gftp_match_filespec (request, fle->file, filespec));
|
1
|
490
|
|
491 return (ret);
|
|
492 }
|
|
493
|
|
494
|
|
495 int
|
243
|
496 gftp_parse_bookmark (gftp_request * request, gftp_request * local_request,
|
275
|
497 const char * bookmark, int *refresh_local)
|
87
|
498 {
|
|
499 gftp_logging_func logging_function;
|
122
|
500 gftp_bookmarks_var * tempentry;
|
838
|
501 char *default_protocol;
|
646
|
502 const char *email;
|
173
|
503 int i, init_ret;
|
87
|
504
|
|
505 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
506 g_return_val_if_fail (bookmark != NULL, GFTP_EFATAL);
|
|
507
|
|
508 logging_function = request->logging_function;
|
|
509 gftp_request_destroy (request, 0);
|
|
510 request->logging_function = logging_function;
|
|
511
|
122
|
512 if ((tempentry = g_hash_table_lookup (gftp_bookmarks_htable,
|
|
513 bookmark)) == NULL)
|
87
|
514 {
|
186
|
515 request->logging_function (gftp_logging_error, request,
|
87
|
516 _("Error: Could not find bookmark %s\n"),
|
|
517 bookmark);
|
|
518 return (GFTP_EFATAL);
|
|
519 }
|
|
520 else if (tempentry->hostname == NULL || *tempentry->hostname == '\0')
|
|
521 {
|
186
|
522 request->logging_function (gftp_logging_error, request,
|
87
|
523 _("Bookmarks Error: The bookmark entry %s does not have a hostname\n"), bookmark);
|
|
524 return (GFTP_EFATAL);
|
|
525 }
|
|
526
|
|
527 if (tempentry->user != NULL)
|
|
528 gftp_set_username (request, tempentry->user);
|
|
529
|
|
530 if (tempentry->pass != NULL)
|
646
|
531 {
|
|
532 if (strcmp (tempentry->pass, "@EMAIL@") == 0)
|
|
533 {
|
|
534 gftp_lookup_request_option (request, "email", &email);
|
|
535 gftp_set_password (request, email);
|
|
536 }
|
|
537 else
|
|
538 gftp_set_password (request, tempentry->pass);
|
|
539 }
|
87
|
540
|
|
541 if (tempentry->acct != NULL)
|
|
542 gftp_set_account (request, tempentry->acct);
|
|
543
|
|
544 gftp_set_hostname (request, tempentry->hostname);
|
838
|
545 gftp_set_directory (request, tempentry->remote_dir);
|
87
|
546 gftp_set_port (request, tempentry->port);
|
|
547
|
516
|
548 if (local_request != NULL && tempentry->local_dir != NULL &&
|
243
|
549 *tempentry->local_dir != '\0')
|
275
|
550 {
|
838
|
551 gftp_set_directory (local_request, tempentry->local_dir);
|
516
|
552 if (refresh_local != NULL)
|
|
553 *refresh_local = 1;
|
275
|
554 }
|
516
|
555 else if (refresh_local != NULL)
|
275
|
556 *refresh_local = 0;
|
243
|
557
|
87
|
558 for (i = 0; gftp_protocols[i].name; i++)
|
|
559 {
|
|
560 if (strcmp (gftp_protocols[i].name, tempentry->protocol) == 0)
|
|
561 {
|
173
|
562 if ((init_ret = gftp_protocols[i].init (request)) < 0)
|
|
563 {
|
|
564 gftp_request_destroy (request, 0);
|
|
565 return (init_ret);
|
|
566 }
|
87
|
567 break;
|
|
568 }
|
|
569 }
|
|
570
|
122
|
571 if (gftp_protocols[i].name == NULL)
|
87
|
572 {
|
122
|
573 gftp_lookup_request_option (request, "default_protocol",
|
|
574 &default_protocol);
|
|
575
|
125
|
576 if (default_protocol != NULL && *default_protocol != '\0')
|
87
|
577 {
|
122
|
578 for (i = 0; gftp_protocols[i].url_prefix; i++)
|
|
579 {
|
|
580 if (strcmp (gftp_protocols[i].name, default_protocol) == 0)
|
|
581 break;
|
|
582 }
|
87
|
583 }
|
|
584
|
|
585 if (gftp_protocols[i].url_prefix == NULL)
|
|
586 i = GFTP_FTP_NUM;
|
|
587 }
|
|
588
|
199
|
589 gftp_copy_local_options (&request->local_options_vars,
|
|
590 &request->local_options_hash,
|
429
|
591 &request->num_local_options_vars,
|
199
|
592 tempentry->local_options_vars,
|
|
593 tempentry->num_local_options_vars);
|
|
594
|
173
|
595 if ((init_ret = gftp_protocols[i].init (request)) < 0)
|
|
596 {
|
|
597 gftp_request_destroy (request, 0);
|
|
598 return (init_ret);
|
|
599 }
|
|
600
|
87
|
601 return (0);
|
|
602 }
|
|
603
|
|
604
|
|
605 int
|
1
|
606 gftp_parse_url (gftp_request * request, const char *url)
|
|
607 {
|
676
|
608 char *pos, *endpos, *default_protocol, *new_url;
|
67
|
609 gftp_logging_func logging_function;
|
676
|
610 const char *clear_pos;
|
|
611 int i, ret;
|
1
|
612
|
84
|
613 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
614 g_return_val_if_fail (url != NULL, GFTP_EFATAL);
|
1
|
615
|
67
|
616 logging_function = request->logging_function;
|
|
617 gftp_request_destroy (request, 0);
|
|
618 request->logging_function = logging_function;
|
|
619
|
676
|
620 for (clear_pos = url;
|
|
621 *clear_pos == ' ' || *clear_pos == '\t';
|
|
622 clear_pos++);
|
|
623
|
|
624 new_url = g_strdup (clear_pos);
|
|
625
|
|
626 for (pos = new_url + strlen (new_url) - 1;
|
|
627 *pos == ' ' || *pos == '\t';
|
|
628 pos--)
|
168
|
629 *pos = '\0';
|
1
|
630
|
676
|
631 /* See if the URL has a protocol... */
|
|
632 if ((pos = strstr (new_url, "://")) != NULL)
|
1
|
633 {
|
|
634 *pos = '\0';
|
|
635
|
|
636 for (i = 0; gftp_protocols[i].url_prefix; i++)
|
|
637 {
|
676
|
638 if (strcmp (gftp_protocols[i].url_prefix, new_url) == 0)
|
1
|
639 break;
|
|
640 }
|
|
641
|
|
642 if (gftp_protocols[i].url_prefix == NULL)
|
168
|
643 {
|
677
|
644 request->logging_function (gftp_logging_error, NULL,
|
173
|
645 _("The protocol '%s' is currently not supported.\n"),
|
676
|
646 new_url);
|
|
647 g_free (new_url);
|
168
|
648 return (GFTP_EFATAL);
|
|
649 }
|
173
|
650
|
|
651 *pos = ':';
|
676
|
652 pos += 3;
|
1
|
653 }
|
|
654 else
|
|
655 {
|
122
|
656 gftp_lookup_request_option (request, "default_protocol",
|
|
657 &default_protocol);
|
|
658
|
676
|
659 i = GFTP_FTP_NUM;
|
125
|
660 if (default_protocol != NULL && *default_protocol != '\0')
|
1
|
661 {
|
122
|
662 for (i = 0; gftp_protocols[i].url_prefix; i++)
|
|
663 {
|
|
664 if (strcmp (gftp_protocols[i].name, default_protocol) == 0)
|
|
665 break;
|
|
666 }
|
1
|
667 }
|
676
|
668
|
|
669 if (gftp_protocols[i].url_prefix == NULL)
|
|
670 {
|
677
|
671 request->logging_function (gftp_logging_error, NULL,
|
676
|
672 _("The protocol '%s' is currently not supported.\n"),
|
|
673 default_protocol);
|
|
674 g_free (new_url);
|
|
675 return (GFTP_EFATAL);
|
|
676 }
|
|
677
|
|
678 pos = new_url;
|
122
|
679 }
|
1
|
680
|
676
|
681 if ((ret = gftp_protocols[i].init (request)) < 0)
|
173
|
682 {
|
|
683 gftp_request_destroy (request, 0);
|
676
|
684 return (ret);
|
|
685 }
|
|
686
|
|
687 if ((endpos = strchr (pos, '/')) != NULL)
|
|
688 {
|
|
689 gftp_set_directory (request, endpos);
|
|
690 *endpos = '\0';
|
173
|
691 }
|
1
|
692
|
|
693 if (request->parse_url != NULL)
|
168
|
694 {
|
676
|
695 ret = request->parse_url (request, new_url);
|
|
696 g_free (new_url);
|
|
697 return (ret);
|
168
|
698 }
|
|
699
|
676
|
700 if (*pos != '\0')
|
1
|
701 {
|
676
|
702 if (endpos == NULL)
|
|
703 endpos = pos + strlen (pos) - 1;
|
|
704 else
|
|
705 endpos--;
|
|
706
|
|
707 for (; isdigit (*endpos); endpos--);
|
|
708
|
|
709 if (*endpos == ':' && isdigit (*(endpos + 1)))
|
168
|
710 {
|
676
|
711 gftp_set_port (request, strtol (endpos + 1, NULL, 10));
|
|
712 *endpos = '\0';
|
168
|
713 }
|
1
|
714
|
676
|
715 if ((endpos = strrchr (pos, '@')) != NULL)
|
168
|
716 {
|
676
|
717 gftp_set_hostname (request, endpos + 1);
|
168
|
718 *endpos = '\0';
|
676
|
719
|
|
720 if ((endpos = strchr (pos, ':')) != NULL)
|
|
721 {
|
|
722 *endpos = '\0';
|
|
723 gftp_set_username (request, pos);
|
|
724 gftp_set_password (request, endpos + 1);
|
|
725 }
|
|
726 else
|
|
727 {
|
|
728 gftp_set_username (request, pos);
|
|
729 gftp_set_password (request, "");
|
|
730 }
|
168
|
731 }
|
676
|
732 else
|
|
733 gftp_set_hostname (request, pos);
|
1
|
734 }
|
|
735
|
676
|
736 g_free (new_url);
|
1
|
737 return (0);
|
|
738 }
|
|
739
|
|
740
|
|
741 void
|
|
742 gftp_set_hostname (gftp_request * request, const char *hostname)
|
|
743 {
|
|
744 g_return_if_fail (request != NULL);
|
|
745 g_return_if_fail (hostname != NULL);
|
|
746
|
|
747 if (request->hostname)
|
|
748 g_free (request->hostname);
|
124
|
749 request->hostname = g_strdup (hostname);
|
1
|
750 }
|
|
751
|
|
752
|
|
753 void
|
|
754 gftp_set_username (gftp_request * request, const char *username)
|
|
755 {
|
|
756 g_return_if_fail (request != NULL);
|
|
757
|
|
758 if (request->username)
|
|
759 g_free (request->username);
|
169
|
760
|
|
761 if (username != NULL)
|
|
762 request->username = g_strdup (username);
|
|
763 else
|
|
764 request->username = NULL;
|
1
|
765 }
|
|
766
|
|
767
|
|
768 void
|
|
769 gftp_set_password (gftp_request * request, const char *password)
|
|
770 {
|
|
771 g_return_if_fail (request != NULL);
|
|
772
|
|
773 if (request->password)
|
|
774 g_free (request->password);
|
169
|
775
|
|
776 if (password != NULL)
|
|
777 request->password = g_strdup (password);
|
|
778 else
|
|
779 request->password = NULL;
|
1
|
780 }
|
|
781
|
|
782
|
|
783 void
|
|
784 gftp_set_account (gftp_request * request, const char *account)
|
|
785 {
|
|
786 g_return_if_fail (request != NULL);
|
|
787 g_return_if_fail (account != NULL);
|
|
788
|
|
789 if (request->account)
|
|
790 g_free (request->account);
|
124
|
791 request->account = g_strdup (account);
|
1
|
792 }
|
|
793
|
|
794
|
|
795 int
|
|
796 gftp_set_directory (gftp_request * request, const char *directory)
|
|
797 {
|
84
|
798 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
799 g_return_val_if_fail (directory != NULL, GFTP_EFATAL);
|
1
|
800
|
|
801
|
169
|
802 if (request->datafd <= 0 && !request->always_connected)
|
1
|
803 {
|
|
804 if (directory != request->directory)
|
168
|
805 {
|
|
806 if (request->directory)
|
|
807 g_free (request->directory);
|
|
808 request->directory = g_strdup (directory);
|
|
809 }
|
1
|
810 return (0);
|
|
811 }
|
|
812 else if (request->chdir == NULL)
|
84
|
813 return (GFTP_EFATAL);
|
1
|
814 return (request->chdir (request, directory));
|
|
815 }
|
|
816
|
|
817
|
|
818 void
|
|
819 gftp_set_port (gftp_request * request, unsigned int port)
|
|
820 {
|
|
821 g_return_if_fail (request != NULL);
|
|
822
|
|
823 request->port = port;
|
|
824 }
|
|
825
|
|
826
|
|
827 int
|
|
828 gftp_remove_directory (gftp_request * request, const char *directory)
|
|
829 {
|
84
|
830 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
1
|
831
|
|
832 if (request->rmdir == NULL)
|
84
|
833 return (GFTP_EFATAL);
|
1
|
834 return (request->rmdir (request, directory));
|
|
835 }
|
|
836
|
|
837
|
|
838 int
|
|
839 gftp_remove_file (gftp_request * request, const char *file)
|
|
840 {
|
84
|
841 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
1
|
842
|
|
843 if (request->rmfile == NULL)
|
84
|
844 return (GFTP_EFATAL);
|
1
|
845 return (request->rmfile (request, file));
|
|
846 }
|
|
847
|
|
848
|
|
849 int
|
|
850 gftp_make_directory (gftp_request * request, const char *directory)
|
|
851 {
|
84
|
852 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
1
|
853
|
|
854 if (request->mkdir == NULL)
|
84
|
855 return (GFTP_EFATAL);
|
291
|
856
|
838
|
857 return (request->mkdir (request, directory));
|
1
|
858 }
|
|
859
|
|
860
|
|
861 int
|
|
862 gftp_rename_file (gftp_request * request, const char *oldname,
|
168
|
863 const char *newname)
|
1
|
864 {
|
84
|
865 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
1
|
866
|
|
867 if (request->rename == NULL)
|
84
|
868 return (GFTP_EFATAL);
|
291
|
869
|
838
|
870 return (request->rename (request, oldname, newname));
|
1
|
871 }
|
|
872
|
|
873
|
|
874 int
|
499
|
875 gftp_chmod (gftp_request * request, const char *file, mode_t mode)
|
1
|
876 {
|
84
|
877 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
1
|
878
|
|
879 if (request->chmod == NULL)
|
84
|
880 return (GFTP_EFATAL);
|
504
|
881
|
|
882 mode &= S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX;
|
1
|
883 return (request->chmod (request, file, mode));
|
|
884 }
|
|
885
|
|
886
|
|
887 int
|
|
888 gftp_set_file_time (gftp_request * request, const char *file, time_t datetime)
|
|
889 {
|
84
|
890 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
1
|
891
|
|
892 if (request->set_file_time == NULL)
|
84
|
893 return (GFTP_EFATAL);
|
1
|
894 return (request->set_file_time (request, file, datetime));
|
|
895 }
|
|
896
|
|
897
|
765
|
898 int
|
478
|
899 gftp_site_cmd (gftp_request * request, int specify_site, const char *command)
|
1
|
900 {
|
84
|
901 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
1
|
902
|
|
903 if (request->site == NULL)
|
84
|
904 return (GFTP_EFATAL);
|
478
|
905 return (request->site (request, specify_site, command));
|
1
|
906 }
|
|
907
|
|
908
|
58
|
909 off_t
|
1
|
910 gftp_get_file_size (gftp_request * request, const char *filename)
|
|
911 {
|
|
912 g_return_val_if_fail (request != NULL, 0);
|
|
913
|
|
914 if (request->get_file_size == NULL)
|
|
915 return (0);
|
|
916 return (request->get_file_size (request, filename));
|
|
917 }
|
|
918
|
|
919
|
48
|
920 static GHashTable *
|
469
|
921 gftp_gen_dir_hash (gftp_request * request, int *ret)
|
1
|
922 {
|
48
|
923 GHashTable * dirhash;
|
|
924 gftp_file * fle;
|
516
|
925 off_t *newsize;
|
48
|
926
|
851
|
927 dirhash = g_hash_table_new (string_hash_function, string_hash_compare);
|
850
|
928 *ret = gftp_list_files (request);
|
851
|
929 if (*ret == 0)
|
48
|
930 {
|
851
|
931 fle = g_malloc0 (sizeof (*fle));
|
|
932 while (gftp_get_next_file (request, NULL, fle) > 0)
|
48
|
933 {
|
944
|
934 newsize = g_malloc0 (sizeof (*newsize));
|
851
|
935 *newsize = fle->size;
|
|
936 g_hash_table_insert (dirhash, fle->file, newsize);
|
|
937 fle->file = NULL;
|
598
|
938 gftp_file_destroy (fle, 0);
|
48
|
939 }
|
851
|
940 gftp_end_transfer (request);
|
|
941 g_free (fle);
|
48
|
942 }
|
851
|
943 else
|
|
944 {
|
|
945 g_hash_table_destroy (dirhash);
|
|
946 dirhash = NULL;
|
|
947 }
|
509
|
948
|
48
|
949 return (dirhash);
|
|
950 }
|
39
|
951
|
48
|
952
|
|
953 static void
|
|
954 destroy_hash_ent (gpointer key, gpointer value, gpointer user_data)
|
|
955 {
|
39
|
956
|
48
|
957 g_free (key);
|
|
958 g_free (value);
|
|
959 }
|
|
960
|
|
961
|
|
962 static void
|
|
963 gftp_destroy_dir_hash (GHashTable * dirhash)
|
|
964 {
|
787
|
965 if (dirhash == NULL)
|
|
966 return;
|
|
967
|
48
|
968 g_hash_table_foreach (dirhash, destroy_hash_ent, NULL);
|
|
969 g_hash_table_destroy (dirhash);
|
1
|
970 }
|
|
971
|
|
972
|
|
973 static GList *
|
469
|
974 gftp_get_dir_listing (gftp_transfer * transfer, int getothdir, int *ret)
|
1
|
975 {
|
|
976 GHashTable * dirhash;
|
|
977 GList * templist;
|
|
978 gftp_file * fle;
|
516
|
979 off_t *newsize;
|
1
|
980 char *newname;
|
|
981
|
787
|
982 if (getothdir && transfer->toreq != NULL)
|
469
|
983 {
|
|
984 dirhash = gftp_gen_dir_hash (transfer->toreq, ret);
|
787
|
985 if (*ret == GFTP_EFATAL)
|
469
|
986 return (NULL);
|
|
987 }
|
1
|
988 else
|
|
989 dirhash = NULL;
|
|
990
|
509
|
991 *ret = gftp_list_files (transfer->fromreq);
|
|
992 if (*ret < 0)
|
787
|
993 {
|
|
994 gftp_destroy_dir_hash (dirhash);
|
|
995 return (NULL);
|
|
996 }
|
1
|
997
|
944
|
998 fle = g_malloc0 (sizeof (*fle));
|
1
|
999 templist = NULL;
|
|
1000 while (gftp_get_next_file (transfer->fromreq, NULL, fle) > 0)
|
|
1001 {
|
851
|
1002 if (strcmp (fle->file, ".") == 0 || strcmp (fle->file, "..") == 0)
|
1
|
1003 {
|
598
|
1004 gftp_file_destroy (fle, 0);
|
1
|
1005 continue;
|
|
1006 }
|
|
1007
|
|
1008 if (dirhash &&
|
|
1009 (newsize = g_hash_table_lookup (dirhash, fle->file)) != NULL)
|
787
|
1010 {
|
|
1011 fle->exists_other_side = 1;
|
|
1012 fle->startsize = *newsize;
|
|
1013 }
|
|
1014 else
|
|
1015 fle->exists_other_side = 0;
|
1
|
1016
|
381
|
1017 if (transfer->toreq && fle->destfile == NULL)
|
555
|
1018 fle->destfile = gftp_build_path (transfer->toreq,
|
|
1019 transfer->toreq->directory,
|
245
|
1020 fle->file, NULL);
|
|
1021
|
381
|
1022 if (transfer->fromreq->directory != NULL &&
|
|
1023 *transfer->fromreq->directory != '\0' &&
|
|
1024 *fle->file != '/')
|
|
1025 {
|
555
|
1026 newname = gftp_build_path (transfer->fromreq,
|
|
1027 transfer->fromreq->directory,
|
381
|
1028 fle->file, NULL);
|
|
1029
|
|
1030 g_free (fle->file);
|
|
1031 fle->file = newname;
|
|
1032 }
|
1
|
1033
|
|
1034 templist = g_list_append (templist, fle);
|
|
1035
|
787
|
1036 fle = g_malloc0 (sizeof (*fle));
|
1
|
1037 }
|
|
1038 gftp_end_transfer (transfer->fromreq);
|
|
1039
|
598
|
1040 gftp_file_destroy (fle, 1);
|
787
|
1041 gftp_destroy_dir_hash (dirhash);
|
1
|
1042
|
|
1043 return (templist);
|
|
1044 }
|
|
1045
|
|
1046
|
787
|
1047 static void
|
|
1048 _cleanup_get_all_subdirs (gftp_transfer * transfer, char *oldfromdir,
|
|
1049 char *oldtodir,
|
|
1050 void (*update_func) (gftp_transfer * transfer))
|
1
|
1051 {
|
787
|
1052 if (update_func != NULL)
|
|
1053 {
|
|
1054 transfer->numfiles = transfer->numdirs = -1;
|
|
1055 update_func (transfer);
|
|
1056 }
|
|
1057
|
|
1058 if (oldfromdir != NULL)
|
|
1059 g_free (oldfromdir);
|
|
1060
|
|
1061 if (oldtodir != NULL)
|
|
1062 g_free (oldtodir);
|
|
1063 }
|
|
1064
|
|
1065
|
|
1066 static GList *
|
|
1067 _setup_current_directory_transfer (gftp_transfer * transfer, int *ret)
|
|
1068 {
|
1
|
1069 GHashTable * dirhash;
|
787
|
1070 char *pos, *newname;
|
1
|
1071 gftp_file * curfle;
|
787
|
1072 GList * lastlist;
|
516
|
1073 off_t *newsize;
|
787
|
1074
|
|
1075 *ret = 0;
|
1
|
1076 if (transfer->toreq != NULL)
|
469
|
1077 {
|
787
|
1078 dirhash = gftp_gen_dir_hash (transfer->toreq, ret);
|
|
1079 if (*ret == GFTP_EFATAL)
|
|
1080 return (NULL);
|
469
|
1081 }
|
1
|
1082 else
|
|
1083 dirhash = NULL;
|
|
1084
|
|
1085 for (lastlist = transfer->files; ; lastlist = lastlist->next)
|
|
1086 {
|
|
1087 curfle = lastlist->data;
|
381
|
1088
|
|
1089 if ((pos = strrchr (curfle->file, '/')) != NULL)
|
|
1090 pos++;
|
|
1091 else
|
|
1092 pos = curfle->file;
|
|
1093
|
|
1094 if (dirhash != NULL &&
|
|
1095 (newsize = g_hash_table_lookup (dirhash, pos)) != NULL)
|
787
|
1096 {
|
|
1097 curfle->exists_other_side = 1;
|
|
1098 curfle->startsize = *newsize;
|
|
1099 }
|
|
1100 else
|
|
1101 curfle->exists_other_side = 0;
|
1
|
1102
|
381
|
1103 if (curfle->size < 0 && GFTP_IS_CONNECTED (transfer->fromreq))
|
509
|
1104 {
|
|
1105 curfle->size = gftp_get_file_size (transfer->fromreq, curfle->file);
|
787
|
1106 if (curfle->size == GFTP_EFATAL)
|
|
1107 {
|
|
1108 gftp_destroy_dir_hash (dirhash);
|
|
1109 *ret = curfle->size;
|
|
1110 return (NULL);
|
|
1111 }
|
509
|
1112 }
|
381
|
1113
|
|
1114 if (transfer->toreq && curfle->destfile == NULL)
|
555
|
1115 curfle->destfile = gftp_build_path (transfer->toreq,
|
|
1116 transfer->toreq->directory,
|
381
|
1117 curfle->file, NULL);
|
|
1118
|
|
1119 if (transfer->fromreq->directory != NULL &&
|
509
|
1120 *transfer->fromreq->directory != '\0' && *curfle->file != '/')
|
381
|
1121 {
|
555
|
1122 newname = gftp_build_path (transfer->fromreq,
|
|
1123 transfer->fromreq->directory,
|
381
|
1124 curfle->file, NULL);
|
|
1125 g_free (curfle->file);
|
|
1126 curfle->file = newname;
|
|
1127 }
|
1
|
1128
|
|
1129 if (lastlist->next == NULL)
|
|
1130 break;
|
|
1131 }
|
|
1132
|
787
|
1133 gftp_destroy_dir_hash (dirhash);
|
|
1134
|
|
1135 return (lastlist);
|
|
1136 }
|
|
1137
|
|
1138
|
852
|
1139 static int
|
|
1140 _lookup_curfle_in_device_hash (gftp_request * request, gftp_file * curfle,
|
|
1141 GHashTable * device_hash)
|
|
1142 {
|
|
1143 GHashTable * inode_hash;
|
|
1144
|
|
1145 if (curfle->st_dev == 0 || curfle->st_ino == 0)
|
|
1146 return (0);
|
|
1147
|
|
1148 if ((inode_hash = g_hash_table_lookup (device_hash,
|
|
1149 GUINT_TO_POINTER ((guint) curfle->st_dev))) != NULL)
|
|
1150 {
|
|
1151 if (g_hash_table_lookup (inode_hash,
|
|
1152 GUINT_TO_POINTER ((guint) curfle->st_ino)))
|
|
1153 {
|
|
1154 request->logging_function (gftp_logging_error, request,
|
|
1155 _("Found recursive symbolic link %s\n"),
|
|
1156 curfle->file);
|
|
1157 return (1);
|
|
1158 }
|
|
1159
|
|
1160 g_hash_table_insert (inode_hash, GUINT_TO_POINTER ((guint) curfle->st_ino),
|
|
1161 GUINT_TO_POINTER (1));
|
|
1162 return (0);
|
|
1163 }
|
|
1164 else
|
|
1165 {
|
|
1166 inode_hash = g_hash_table_new (uint_hash_function, uint_hash_compare);
|
|
1167 g_hash_table_insert (inode_hash, GUINT_TO_POINTER ((guint) curfle->st_ino),
|
|
1168 GUINT_TO_POINTER (1));
|
|
1169 g_hash_table_insert (device_hash, GUINT_TO_POINTER ((guint) curfle->st_dev),
|
|
1170 inode_hash);
|
|
1171 return (0);
|
|
1172 }
|
|
1173
|
|
1174 }
|
|
1175
|
|
1176
|
|
1177 static void
|
|
1178 _free_inode_hash (gpointer key, gpointer value, gpointer user_data)
|
|
1179 {
|
|
1180 g_hash_table_destroy (value);
|
|
1181 }
|
|
1182
|
|
1183
|
|
1184 static void
|
|
1185 _free_device_hash (GHashTable * device_hash)
|
|
1186 {
|
|
1187 g_hash_table_foreach (device_hash, _free_inode_hash, NULL);
|
|
1188 g_hash_table_destroy (device_hash);
|
|
1189 }
|
|
1190
|
|
1191
|
787
|
1192 int
|
|
1193 gftp_get_all_subdirs (gftp_transfer * transfer,
|
|
1194 void (*update_func) (gftp_transfer * transfer))
|
|
1195 {
|
|
1196 GList * templist, * lastlist;
|
|
1197 char *oldfromdir, *oldtodir;
|
852
|
1198 GHashTable * device_hash;
|
787
|
1199 gftp_file * curfle;
|
|
1200 off_t linksize;
|
|
1201 mode_t st_mode;
|
|
1202 int ret;
|
|
1203
|
|
1204 g_return_val_if_fail (transfer != NULL, GFTP_EFATAL);
|
|
1205 g_return_val_if_fail (transfer->fromreq != NULL, GFTP_EFATAL);
|
|
1206 g_return_val_if_fail (transfer->files != NULL, GFTP_EFATAL);
|
|
1207
|
|
1208 if (transfer->files == NULL)
|
|
1209 return (0);
|
|
1210
|
|
1211 ret = 0;
|
|
1212 lastlist = _setup_current_directory_transfer (transfer, &ret);
|
|
1213 if (lastlist == NULL)
|
|
1214 return (ret);
|
1
|
1215
|
|
1216 oldfromdir = oldtodir = NULL;
|
852
|
1217 device_hash = g_hash_table_new (uint_hash_function, uint_hash_compare);
|
787
|
1218
|
1
|
1219 for (templist = transfer->files; templist != NULL; templist = templist->next)
|
|
1220 {
|
|
1221 curfle = templist->data;
|
|
1222
|
852
|
1223 if (_lookup_curfle_in_device_hash (transfer->fromreq, curfle,
|
|
1224 device_hash))
|
|
1225 continue;
|
|
1226
|
500
|
1227 if (S_ISLNK (curfle->st_mode) && !S_ISDIR (curfle->st_mode))
|
|
1228 {
|
520
|
1229 st_mode = 0;
|
787
|
1230 linksize = 0;
|
|
1231 ret = gftp_stat_filename (transfer->fromreq, curfle->file, &st_mode,
|
|
1232 &linksize);
|
855
|
1233 if (ret == GFTP_EFATAL)
|
787
|
1234 {
|
|
1235 _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
|
|
1236 update_func);
|
|
1237 return (ret);
|
|
1238 }
|
855
|
1239 else if (ret == 0)
|
|
1240 {
|
|
1241 if (S_ISDIR (st_mode))
|
|
1242 curfle->st_mode = st_mode;
|
|
1243 else
|
|
1244 curfle->size = linksize;
|
|
1245 }
|
500
|
1246 }
|
|
1247
|
826
|
1248 if (!S_ISDIR (curfle->st_mode))
|
1
|
1249 {
|
787
|
1250 transfer->numfiles++;
|
|
1251 continue;
|
|
1252 }
|
|
1253
|
|
1254 /* Got a directory... */
|
826
|
1255 transfer->numdirs++;
|
|
1256
|
787
|
1257 if (oldfromdir == NULL)
|
|
1258 oldfromdir = g_strdup (transfer->fromreq->directory);
|
|
1259
|
|
1260 ret = gftp_set_directory (transfer->fromreq, curfle->file);
|
|
1261 if (ret < 0)
|
|
1262 {
|
|
1263 _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
|
|
1264 update_func);
|
852
|
1265 _free_device_hash (device_hash);
|
787
|
1266 return (ret);
|
|
1267 }
|
|
1268
|
|
1269 if (transfer->toreq != NULL)
|
|
1270 {
|
|
1271 if (oldtodir == NULL)
|
|
1272 oldtodir = g_strdup (transfer->toreq->directory);
|
|
1273
|
|
1274 if (curfle->exists_other_side)
|
1
|
1275 {
|
787
|
1276 ret = gftp_set_directory (transfer->toreq, curfle->destfile);
|
|
1277 if (ret == GFTP_EFATAL)
|
|
1278 {
|
|
1279 _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
|
|
1280 update_func);
|
852
|
1281 _free_device_hash (device_hash);
|
787
|
1282 return (ret);
|
|
1283 }
|
|
1284 }
|
|
1285 else
|
509
|
1286 {
|
787
|
1287 if (transfer->toreq->directory != NULL)
|
|
1288 g_free (transfer->toreq->directory);
|
|
1289
|
|
1290 transfer->toreq->directory = g_strdup (curfle->destfile);
|
1
|
1291 }
|
787
|
1292 }
|
|
1293
|
|
1294 ret = 0;
|
|
1295 lastlist->next = gftp_get_dir_listing (transfer,
|
|
1296 curfle->exists_other_side, &ret);
|
|
1297 if (ret < 0)
|
|
1298 {
|
|
1299 _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
|
|
1300 update_func);
|
852
|
1301 _free_device_hash (device_hash);
|
787
|
1302 return (ret);
|
1
|
1303 }
|
787
|
1304
|
|
1305 if (lastlist->next != NULL)
|
|
1306 {
|
|
1307 lastlist->next->prev = lastlist;
|
|
1308 for (; lastlist->next != NULL; lastlist = lastlist->next);
|
|
1309 }
|
|
1310
|
|
1311 if (update_func != NULL)
|
|
1312 update_func (transfer);
|
1
|
1313 }
|
|
1314
|
852
|
1315 _free_device_hash (device_hash);
|
|
1316
|
787
|
1317 if (oldfromdir != NULL)
|
509
|
1318 {
|
787
|
1319 ret = gftp_set_directory (transfer->fromreq, oldfromdir);
|
855
|
1320 if (ret == GFTP_EFATAL)
|
787
|
1321 {
|
|
1322 _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
|
|
1323 update_func);
|
|
1324 return (ret);
|
|
1325 }
|
509
|
1326 }
|
|
1327
|
787
|
1328 if (oldtodir != NULL)
|
509
|
1329 {
|
787
|
1330 ret = gftp_set_directory (transfer->toreq, oldtodir);
|
855
|
1331 if (ret == GFTP_EFATAL)
|
787
|
1332 {
|
|
1333 _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
|
|
1334 update_func);
|
|
1335 return (ret);
|
|
1336 }
|
509
|
1337 }
|
|
1338
|
787
|
1339 _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir, update_func);
|
509
|
1340
|
1
|
1341 return (0);
|
|
1342 }
|
|
1343
|
|
1344
|
177
|
1345 int
|
1
|
1346 gftp_set_config_options (gftp_request * request)
|
|
1347 {
|
58
|
1348 if (request->set_config_options != NULL)
|
177
|
1349 return (request->set_config_options (request));
|
|
1350 else
|
|
1351 return (0);
|
1
|
1352 }
|
|
1353
|
|
1354
|
|
1355 void
|
|
1356 print_file_list (GList * list)
|
|
1357 {
|
|
1358 gftp_file * tempfle;
|
|
1359 GList * templist;
|
499
|
1360 char *attribs;
|
1
|
1361
|
|
1362 printf ("--START OF FILE LISTING - TOP TO BOTTOM--\n");
|
|
1363 for (templist = list; ; templist = templist->next)
|
|
1364 {
|
|
1365 tempfle = templist->data;
|
499
|
1366 attribs = gftp_convert_attributes_from_mode_t (tempfle->st_mode);
|
|
1367
|
532
|
1368 printf ("%s:%s:" GFTP_OFF_T_PRINTF_MOD ":" GFTP_OFF_T_PRINTF_MOD ":%s:%s:%s\n",
|
372
|
1369 tempfle->file, tempfle->destfile,
|
516
|
1370 tempfle->size, tempfle->startsize,
|
499
|
1371 tempfle->user, tempfle->group, attribs);
|
|
1372
|
|
1373 g_free (attribs);
|
1
|
1374 if (templist->next == NULL)
|
|
1375 break;
|
|
1376 }
|
|
1377
|
|
1378 printf ("--START OF FILE LISTING - BOTTOM TO TOP--\n");
|
|
1379 for (; ; templist = templist->prev)
|
|
1380 {
|
|
1381 tempfle = templist->data;
|
499
|
1382 attribs = gftp_convert_attributes_from_mode_t (tempfle->st_mode);
|
|
1383
|
532
|
1384 printf ("%s:%s:" GFTP_OFF_T_PRINTF_MOD ":" GFTP_OFF_T_PRINTF_MOD ":%s:%s:%s\n",
|
372
|
1385 tempfle->file, tempfle->destfile,
|
516
|
1386 tempfle->size, tempfle->startsize,
|
499
|
1387 tempfle->user, tempfle->group, attribs);
|
|
1388
|
|
1389 g_free (attribs);
|
1
|
1390 if (templist == list)
|
|
1391 break;
|
|
1392 }
|
|
1393 printf ("--END OF FILE LISTING--\n");
|
|
1394 }
|
|
1395
|
41
|
1396
|
201
|
1397 void
|
63
|
1398 gftp_swap_socks (gftp_request * dest, gftp_request * source)
|
|
1399 {
|
|
1400 g_return_if_fail (dest != NULL);
|
|
1401 g_return_if_fail (source != NULL);
|
|
1402 g_return_if_fail (dest->protonum == source->protonum);
|
|
1403
|
|
1404 dest->datafd = source->datafd;
|
|
1405 dest->cached = 0;
|
397
|
1406 #ifdef USE_SSL
|
|
1407 dest->ssl = source->ssl;
|
|
1408 #endif
|
|
1409
|
63
|
1410 if (!source->always_connected)
|
|
1411 {
|
|
1412 source->datafd = -1;
|
|
1413 source->cached = 1;
|
397
|
1414 #ifdef USE_SSL
|
|
1415 source->ssl = NULL;
|
|
1416 #endif
|
63
|
1417 }
|
|
1418
|
516
|
1419 if (dest->swap_socks != NULL)
|
63
|
1420 dest->swap_socks (dest, source);
|
|
1421 }
|
|
1422
|
122
|
1423
|
|
1424 void
|
|
1425 gftp_calc_kbs (gftp_transfer * tdata, ssize_t num_read)
|
|
1426 {
|
469
|
1427 /* Needed for systems that size(float) < size(void *) */
|
|
1428 union { intptr_t i; float f; } maxkbs;
|
122
|
1429 unsigned long waitusecs;
|
220
|
1430 double start_difftime;
|
122
|
1431 struct timeval tv;
|
222
|
1432 int waited;
|
122
|
1433
|
469
|
1434 gftp_lookup_request_option (tdata->fromreq, "maxkbs", &maxkbs.f);
|
122
|
1435
|
|
1436 if (g_thread_supported ())
|
|
1437 g_static_mutex_lock (&tdata->statmutex);
|
|
1438
|
220
|
1439 gettimeofday (&tv, NULL);
|
|
1440
|
122
|
1441 tdata->trans_bytes += num_read;
|
|
1442 tdata->curtrans += num_read;
|
|
1443 tdata->stalled = 0;
|
|
1444
|
220
|
1445 start_difftime = (tv.tv_sec - tdata->starttime.tv_sec) + ((double) (tv.tv_usec - tdata->starttime.tv_usec) / 1000000.0);
|
|
1446
|
|
1447 if (start_difftime <= 0)
|
|
1448 tdata->kbs = tdata->trans_bytes / 1024.0;
|
122
|
1449 else
|
220
|
1450 tdata->kbs = tdata->trans_bytes / 1024.0 / start_difftime;
|
|
1451
|
222
|
1452 waited = 0;
|
469
|
1453 if (maxkbs.f > 0 && tdata->kbs > maxkbs.f)
|
122
|
1454 {
|
469
|
1455 waitusecs = num_read / 1024.0 / maxkbs.f * 1000000.0 - start_difftime;
|
122
|
1456
|
|
1457 if (waitusecs > 0)
|
|
1458 {
|
|
1459 if (g_thread_supported ())
|
|
1460 g_static_mutex_unlock (&tdata->statmutex);
|
|
1461
|
222
|
1462 waited = 1;
|
122
|
1463 usleep (waitusecs);
|
|
1464
|
|
1465 if (g_thread_supported ())
|
|
1466 g_static_mutex_lock (&tdata->statmutex);
|
|
1467 }
|
222
|
1468
|
122
|
1469 }
|
|
1470
|
222
|
1471 if (waited)
|
|
1472 gettimeofday (&tdata->lasttime, NULL);
|
|
1473 else
|
|
1474 memcpy (&tdata->lasttime, &tv, sizeof (tdata->lasttime));
|
122
|
1475
|
|
1476 if (g_thread_supported ())
|
|
1477 g_static_mutex_unlock (&tdata->statmutex);
|
|
1478 }
|
|
1479
|
125
|
1480
|
764
|
1481 static int
|
|
1482 _do_sleep (int sleep_time)
|
|
1483 {
|
|
1484 struct timeval tv;
|
|
1485
|
|
1486 tv.tv_sec = sleep_time;
|
|
1487 tv.tv_usec = 0;
|
|
1488
|
872
|
1489 return (select (0, NULL, NULL, NULL, &tv));
|
764
|
1490 }
|
|
1491
|
|
1492
|
125
|
1493 int
|
|
1494 gftp_get_transfer_status (gftp_transfer * tdata, ssize_t num_read)
|
|
1495 {
|
325
|
1496 intptr_t retries, sleep_time;
|
125
|
1497 gftp_file * tempfle;
|
498
|
1498 int ret1, ret2;
|
125
|
1499
|
|
1500 gftp_lookup_request_option (tdata->fromreq, "retries", &retries);
|
|
1501 gftp_lookup_request_option (tdata->fromreq, "sleep_time", &sleep_time);
|
|
1502
|
|
1503 if (g_thread_supported ())
|
|
1504 g_static_mutex_lock (&tdata->structmutex);
|
|
1505
|
|
1506 if (tdata->curfle == NULL)
|
|
1507 {
|
|
1508 if (g_thread_supported ())
|
|
1509 g_static_mutex_unlock (&tdata->structmutex);
|
|
1510
|
|
1511 return (GFTP_EFATAL);
|
|
1512 }
|
|
1513
|
|
1514 tempfle = tdata->curfle->data;
|
|
1515
|
|
1516 if (g_thread_supported ())
|
|
1517 g_static_mutex_unlock (&tdata->structmutex);
|
|
1518
|
|
1519 gftp_disconnect (tdata->fromreq);
|
|
1520 gftp_disconnect (tdata->toreq);
|
|
1521
|
764
|
1522 if (tdata->cancel || num_read == GFTP_EFATAL)
|
|
1523 return (GFTP_EFATAL);
|
|
1524 else if (num_read >= 0 && !tdata->skip_file)
|
|
1525 return (0);
|
|
1526
|
|
1527 if (num_read != GFTP_ETIMEDOUT && !tdata->conn_error_no_timeout)
|
125
|
1528 {
|
764
|
1529 if (retries != 0 &&
|
|
1530 tdata->current_file_retries >= retries)
|
|
1531 {
|
|
1532 tdata->fromreq->logging_function (gftp_logging_error, tdata->fromreq,
|
|
1533 _("Error: Remote site %s disconnected. Max retries reached...giving up\n"),
|
|
1534 tdata->fromreq->hostname != NULL ?
|
|
1535 tdata->fromreq->hostname : tdata->toreq->hostname);
|
|
1536 return (GFTP_EFATAL);
|
|
1537 }
|
|
1538 else
|
125
|
1539 {
|
764
|
1540 tdata->fromreq->logging_function (gftp_logging_error, tdata->fromreq,
|
|
1541 _("Error: Remote site %s disconnected. Will reconnect in %d seconds\n"),
|
|
1542 tdata->fromreq->hostname != NULL ?
|
|
1543 tdata->fromreq->hostname : tdata->toreq->hostname,
|
|
1544 sleep_time);
|
|
1545 }
|
|
1546 }
|
|
1547
|
|
1548 while (retries == 0 ||
|
|
1549 tdata->current_file_retries <= retries)
|
|
1550 {
|
|
1551 /* Look up the options in case the user changes them... */
|
|
1552 gftp_lookup_request_option (tdata->fromreq, "retries", &retries);
|
|
1553 gftp_lookup_request_option (tdata->fromreq, "sleep_time", &sleep_time);
|
|
1554
|
|
1555 if (num_read != GFTP_ETIMEDOUT && !tdata->conn_error_no_timeout &&
|
|
1556 !tdata->skip_file)
|
|
1557 _do_sleep (sleep_time);
|
|
1558
|
|
1559 tdata->current_file_retries++;
|
|
1560
|
|
1561 ret1 = ret2 = 0;
|
|
1562 if ((ret1 = gftp_connect (tdata->fromreq)) == 0 &&
|
|
1563 (ret2 = gftp_connect (tdata->toreq)) == 0)
|
|
1564 {
|
|
1565 if (g_thread_supported ())
|
|
1566 g_static_mutex_lock (&tdata->structmutex);
|
|
1567
|
|
1568 tdata->resumed_bytes = tdata->resumed_bytes + tdata->trans_bytes - tdata->curresumed - tdata->curtrans;
|
|
1569 tdata->trans_bytes = 0;
|
|
1570 if (tdata->skip_file)
|
303
|
1571 {
|
764
|
1572 tdata->total_bytes -= tempfle->size;
|
|
1573 tdata->curtrans = 0;
|
|
1574
|
|
1575 tdata->curfle = tdata->curfle->next;
|
|
1576 tdata->next_file = 1;
|
|
1577 tdata->skip_file = 0;
|
|
1578 tdata->cancel = 0;
|
|
1579 tdata->fromreq->cancel = 0;
|
|
1580 tdata->toreq->cancel = 0;
|
303
|
1581 }
|
|
1582 else
|
|
1583 {
|
764
|
1584 tempfle->transfer_action = GFTP_TRANS_ACTION_RESUME;
|
|
1585 tempfle->startsize = tdata->curtrans + tdata->curresumed;
|
|
1586 /* We decrement this here because it will be incremented in
|
|
1587 the loop again */
|
|
1588 tdata->curresumed = 0;
|
|
1589 tdata->current_file_number--; /* Decrement this because it
|
|
1590 will be incremented when we
|
|
1591 continue in the loop */
|
125
|
1592 }
|
|
1593
|
764
|
1594 gettimeofday (&tdata->starttime, NULL);
|
|
1595
|
|
1596 if (g_thread_supported ())
|
|
1597 g_static_mutex_unlock (&tdata->structmutex);
|
|
1598
|
|
1599 return (GFTP_ERETRYABLE);
|
|
1600 }
|
|
1601 else if (ret1 == GFTP_EFATAL || ret2 == GFTP_EFATAL)
|
|
1602 {
|
|
1603 gftp_disconnect (tdata->fromreq);
|
|
1604 gftp_disconnect (tdata->toreq);
|
|
1605 return (GFTP_EFATAL);
|
125
|
1606 }
|
|
1607 }
|
|
1608
|
|
1609 return (0);
|
|
1610 }
|
|
1611
|
182
|
1612
|
|
1613 int
|
|
1614 gftp_fd_open (gftp_request * request, const char *pathname, int flags, mode_t mode)
|
|
1615 {
|
|
1616 int fd;
|
|
1617
|
227
|
1618 if (mode == 0)
|
|
1619 fd = open (pathname, flags);
|
|
1620 else
|
|
1621 fd = open (pathname, flags, mode);
|
|
1622
|
|
1623 if (fd < 0)
|
182
|
1624 {
|
|
1625 if (request != NULL)
|
186
|
1626 request->logging_function (gftp_logging_error, request,
|
182
|
1627 _("Error: Cannot open local file %s: %s\n"),
|
|
1628 pathname, g_strerror (errno));
|
|
1629 return (GFTP_ERETRYABLE);
|
|
1630 }
|
|
1631
|
|
1632 if (fcntl (fd, F_SETFD, 1) == -1)
|
|
1633 {
|
|
1634 if (request != NULL)
|
186
|
1635 request->logging_function (gftp_logging_error, request,
|
182
|
1636 _("Error: Cannot set close on exec flag: %s\n"),
|
|
1637 g_strerror (errno));
|
|
1638
|
|
1639 return (-1);
|
|
1640 }
|
|
1641
|
|
1642 return (fd);
|
|
1643 }
|
422
|
1644
|
|
1645
|
|
1646 void
|
792
|
1647 gftp_setup_startup_directory (gftp_request * request, const char *option_name)
|
422
|
1648 {
|
|
1649 char *startup_directory, *tempstr;
|
|
1650
|
792
|
1651 gftp_lookup_request_option (request, option_name, &startup_directory);
|
422
|
1652
|
|
1653 if (*startup_directory != '\0' &&
|
555
|
1654 (tempstr = gftp_expand_path (request, startup_directory)) != NULL)
|
422
|
1655 {
|
|
1656 gftp_set_directory (request, tempstr);
|
|
1657 g_free (tempstr);
|
|
1658 }
|
|
1659 }
|
|
1660
|
499
|
1661
|
|
1662 char *
|
|
1663 gftp_convert_attributes_from_mode_t (mode_t mode)
|
|
1664 {
|
|
1665 char *str;
|
|
1666
|
765
|
1667 str = g_malloc0 (11UL);
|
499
|
1668
|
|
1669 str[0] = '?';
|
|
1670 if (S_ISREG (mode))
|
|
1671 str[0] = '-';
|
|
1672
|
|
1673 if (S_ISLNK (mode))
|
|
1674 str[0] = 'l';
|
|
1675
|
|
1676 if (S_ISBLK (mode))
|
|
1677 str[0] = 'b';
|
|
1678
|
|
1679 if (S_ISCHR (mode))
|
|
1680 str[0] = 'c';
|
|
1681
|
|
1682 if (S_ISFIFO (mode))
|
|
1683 str[0] = 'p';
|
|
1684
|
|
1685 if (S_ISSOCK (mode))
|
|
1686 str[0] = 's';
|
|
1687
|
|
1688 if (S_ISDIR (mode))
|
|
1689 str[0] = 'd';
|
|
1690
|
|
1691 str[1] = mode & S_IRUSR ? 'r' : '-';
|
|
1692 str[2] = mode & S_IWUSR ? 'w' : '-';
|
|
1693
|
|
1694 if ((mode & S_ISUID) && (mode & S_IXUSR))
|
|
1695 str[3] = 's';
|
|
1696 else if (mode & S_ISUID)
|
|
1697 str[3] = 'S';
|
|
1698 else if (mode & S_IXUSR)
|
|
1699 str[3] = 'x';
|
|
1700 else
|
|
1701 str[3] = '-';
|
|
1702
|
|
1703 str[4] = mode & S_IRGRP ? 'r' : '-';
|
|
1704 str[5] = mode & S_IWGRP ? 'w' : '-';
|
|
1705
|
|
1706 if ((mode & S_ISGID) && (mode & S_IXGRP))
|
|
1707 str[6] = 's';
|
|
1708 else if (mode & S_ISGID)
|
|
1709 str[6] = 'S';
|
|
1710 else if (mode & S_IXGRP)
|
|
1711 str[6] = 'x';
|
|
1712 else
|
|
1713 str[6] = '-';
|
|
1714
|
|
1715 str[7] = mode & S_IROTH ? 'r' : '-';
|
|
1716 str[8] = mode & S_IWOTH ? 'w' : '-';
|
|
1717
|
|
1718 if ((mode & S_ISVTX) && (mode & S_IXOTH))
|
|
1719 str[9] = 't';
|
|
1720 else if (mode & S_ISVTX)
|
|
1721 str[9] = 'T';
|
|
1722 else if (mode & S_IXOTH)
|
|
1723 str[9] = 'x';
|
|
1724 else
|
|
1725 str[9] = '-';
|
|
1726
|
|
1727 return (str);
|
|
1728 }
|
|
1729
|
|
1730
|
|
1731 mode_t
|
|
1732 gftp_convert_attributes_to_mode_t (char *attribs)
|
|
1733 {
|
|
1734 mode_t mode;
|
|
1735
|
|
1736 if (attribs[0] == 'd')
|
|
1737 mode = S_IFDIR;
|
|
1738 else if (attribs[0] == 'l')
|
|
1739 mode = S_IFLNK;
|
|
1740 else if (attribs[0] == 's')
|
|
1741 mode = S_IFSOCK;
|
|
1742 else if (attribs[0] == 'b')
|
|
1743 mode = S_IFBLK;
|
|
1744 else if (attribs[0] == 'c')
|
|
1745 mode = S_IFCHR;
|
|
1746 else
|
|
1747 mode = S_IFREG;
|
|
1748
|
|
1749 if (attribs[1] == 'r')
|
|
1750 mode |= S_IRUSR;
|
|
1751 if (attribs[2] == 'w')
|
|
1752 mode |= S_IWUSR;
|
|
1753 if (attribs[3] == 'x' || attribs[3] == 's')
|
|
1754 mode |= S_IXUSR;
|
|
1755 if (attribs[3] == 's' || attribs[3] == 'S')
|
|
1756 mode |= S_ISUID;
|
|
1757
|
|
1758 if (attribs[4] == 'r')
|
|
1759 mode |= S_IRGRP;
|
|
1760 if (attribs[5] == 'w')
|
|
1761 mode |= S_IWGRP;
|
|
1762 if (attribs[6] == 'x' ||
|
|
1763 attribs[6] == 's')
|
|
1764 mode |= S_IXGRP;
|
|
1765 if (attribs[6] == 's' || attribs[6] == 'S')
|
|
1766 mode |= S_ISGID;
|
|
1767
|
|
1768 if (attribs[7] == 'r')
|
|
1769 mode |= S_IROTH;
|
|
1770 if (attribs[8] == 'w')
|
|
1771 mode |= S_IWOTH;
|
|
1772 if (attribs[9] == 'x' ||
|
|
1773 attribs[9] == 's')
|
|
1774 mode |= S_IXOTH;
|
|
1775 if (attribs[9] == 't' || attribs[9] == 'T')
|
|
1776 mode |= S_ISVTX;
|
|
1777
|
|
1778 return (mode);
|
|
1779 }
|
|
1780
|
542
|
1781
|
|
1782 unsigned int
|
|
1783 gftp_protocol_default_port (gftp_request * request)
|
|
1784 {
|
|
1785 struct servent serv_struct;
|
|
1786
|
|
1787 if (r_getservbyname (gftp_protocols[request->protonum].url_prefix, "tcp",
|
|
1788 &serv_struct, NULL) == NULL)
|
|
1789 return (gftp_protocols[request->protonum].default_port);
|
|
1790 else
|
|
1791 return (ntohs (serv_struct.s_port));
|
|
1792 }
|
|
1793
|