Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 52 additions & 25 deletions src/udiskslinuxfilesystem.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
#include <libmount/libmount.h>

#include <glib/gstdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include "udiskslogging.h"
#include "udiskslinuxfilesystem.h"
Expand Down Expand Up @@ -419,45 +423,68 @@ static gboolean
is_in_filesystem_file (const gchar *filesystems_file,
const gchar *fstype)
{
gchar *filesystems = NULL;
GError *error = NULL;
gboolean ret = FALSE;
int fd = -1;
struct stat sb;
void *addr = NULL;
gchar *contents = NULL;
gchar **lines = NULL;
guint n;

if (!g_file_get_contents (filesystems_file,
&filesystems,
NULL, /* gsize *out_length */
&error))
fd = open (filesystems_file, O_RDONLY);
if (fd == -1)
{
udisks_warning ("Error reading %s: %s (%s %d)",
filesystems_file,
error->message,
g_quark_to_string (error->domain),
error->code);
g_clear_error (&error);
if (errno != ENOENT)
udisks_warning ("Error opening %s: %m", filesystems_file);
goto out;
}

if (fstat (fd, &sb) == -1)
{
udisks_warning ("Error stating %s: %m", filesystems_file);
goto out;
}

lines = g_strsplit (filesystems, "\n", -1);
for (n = 0; lines != NULL && lines[n] != NULL && !ret; n++)
if (sb.st_size > 0)
{
gchar **tokens;
gint num_tokens;
g_strdelimit (lines[n], " \t", ' ');
g_strstrip (lines[n]);
tokens = g_strsplit (lines[n], " ", -1);
num_tokens = g_strv_length (tokens);
if (num_tokens == 1 && g_strcmp0 (tokens[0], fstype) == 0)
addr = mmap (NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (addr == MAP_FAILED)
{
ret = TRUE;
udisks_warning ("Error mmaping %s: %m", filesystems_file);
addr = NULL;
goto out;
}
contents = g_strndup (addr, sb.st_size);
}
else
{
contents = g_strdup ("");
}

if (contents != NULL)
{
lines = g_strsplit (contents, "\n", -1);
for (n = 0; lines != NULL && lines[n] != NULL && !ret; n++)
{
gchar **tokens;
g_strdelimit (lines[n], " \t", ' ');
g_strstrip (lines[n]);
tokens = g_strsplit (lines[n], " ", -1);
if (g_strv_length (tokens) == 1 && g_strcmp0 (tokens[0], fstype) == 0)
{
ret = TRUE;
}
g_strfreev (tokens);
}
g_strfreev (tokens);
}

out:
out:
g_strfreev (lines);
g_free (filesystems);
g_free (contents);
if (addr != NULL)
munmap (addr, sb.st_size);
if (fd != -1)
close (fd);
return ret;
}

Expand Down
70 changes: 33 additions & 37 deletions src/udisksstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#include <limits.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>
#include <unistd.h>

#include "udisksdaemon.h"
#include "udisksstate.h"
Expand Down Expand Up @@ -2302,65 +2304,59 @@ udisks_state_get (UDisksState *state,
const GVariantType *type)
{
gchar *path;
GVariant *ret;
gchar *contents = NULL;
GError *local_error = NULL;
gsize length = 0;
GVariant *ret = NULL;
int fd = -1;
struct stat sb;
void *addr = NULL;

g_return_val_if_fail (UDISKS_IS_STATE (state), NULL);
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (g_variant_type_is_definite (type), NULL);

/* TODO:
*
* - could use a cache here to avoid loading files all the time
* - could also mmap the file
*/

path = get_state_file_path (key);

/* see if it's already in the cache */
ret = g_hash_table_lookup (state->cache, path);
if (ret != NULL)
{
g_variant_ref (ret);
goto out;
}

if (!g_file_get_contents (path,
&contents,
&length,
&local_error))
fd = open (path, O_RDONLY);
if (fd == -1)
{
if (local_error->domain == G_FILE_ERROR && local_error->code == G_FILE_ERROR_NOENT)
{
/* this is not an error */
g_clear_error (&local_error);
goto out;
}
if (errno != ENOENT)
udisks_warning ("Error opening state file %s: %m", path);
goto out;
}

udisks_warning ("Error getting state data %s: %s (%s, %d)",
key,
local_error->message,
g_quark_to_string (local_error->domain),
local_error->code);
g_clear_error (&local_error);
if (fstat (fd, &sb) == -1)
{
udisks_warning ("Error stating state file %s: %m", path);
goto out;
}

ret = g_variant_new_from_data (type,
(gconstpointer) contents,
length,
FALSE,
g_free,
contents);
g_warn_if_fail (ret != NULL);
g_variant_ref_sink (ret);
if (sb.st_size > 0)
{
addr = mmap (NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (addr == MAP_FAILED)
{
udisks_warning ("Error mmaping state file %s: %m", path);
addr = NULL;
goto out;
}
}

contents = NULL; /* ownership transferred to the returned GVariant */
if (addr != NULL)
{
GBytes *bytes = g_bytes_new_with_free_func (addr, sb.st_size, (GDestroyNotify) munmap, addr);
ret = g_variant_new_from_bytes (type, bytes, FALSE);
g_bytes_unref (bytes);
}

out:
g_free (contents);
if (fd != -1)
close (fd);
g_free (path);
return ret;
}
Expand Down
Loading