[Nautilus-list] symlink-chasing
- From: Havoc Pennington <hp redhat com>
- To: gnome-vfs ximian com, nautilus-list eazel com
- Subject: [Nautilus-list] symlink-chasing
- Date: Mon, 22 Oct 2001 17:01:19 -0400
Hi,
file-method.c:get_stat_info() seems to leak file_info->symlink_name
anytime you have two levels of symlink; also, for circular links it
gets in an infinite loop, leaking that string each time.
I'm guessing this is the cause of:
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=54684
http://bugzilla.gnome.org/show_bug.cgi?id=62494
Can someone precisely define for me what file_info->symlink_name is
supposed to contain, so I can figure out the best way to handle
cycles?
If I just add "recursive == TRUE" as another termination condition to
this if statement, will it fix it?
if ((options & GNOME_VFS_FILE_INFO_FOLLOW_LINKS) == 0
/* we don't care to follow links */
|| lstat (file_info->symlink_name, statptr) != 0
/* we can't make out where this points to */
|| !S_ISLNK (statptr->st_mode)) {
/* the next level is not a link */
break;
}
Obviously the memleak needs fixing as well, aside from ending the
infinite loop.
Appending the function for reference.
Havoc
static GnomeVFSResult
get_stat_info (GnomeVFSFileInfo *file_info,
const gchar *full_name,
GnomeVFSFileInfoOptions options,
struct stat *statptr)
{
struct stat statbuf;
gboolean followed_symlink;
gboolean is_symlink;
gboolean recursive;
char *link_file_path;
followed_symlink = FALSE;
recursive = FALSE;
GNOME_VFS_FILE_INFO_SET_LOCAL (file_info, TRUE);
if (statptr == NULL) {
statptr = &statbuf;
}
if (lstat (full_name, statptr) != 0) {
return gnome_vfs_result_from_errno ();
}
is_symlink = S_ISLNK (statptr->st_mode);
if ((options & GNOME_VFS_FILE_INFO_FOLLOW_LINKS) && is_symlink) {
if (stat (full_name, statptr) != 0) {
if (errno == ELOOP) {
recursive = TRUE;
}
/* It's a broken symlink, revert to the lstat. This is sub-optimal but
* acceptable because it's not a common case.
*/
if (lstat (full_name, statptr) != 0) {
return gnome_vfs_result_from_errno ();
}
}
GNOME_VFS_FILE_INFO_SET_SYMLINK (file_info, TRUE);
followed_symlink = TRUE;
}
gnome_vfs_stat_to_file_info (file_info, statptr);
if (is_symlink) {
link_file_path = g_strdup (full_name);
/* We will either successfully read the link name or return
* NULL if read_link fails -- flag it as a valid field either
* way.
*/
file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME;
while (TRUE) {
/* Deal with multiple-level symlinks by following them as
* far as we can.
*/
file_info->symlink_name = read_link (link_file_path);
if (file_info->symlink_name == NULL) {
g_free (link_file_path);
return gnome_vfs_result_from_errno ();
}
if ((options & GNOME_VFS_FILE_INFO_FOLLOW_LINKS) == 0
/* we don't care to follow links */
|| lstat (file_info->symlink_name, statptr) != 0
/* we can't make out where this points to */
|| !S_ISLNK (statptr->st_mode)) {
/* the next level is not a link */
break;
}
g_free (link_file_path);
link_file_path = g_strdup (file_info->symlink_name);
}
g_free (link_file_path);
}
return GNOME_VFS_OK;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]