platform: set errno to ENOENT for nm_platform_sysctl_get()

This commit is contained in:
Thomas Haller 2019-04-04 10:57:32 +02:00 committed by Beniamino Galvani
parent e7e5f4a2d6
commit dc64745dd8
4 changed files with 71 additions and 13 deletions

View file

@ -154,10 +154,17 @@ static char *
sysctl_get (NMPlatform *platform, const char *pathid, int dirfd, const char *path)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform);
const char *v;
ASSERT_SYSCTL_ARGS (pathid, dirfd, path);
return g_strdup (g_hash_table_lookup (priv->options, path));
v = g_hash_table_lookup (priv->options, path);
if (!v) {
errno = ENOENT;
return NULL;
}
return g_strdup (v);
}
static NMFakePlatformLink *

View file

@ -4618,22 +4618,31 @@ sysctl_get (NMPlatform *platform, const char *pathid, int dirfd, const char *pat
ASSERT_SYSCTL_ARGS (pathid, dirfd, path);
if (dirfd < 0) {
if (!nm_platform_netns_push (platform, &netns))
if (!nm_platform_netns_push (platform, &netns)) {
errno = EBUSY;
return NULL;
}
pathid = path;
}
if (nm_utils_file_get_contents (dirfd, path, 1*1024*1024,
NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE,
&contents, NULL, &error) < 0) {
/* We assume FAILED means EOPNOTSUP */
if ( g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)
|| g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NODEV)
|| g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_FAILED))
_LOGD ("error reading %s: %s", pathid, error->message);
else
_LOGE ("error reading %s: %s", pathid, error->message);
NMLogLevel log_level = LOGL_ERR;
int errsv = EBUSY;
if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) {
errsv = ENOENT;
log_level = LOGL_DEBUG;
} else if ( g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NODEV)
|| g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_FAILED)) {
/* We assume FAILED means EOPNOTSUP and don't log a error message. */
log_level = LOGL_DEBUG;
}
_NMLOG (log_level, "error reading %s: %s", pathid, error->message);
g_clear_error (&error);
errno = errsv;
return NULL;
}
@ -4641,6 +4650,7 @@ sysctl_get (NMPlatform *platform, const char *pathid, int dirfd, const char *pat
_log_dbg_sysctl_get (platform, pathid, contents);
/* errno is left undefined (as we don't return NULL). */
return contents;
}

View file

@ -469,6 +469,8 @@ nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe (NMPlatform *self,
* @path: Absolute path to sysctl
*
* Returns: (transfer full): Contents of the virtual sysctl file.
*
* If the path does not exist, %NULL is returned and %errno set to %ENOENT.
*/
char *
nm_platform_sysctl_get (NMPlatform *self, const char *pathid, int dirfd, const char *path)
@ -518,6 +520,8 @@ nm_platform_sysctl_get_int32 (NMPlatform *self, const char *pathid, int dirfd, c
* value. On success, %errno will be set to zero. The returned value
* will always be in the range between @min and @max
* (inclusive) or @fallback.
* If the file does not exist, the fallback is returned and %errno
* is set to ENOENT.
*/
gint64
nm_platform_sysctl_get_int_checked (NMPlatform *self,
@ -537,14 +541,20 @@ nm_platform_sysctl_get_int_checked (NMPlatform *self,
g_return_val_if_fail (path, fallback);
if (path)
value = nm_platform_sysctl_get (self, pathid, dirfd, path);
if (!value) {
if (!path) {
errno = EINVAL;
return fallback;
}
value = nm_platform_sysctl_get (self, pathid, dirfd, path);
if (!value) {
/* nm_platform_sysctl_get() set errno to ENOENT if the file does not exist.
* Propagate/preserve that. */
if (errno != ENOENT)
errno = EINVAL;
return fallback;
}
ret = _nm_utils_ascii_str_to_int64 (value, base, min, max, fallback);
errsv = errno;
g_free (value);

View file

@ -2963,6 +2963,37 @@ test_sysctl_netns_switch (void)
g_assert_cmpint (ifindex, ==, (gint32) nm_platform_sysctl_get_int32 (PL, NMP_SYSCTL_PATHID_NETDIR (dirfd, s ?: "<unknown>", "ifindex"), -1));
g_assert_cmpint (ifindex, ==, (gint32) nm_platform_sysctl_get_int32 (PL, NMP_SYSCTL_PATHID_ABSOLUTE (nm_sprintf_bufa (100, "/sys/class/net/%s/ifindex", IFNAME)), -1));
/* also test that nm_platform_sysctl_get() sets errno to ENOENT for non-existing paths. */
{
gint64 i64;
int errsv;
char *v;
errno = ESRCH;
v = nm_platform_sysctl_get (PL, NMP_SYSCTL_PATHID_ABSOLUTE ("/sys/devices/virtual/net/not-existing/ifindex"));
errsv = errno;
g_assert (!v);
g_assert_cmpint (errsv, ==, ENOENT);
errno = ESRCH;
i64 = nm_platform_sysctl_get_int_checked (PL, NMP_SYSCTL_PATHID_ABSOLUTE ("/sys/devices/virtual/net/not-existing/ifindex"), 10, 1, G_MAXINT, -1);
errsv = errno;
g_assert_cmpint (i64, ==, -1);
g_assert_cmpint (errsv, ==, ENOENT);
errno = ESRCH;
v = nm_platform_sysctl_get (PL, NMP_SYSCTL_PATHID_ABSOLUTE ("/sys/devices/virtual/net/lo/not-existing"));
errsv = errno;
g_assert (!v);
g_assert_cmpint (errsv, ==, ENOENT);
errno = ESRCH;
i64 = nm_platform_sysctl_get_int_checked (PL, NMP_SYSCTL_PATHID_ABSOLUTE ("/sys/devices/virtual/net/lo/not-existing"), 10, 1, G_MAXINT, -1);
errsv = errno;
g_assert_cmpint (i64, ==, -1);
g_assert_cmpint (errsv, ==, ENOENT);
}
/* accessing the path directly, only succeeds iff the current namespace happens to be the namespace
* in which we created the link. */
{