Mercurial > gftp.yaz
diff lib/protocols.c @ 852:5e3005923374
2006-11-16 Brian Masney <masneyb@gftp.org>
* lib/gftp.h lib/protocols.c lib/local.c - added support for detecting
recursive symbolic links. This currently only works when uploading
files. It will only work when downloading files if the inode and device
are properly populated. I need to check but it may be possible to get
this information from the SSH and FSP protocols. (closes #172499)
author | masneyb |
---|---|
date | Fri, 17 Nov 2006 02:24:14 +0000 |
parents | 83d39217749c |
children | 30eaf54a63f7 |
line wrap: on
line diff
--- a/lib/protocols.c Fri Nov 17 01:38:51 2006 +0000 +++ b/lib/protocols.c Fri Nov 17 02:24:14 2006 +0000 @@ -2077,12 +2077,66 @@ } +static int +_lookup_curfle_in_device_hash (gftp_request * request, gftp_file * curfle, + GHashTable * device_hash) +{ + GHashTable * inode_hash; + + if (curfle->st_dev == 0 || curfle->st_ino == 0) + return (0); + + if ((inode_hash = g_hash_table_lookup (device_hash, + GUINT_TO_POINTER ((guint) curfle->st_dev))) != NULL) + { + if (g_hash_table_lookup (inode_hash, + GUINT_TO_POINTER ((guint) curfle->st_ino))) + { + request->logging_function (gftp_logging_error, request, + _("Found recursive symbolic link %s\n"), + curfle->file); + return (1); + } + + g_hash_table_insert (inode_hash, GUINT_TO_POINTER ((guint) curfle->st_ino), + GUINT_TO_POINTER (1)); + return (0); + } + else + { + inode_hash = g_hash_table_new (uint_hash_function, uint_hash_compare); + g_hash_table_insert (inode_hash, GUINT_TO_POINTER ((guint) curfle->st_ino), + GUINT_TO_POINTER (1)); + g_hash_table_insert (device_hash, GUINT_TO_POINTER ((guint) curfle->st_dev), + inode_hash); + return (0); + } + +} + + +static void +_free_inode_hash (gpointer key, gpointer value, gpointer user_data) +{ + g_hash_table_destroy (value); +} + + +static void +_free_device_hash (GHashTable * device_hash) +{ + g_hash_table_foreach (device_hash, _free_inode_hash, NULL); + g_hash_table_destroy (device_hash); +} + + int gftp_get_all_subdirs (gftp_transfer * transfer, void (*update_func) (gftp_transfer * transfer)) { GList * templist, * lastlist; char *oldfromdir, *oldtodir; + GHashTable * device_hash; gftp_file * curfle; off_t linksize; mode_t st_mode; @@ -2101,11 +2155,16 @@ return (ret); oldfromdir = oldtodir = NULL; + device_hash = g_hash_table_new (uint_hash_function, uint_hash_compare); for (templist = transfer->files; templist != NULL; templist = templist->next) { curfle = templist->data; + if (_lookup_curfle_in_device_hash (transfer->fromreq, curfle, + device_hash)) + continue; + if (S_ISLNK (curfle->st_mode) && !S_ISDIR (curfle->st_mode)) { st_mode = 0; @@ -2141,6 +2200,7 @@ { _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir, update_func); + _free_device_hash (device_hash); return (ret); } @@ -2156,6 +2216,7 @@ { _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir, update_func); + _free_device_hash (device_hash); return (ret); } } @@ -2175,6 +2236,7 @@ { _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir, update_func); + _free_device_hash (device_hash); return (ret); } @@ -2188,6 +2250,8 @@ update_func (transfer); } + _free_device_hash (device_hash); + if (oldfromdir != NULL) { ret = gftp_set_directory (transfer->fromreq, oldfromdir);