Handle MLS selinux policy better

Following the behaviour of ls here, we should return at least the
file name, if we can't get any other information about a file. To
do this, handle EACCESS on stat() calls.

Patch by Tomas Bzatek, see bug 623692
This commit is contained in:
Matthias Clasen 2010-07-08 14:19:08 -04:00
parent 1e8656fe24
commit 71e7b5800a

View File

@ -1215,19 +1215,19 @@ get_content_type (const char *basename,
{ {
if (is_symlink && if (is_symlink &&
(symlink_broken || (flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS))) (symlink_broken || (flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS)))
return g_strdup ("inode/symlink"); return g_strdup ("inode/symlink");
else if (S_ISDIR(statbuf->st_mode)) else if (statbuf != NULL && S_ISDIR(statbuf->st_mode))
return g_strdup ("inode/directory"); return g_strdup ("inode/directory");
#ifndef G_OS_WIN32 #ifndef G_OS_WIN32
else if (S_ISCHR(statbuf->st_mode)) else if (statbuf != NULL && S_ISCHR(statbuf->st_mode))
return g_strdup ("inode/chardevice"); return g_strdup ("inode/chardevice");
else if (S_ISBLK(statbuf->st_mode)) else if (statbuf != NULL && S_ISBLK(statbuf->st_mode))
return g_strdup ("inode/blockdevice"); return g_strdup ("inode/blockdevice");
else if (S_ISFIFO(statbuf->st_mode)) else if (statbuf != NULL && S_ISFIFO(statbuf->st_mode))
return g_strdup ("inode/fifo"); return g_strdup ("inode/fifo");
#endif #endif
#ifdef S_ISSOCK #ifdef S_ISSOCK
else if (S_ISSOCK(statbuf->st_mode)) else if (statbuf != NULL && S_ISSOCK(statbuf->st_mode))
return g_strdup ("inode/socket"); return g_strdup ("inode/socket");
#endif #endif
else else
@ -1421,6 +1421,7 @@ _g_local_file_info_get (const char *basename,
struct stat statbuf2; struct stat statbuf2;
#endif #endif
int res; int res;
gboolean stat_ok;
gboolean is_symlink, symlink_broken; gboolean is_symlink, symlink_broken;
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
DWORD dos_attributes; DWORD dos_attributes;
@ -1471,20 +1472,31 @@ _g_local_file_info_get (const char *basename,
if (res == -1) if (res == -1)
{ {
int errsv = errno; int errsv = errno;
char *display_name = g_filename_display_name (path);
g_object_unref (info); /* Don't bail out if we get Permission denied (SELinux?) */
g_set_error (error, G_IO_ERROR, if (errsv != EACCES)
g_io_error_from_errno (errsv), {
_("Error stating file '%s': %s"), char *display_name = g_filename_display_name (path);
display_name, g_strerror (errsv)); g_object_unref (info);
g_free (display_name); g_set_error (error, G_IO_ERROR,
return NULL; g_io_error_from_errno (errsv),
_("Error stating file '%s': %s"),
display_name, g_strerror (errsv));
g_free (display_name);
return NULL;
}
} }
device = statbuf.st_dev; /* Even if stat() fails, try to get as much as other attributes possible */
stat_ok = res != -1;
if (stat_ok)
device = statbuf.st_dev;
else
device = 0;
#ifdef S_ISLNK #ifdef S_ISLNK
is_symlink = S_ISLNK (statbuf.st_mode); is_symlink = stat_ok && S_ISLNK (statbuf.st_mode);
#else #else
is_symlink = FALSE; is_symlink = FALSE;
#endif #endif
@ -1499,23 +1511,27 @@ _g_local_file_info_get (const char *basename,
{ {
res = stat (path, &statbuf2); res = stat (path, &statbuf2);
/* Report broken links as symlinks */ /* Report broken links as symlinks */
if (res != -1) if (res != -1)
statbuf = statbuf2; {
statbuf = statbuf2;
stat_ok = TRUE;
}
else else
symlink_broken = TRUE; symlink_broken = TRUE;
} }
} }
#endif #endif
set_info_from_stat (info, &statbuf, attribute_matcher); if (stat_ok)
set_info_from_stat (info, &statbuf, attribute_matcher);
#ifndef G_OS_WIN32 #ifndef G_OS_WIN32
if (basename != NULL && basename[0] == '.') if (basename != NULL && basename[0] == '.')
g_file_info_set_is_hidden (info, TRUE); g_file_info_set_is_hidden (info, TRUE);
if (basename != NULL && basename[strlen (basename) -1] == '~' && if (basename != NULL && basename[strlen (basename) -1] == '~' &&
S_ISREG (statbuf.st_mode)) (stat_ok && S_ISREG (statbuf.st_mode)))
_g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_IS_BACKUP, TRUE); _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_IS_BACKUP, TRUE);
#else #else
if (dos_attributes & FILE_ATTRIBUTE_HIDDEN) if (dos_attributes & FILE_ATTRIBUTE_HIDDEN)
@ -1578,7 +1594,7 @@ _g_local_file_info_get (const char *basename,
_g_file_attribute_matcher_matches_id (attribute_matcher, _g_file_attribute_matcher_matches_id (attribute_matcher,
G_FILE_ATTRIBUTE_ID_STANDARD_ICON)) G_FILE_ATTRIBUTE_ID_STANDARD_ICON))
{ {
char *content_type = get_content_type (basename, path, &statbuf, is_symlink, symlink_broken, flags, FALSE); char *content_type = get_content_type (basename, path, stat_ok ? &statbuf : NULL, is_symlink, symlink_broken, flags, FALSE);
if (content_type) if (content_type)
{ {
@ -1635,7 +1651,7 @@ _g_local_file_info_get (const char *basename,
if (_g_file_attribute_matcher_matches_id (attribute_matcher, if (_g_file_attribute_matcher_matches_id (attribute_matcher,
G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE)) G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE))
{ {
char *content_type = get_content_type (basename, path, &statbuf, is_symlink, symlink_broken, flags, TRUE); char *content_type = get_content_type (basename, path, stat_ok ? &statbuf : NULL, is_symlink, symlink_broken, flags, TRUE);
if (content_type) if (content_type)
{ {
@ -1652,7 +1668,8 @@ _g_local_file_info_get (const char *basename,
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
win32_get_file_user_info (path, NULL, &name, NULL); win32_get_file_user_info (path, NULL, &name, NULL);
#else #else
name = get_username_from_uid (statbuf.st_uid); if (stat_ok)
name = get_username_from_uid (statbuf.st_uid);
#endif #endif
if (name) if (name)
_g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_OWNER_USER, name); _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_OWNER_USER, name);
@ -1666,7 +1683,8 @@ _g_local_file_info_get (const char *basename,
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
win32_get_file_user_info (path, NULL, NULL, &name); win32_get_file_user_info (path, NULL, NULL, &name);
#else #else
name = get_realname_from_uid (statbuf.st_uid); if (stat_ok)
name = get_realname_from_uid (statbuf.st_uid);
#endif #endif
if (name) if (name)
_g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_OWNER_USER_REAL, name); _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_OWNER_USER_REAL, name);
@ -1680,19 +1698,21 @@ _g_local_file_info_get (const char *basename,
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
win32_get_file_user_info (path, &name, NULL, NULL); win32_get_file_user_info (path, &name, NULL, NULL);
#else #else
name = get_groupname_from_gid (statbuf.st_gid); if (stat_ok)
name = get_groupname_from_gid (statbuf.st_gid);
#endif #endif
if (name) if (name)
_g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_OWNER_GROUP, name); _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_OWNER_GROUP, name);
g_free (name); g_free (name);
} }
if (parent_info && parent_info->device != 0 && if (stat_ok && parent_info && parent_info->device != 0 &&
_g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_UNIX_IS_MOUNTPOINT) && _g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_UNIX_IS_MOUNTPOINT) &&
statbuf.st_dev != parent_info->device) statbuf.st_dev != parent_info->device)
_g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_IS_MOUNTPOINT, TRUE); _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_IS_MOUNTPOINT, TRUE);
get_access_rights (attribute_matcher, info, path, &statbuf, parent_info); if (stat_ok)
get_access_rights (attribute_matcher, info, path, &statbuf, parent_info);
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
get_selinux_context (path, info, attribute_matcher, (flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS) == 0); get_selinux_context (path, info, attribute_matcher, (flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS) == 0);