Commit e4a777f5 authored by Christian Kellner's avatar Christian Kellner
Browse files

device: rework ctor to work directly with sysfs

Instead of getting the unique-id (and other properties) via udev,
we open the sysfs directory itself and then read the attribute
via a combination of openat() and fgets(). This will ensure that
the uid we obtain is in the same directory that will later be to
authorize the device (by writing to the "authorized" sysfs attr).
parent 37d79bce
......@@ -22,7 +22,9 @@
#include "bolt-device.h"
#include "bolt-error.h"
#include "bolt-io.h"
#include <dirent.h>
#include <libudev.h>
struct _BoltDevice
......@@ -35,6 +37,7 @@ struct _BoltDevice
/* when device is attached */
char *syspath;
DIR *devdir;
};
......@@ -64,6 +67,9 @@ bolt_device_finalize (GObject *object)
g_free (dev->vendor);
g_free (dev->syspath);
if (dev->devdir)
closedir (dev->devdir);
G_OBJECT_CLASS (bolt_device_parent_class)->finalize (object);
}
......@@ -163,6 +169,22 @@ bolt_device_class_init (BoltDeviceClass *klass)
"sysfs-path");
}
/* internal methods */
static char *
read_sysattr_name (int fd, const char *attr, GError **error)
{
g_autofree char *s = NULL;
char *v;
s = g_strdup_printf ("%s_name", attr);
v = bolt_read_value_at (fd, s, NULL);
if (!v)
v = bolt_read_value_at (fd, attr, error);
return v;
}
/* public methods */
......@@ -172,22 +194,44 @@ bolt_device_new_for_udev (BoltManager *mgr,
struct udev_device *udev,
GError **error)
{
g_autofree char *uid = NULL;
g_autofree char *name = NULL;
g_autofree char *vendor = NULL;
g_autoptr(DIR) devdir = NULL;
BoltDevice *dev;
const char *uid;
const char *sysfs;
int fd;
uid = udev_device_get_sysattr_value (udev, "unique_id");
sysfs = udev_device_get_syspath (udev);
devdir = bolt_opendir (sysfs, error);
if (devdir == NULL)
return NULL;
fd = dirfd (devdir);
uid = bolt_read_value_at (fd, "unique_id", error);
if (uid == NULL)
{
g_set_error_literal (error,
BOLT_ERROR, BOLT_ERROR_UDEV,
"failed to read unique_id");
return NULL;
}
return NULL;
name = read_sysattr_name (fd, "device", error);
if (name == NULL)
return NULL;
vendor = read_sysattr_name (fd, "vendor", error);
if (vendor == NULL)
return NULL;
dev = g_object_new (BOLT_TYPE_DEVICE,
"uid", uid,
NULL);
dev->uid = g_steal_pointer (&uid);
dev->name = g_steal_pointer (&name);
dev->vendor = g_steal_pointer (&vendor);
dev->syspath = g_strdup (sysfs);
dev->devdir = g_steal_pointer (&devdir);
return dev;
}
......
/*
* Copyright © 2017 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Christian J. Kellner <christian@kellner.me>
*/
#include "config.h"
#include <gio/gio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include "bolt-io.h"
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FILE, fclose);
int
bolt_open (const char *path, int flags, GError **error)
{
int fd = open (path, flags);
if (fd < 0)
{
gint code = g_io_error_from_errno (errno);
g_set_error (error, G_IO_ERROR, code,
"could not open '%s': %s",
path, g_strerror (errno));
return -1;
}
return fd;
}
static FILE *
bolt_fdopen (int fd, const char *mode, GError **error)
{
FILE *fp = fdopen (fd, mode);
if (fp == NULL)
{
gint code = g_io_error_from_errno (errno);
g_set_error (error, G_IO_ERROR, code,
"fdopen ('%d') error: %s",
fd, g_strerror (errno));
return NULL;
}
return fp;
}
gboolean
bolt_close (int fd, GError **error)
{
int r;
r = close (fd);
if (r == 0)
return TRUE;
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errno),
"could not close file: %s",
g_strerror (errno));
return FALSE;
}
DIR *
bolt_opendir (const char *path,
GError **error)
{
DIR *d = NULL;
d = opendir (path);
if (d == NULL)
{
g_set_error (error,
G_IO_ERROR,
g_io_error_from_errno (errno),
"could not open directory ('%s'): %s",
path,
g_strerror (errno));
return NULL;
}
return d;
}
int
bolt_openat (int dirfd, const char *path, int oflag, GError **error)
{
int fd = -1;
fd = openat (dirfd, path, oflag);
if (fd < 0)
{
g_set_error (error,
G_IO_ERROR,
g_io_error_from_errno (errno),
"Could not open file %s: %s",
path,
g_strerror (errno));
}
return fd;
}
char *
bolt_read_value_at (int dirfd,
const char *name,
GError **error)
{
g_autoptr(FILE) fp = NULL;
char line[LINE_MAX], *l;
int fd;
fd = bolt_openat (dirfd, name, O_NOFOLLOW | O_CLOEXEC | O_RDONLY, error);
if (fd < 0)
return NULL;
fp = bolt_fdopen (fd, "re", error);
if (!fp)
{
g_prefix_error (error, "could not open %s: ", name);
return NULL;
}
l = fgets (line, sizeof (line) - 1, fp);
if (!l)
{
if (ferror (fp))
{
if (errno < 1)
errno = -EIO;
g_set_error (error,
G_IO_ERROR,
g_io_error_from_errno (errno),
"io error of file %s: %s",
name,
g_strerror (errno));
}
line[0] = '\0';
}
g_strstrip (line);
return g_strdup (line);
}
/*
* Copyright © 2017 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Christian J. Kellner <christian@kellner.me>
*/
#pragma once
#include <glib.h>
#include <sys/types.h>
G_BEGIN_DECLS
G_DEFINE_AUTOPTR_CLEANUP_FUNC (DIR, closedir);
int bolt_open (const char *path,
int flags,
GError **error);
gboolean bolt_close (int fd,
GError **error);
DIR * bolt_opendir (const char *path,
GError **error);
int bolt_openat (int dirfd,
const char *path,
int oflag,
GError **error);
char * bolt_read_value_at (int dirfd,
const char *name,
GError **error);
G_END_DECLS
......@@ -104,7 +104,8 @@ common_headers = [
]
common_sources = [
'common/bolt-error.c'
'common/bolt-error.c',
'common/bolt-io.c'
]
common_enums = gnome.mkenums_simple('common-enums',
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment