| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Copyright (c) 2020 Bastien Nocera <hadess@hadess.net> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify it | ||
| 5 | * under the terms of the GNU General Public License version 3 as published by | ||
| 6 | * the Free Software Foundation. | ||
| 7 | * | ||
| 8 | */ | ||
| 9 | |||
| 10 | #define G_LOG_DOMAIN "Utils" | ||
| 11 | |||
| 12 | #include "ppd-utils.h" | ||
| 13 | #include <glib/gstdio.h> | ||
| 14 | #include <gio/gio.h> | ||
| 15 | #include <fcntl.h> | ||
| 16 | #include <stdio.h> | ||
| 17 | #include <errno.h> | ||
| 18 | |||
| 19 | #define PROC_CPUINFO_PATH "/proc/cpuinfo" | ||
| 20 | |||
| 21 | char * | ||
| 22 | 1144 | ppd_utils_get_sysfs_path (const char *filename) | |
| 23 | { | ||
| 24 | 1144 | const char *root; | |
| 25 | |||
| 26 | 1144 | root = g_getenv ("UMOCKDEV_DIR"); | |
| 27 |
2/4✓ Branch 0 taken 1144 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1144 times.
|
1144 | if (!root || *root == '\0') |
| 28 | ✗ | root = "/"; | |
| 29 | |||
| 30 | 1144 | return g_build_filename (root, filename, NULL); | |
| 31 | } | ||
| 32 | |||
| 33 | gboolean | ||
| 34 | 535 | ppd_utils_write (const char *filename, | |
| 35 | const char *value, | ||
| 36 | GError **error) | ||
| 37 | { | ||
| 38 | #if GLIB_CHECK_VERSION (2, 76, 0) | ||
| 39 | 535 | g_autofd | |
| 40 | #endif | ||
| 41 | 535 | int fd = -1; | |
| 42 | 535 | size_t size; | |
| 43 | |||
| 44 |
1/2✓ Branch 0 taken 535 times.
✗ Branch 1 not taken.
|
535 | g_return_val_if_fail (filename, FALSE); |
| 45 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 535 times.
|
535 | g_return_val_if_fail (value, FALSE); |
| 46 | |||
| 47 | 535 | g_debug ("Writing '%s' to '%s'", value, filename); | |
| 48 | |||
| 49 | 535 | fd = g_open (filename, O_WRONLY | O_TRUNC | O_SYNC); | |
| 50 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 523 times.
|
535 | if (fd == -1) { |
| 51 | 12 | g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), | |
| 52 | "Could not open '%s' for writing", filename); | ||
| 53 | 12 | g_debug ("Could not open for writing '%s'", filename); | |
| 54 | 12 | return FALSE; | |
| 55 | } | ||
| 56 | |||
| 57 | 523 | size = strlen (value); | |
| 58 |
2/2✓ Branch 0 taken 523 times.
✓ Branch 1 taken 523 times.
|
1046 | while (size) { |
| 59 | 523 | ssize_t written = write (fd, value, size); | |
| 60 | |||
| 61 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 523 times.
|
523 | if (written == -1) { |
| 62 | ✗ | g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), | |
| 63 | ✗ | "Error writing '%s': %s", filename, g_strerror (errno)); | |
| 64 | ✗ | g_debug ("Error writing '%s': %s", filename, g_strerror (errno)); | |
| 65 | #if !GLIB_CHECK_VERSION (2, 76, 0) | ||
| 66 | g_close (fd, NULL); | ||
| 67 | #endif | ||
| 68 | ✗ | return FALSE; | |
| 69 | } | ||
| 70 | |||
| 71 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 523 times.
|
523 | g_return_val_if_fail (written <= size, FALSE); |
| 72 | 523 | size -= written; | |
| 73 | } | ||
| 74 | |||
| 75 | #if !GLIB_CHECK_VERSION (2, 76, 0) | ||
| 76 | g_close (fd, NULL); | ||
| 77 | #endif | ||
| 78 | |||
| 79 | return TRUE; | ||
| 80 | } | ||
| 81 | |||
| 82 | gboolean | ||
| 83 | 54 | ppd_utils_write_files (GPtrArray *filenames, | |
| 84 | const char *value, | ||
| 85 | GError **error) | ||
| 86 | { | ||
| 87 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | g_return_val_if_fail (filenames != NULL, FALSE); |
| 88 | |||
| 89 |
2/2✓ Branch 0 taken 60 times.
✓ Branch 1 taken 50 times.
|
110 | for (guint i = 0; i < filenames->len; i++) { |
| 90 | 60 | const char *file = g_ptr_array_index (filenames, i); | |
| 91 | |||
| 92 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 56 times.
|
60 | if (!ppd_utils_write (file, value, error)) |
| 93 | return FALSE; | ||
| 94 | } | ||
| 95 | |||
| 96 | return TRUE; | ||
| 97 | } | ||
| 98 | |||
| 99 | 14 | gboolean ppd_utils_write_sysfs (GUdevDevice *device, | |
| 100 | const char *attribute, | ||
| 101 | const char *value, | ||
| 102 | GError **error) | ||
| 103 | { | ||
| 104 | 28 | g_autofree char *filename = NULL; | |
| 105 | |||
| 106 |
3/8✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
14 | g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE); |
| 107 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | g_return_val_if_fail (attribute, FALSE); |
| 108 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | g_return_val_if_fail (value, FALSE); |
| 109 | |||
| 110 | 14 | filename = g_build_filename (g_udev_device_get_sysfs_path (device), attribute, NULL); | |
| 111 | 14 | return ppd_utils_write (filename, value, error); | |
| 112 | } | ||
| 113 | |||
| 114 | 5 | gboolean ppd_utils_write_sysfs_int (GUdevDevice *device, | |
| 115 | const char *attribute, | ||
| 116 | gint64 value, | ||
| 117 | GError **error) | ||
| 118 | { | ||
| 119 | 10 | g_autofree char *str_value = NULL; | |
| 120 | |||
| 121 | 5 | str_value = g_strdup_printf ("%" G_GINT64_FORMAT, value); | |
| 122 | 5 | return ppd_utils_write_sysfs (device, attribute, str_value, error); | |
| 123 | } | ||
| 124 | |||
| 125 | GFileMonitor * | ||
| 126 | 8 | ppd_utils_monitor_sysfs_attr (GUdevDevice *device, | |
| 127 | const char *attribute, | ||
| 128 | GError **error) | ||
| 129 | { | ||
| 130 | 16 | g_autofree char *path = NULL; | |
| 131 | 8 | g_autoptr(GFile) file = NULL; | |
| 132 | |||
| 133 | 8 | path = g_build_filename (g_udev_device_get_sysfs_path (device), attribute, NULL); | |
| 134 | 8 | file = g_file_new_for_path (path); | |
| 135 | 8 | g_debug ("Monitoring file %s for changes", path); | |
| 136 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | return g_file_monitor_file (file, |
| 137 | G_FILE_MONITOR_NONE, | ||
| 138 | NULL, | ||
| 139 | error); | ||
| 140 | } | ||
| 141 | |||
| 142 | GUdevDevice * | ||
| 143 | 51 | ppd_utils_find_device (const char *subsystem, | |
| 144 | GCompareFunc func, | ||
| 145 | gpointer user_data) | ||
| 146 | { | ||
| 147 | 51 | const gchar * subsystems[] = { NULL, NULL }; | |
| 148 | 102 | g_autoptr(GUdevClient) client = NULL; | |
| 149 | 51 | GUdevDevice *ret = NULL; | |
| 150 | 51 | GList *devices, *l; | |
| 151 | |||
| 152 |
1/2✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
|
51 | g_return_val_if_fail (subsystem != NULL, NULL); |
| 153 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
|
51 | g_return_val_if_fail (func != NULL, NULL); |
| 154 | |||
| 155 | 51 | subsystems[0] = subsystem; | |
| 156 | 51 | client = g_udev_client_new (subsystems); | |
| 157 | 51 | devices = g_udev_client_query_by_subsystem (client, subsystem); | |
| 158 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 43 times.
|
51 | if (devices == NULL) |
| 159 | return NULL; | ||
| 160 | |||
| 161 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | for (l = devices; l != NULL; l = l->next) { |
| 162 | 8 | GUdevDevice *dev = l->data; | |
| 163 | |||
| 164 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | if ((func) (dev, user_data) != 0) |
| 165 | ✗ | continue; | |
| 166 | |||
| 167 | 8 | ret = g_object_ref (dev); | |
| 168 | 8 | break; | |
| 169 | } | ||
| 170 | 8 | g_list_free_full (devices, g_object_unref); | |
| 171 | |||
| 172 | 8 | return ret; | |
| 173 | } | ||
| 174 | |||
| 175 | gboolean | ||
| 176 | 4 | ppd_utils_match_cpu_vendor (const char *vendor) | |
| 177 | { | ||
| 178 | 8 | g_autofree gchar *cpuinfo_path = NULL; | |
| 179 | 4 | g_autofree gchar *cpuinfo = NULL; | |
| 180 | 4 | g_auto(GStrv) lines = NULL; | |
| 181 | |||
| 182 | 4 | cpuinfo_path = ppd_utils_get_sysfs_path (PROC_CPUINFO_PATH); | |
| 183 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | if (!g_file_get_contents (cpuinfo_path, &cpuinfo, NULL, NULL)) |
| 184 | return FALSE; | ||
| 185 | |||
| 186 | 4 | lines = g_strsplit (cpuinfo, "\n", -1); | |
| 187 | |||
| 188 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | for (gchar **line = lines; *line != NULL; line++) { |
| 189 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | if (g_str_has_prefix (*line, "vendor_id") && |
| 190 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | strchr (*line, ':')) { |
| 191 | 8 | g_auto(GStrv) sections = g_strsplit (*line, ":", 2); | |
| 192 | |||
| 193 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (g_strv_length (sections) < 2) |
| 194 | ✗ | continue; | |
| 195 |
1/2✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
4 | if (g_strcmp0 (g_strstrip (sections[1]), vendor) == 0) |
| 196 | 4 | return TRUE; | |
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | return FALSE; | ||
| 201 | } | ||
| 202 |