diff options
| author | Michael Biebl <biebl@debian.org> | 2018-10-20 01:30:31 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2018-10-20 01:30:31 +0200 |
| commit | 6518e361171f64bcaaa4bf868139362ed95cc2e0 (patch) | |
| tree | d2d5b53faf80646a40ec2c0c7f2a42b3959612f5 /src/nm-core-utils.c | |
| parent | e126f3e804c35480c4f075777430419d6ece23da (diff) | |
New upstream version 1.14.2 upstream/1.14.2
Diffstat (limited to 'src/nm-core-utils.c')
| -rw-r--r-- | src/nm-core-utils.c | 425 |
1 files changed, 45 insertions, 380 deletions
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index 54ccdb83..ca8c9526 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2004 - 2014 Red Hat, Inc. + * Copyright 2004 - 2018 Red Hat, Inc. * Copyright 2005 - 2008 Novell, Inc. */ @@ -25,6 +25,7 @@ #include <errno.h> #include <fcntl.h> +#include <fnmatch.h> #include <string.h> #include <unistd.h> #include <stdlib.h> @@ -37,6 +38,7 @@ #include <net/ethernet.h> #include "nm-utils/nm-random-utils.h" +#include "nm-utils/nm-io-utils.h" #include "nm-utils.h" #include "nm-core-internal.h" #include "nm-setting-connection.h" @@ -45,15 +47,6 @@ #include "nm-setting-wireless.h" #include "nm-setting-wireless-security.h" -/* - * Some toolchains (E.G. uClibc 0.9.33 and earlier) don't export - * CLOCK_BOOTTIME even though the kernel supports it, so provide a - * local definition - */ -#ifndef CLOCK_BOOTTIME -#define CLOCK_BOOTTIME 7 -#endif - G_STATIC_ASSERT (sizeof (NMUtilsTestFlags) <= sizeof (int)); static int _nm_utils_testing = 0; @@ -532,7 +525,7 @@ _kc_waited_to_string (char *buf, gint64 wait_start_us) } static void -_kc_cb_watch_child (GPid pid, gint status, gpointer user_data) +_kc_cb_watch_child (GPid pid, int status, gpointer user_data) { KillChildAsyncData *data = user_data; char buf_exit[KC_EXIT_TO_STRING_BUF_SIZE], buf_wait[KC_WAITED_TO_STRING]; @@ -1455,7 +1448,7 @@ match_config_eval (const char *str, const char *tag, guint cur_nm_version) { gs_free char *s_ver = NULL; gs_strfreev char **s_ver_tokens = NULL; - gint v_maj = -1, v_min = -1, v_mic = -1; + int v_maj = -1, v_min = -1, v_mic = -1; guint c_maj = -1, c_min = -1, c_mic = -1; guint n_tokens; @@ -1587,9 +1580,9 @@ nm_match_spec_split (const char *value) /* Copied from glibs g_key_file_parse_value_as_string() function * and adjusted. */ - string_value = g_new (gchar, strlen (value) + 1); + string_value = g_new (char, strlen (value) + 1); - p = (gchar *) value; + p = (char *) value; /* skip over leading whitespace */ while (g_ascii_isspace (*p)) @@ -1739,6 +1732,33 @@ nm_match_spec_join (GSList *specs) return g_string_free (str, FALSE); } +gboolean +nm_wildcard_match_check (const char *str, + const char *const *patterns, + guint num_patterns) +{ + guint i, neg = 0; + + for (i = 0; i < num_patterns; i++) { + if (patterns[i][0] == '!') { + neg++; + if (!fnmatch (patterns[i] + 1, str, 0)) + return FALSE; + } + } + + if (neg == num_patterns) + return TRUE; + + for (i = 0; i < num_patterns; i++) { + if ( patterns[i][0] != '!' + && !fnmatch (patterns[i], str, 0)) + return TRUE; + } + + return FALSE; +} + /*****************************************************************************/ char * @@ -2036,7 +2056,7 @@ typedef struct NMSettingDiffResult diff_result; } LogConnectionSettingItem; -static gint +static int _log_connection_sort_hashes_fcn (gconstpointer a, gconstpointer b) { const LogConnectionSettingData *v1 = a; @@ -2079,7 +2099,7 @@ _log_connection_sort_hashes (NMConnection *connection, NMConnection *diff_base, return sorted_hashes; } -static gint +static int _log_connection_sort_names_fcn (gconstpointer a, gconstpointer b) { const LogConnectionSettingItem *v1 = a; @@ -2541,262 +2561,6 @@ nm_utils_machine_id_read (void) /*****************************************************************************/ -_nm_printf (3, 4) -static int -_get_contents_error (GError **error, int errsv, const char *format, ...) -{ - if (errsv < 0) - errsv = -errsv; - else if (!errsv) - errsv = errno; - - if (error) { - char *msg; - va_list args; - - va_start (args, format); - msg = g_strdup_vprintf (format, args); - va_end (args); - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errsv), - "%s: %s", - msg, g_strerror (errsv)); - g_free (msg); - } - return -errsv; -} - -/** - * nm_utils_fd_get_contents: - * @fd: open file descriptor to read. The fd will not be closed, - * but don't rely on its state afterwards. - * @close_fd: if %TRUE, @fd will be closed by the function. - * Passing %TRUE here might safe a syscall for dup(). - * @max_length: allocate at most @max_length bytes. If the - * file is larger, reading will fail. Set to zero to use - * a very large default. - * - * WARNING: @max_length is here to avoid a crash for huge/unlimited files. - * For example, stat(/sys/class/net/enp0s25/ifindex) gives a filesize of - * 4K, although the actual real is small. @max_length is the memory - * allocated in the process of reading the file, thus it must be at least - * the size reported by fstat. - * If you set it to 1K, read will fail because fstat() claims the - * file is larger. - * - * @contents: the output buffer with the file read. It is always - * NUL terminated. The buffer is at most @max_length long, including - * the NUL byte. That is, it reads only files up to a length of - * @max_length - 1 bytes. - * @length: optional output argument of the read file size. - * - * A reimplementation of g_file_get_contents() with a few differences: - * - accepts an open fd, instead of a path name. This allows you to - * use openat(). - * - limits the maxium filesize to max_length. - * - * Returns: a negative error code on failure. - */ -int -nm_utils_fd_get_contents (int fd, - gboolean close_fd, - gsize max_length, - char **contents, - gsize *length, - GError **error) -{ - nm_auto_close int fd_keeper = close_fd ? fd : -1; - struct stat stat_buf; - gs_free char *str = NULL; - - g_return_val_if_fail (fd >= 0, -EINVAL); - g_return_val_if_fail (contents, -EINVAL); - g_return_val_if_fail (!error || !*error, -EINVAL); - - if (fstat (fd, &stat_buf) < 0) - return _get_contents_error (error, 0, "failure during fstat"); - - if (!max_length) { - /* default to a very large size, but not extreme */ - max_length = 2 * 1024 * 1024; - } - - if ( stat_buf.st_size > 0 - && S_ISREG (stat_buf.st_mode)) { - const gsize n_stat = stat_buf.st_size; - ssize_t n_read; - - if (n_stat > max_length - 1) - return _get_contents_error (error, EMSGSIZE, "file too large (%zu+1 bytes with maximum %zu bytes)", n_stat, max_length); - - str = g_try_malloc (n_stat + 1); - if (!str) - return _get_contents_error (error, ENOMEM, "failure to allocate buffer of %zu+1 bytes", n_stat); - - n_read = nm_utils_fd_read_loop (fd, str, n_stat, TRUE); - if (n_read < 0) - return _get_contents_error (error, n_read, "error reading %zu bytes from file descriptor", n_stat); - str[n_read] = '\0'; - - if (n_read < n_stat) { - char *tmp; - - tmp = g_try_realloc (str, n_read + 1); - if (!tmp) - return _get_contents_error (error, ENOMEM, "failure to reallocate buffer with %zu bytes", n_read + 1); - str = tmp; - } - NM_SET_OUT (length, n_read); - } else { - nm_auto_fclose FILE *f = NULL; - char buf[4096]; - gsize n_have, n_alloc; - int fd2; - - if (fd_keeper >= 0) - fd2 = nm_steal_fd (&fd_keeper); - else { - fd2 = fcntl (fd, F_DUPFD_CLOEXEC, 0); - if (fd2 < 0) - return _get_contents_error (error, 0, "error during dup"); - } - - if (!(f = fdopen (fd2, "r"))) { - nm_close (fd2); - return _get_contents_error (error, 0, "failure during fdopen"); - } - - n_have = 0; - n_alloc = 0; - - while (!feof (f)) { - int errsv; - gsize n_read; - - n_read = fread (buf, 1, sizeof (buf), f); - errsv = errno; - if (ferror (f)) - return _get_contents_error (error, errsv, "error during fread"); - - if ( n_have > G_MAXSIZE - 1 - n_read - || n_have + n_read + 1 > max_length) { - return _get_contents_error (error, EMSGSIZE, "file stream too large (%zu+1 bytes with maximum %zu bytes)", - (n_have > G_MAXSIZE - 1 - n_read) ? G_MAXSIZE : n_have + n_read, - max_length); - } - - if (n_have + n_read + 1 >= n_alloc) { - char *tmp; - - if (str) { - if (n_alloc >= max_length / 2) - n_alloc = max_length; - else - n_alloc *= 2; - } else - n_alloc = NM_MIN (n_read + 1, sizeof (buf)); - - tmp = g_try_realloc (str, n_alloc); - if (!tmp) - return _get_contents_error (error, ENOMEM, "failure to allocate buffer of %zu bytes", n_alloc); - str = tmp; - } - - memcpy (str + n_have, buf, n_read); - n_have += n_read; - } - - if (n_alloc == 0) - str = g_new0 (gchar, 1); - else { - str[n_have] = '\0'; - if (n_have + 1 < n_alloc) { - char *tmp; - - tmp = g_try_realloc (str, n_have + 1); - if (!tmp) - return _get_contents_error (error, ENOMEM, "failure to truncate buffer to %zu bytes", n_have + 1); - str = tmp; - } - } - - NM_SET_OUT (length, n_have); - } - - *contents = g_steal_pointer (&str); - return 0; -} - -/** - * nm_utils_file_get_contents: - * @dirfd: optional file descriptor to use openat(). If negative, use plain open(). - * @filename: the filename to open. Possibly relative to @dirfd. - * @max_length: allocate at most @max_length bytes. - * WARNING: see nm_utils_fd_get_contents() hint about @max_length. - * @contents: the output buffer with the file read. It is always - * NUL terminated. The buffer is at most @max_length long, including - * the NUL byte. That is, it reads only files up to a length of - * @max_length - 1 bytes. - * @length: optional output argument of the read file size. - * - * A reimplementation of g_file_get_contents() with a few differences: - * - accepts an @dirfd to open @filename relative to that path via openat(). - * - limits the maxium filesize to max_length. - * - uses O_CLOEXEC on internal file descriptor - * - * Returns: a negative error code on failure. - */ -int -nm_utils_file_get_contents (int dirfd, - const char *filename, - gsize max_length, - char **contents, - gsize *length, - GError **error) -{ - int fd; - int errsv; - - g_return_val_if_fail (filename && filename[0], -EINVAL); - - if (dirfd >= 0) { - fd = openat (dirfd, filename, O_RDONLY | O_CLOEXEC); - if (fd < 0) { - errsv = errno; - - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errsv), - "Failed to open file \"%s\" with openat: %s", - filename, - g_strerror (errsv)); - return -errsv; - } - } else { - fd = open (filename, O_RDONLY | O_CLOEXEC); - if (fd < 0) { - errsv = errno; - - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errsv), - "Failed to open file \"%s\": %s", - filename, - g_strerror (errsv)); - return -errsv; - } - } - return nm_utils_fd_get_contents (fd, - TRUE, - max_length, - contents, - length, - error); -} - -/*****************************************************************************/ - static gboolean _secret_key_read (guint8 **out_secret_key, gsize *out_key_len) @@ -2923,6 +2687,7 @@ nm_utils_get_boot_id (void) gs_free char *contents = NULL; nm_utils_file_get_contents (-1, "/proc/sys/kernel/random/boot_id", 0, + NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, &contents, NULL, NULL); if (contents) { g_strstrip (contents); @@ -3017,7 +2782,6 @@ nm_utils_get_ipv6_interface_identifier (NMLinkType link_type, out_iid->id_u8[0] |= 0x02; return TRUE; case NM_LINK_TYPE_GRE: - case NM_LINK_TYPE_GRETAP: /* Hardware address is the network-endian IPv4 address */ g_return_val_if_fail (hwaddr_len == 4, FALSE); addr = * (guint32 *) hwaddr; @@ -3027,6 +2791,11 @@ nm_utils_get_ipv6_interface_identifier (NMLinkType link_type, out_iid->id_u8[3] = 0xFE; memcpy (out_iid->id_u8 + 4, &addr, 4); return TRUE; + case NM_LINK_TYPE_6LOWPAN: + /* The hardware address is already 64-bit. This is the case for + * IEEE 802.15.4 networks. */ + memcpy (out_iid->id_u8, hwaddr, sizeof (out_iid->id_u8)); + return TRUE; default: if (hwaddr_len == ETH_ALEN) { /* Translate 48-bit MAC address to a 64-bit Modified EUI-64. See @@ -3661,8 +3430,8 @@ nm_utils_g_value_set_strv (GValue *value, GPtrArray *strings) /*****************************************************************************/ static gboolean -debug_key_matches (const gchar *key, - const gchar *token, +debug_key_matches (const char *key, + const char *token, guint length) { /* may not call GLib functions: see note in g_parse_debug_string() */ @@ -3964,116 +3733,12 @@ nm_utils_get_reverse_dns_domains_ip6 (const struct in6_addr *ip, guint8 plen, GP #undef N_SHIFT } -/** - * Copied from GLib's g_file_set_contents() et al., but allows - * specifying a mode for the new file. - */ -gboolean -nm_utils_file_set_contents (const gchar *filename, - const gchar *contents, - gssize length, - mode_t mode, - GError **error) -{ - gs_free char *tmp_name = NULL; - struct stat statbuf; - int errsv; - gssize s; - int fd; - - g_return_val_if_fail (filename, FALSE); - g_return_val_if_fail (contents || !length, FALSE); - g_return_val_if_fail (!error || !*error, FALSE); - g_return_val_if_fail (length >= -1, FALSE); - - if (length == -1) - length = strlen (contents); - - tmp_name = g_strdup_printf ("%s.XXXXXX", filename); - fd = g_mkstemp_full (tmp_name, O_RDWR, mode); - if (fd < 0) { - errsv = errno; - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errsv), - "failed to create file %s: %s", - tmp_name, - g_strerror (errsv)); - return FALSE; - } - - while (length > 0) { - s = write (fd, contents, length); - if (s < 0) { - errsv = errno; - if (errsv == EINTR) - continue; - - nm_close (fd); - unlink (tmp_name); - - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errsv), - "failed to write to file %s: %s", - tmp_name, - g_strerror (errsv)); - return FALSE; - } - - g_assert (s <= length); - - contents += s; - length -= s; - } - - /* If the final destination exists and is > 0 bytes, we want to sync the - * newly written file to ensure the data is on disk when we rename over - * the destination. Otherwise if we get a system crash we can lose both - * the new and the old file on some filesystems. (I.E. those that don't - * guarantee the data is written to the disk before the metadata.) - */ - if ( lstat (filename, &statbuf) == 0 - && statbuf.st_size > 0 - && fsync (fd) != 0) { - errsv = errno; - - nm_close (fd); - unlink (tmp_name); - - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errsv), - "failed to fsync %s: %s", - tmp_name, - g_strerror (errsv)); - return FALSE; - } - - nm_close (fd); - - if (rename (tmp_name, filename)) { - errsv = errno; - unlink (tmp_name); - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errsv), - "failed to rename %s to %s: %s", - tmp_name, - filename, - g_strerror (errsv)); - return FALSE; - } - - return TRUE; -} - struct plugin_info { char *path; struct stat st; }; -static gint +static int read_device_factory_paths_sort_fcn (gconstpointer a, gconstpointer b) { const struct plugin_info *da = a; |