mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-23 12:41:50 +01:00
gcredentials: add Solaris support
Based on patches from Igor Pashev. https://bugzilla.gnome.org/show_bug.cgi?id=705029
This commit is contained in:
parent
66edac7fb9
commit
5a269e5a90
@ -65,6 +65,10 @@
|
|||||||
*
|
*
|
||||||
* On OpenBSD, the native credential type is a <type>struct sockpeercred</type>.
|
* On OpenBSD, the native credential type is a <type>struct sockpeercred</type>.
|
||||||
* This corresponds to %G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED.
|
* This corresponds to %G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED.
|
||||||
|
*
|
||||||
|
* On Solaris (including OpenSolaris and its derivatives), the native
|
||||||
|
* credential type is a <type>ucred_t</type>. This corresponds to
|
||||||
|
* %G_CREDENTIALS_TYPE_SOLARIS_UCRED.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,6 +90,8 @@ struct _GCredentials
|
|||||||
struct cmsgcred native;
|
struct cmsgcred native;
|
||||||
#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
|
#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
|
||||||
struct sockpeercred native;
|
struct sockpeercred native;
|
||||||
|
#elif G_CREDENTIALS_USE_SOLARIS_UCRED
|
||||||
|
ucred_t *native;
|
||||||
#else
|
#else
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#warning Please add GCredentials support for your OS
|
#warning Please add GCredentials support for your OS
|
||||||
@ -111,7 +117,11 @@ G_DEFINE_TYPE (GCredentials, g_credentials, G_TYPE_OBJECT);
|
|||||||
static void
|
static void
|
||||||
g_credentials_finalize (GObject *object)
|
g_credentials_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
G_GNUC_UNUSED GCredentials *credentials = G_CREDENTIALS (object);
|
#if G_CREDENTIALS_USE_SOLARIS_UCRED
|
||||||
|
GCredentials *credentials = G_CREDENTIALS (object);
|
||||||
|
|
||||||
|
ucred_free (credentials->native);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (G_OBJECT_CLASS (g_credentials_parent_class)->finalize != NULL)
|
if (G_OBJECT_CLASS (g_credentials_parent_class)->finalize != NULL)
|
||||||
G_OBJECT_CLASS (g_credentials_parent_class)->finalize (object);
|
G_OBJECT_CLASS (g_credentials_parent_class)->finalize (object);
|
||||||
@ -143,6 +153,8 @@ g_credentials_init (GCredentials *credentials)
|
|||||||
credentials->native.pid = getpid ();
|
credentials->native.pid = getpid ();
|
||||||
credentials->native.uid = geteuid ();
|
credentials->native.uid = geteuid ();
|
||||||
credentials->native.gid = getegid ();
|
credentials->native.gid = getegid ();
|
||||||
|
#elif G_CREDENTIALS_USE_SOLARIS_UCRED
|
||||||
|
credentials->native = ucred_get (P_MYID);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,6 +226,19 @@ g_credentials_to_string (GCredentials *credentials)
|
|||||||
g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.gid);
|
g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.gid);
|
||||||
if (ret->str[ret->len - 1] == ',')
|
if (ret->str[ret->len - 1] == ',')
|
||||||
ret->str[ret->len - 1] = '\0';
|
ret->str[ret->len - 1] = '\0';
|
||||||
|
#elif G_CREDENTIALS_USE_SOLARIS_UCRED
|
||||||
|
g_string_append (ret, "solaris-ucred:");
|
||||||
|
{
|
||||||
|
id_t id;
|
||||||
|
if ((id = ucred_getpid (credentials->native)) != -1)
|
||||||
|
g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) id);
|
||||||
|
if ((id = ucred_geteuid (credentials->native)) != -1)
|
||||||
|
g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) id);
|
||||||
|
if ((id = ucred_getegid (credentials->native)) != -1)
|
||||||
|
g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) id);
|
||||||
|
if (ret->str[ret->len - 1] == ',')
|
||||||
|
ret->str[ret->len - 1] = '\0';
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
g_string_append (ret, "unknown");
|
g_string_append (ret, "unknown");
|
||||||
#endif
|
#endif
|
||||||
@ -260,6 +285,9 @@ g_credentials_is_same_user (GCredentials *credentials,
|
|||||||
#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
|
#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
|
||||||
if (credentials->native.uid == other_credentials->native.uid)
|
if (credentials->native.uid == other_credentials->native.uid)
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
|
#elif G_CREDENTIALS_USE_SOLARIS_UCRED
|
||||||
|
if (ucred_geteuid (credentials->native) == ucred_geteuid (other_credentials->native))
|
||||||
|
ret = TRUE;
|
||||||
#else
|
#else
|
||||||
g_set_error_literal (error,
|
g_set_error_literal (error,
|
||||||
G_IO_ERROR,
|
G_IO_ERROR,
|
||||||
@ -334,7 +362,9 @@ g_credentials_get_native (GCredentials *credentials,
|
|||||||
if (!credentials_native_type_check (native_type, "get"))
|
if (!credentials_native_type_check (native_type, "get"))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
#if G_CREDENTIALS_SUPPORTED
|
#if G_CREDENTIALS_USE_SOLARIS_UCRED
|
||||||
|
return credentials->native;
|
||||||
|
#elif G_CREDENTIALS_SUPPORTED
|
||||||
return &credentials->native;
|
return &credentials->native;
|
||||||
#else
|
#else
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
@ -364,7 +394,9 @@ g_credentials_set_native (GCredentials *credentials,
|
|||||||
if (!credentials_native_type_check (native_type, "set"))
|
if (!credentials_native_type_check (native_type, "set"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if G_CREDENTIALS_SUPPORTED
|
#if G_CREDENTIALS_USE_SOLARIS_UCRED
|
||||||
|
memcpy (credentials->native, native, ucred_size ());
|
||||||
|
#elif G_CREDENTIALS_SUPPORTED
|
||||||
memcpy (&credentials->native, native, sizeof (credentials->native));
|
memcpy (&credentials->native, native, sizeof (credentials->native));
|
||||||
#else
|
#else
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
@ -405,6 +437,8 @@ g_credentials_get_unix_user (GCredentials *credentials,
|
|||||||
ret = credentials->native.cmcred_euid;
|
ret = credentials->native.cmcred_euid;
|
||||||
#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
|
#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
|
||||||
ret = credentials->native.uid;
|
ret = credentials->native.uid;
|
||||||
|
#elif G_CREDENTIALS_USE_SOLARIS_UCRED
|
||||||
|
ret = ucred_geteuid (credentials->native);
|
||||||
#else
|
#else
|
||||||
ret = -1;
|
ret = -1;
|
||||||
g_set_error_literal (error,
|
g_set_error_literal (error,
|
||||||
@ -447,6 +481,8 @@ g_credentials_get_unix_pid (GCredentials *credentials,
|
|||||||
ret = credentials->native.cmcred_pid;
|
ret = credentials->native.cmcred_pid;
|
||||||
#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
|
#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
|
||||||
ret = credentials->native.pid;
|
ret = credentials->native.pid;
|
||||||
|
#elif G_CREDENTIALS_USE_SOLARIS_UCRED
|
||||||
|
ret = ucred_getpid (credentials->native);
|
||||||
#else
|
#else
|
||||||
ret = -1;
|
ret = -1;
|
||||||
g_set_error_literal (error,
|
g_set_error_literal (error,
|
||||||
@ -469,7 +505,8 @@ g_credentials_get_unix_pid (GCredentials *credentials,
|
|||||||
*
|
*
|
||||||
* This operation can fail if #GCredentials is not supported on the
|
* This operation can fail if #GCredentials is not supported on the
|
||||||
* OS or if the native credentials type does not contain information
|
* OS or if the native credentials type does not contain information
|
||||||
* about the UNIX user.
|
* about the UNIX user. It can also fail if the OS does not allow the
|
||||||
|
* use of "spoofed" credentials.
|
||||||
*
|
*
|
||||||
* Returns: %TRUE if @uid was set, %FALSE if error is set.
|
* Returns: %TRUE if @uid was set, %FALSE if error is set.
|
||||||
*
|
*
|
||||||
@ -496,11 +533,18 @@ g_credentials_set_unix_user (GCredentials *credentials,
|
|||||||
#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
|
#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
|
||||||
credentials->native.uid = uid;
|
credentials->native.uid = uid;
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
|
#elif !G_CREDENTIALS_SPOOFING_SUPPORTED
|
||||||
|
g_set_error_literal (error,
|
||||||
|
G_IO_ERROR,
|
||||||
|
G_IO_ERROR_PERMISSION_DENIED,
|
||||||
|
_("Credentials spoofing is not possible on this OS"));
|
||||||
|
ret = FALSE;
|
||||||
#else
|
#else
|
||||||
g_set_error_literal (error,
|
g_set_error_literal (error,
|
||||||
G_IO_ERROR,
|
G_IO_ERROR,
|
||||||
G_IO_ERROR_NOT_SUPPORTED,
|
G_IO_ERROR_NOT_SUPPORTED,
|
||||||
_("GCredentials is not implemented on this OS"));
|
_("GCredentials is not implemented on this OS"));
|
||||||
|
ret = FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct ucred))
|
#define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct ucred))
|
||||||
#define G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1
|
#define G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1
|
||||||
#define G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED 1
|
#define G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED 1
|
||||||
|
#define G_CREDENTIALS_SPOOFING_SUPPORTED 1
|
||||||
|
|
||||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
|
||||||
#define G_CREDENTIALS_SUPPORTED 1
|
#define G_CREDENTIALS_SUPPORTED 1
|
||||||
@ -38,6 +39,7 @@
|
|||||||
#define G_CREDENTIALS_NATIVE_TYPE G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED
|
#define G_CREDENTIALS_NATIVE_TYPE G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED
|
||||||
#define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct cmsgcred))
|
#define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct cmsgcred))
|
||||||
#define G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1
|
#define G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1
|
||||||
|
#define G_CREDENTIALS_SPOOFING_SUPPORTED 1
|
||||||
|
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__)
|
||||||
#define G_CREDENTIALS_SUPPORTED 1
|
#define G_CREDENTIALS_SUPPORTED 1
|
||||||
@ -45,6 +47,16 @@
|
|||||||
#define G_CREDENTIALS_NATIVE_TYPE G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED
|
#define G_CREDENTIALS_NATIVE_TYPE G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED
|
||||||
#define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct sockpeercred))
|
#define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct sockpeercred))
|
||||||
#define G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED 1
|
#define G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED 1
|
||||||
|
#define G_CREDENTIALS_SPOOFING_SUPPORTED 1
|
||||||
|
|
||||||
|
#elif defined(__sun__) || defined(__illumos__) || defined (__OpenSolaris_kernel__)
|
||||||
|
#include <ucred.h>
|
||||||
|
#define G_CREDENTIALS_SUPPORTED 1
|
||||||
|
#define G_CREDENTIALS_USE_SOLARIS_UCRED 1
|
||||||
|
#define G_CREDENTIALS_NATIVE_TYPE G_CREDENTIALS_TYPE_SOLARIS_UCRED
|
||||||
|
#define G_CREDENTIALS_NATIVE_SIZE (ucred_size ())
|
||||||
|
#define G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1
|
||||||
|
#define G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED 1
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1342,6 +1342,7 @@ typedef enum
|
|||||||
* @G_CREDENTIALS_TYPE_LINUX_UCRED: The native credentials type is a <type>struct ucred</type>.
|
* @G_CREDENTIALS_TYPE_LINUX_UCRED: The native credentials type is a <type>struct ucred</type>.
|
||||||
* @G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED: The native credentials type is a <type>struct cmsgcred</type>.
|
* @G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED: The native credentials type is a <type>struct cmsgcred</type>.
|
||||||
* @G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED: The native credentials type is a <type>struct sockpeercred</type>. Added in 2.30.
|
* @G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED: The native credentials type is a <type>struct sockpeercred</type>. Added in 2.30.
|
||||||
|
* @G_CREDENTIALS_TYPE_SOLARIS_UCRED: The native credentials type is a <type>ucred_t</type>. Added in 2.40.
|
||||||
*
|
*
|
||||||
* Enumeration describing different kinds of native credential types.
|
* Enumeration describing different kinds of native credential types.
|
||||||
*
|
*
|
||||||
@ -1352,7 +1353,8 @@ typedef enum
|
|||||||
G_CREDENTIALS_TYPE_INVALID,
|
G_CREDENTIALS_TYPE_INVALID,
|
||||||
G_CREDENTIALS_TYPE_LINUX_UCRED,
|
G_CREDENTIALS_TYPE_LINUX_UCRED,
|
||||||
G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED,
|
G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED,
|
||||||
G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED
|
G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED,
|
||||||
|
G_CREDENTIALS_TYPE_SOLARIS_UCRED
|
||||||
} GCredentialsType;
|
} GCredentialsType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4449,6 +4449,8 @@ g_socket_get_credentials (GSocket *socket,
|
|||||||
ret = NULL;
|
ret = NULL;
|
||||||
|
|
||||||
#if G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED
|
#if G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED
|
||||||
|
|
||||||
|
#ifdef SO_PEERCRED
|
||||||
{
|
{
|
||||||
guint8 native_creds_buf[G_CREDENTIALS_NATIVE_SIZE];
|
guint8 native_creds_buf[G_CREDENTIALS_NATIVE_SIZE];
|
||||||
socklen_t optlen = sizeof (native_creds_buf);
|
socklen_t optlen = sizeof (native_creds_buf);
|
||||||
@ -4464,17 +4466,37 @@ g_socket_get_credentials (GSocket *socket,
|
|||||||
G_CREDENTIALS_NATIVE_TYPE,
|
G_CREDENTIALS_NATIVE_TYPE,
|
||||||
native_creds_buf);
|
native_creds_buf);
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
#elif G_CREDENTIALS_USE_SOLARIS_UCRED
|
||||||
|
{
|
||||||
|
ucred_t *ucred = NULL;
|
||||||
|
|
||||||
|
if (getpeerucred (socket->priv->fd, &ucred) == 0)
|
||||||
{
|
{
|
||||||
int errsv = get_socket_errno ();
|
ret = g_credentials_new ();
|
||||||
g_set_error (error,
|
g_credentials_set_native (ret,
|
||||||
G_IO_ERROR,
|
G_CREDENTIALS_TYPE_SOLARIS_UCRED,
|
||||||
socket_io_error_from_errno (errsv),
|
ucred);
|
||||||
_("Unable to read socket credentials: %s"),
|
ucred_free (ucred);
|
||||||
socket_strerror (errsv));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
#error "G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED is set but this is no code for this platform"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
int errsv = get_socket_errno ();
|
||||||
|
|
||||||
|
g_set_error (error,
|
||||||
|
G_IO_ERROR,
|
||||||
|
socket_io_error_from_errno (errsv),
|
||||||
|
_("Unable to read socket credentials: %s"),
|
||||||
|
socket_strerror (errsv));
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
g_set_error_literal (error,
|
g_set_error_literal (error,
|
||||||
G_IO_ERROR,
|
G_IO_ERROR,
|
||||||
G_IO_ERROR_NOT_SUPPORTED,
|
G_IO_ERROR_NOT_SUPPORTED,
|
||||||
|
@ -89,6 +89,8 @@ g_unix_credentials_message_get_msg_type (GSocketControlMessage *message)
|
|||||||
return SCM_CREDENTIALS;
|
return SCM_CREDENTIALS;
|
||||||
#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
|
#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
|
||||||
return SCM_CREDS;
|
return SCM_CREDS;
|
||||||
|
#elif G_CREDENTIALS_USE_SOLARIS_UCRED
|
||||||
|
return SCM_UCRED;
|
||||||
#elif G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED
|
#elif G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED
|
||||||
#error "G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED is set but there is no msg_type defined for this platform"
|
#error "G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED is set but there is no msg_type defined for this platform"
|
||||||
#else
|
#else
|
||||||
|
@ -59,12 +59,22 @@ test_basic (void)
|
|||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
|
|
||||||
set = g_credentials_set_unix_user (other, not_me, &error);
|
set = g_credentials_set_unix_user (other, not_me, &error);
|
||||||
|
#if G_CREDENTIALS_SPOOFING_SUPPORTED
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
g_assert (set);
|
g_assert (set);
|
||||||
|
|
||||||
g_assert_cmpuint (g_credentials_get_unix_user (other, &error), ==, not_me);
|
g_assert_cmpuint (g_credentials_get_unix_user (other, &error), ==, not_me);
|
||||||
g_assert (!g_credentials_is_same_user (creds, other, &error));
|
g_assert (!g_credentials_is_same_user (creds, other, &error));
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
|
#else
|
||||||
|
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED);
|
||||||
|
g_assert (!set);
|
||||||
|
g_clear_error (&error);
|
||||||
|
|
||||||
|
g_assert_cmpuint (g_credentials_get_unix_user (other, &error), ==, geteuid ());
|
||||||
|
g_assert (g_credentials_is_same_user (creds, other, &error));
|
||||||
|
g_assert_no_error (error);
|
||||||
|
#endif
|
||||||
|
|
||||||
stringified = g_credentials_to_string (creds);
|
stringified = g_credentials_to_string (creds);
|
||||||
g_test_message ("%s", stringified);
|
g_test_message ("%s", stringified);
|
||||||
@ -98,6 +108,14 @@ test_basic (void)
|
|||||||
g_assert_cmpuint (native->uid, ==, geteuid ());
|
g_assert_cmpuint (native->uid, ==, geteuid ());
|
||||||
g_assert_cmpuint (native->pid, ==, getpid ());
|
g_assert_cmpuint (native->pid, ==, getpid ());
|
||||||
}
|
}
|
||||||
|
#elif G_CREDENTIALS_USE_SOLARIS_UCRED
|
||||||
|
{
|
||||||
|
ucred_t *native = g_credentials_get_native (creds,
|
||||||
|
G_CREDENTIALS_TYPE_SOLARIS_UCRED);
|
||||||
|
|
||||||
|
g_assert_cmpuint (ucred_geteuid (native), ==, geteuid ());
|
||||||
|
g_assert_cmpuint (ucred_getpid (native), ==, getpid ());
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
#error "G_CREDENTIALS_SUPPORTED is set but there is no test for this platform"
|
#error "G_CREDENTIALS_SUPPORTED is set but there is no test for this platform"
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user