glib/glib/tests/fileutils.c
Philip Withnall 648986a290 glib: Avoid redefining GLIB_DISABLE_DEPRECATION_WARNINGS
It may be defined by the environment (we document that as being allowed)
— if so, individual files should not try to redefine it, as that causes
a preprocessor warning.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
2020-07-27 15:41:09 +01:00

1810 lines
68 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Unit tests for gfileutils
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This work is provided "as is"; redistribution and modification
* in whole or in part, in any medium, physical or electronic is
* permitted without restriction.
*
* This work 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.
*
* In no event shall the authors or contributors be liable for any
* direct, indirect, incidental, special, exemplary, or consequential
* damages (including, but not limited to, procurement of substitute
* goods or services; loss of use, data, or profits; or business
* interruption) however caused and on any theory of liability, whether
* in contract, strict liability, or tort (including negligence or
* otherwise) arising in any way out of the use of this software, even
* if advised of the possibility of such damage.
*/
#include "config.h"
#include <string.h>
#include <errno.h>
/* We are testing some deprecated APIs here */
#ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#endif
#include <glib.h>
/* Test our stdio wrappers here; this disables redefining (e.g.) g_open() to open() */
#define G_STDIO_WRAP_ON_UNIX
#include <glib/gstdio.h>
#ifdef G_OS_UNIX
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <utime.h>
#define G_TEST_DIR_MODE 0555
#endif
#include <fcntl.h>
#ifdef G_OS_WIN32
#include <windows.h>
#include <sys/utime.h>
#include <io.h>
#ifndef S_ISDIR
#define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
#endif
#ifndef F_OK
#define F_OK 0
#endif
#define G_TEST_DIR_MODE (S_IWRITE | S_IREAD)
#endif
#define S G_DIR_SEPARATOR_S
static void
check_string (gchar *str, const gchar *expected)
{
g_assert_nonnull (str);
g_assert_cmpstr (str, ==, expected);
g_free (str);
}
static void
test_build_path (void)
{
/* check_string (g_build_path ("", NULL), "");*/
check_string (g_build_path ("", "", NULL), "");
check_string (g_build_path ("", "x", NULL), "x");
check_string (g_build_path ("", "x", "y", NULL), "xy");
check_string (g_build_path ("", "x", "y", "z", NULL), "xyz");
/* check_string (g_build_path (":", NULL), "");*/
check_string (g_build_path (":", ":", NULL), ":");
check_string (g_build_path (":", ":x", NULL), ":x");
check_string (g_build_path (":", "x:", NULL), "x:");
check_string (g_build_path (":", "", "x", NULL), "x");
check_string (g_build_path (":", "", ":x", NULL), ":x");
check_string (g_build_path (":", ":", "x", NULL), ":x");
check_string (g_build_path (":", "::", "x", NULL), "::x");
check_string (g_build_path (":", "x", "", NULL), "x");
check_string (g_build_path (":", "x:", "", NULL), "x:");
check_string (g_build_path (":", "x", ":", NULL), "x:");
check_string (g_build_path (":", "x", "::", NULL), "x::");
check_string (g_build_path (":", "x", "y", NULL), "x:y");
check_string (g_build_path (":", ":x", "y", NULL), ":x:y");
check_string (g_build_path (":", "x", "y:", NULL), "x:y:");
check_string (g_build_path (":", ":x:", ":y:", NULL), ":x:y:");
check_string (g_build_path (":", ":x::", "::y:", NULL), ":x:y:");
check_string (g_build_path (":", "x", "","y", NULL), "x:y");
check_string (g_build_path (":", "x", ":", "y", NULL), "x:y");
check_string (g_build_path (":", "x", "::", "y", NULL), "x:y");
check_string (g_build_path (":", "x", "y", "z", NULL), "x:y:z");
check_string (g_build_path (":", ":x:", ":y:", ":z:", NULL), ":x:y:z:");
check_string (g_build_path (":", "::x::", "::y::", "::z::", NULL), "::x:y:z::");
/* check_string (g_build_path ("::", NULL), "");*/
check_string (g_build_path ("::", "::", NULL), "::");
check_string (g_build_path ("::", ":::", NULL), ":::");
check_string (g_build_path ("::", "::x", NULL), "::x");
check_string (g_build_path ("::", "x::", NULL), "x::");
check_string (g_build_path ("::", "", "x", NULL), "x");
check_string (g_build_path ("::", "", "::x", NULL), "::x");
check_string (g_build_path ("::", "::", "x", NULL), "::x");
check_string (g_build_path ("::", "::::", "x", NULL), "::::x");
check_string (g_build_path ("::", "x", "", NULL), "x");
check_string (g_build_path ("::", "x::", "", NULL), "x::");
check_string (g_build_path ("::", "x", "::", NULL), "x::");
/* This following is weird, but keeps the definition simple */
check_string (g_build_path ("::", "x", ":::", NULL), "x:::::");
check_string (g_build_path ("::", "x", "::::", NULL), "x::::");
check_string (g_build_path ("::", "x", "y", NULL), "x::y");
check_string (g_build_path ("::", "::x", "y", NULL), "::x::y");
check_string (g_build_path ("::", "x", "y::", NULL), "x::y::");
check_string (g_build_path ("::", "::x::", "::y::", NULL), "::x::y::");
check_string (g_build_path ("::", "::x:::", ":::y::", NULL), "::x::::y::");
check_string (g_build_path ("::", "::x::::", "::::y::", NULL), "::x::y::");
check_string (g_build_path ("::", "x", "", "y", NULL), "x::y");
check_string (g_build_path ("::", "x", "::", "y", NULL), "x::y");
check_string (g_build_path ("::", "x", "::::", "y", NULL), "x::y");
check_string (g_build_path ("::", "x", "y", "z", NULL), "x::y::z");
check_string (g_build_path ("::", "::x::", "::y::", "::z::", NULL), "::x::y::z::");
check_string (g_build_path ("::", ":::x:::", ":::y:::", ":::z:::", NULL), ":::x::::y::::z:::");
check_string (g_build_path ("::", "::::x::::", "::::y::::", "::::z::::", NULL), "::::x::y::z::::");
}
static void
test_build_pathv (void)
{
gchar *args[10];
g_assert_null (g_build_pathv ("", NULL));
args[0] = NULL;
check_string (g_build_pathv ("", args), "");
args[0] = ""; args[1] = NULL;
check_string (g_build_pathv ("", args), "");
args[0] = "x"; args[1] = NULL;
check_string (g_build_pathv ("", args), "x");
args[0] = "x"; args[1] = "y"; args[2] = NULL;
check_string (g_build_pathv ("", args), "xy");
args[0] = "x"; args[1] = "y"; args[2] = "z", args[3] = NULL;
check_string (g_build_pathv ("", args), "xyz");
args[0] = NULL;
check_string (g_build_pathv (":", args), "");
args[0] = ":"; args[1] = NULL;
check_string (g_build_pathv (":", args), ":");
args[0] = ":x"; args[1] = NULL;
check_string (g_build_pathv (":", args), ":x");
args[0] = "x:"; args[1] = NULL;
check_string (g_build_pathv (":", args), "x:");
args[0] = ""; args[1] = "x"; args[2] = NULL;
check_string (g_build_pathv (":", args), "x");
args[0] = ""; args[1] = ":x"; args[2] = NULL;
check_string (g_build_pathv (":", args), ":x");
args[0] = ":"; args[1] = "x"; args[2] = NULL;
check_string (g_build_pathv (":", args), ":x");
args[0] = "::"; args[1] = "x"; args[2] = NULL;
check_string (g_build_pathv (":", args), "::x");
args[0] = "x"; args[1] = ""; args[2] = NULL;
check_string (g_build_pathv (":", args), "x");
args[0] = "x:"; args[1] = ""; args[2] = NULL;
check_string (g_build_pathv (":", args), "x:");
args[0] = "x"; args[1] = ":"; args[2] = NULL;
check_string (g_build_pathv (":", args), "x:");
args[0] = "x"; args[1] = "::"; args[2] = NULL;
check_string (g_build_pathv (":", args), "x::");
args[0] = "x"; args[1] = "y"; args[2] = NULL;
check_string (g_build_pathv (":", args), "x:y");
args[0] = ":x"; args[1] = "y"; args[2] = NULL;
check_string (g_build_pathv (":", args), ":x:y");
args[0] = "x"; args[1] = "y:"; args[2] = NULL;
check_string (g_build_pathv (":", args), "x:y:");
args[0] = ":x:"; args[1] = ":y:"; args[2] = NULL;
check_string (g_build_pathv (":", args), ":x:y:");
args[0] = ":x::"; args[1] = "::y:"; args[2] = NULL;
check_string (g_build_pathv (":", args), ":x:y:");
args[0] = "x"; args[1] = ""; args[2] = "y"; args[3] = NULL;
check_string (g_build_pathv (":", args), "x:y");
args[0] = "x"; args[1] = ":"; args[2] = "y"; args[3] = NULL;
check_string (g_build_pathv (":", args), "x:y");
args[0] = "x"; args[1] = "::"; args[2] = "y"; args[3] = NULL;
check_string (g_build_pathv (":", args), "x:y");
args[0] = "x"; args[1] = "y"; args[2] = "z"; args[3] = NULL;
check_string (g_build_pathv (":", args), "x:y:z");
args[0] = ":x:"; args[1] = ":y:"; args[2] = ":z:"; args[3] = NULL;
check_string (g_build_pathv (":", args), ":x:y:z:");
args[0] = "::x::"; args[1] = "::y::"; args[2] = "::z::"; args[3] = NULL;
check_string (g_build_pathv (":", args), "::x:y:z::");
args[0] = NULL;
check_string (g_build_pathv ("::", args), "");
args[0] = "::"; args[1] = NULL;
check_string (g_build_pathv ("::", args), "::");
args[0] = ":::"; args[1] = NULL;
check_string (g_build_pathv ("::", args), ":::");
args[0] = "::x"; args[1] = NULL;
check_string (g_build_pathv ("::", args), "::x");
args[0] = "x::"; args[1] = NULL;
check_string (g_build_pathv ("::", args), "x::");
args[0] = ""; args[1] = "x"; args[2] = NULL;
check_string (g_build_pathv ("::", args), "x");
args[0] = ""; args[1] = "::x"; args[2] = NULL;
check_string (g_build_pathv ("::", args), "::x");
args[0] = "::"; args[1] = "x"; args[2] = NULL;
check_string (g_build_pathv ("::", args), "::x");
args[0] = "::::"; args[1] = "x"; args[2] = NULL;
check_string (g_build_pathv ("::", args), "::::x");
args[0] = "x"; args[1] = ""; args[2] = NULL;
check_string (g_build_pathv ("::", args), "x");
args[0] = "x::"; args[1] = ""; args[2] = NULL;
check_string (g_build_pathv ("::", args), "x::");
args[0] = "x"; args[1] = "::"; args[2] = NULL;
check_string (g_build_pathv ("::", args), "x::");
/* This following is weird, but keeps the definition simple */
args[0] = "x"; args[1] = ":::"; args[2] = NULL;
check_string (g_build_pathv ("::", args), "x:::::");
args[0] = "x"; args[1] = "::::"; args[2] = NULL;
check_string (g_build_pathv ("::", args), "x::::");
args[0] = "x"; args[1] = "y"; args[2] = NULL;
check_string (g_build_pathv ("::", args), "x::y");
args[0] = "::x"; args[1] = "y"; args[2] = NULL;
check_string (g_build_pathv ("::", args), "::x::y");
args[0] = "x"; args[1] = "y::"; args[2] = NULL;
check_string (g_build_pathv ("::", args), "x::y::");
args[0] = "::x::"; args[1] = "::y::"; args[2] = NULL;
check_string (g_build_pathv ("::", args), "::x::y::");
args[0] = "::x:::"; args[1] = ":::y::"; args[2] = NULL;
check_string (g_build_pathv ("::", args), "::x::::y::");
args[0] = "::x::::"; args[1] = "::::y::"; args[2] = NULL;
check_string (g_build_pathv ("::", args), "::x::y::");
args[0] = "x"; args[1] = ""; args[2] = "y"; args[3] = NULL;
check_string (g_build_pathv ("::", args), "x::y");
args[0] = "x"; args[1] = "::"; args[2] = "y"; args[3] = NULL;
check_string (g_build_pathv ("::", args), "x::y");
args[0] = "x"; args[1] = "::::"; args[2] = "y"; args[3] = NULL;
check_string (g_build_pathv ("::", args), "x::y");
args[0] = "x"; args[1] = "y"; args[2] = "z"; args[3] = NULL;
check_string (g_build_pathv ("::", args), "x::y::z");
args[0] = "::x::"; args[1] = "::y::"; args[2] = "::z::"; args[3] = NULL;
check_string (g_build_pathv ("::", args), "::x::y::z::");
args[0] = ":::x:::"; args[1] = ":::y:::"; args[2] = ":::z:::"; args[3] = NULL;
check_string (g_build_pathv ("::", args), ":::x::::y::::z:::");
args[0] = "::::x::::"; args[1] = "::::y::::"; args[2] = "::::z::::"; args[3] = NULL;
check_string (g_build_pathv ("::", args), "::::x::y::z::::");
}
static void
test_build_filename (void)
{
/* check_string (g_build_filename (NULL), "");*/
check_string (g_build_filename (S, NULL), S);
check_string (g_build_filename (S"x", NULL), S"x");
check_string (g_build_filename ("x"S, NULL), "x"S);
check_string (g_build_filename ("", "x", NULL), "x");
check_string (g_build_filename ("", S"x", NULL), S"x");
check_string (g_build_filename (S, "x", NULL), S"x");
check_string (g_build_filename (S S, "x", NULL), S S"x");
check_string (g_build_filename ("x", "", NULL), "x");
check_string (g_build_filename ("x"S, "", NULL), "x"S);
check_string (g_build_filename ("x", S, NULL), "x"S);
check_string (g_build_filename ("x", S S, NULL), "x"S S);
check_string (g_build_filename ("x", "y", NULL), "x"S"y");
check_string (g_build_filename (S"x", "y", NULL), S"x"S"y");
check_string (g_build_filename ("x", "y"S, NULL), "x"S"y"S);
check_string (g_build_filename (S"x"S, S"y"S, NULL), S"x"S"y"S);
check_string (g_build_filename (S"x"S S, S S"y"S, NULL), S"x"S"y"S);
check_string (g_build_filename ("x", "", "y", NULL), "x"S"y");
check_string (g_build_filename ("x", S, "y", NULL), "x"S"y");
check_string (g_build_filename ("x", S S, "y", NULL), "x"S"y");
check_string (g_build_filename ("x", "y", "z", NULL), "x"S"y"S"z");
check_string (g_build_filename (S"x"S, S"y"S, S"z"S, NULL), S"x"S"y"S"z"S);
check_string (g_build_filename (S S"x"S S, S S"y"S S, S S"z"S S, NULL), S S"x"S"y"S"z"S S);
#ifdef G_OS_WIN32
/* Test also using the slash as file name separator */
#define Z "/"
/* check_string (g_build_filename (NULL), ""); */
check_string (g_build_filename (Z, NULL), Z);
check_string (g_build_filename (Z"x", NULL), Z"x");
check_string (g_build_filename ("x"Z, NULL), "x"Z);
check_string (g_build_filename ("", Z"x", NULL), Z"x");
check_string (g_build_filename ("", Z"x", NULL), Z"x");
check_string (g_build_filename (Z, "x", NULL), Z"x");
check_string (g_build_filename (Z Z, "x", NULL), Z Z"x");
check_string (g_build_filename (Z S, "x", NULL), Z S"x");
check_string (g_build_filename ("x"Z, "", NULL), "x"Z);
check_string (g_build_filename ("x"S"y", "z"Z"a", NULL), "x"S"y"S"z"Z"a");
check_string (g_build_filename ("x", Z, NULL), "x"Z);
check_string (g_build_filename ("x", Z Z, NULL), "x"Z Z);
check_string (g_build_filename ("x", S Z, NULL), "x"S Z);
check_string (g_build_filename (Z"x", "y", NULL), Z"x"Z"y");
check_string (g_build_filename ("x", "y"Z, NULL), "x"Z"y"Z);
check_string (g_build_filename (Z"x"Z, Z"y"Z, NULL), Z"x"Z"y"Z);
check_string (g_build_filename (Z"x"Z Z, Z Z"y"Z, NULL), Z"x"Z"y"Z);
check_string (g_build_filename ("x", Z, "y", NULL), "x"Z"y");
check_string (g_build_filename ("x", Z Z, "y", NULL), "x"Z"y");
check_string (g_build_filename ("x", Z S, "y", NULL), "x"S"y");
check_string (g_build_filename ("x", S Z, "y", NULL), "x"Z"y");
check_string (g_build_filename ("x", Z "y", "z", NULL), "x"Z"y"Z"z");
check_string (g_build_filename ("x", S "y", "z", NULL), "x"S"y"S"z");
check_string (g_build_filename ("x", S "y", "z", Z, "a", "b", NULL), "x"S"y"S"z"Z"a"Z"b");
check_string (g_build_filename (Z"x"Z, Z"y"Z, Z"z"Z, NULL), Z"x"Z"y"Z"z"Z);
check_string (g_build_filename (Z Z"x"Z Z, Z Z"y"Z Z, Z Z"z"Z Z, NULL), Z Z"x"Z"y"Z"z"Z Z);
#undef Z
#endif /* G_OS_WIN32 */
}
static void
test_build_filenamev (void)
{
gchar *args[10];
args[0] = NULL;
check_string (g_build_filenamev (args), "");
args[0] = S; args[1] = NULL;
check_string (g_build_filenamev (args), S);
args[0] = S"x"; args[1] = NULL;
check_string (g_build_filenamev (args), S"x");
args[0] = "x"S; args[1] = NULL;
check_string (g_build_filenamev (args), "x"S);
args[0] = ""; args[1] = "x"; args[2] = NULL;
check_string (g_build_filenamev (args), "x");
args[0] = ""; args[1] = S"x"; args[2] = NULL;
check_string (g_build_filenamev (args), S"x");
args[0] = S; args[1] = "x"; args[2] = NULL;
check_string (g_build_filenamev (args), S"x");
args[0] = S S; args[1] = "x"; args[2] = NULL;
check_string (g_build_filenamev (args), S S"x");
args[0] = "x"; args[1] = ""; args[2] = NULL;
check_string (g_build_filenamev (args), "x");
args[0] = "x"S; args[1] = ""; args[2] = NULL;
check_string (g_build_filenamev (args), "x"S);
args[0] = "x"; args[1] = S; args[2] = NULL;
check_string (g_build_filenamev (args), "x"S);
args[0] = "x"; args[1] = S S; args[2] = NULL;
check_string (g_build_filenamev (args), "x"S S);
args[0] = "x"; args[1] = "y"; args[2] = NULL;
check_string (g_build_filenamev (args), "x"S"y");
args[0] = S"x"; args[1] = "y"; args[2] = NULL;
check_string (g_build_filenamev (args), S"x"S"y");
args[0] = "x"; args[1] = "y"S; args[2] = NULL;
check_string (g_build_filenamev (args), "x"S"y"S);
args[0] = S"x"S; args[1] = S"y"S; args[2] = NULL;
check_string (g_build_filenamev (args), S"x"S"y"S);
args[0] = S"x"S S; args[1] = S S"y"S; args[2] = NULL;
check_string (g_build_filenamev (args), S"x"S"y"S);
args[0] = "x"; args[1] = ""; args[2] = "y"; args[3] = NULL;
check_string (g_build_filenamev (args), "x"S"y");
args[0] = "x"; args[1] = S; args[2] = "y"; args[3] = NULL;
check_string (g_build_filenamev (args), "x"S"y");
args[0] = "x"; args[1] = S S; args[2] = "y"; args[3] = NULL;
check_string (g_build_filenamev (args), "x"S"y");
args[0] = "x"; args[1] = "y"; args[2] = "z"; args[3] = NULL;
check_string (g_build_filenamev (args), "x"S"y"S"z");
args[0] = S"x"S; args[1] = S"y"S; args[2] = S"z"S; args[3] = NULL;
check_string (g_build_filenamev (args), S"x"S"y"S"z"S);
args[0] = S S"x"S S; args[1] = S S"y"S S; args[2] = S S"z"S S; args[3] = NULL;
check_string (g_build_filenamev (args), S S"x"S"y"S"z"S S);
#ifdef G_OS_WIN32
/* Test also using the slash as file name separator */
#define Z "/"
args[0] = NULL;
check_string (g_build_filenamev (args), "");
args[0] = Z; args[1] = NULL;
check_string (g_build_filenamev (args), Z);
args[0] = Z"x"; args[1] = NULL;
check_string (g_build_filenamev (args), Z"x");
args[0] = "x"Z; args[1] = NULL;
check_string (g_build_filenamev (args), "x"Z);
args[0] = ""; args[1] = Z"x"; args[2] = NULL;
check_string (g_build_filenamev (args), Z"x");
args[0] = ""; args[1] = Z"x"; args[2] = NULL;
check_string (g_build_filenamev (args), Z"x");
args[0] = Z; args[1] = "x"; args[2] = NULL;
check_string (g_build_filenamev (args), Z"x");
args[0] = Z Z; args[1] = "x"; args[2] = NULL;
check_string (g_build_filenamev (args), Z Z"x");
args[0] = Z S; args[1] = "x"; args[2] = NULL;
check_string (g_build_filenamev (args), Z S"x");
args[0] = "x"Z; args[1] = ""; args[2] = NULL;
check_string (g_build_filenamev (args), "x"Z);
args[0] = "x"S"y"; args[1] = "z"Z"a"; args[2] = NULL;
check_string (g_build_filenamev (args), "x"S"y"S"z"Z"a");
args[0] = "x"; args[1] = Z; args[2] = NULL;
check_string (g_build_filenamev (args), "x"Z);
args[0] = "x"; args[1] = Z Z; args[2] = NULL;
check_string (g_build_filenamev (args), "x"Z Z);
args[0] = "x"; args[1] = S Z; args[2] = NULL;
check_string (g_build_filenamev (args), "x"S Z);
args[0] = Z"x"; args[1] = "y"; args[2] = NULL;
check_string (g_build_filenamev (args), Z"x"Z"y");
args[0] = "x"; args[1] = "y"Z; args[2] = NULL;
check_string (g_build_filenamev (args), "x"Z"y"Z);
args[0] = Z"x"Z; args[1] = Z"y"Z; args[2] = NULL;
check_string (g_build_filenamev (args), Z"x"Z"y"Z);
args[0] = Z"x"Z Z; args[1] = Z Z"y"Z; args[2] = NULL;
check_string (g_build_filenamev (args), Z"x"Z"y"Z);
args[0] = "x"; args[1] = Z; args[2] = "y", args[3] = NULL;
check_string (g_build_filenamev (args), "x"Z"y");
args[0] = "x"; args[1] = Z Z; args[2] = "y", args[3] = NULL;
check_string (g_build_filenamev (args), "x"Z"y");
args[0] = "x"; args[1] = Z S; args[2] = "y", args[3] = NULL;
check_string (g_build_filenamev (args), "x"S"y");
args[0] = "x"; args[1] = S Z; args[2] = "y", args[3] = NULL;
check_string (g_build_filenamev (args), "x"Z"y");
args[0] = "x"; args[1] = Z "y"; args[2] = "z", args[3] = NULL;
check_string (g_build_filenamev (args), "x"Z"y"Z"z");
args[0] = "x"; args[1] = S "y"; args[2] = "z", args[3] = NULL;
check_string (g_build_filenamev (args), "x"S"y"S"z");
args[0] = "x"; args[1] = S "y"; args[2] = "z", args[3] = Z;
args[4] = "a"; args[5] = "b"; args[6] = NULL;
check_string (g_build_filenamev (args), "x"S"y"S"z"Z"a"Z"b");
args[0] = Z"x"Z; args[1] = Z"y"Z; args[2] = Z"z"Z, args[3] = NULL;
check_string (g_build_filenamev (args), Z"x"Z"y"Z"z"Z);
args[0] = Z Z"x"Z Z; args[1] = Z Z"y"Z Z; args[2] = Z Z"z"Z Z, args[3] = NULL;
check_string (g_build_filenamev (args), Z Z"x"Z"y"Z"z"Z Z);
#undef Z
#endif /* G_OS_WIN32 */
}
#undef S
static void
test_mkdir_with_parents_1 (const gchar *base)
{
char *p0 = g_build_filename (base, "fum", NULL);
char *p1 = g_build_filename (p0, "tem", NULL);
char *p2 = g_build_filename (p1, "zap", NULL);
FILE *f;
g_remove (p2);
g_remove (p1);
g_remove (p0);
if (g_file_test (p0, G_FILE_TEST_EXISTS))
g_error ("failed, %s exists, cannot test g_mkdir_with_parents", p0);
if (g_file_test (p1, G_FILE_TEST_EXISTS))
g_error ("failed, %s exists, cannot test g_mkdir_with_parents", p1);
if (g_file_test (p2, G_FILE_TEST_EXISTS))
g_error ("failed, %s exists, cannot test g_mkdir_with_parents", p2);
if (g_mkdir_with_parents (p2, 0777) == -1)
{
int errsv = errno;
g_error ("failed, g_mkdir_with_parents(%s) failed: %s", p2, g_strerror (errsv));
}
if (!g_file_test (p2, G_FILE_TEST_IS_DIR))
g_error ("failed, g_mkdir_with_parents(%s) succeeded, but %s is not a directory", p2, p2);
if (!g_file_test (p1, G_FILE_TEST_IS_DIR))
g_error ("failed, g_mkdir_with_parents(%s) succeeded, but %s is not a directory", p2, p1);
if (!g_file_test (p0, G_FILE_TEST_IS_DIR))
g_error ("failed, g_mkdir_with_parents(%s) succeeded, but %s is not a directory", p2, p0);
g_rmdir (p2);
if (g_file_test (p2, G_FILE_TEST_EXISTS))
g_error ("failed, did g_rmdir(%s), but %s is still there", p2, p2);
g_rmdir (p1);
if (g_file_test (p1, G_FILE_TEST_EXISTS))
g_error ("failed, did g_rmdir(%s), but %s is still there", p1, p1);
f = g_fopen (p1, "w");
if (f == NULL)
g_error ("failed, couldn't create file %s", p1);
fclose (f);
if (g_mkdir_with_parents (p1, 0666) == 0)
g_error ("failed, g_mkdir_with_parents(%s) succeeded, even if %s is a file", p1, p1);
if (g_mkdir_with_parents (p2, 0666) == 0)
g_error("failed, g_mkdir_with_parents(%s) succeeded, even if %s is a file", p2, p1);
g_remove (p2);
g_remove (p1);
g_remove (p0);
g_free (p2);
g_free (p1);
g_free (p0);
}
static void
test_mkdir_with_parents (void)
{
gchar *cwd;
if (g_test_verbose())
g_printerr ("checking g_mkdir_with_parents() in subdir ./hum/");
test_mkdir_with_parents_1 ("hum");
g_remove ("hum");
if (g_test_verbose())
g_printerr ("checking g_mkdir_with_parents() in subdir ./hii///haa/hee/");
test_mkdir_with_parents_1 ("hii///haa/hee");
g_remove ("hii/haa/hee");
g_remove ("hii/haa");
g_remove ("hii");
cwd = g_get_current_dir ();
if (g_test_verbose())
g_printerr ("checking g_mkdir_with_parents() in cwd: %s", cwd);
test_mkdir_with_parents_1 (cwd);
g_free (cwd);
g_assert_cmpint (g_mkdir_with_parents (NULL, 0), ==, -1);
g_assert_cmpint (errno, ==, EINVAL);
}
#ifdef G_OS_UNIX
/*
* check_cap_dac_override:
* @tmpdir: A temporary directory in which we can create and delete files
*
* Check whether the current process can bypass DAC permissions.
*
* Traditionally, "privileged" processes (those with effective uid 0)
* could do this (and bypass many other checks), and "unprivileged"
* processes could not.
*
* In Linux, the special powers of euid 0 are divided into many
* capabilities: see `capabilities(7)`. The one we are interested in
* here is `CAP_DAC_OVERRIDE`.
*
* We do this generically instead of actually looking at the capability
* bits, so that the right thing will happen on non-Linux Unix
* implementations, in particular if they have something equivalent to
* but not identical to Linux permissions.
*
* Returns: %TRUE if we have Linux `CAP_DAC_OVERRIDE` or equivalent
* privileges
*/
static gboolean
check_cap_dac_override (const char *tmpdir)
{
gchar *dac_denies_write;
gchar *inside;
gboolean have_cap;
dac_denies_write = g_build_filename (tmpdir, "dac-denies-write", NULL);
inside = g_build_filename (dac_denies_write, "inside", NULL);
g_assert_cmpint (mkdir (dac_denies_write, S_IRWXU) == 0 ? 0 : errno, ==, 0);
g_assert_cmpint (chmod (dac_denies_write, 0) == 0 ? 0 : errno, ==, 0);
if (mkdir (inside, S_IRWXU) == 0)
{
g_test_message ("Looks like we have CAP_DAC_OVERRIDE or equivalent");
g_assert_cmpint (rmdir (inside) == 0 ? 0 : errno, ==, 0);
have_cap = TRUE;
}
else
{
int saved_errno = errno;
g_test_message ("We do not have CAP_DAC_OVERRIDE or equivalent");
g_assert_cmpint (saved_errno, ==, EACCES);
have_cap = FALSE;
}
g_assert_cmpint (chmod (dac_denies_write, S_IRWXU) == 0 ? 0 : errno, ==, 0);
g_assert_cmpint (rmdir (dac_denies_write) == 0 ? 0 : errno, ==, 0);
g_free (dac_denies_write);
g_free (inside);
return have_cap;
}
#endif
/* Reproducer for https://gitlab.gnome.org/GNOME/glib/issues/1852 */
static void
test_mkdir_with_parents_permission (void)
{
#ifdef G_OS_UNIX
gchar *tmpdir;
gchar *subdir;
gchar *subdir2;
gchar *subdir3;
GError *error = NULL;
int result;
int saved_errno;
gboolean have_cap_dac_override;
tmpdir = g_dir_make_tmp ("test-fileutils.XXXXXX", &error);
g_assert_no_error (error);
g_assert_nonnull (tmpdir);
have_cap_dac_override = check_cap_dac_override (tmpdir);
subdir = g_build_filename (tmpdir, "sub", NULL);
subdir2 = g_build_filename (subdir, "sub2", NULL);
subdir3 = g_build_filename (subdir2, "sub3", NULL);
g_assert_cmpint (g_mkdir (subdir, 0700) == 0 ? 0 : errno, ==, 0);
g_assert_cmpint (g_chmod (subdir, 0) == 0 ? 0 : errno, ==, 0);
if (have_cap_dac_override)
{
g_test_skip ("have CAP_DAC_OVERRIDE or equivalent, cannot test");
}
else
{
result = g_mkdir_with_parents (subdir2, 0700);
saved_errno = errno;
g_assert_cmpint (result, ==, -1);
g_assert_cmpint (saved_errno, ==, EACCES);
result = g_mkdir_with_parents (subdir3, 0700);
saved_errno = errno;
g_assert_cmpint (result, ==, -1);
g_assert_cmpint (saved_errno, ==, EACCES);
g_assert_cmpint (g_chmod (subdir, 0700) == 0 ? 0 : errno, ==, 0);
}
g_assert_cmpint (g_remove (subdir) == 0 ? 0 : errno, ==, 0);
g_assert_cmpint (g_remove (tmpdir) == 0 ? 0 : errno, ==, 0);
g_free (subdir3);
g_free (subdir2);
g_free (subdir);
g_free (tmpdir);
#else
g_test_skip ("cannot test without Unix-style permissions");
#endif
}
static void
test_format_size_for_display (void)
{
#ifdef G_OS_WIN32
SetThreadLocale (MAKELCID (MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT));
#endif
/* nobody called setlocale(), so we should get "C" behaviour... */
check_string (g_format_size_for_display (0), "0 bytes");
check_string (g_format_size_for_display (1), "1 byte");
check_string (g_format_size_for_display (2), "2 bytes");
check_string (g_format_size_for_display (1024), "1.0 KB");
check_string (g_format_size_for_display (1024 * 1024), "1.0 MB");
check_string (g_format_size_for_display (1024 * 1024 * 1024), "1.0 GB");
check_string (g_format_size_for_display (1024ULL * 1024 * 1024 * 1024), "1.0 TB");
check_string (g_format_size_for_display (1024ULL * 1024 * 1024 * 1024 * 1024), "1.0 PB");
check_string (g_format_size_for_display (1024ULL * 1024 * 1024 * 1024 * 1024 * 1024), "1.0 EB");
check_string (g_format_size (0), "0 bytes");
check_string (g_format_size (1), "1 byte");
check_string (g_format_size (2), "2 bytes");
/* '\302\240' is a no-break space, to keep quantity and unit symbol together at line breaks*/
check_string (g_format_size (1000ULL), "1.0\302\240kB");
check_string (g_format_size (1000ULL * 1000), "1.0\302\240MB");
check_string (g_format_size (1000ULL * 1000 * 1000), "1.0\302\240GB");
check_string (g_format_size (1000ULL * 1000 * 1000 * 1000), "1.0\302\240TB");
check_string (g_format_size (1000ULL * 1000 * 1000 * 1000 * 1000), "1.0\302\240PB");
check_string (g_format_size (1000ULL * 1000 * 1000 * 1000 * 1000 * 1000), "1.0\302\240EB");
check_string (g_format_size_full (0, G_FORMAT_SIZE_IEC_UNITS), "0 bytes");
check_string (g_format_size_full (1, G_FORMAT_SIZE_IEC_UNITS), "1 byte");
check_string (g_format_size_full (2, G_FORMAT_SIZE_IEC_UNITS), "2 bytes");
check_string (g_format_size_full (2048ULL, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240KiB");
check_string (g_format_size_full (2048ULL * 1024, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240MiB");
check_string (g_format_size_full (2048ULL * 1024 * 1024, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240GiB");
check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240TiB");
check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024 * 1024, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240PiB");
check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024 * 1024 * 1024, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240EiB");
check_string (g_format_size_full (238472938, G_FORMAT_SIZE_IEC_UNITS), "227.4\302\240MiB");
check_string (g_format_size_full (238472938, G_FORMAT_SIZE_DEFAULT), "238.5\302\240MB");
check_string (g_format_size_full (238472938, G_FORMAT_SIZE_LONG_FORMAT), "238.5\302\240MB (238472938 bytes)");
check_string (g_format_size_full (0, G_FORMAT_SIZE_BITS), "0 bits");
check_string (g_format_size_full (1, G_FORMAT_SIZE_BITS), "1 bit");
check_string (g_format_size_full (2, G_FORMAT_SIZE_BITS), "2 bits");
check_string (g_format_size_full (2000ULL, G_FORMAT_SIZE_BITS), "2.0\302\240kb");
check_string (g_format_size_full (2000ULL * 1000, G_FORMAT_SIZE_BITS), "2.0\302\240Mb");
check_string (g_format_size_full (2000ULL * 1000 * 1000, G_FORMAT_SIZE_BITS), "2.0\302\240Gb");
check_string (g_format_size_full (2000ULL * 1000 * 1000 * 1000, G_FORMAT_SIZE_BITS), "2.0\302\240Tb");
check_string (g_format_size_full (2000ULL * 1000 * 1000 * 1000 * 1000, G_FORMAT_SIZE_BITS), "2.0\302\240Pb");
check_string (g_format_size_full (2000ULL * 1000 * 1000 * 1000 * 1000 * 1000, G_FORMAT_SIZE_BITS), "2.0\302\240Eb");
check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS), "238.5\302\240Mb");
check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_LONG_FORMAT), "238.5\302\240Mb (238472938 bits)");
check_string (g_format_size_full (0, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "0 bits");
check_string (g_format_size_full (1, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "1 bit");
check_string (g_format_size_full (2, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2 bits");
check_string (g_format_size_full (2048ULL, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Kib");
check_string (g_format_size_full (2048ULL * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Mib");
check_string (g_format_size_full (2048ULL * 1024 * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Gib");
check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Tib");
check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024 * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Pib");
check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024 * 1024 * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Eib");
check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "227.4\302\240Mib");
check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_LONG_FORMAT), "227.4\302\240Mib (238472938 bits)");
}
static void
test_file_errors (void)
{
#ifdef EEXIST
g_assert_cmpint (g_file_error_from_errno (EEXIST), ==, G_FILE_ERROR_EXIST);
#endif
#ifdef EISDIR
g_assert_cmpint (g_file_error_from_errno (EISDIR), ==, G_FILE_ERROR_ISDIR);
#endif
#ifdef EACCES
g_assert_cmpint (g_file_error_from_errno (EACCES), ==, G_FILE_ERROR_ACCES);
#endif
#ifdef ENAMETOOLONG
g_assert_cmpint (g_file_error_from_errno (ENAMETOOLONG), ==, G_FILE_ERROR_NAMETOOLONG);
#endif
#ifdef ENOENT
g_assert_cmpint (g_file_error_from_errno (ENOENT), ==, G_FILE_ERROR_NOENT);
#endif
#ifdef ENOTDIR
g_assert_cmpint (g_file_error_from_errno (ENOTDIR), ==, G_FILE_ERROR_NOTDIR);
#endif
#ifdef ENXIO
g_assert_cmpint (g_file_error_from_errno (ENXIO), ==, G_FILE_ERROR_NXIO);
#endif
#ifdef ENODEV
g_assert_cmpint (g_file_error_from_errno (ENODEV), ==, G_FILE_ERROR_NODEV);
#endif
#ifdef EROFS
g_assert_cmpint (g_file_error_from_errno (EROFS), ==, G_FILE_ERROR_ROFS);
#endif
#ifdef ETXTBSY
g_assert_cmpint (g_file_error_from_errno (ETXTBSY), ==, G_FILE_ERROR_TXTBSY);
#endif
#ifdef EFAULT
g_assert_cmpint (g_file_error_from_errno (EFAULT), ==, G_FILE_ERROR_FAULT);
#endif
#ifdef ELOOP
g_assert_cmpint (g_file_error_from_errno (ELOOP), ==, G_FILE_ERROR_LOOP);
#endif
#ifdef ENOSPC
g_assert_cmpint (g_file_error_from_errno (ENOSPC), ==, G_FILE_ERROR_NOSPC);
#endif
#ifdef ENOMEM
g_assert_cmpint (g_file_error_from_errno (ENOMEM), ==, G_FILE_ERROR_NOMEM);
#endif
#ifdef EMFILE
g_assert_cmpint (g_file_error_from_errno (EMFILE), ==, G_FILE_ERROR_MFILE);
#endif
#ifdef ENFILE
g_assert_cmpint (g_file_error_from_errno (ENFILE), ==, G_FILE_ERROR_NFILE);
#endif
#ifdef EBADF
g_assert_cmpint (g_file_error_from_errno (EBADF), ==, G_FILE_ERROR_BADF);
#endif
#ifdef EINVAL
g_assert_cmpint (g_file_error_from_errno (EINVAL), ==, G_FILE_ERROR_INVAL);
#endif
#ifdef EPIPE
g_assert_cmpint (g_file_error_from_errno (EPIPE), ==, G_FILE_ERROR_PIPE);
#endif
#ifdef EAGAIN
g_assert_cmpint (g_file_error_from_errno (EAGAIN), ==, G_FILE_ERROR_AGAIN);
#endif
#ifdef EINTR
g_assert_cmpint (g_file_error_from_errno (EINTR), ==, G_FILE_ERROR_INTR);
#endif
#ifdef EIO
g_assert_cmpint (g_file_error_from_errno (EIO), ==, G_FILE_ERROR_IO);
#endif
#ifdef EPERM
g_assert_cmpint (g_file_error_from_errno (EPERM), ==, G_FILE_ERROR_PERM);
#endif
#ifdef ENOSYS
g_assert_cmpint (g_file_error_from_errno (ENOSYS), ==, G_FILE_ERROR_NOSYS);
#endif
}
static void
test_basename (void)
{
gchar *b;
b = g_path_get_basename ("");
g_assert_cmpstr (b, ==, ".");
g_free (b);
b = g_path_get_basename ("///");
g_assert_cmpstr (b, ==, G_DIR_SEPARATOR_S);
g_free (b);
b = g_path_get_basename ("/a/b/c/d");
g_assert_cmpstr (b, ==, "d");
g_free (b);
}
static void
test_dir_make_tmp (void)
{
gchar *name;
GError *error = NULL;
gint ret;
name = g_dir_make_tmp ("testXXXXXXtest", &error);
g_assert_no_error (error);
g_assert_true (g_file_test (name, G_FILE_TEST_IS_DIR));
ret = g_rmdir (name);
g_assert_cmpint (ret, ==, 0);
g_free (name);
name = g_dir_make_tmp (NULL, &error);
g_assert_no_error (error);
g_assert_true (g_file_test (name, G_FILE_TEST_IS_DIR));
ret = g_rmdir (name);
g_assert_cmpint (ret, ==, 0);
g_free (name);
name = g_dir_make_tmp ("test/XXXXXX", &error);
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED);
g_clear_error (&error);
g_assert_null (name);
name = g_dir_make_tmp ("XXXXxX", &error);
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED);
g_clear_error (&error);
g_assert_null (name);
}
static void
test_file_open_tmp (void)
{
gchar *name = NULL;
GError *error = NULL;
gint fd;
fd = g_file_open_tmp ("testXXXXXXtest", &name, &error);
g_assert_cmpint (fd, !=, -1);
g_assert_no_error (error);
g_assert_nonnull (name);
unlink (name);
g_free (name);
close (fd);
fd = g_file_open_tmp (NULL, &name, &error);
g_assert_cmpint (fd, !=, -1);
g_assert_no_error (error);
g_assert_nonnull (name);
g_unlink (name);
g_free (name);
close (fd);
name = NULL;
fd = g_file_open_tmp ("test/XXXXXX", &name, &error);
g_assert_cmpint (fd, ==, -1);
g_assert_null (name);
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED);
g_clear_error (&error);
fd = g_file_open_tmp ("XXXXxX", &name, &error);
g_assert_cmpint (fd, ==, -1);
g_assert_null (name);
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED);
g_clear_error (&error);
}
static void
test_mkstemp (void)
{
gchar *name;
gint fd;
name = g_strdup ("testXXXXXXtest"),
fd = g_mkstemp (name);
g_assert_cmpint (fd, !=, -1);
g_assert_null (strstr (name, "XXXXXX"));
unlink (name);
close (fd);
g_free (name);
name = g_strdup ("testYYYYYYtest"),
fd = g_mkstemp (name);
g_assert_cmpint (fd, ==, -1);
g_free (name);
}
static void
test_mkdtemp (void)
{
gchar *name;
gchar *ret;
name = g_strdup ("testXXXXXXtest"),
ret = g_mkdtemp (name);
g_assert (ret == name);
g_assert_null (strstr (name, "XXXXXX"));
g_rmdir (name);
g_free (name);
name = g_strdup ("testYYYYYYtest"),
ret = g_mkdtemp (name);
g_assert_null (ret);
g_free (name);
}
static void
test_set_contents (void)
{
GError *error = NULL;
gint fd;
gchar *name;
gchar *buf;
gsize len;
gboolean ret;
fd = g_file_open_tmp (NULL, &name, &error);
g_assert_no_error (error);
write (fd, "a", 1);
g_assert_cmpint (g_fsync (fd), ==, 0);
close (fd);
ret = g_file_get_contents (name, &buf, &len, &error);
g_assert_true (ret);
g_assert_no_error (error);
g_assert_cmpstr (buf, ==, "a");
g_free (buf);
ret = g_file_set_contents (name, "b", 1, &error);
g_assert_true (ret);
g_assert_no_error (error);
ret = g_file_get_contents (name, &buf, &len, &error);
g_assert_true (ret);
g_assert_no_error (error);
g_assert_cmpstr (buf, ==, "b");
g_free (buf);
g_remove (name);
g_free (name);
}
static void
test_set_contents_full (void)
{
GFileSetContentsFlags flags_mask =
G_FILE_SET_CONTENTS_ONLY_EXISTING |
G_FILE_SET_CONTENTS_DURABLE |
G_FILE_SET_CONTENTS_CONSISTENT;
gint flags;
const struct
{
enum
{
EXISTING_FILE_NONE,
EXISTING_FILE_REGULAR,
#ifndef G_OS_WIN32
EXISTING_FILE_SYMLINK,
#endif
EXISTING_FILE_DIRECTORY,
}
existing_file;
int new_mode; /* only relevant if @existing_file is %EXISTING_FILE_NONE */
gboolean use_strlen;
gboolean expected_success;
GFileError expected_error;
}
tests[] =
{
{ EXISTING_FILE_NONE, 0644, FALSE, TRUE, 0 },
{ EXISTING_FILE_NONE, 0644, TRUE, TRUE, 0 },
{ EXISTING_FILE_NONE, 0600, FALSE, TRUE, 0 },
{ EXISTING_FILE_REGULAR, 0644, FALSE, TRUE, 0 },
#ifndef G_OS_WIN32
{ EXISTING_FILE_SYMLINK, 0644, FALSE, TRUE, 0 },
#endif
{ EXISTING_FILE_DIRECTORY, 0644, FALSE, FALSE, G_FILE_ERROR_ISDIR },
};
gsize i;
g_test_summary ("Test g_file_set_contents_full() with various flags");
for (flags = 0; flags < (gint) flags_mask; flags++)
{
for (i = 0; i < G_N_ELEMENTS (tests); i++)
{
GError *error = NULL;
gchar *file_name = NULL, *link_name = NULL, *dir_name = NULL;
const gchar *set_contents_name;
gchar *buf = NULL;
gsize len;
gboolean ret;
GStatBuf statbuf;
g_test_message ("Flags %d and test %" G_GSIZE_FORMAT, flags, i);
switch (tests[i].existing_file)
{
case EXISTING_FILE_REGULAR:
#ifndef G_OS_WIN32
case EXISTING_FILE_SYMLINK:
#endif
{
gint fd;
fd = g_file_open_tmp (NULL, &file_name, &error);
g_assert_no_error (error);
write (fd, "a", 1);
g_assert_no_errno (g_fsync (fd));
close (fd);
#ifndef G_OS_WIN32
/* Pass an existing symlink to g_file_set_contents_full() to see
* what it does. */
if (tests[i].existing_file == EXISTING_FILE_SYMLINK)
{
link_name = g_strconcat (file_name, ".link", NULL);
g_assert_no_errno (symlink (file_name, link_name));
set_contents_name = link_name;
}
else
#endif /* !G_OS_WIN32 */
{
set_contents_name = file_name;
}
break;
}
case EXISTING_FILE_DIRECTORY:
{
dir_name = g_dir_make_tmp ("glib-fileutils-set-contents-full-XXXXXX", &error);
g_assert_no_error (error);
set_contents_name = dir_name;
break;
}
case EXISTING_FILE_NONE:
{
file_name = g_build_filename (g_get_tmp_dir (), "glib-file-set-contents-full-test", NULL);
g_remove (file_name);
g_assert_false (g_file_test (file_name, G_FILE_TEST_EXISTS));
set_contents_name = file_name;
break;
}
default:
{
g_assert_not_reached ();
}
}
/* Set the file contents */
ret = g_file_set_contents_full (set_contents_name, "b",
tests[i].use_strlen ? -1 : 1,
flags, tests[i].new_mode, &error);
if (!tests[i].expected_success)
{
g_assert_error (error, G_FILE_ERROR, tests[i].expected_error);
g_assert_false (ret);
g_clear_error (&error);
}
else
{
g_assert_no_error (error);
g_assert_true (ret);
/* Check the contents and mode were set correctly. The mode isnt
* changed on existing files. */
ret = g_file_get_contents (set_contents_name, &buf, &len, &error);
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpstr (buf, ==, "b");
g_assert_cmpuint (len, ==, 1);
g_free (buf);
g_assert_no_errno (g_lstat (set_contents_name, &statbuf));
if (tests[i].existing_file == EXISTING_FILE_NONE)
g_assert_cmpint (statbuf.st_mode & ~S_IFMT, ==, tests[i].new_mode);
#ifndef G_OS_WIN32
if (tests[i].existing_file == EXISTING_FILE_SYMLINK)
{
gchar *target_contents = NULL;
/* If the @set_contents_name was a symlink, it should now be a
* regular file, and the file it pointed to should not have
* changed. */
g_assert_cmpint (statbuf.st_mode & S_IFMT, ==, S_IFREG);
g_file_get_contents (file_name, &target_contents, NULL, &error);
g_assert_no_error (error);
g_assert_cmpstr (target_contents, ==, "a");
g_free (target_contents);
}
#endif /* !G_OS_WIN32 */
}
if (dir_name != NULL)
g_rmdir (dir_name);
if (link_name != NULL)
g_remove (link_name);
if (file_name != NULL)
g_remove (file_name);
g_free (dir_name);
g_free (link_name);
g_free (file_name);
}
}
}
static void
test_set_contents_full_read_only_file (void)
{
gint fd;
GError *error = NULL;
gchar *file_name = NULL;
gboolean ret;
g_test_summary ("Test g_file_set_contents_full() on a read-only file");
/* Cant test this with different #GFileSetContentsFlags as they all have
* different behaviours wrt replacing the file while noticing/ignoring the
* existing file permissions. */
fd = g_file_open_tmp (NULL, &file_name, &error);
g_assert_no_error (error);
write (fd, "a", 1);
g_assert_no_errno (g_fsync (fd));
close (fd);
g_assert_no_errno (chmod (file_name, 0200));
/* Set the file contents */
ret = g_file_set_contents_full (file_name, "b", 1, G_FILE_SET_CONTENTS_NONE, 0644, &error);
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
g_assert_false (ret);
g_clear_error (&error);
g_remove (file_name);
g_free (file_name);
}
static void
test_set_contents_full_read_only_directory (void)
{
GFileSetContentsFlags flags_mask =
G_FILE_SET_CONTENTS_ONLY_EXISTING |
G_FILE_SET_CONTENTS_DURABLE |
G_FILE_SET_CONTENTS_CONSISTENT;
gint flags;
g_test_summary ("Test g_file_set_contents_full() on a file in a read-only directory");
for (flags = 0; flags < (gint) flags_mask; flags++)
{
gint fd;
GError *error = NULL;
gchar *dir_name = NULL;
gchar *file_name = NULL;
gboolean ret;
g_test_message ("Flags %d", flags);
dir_name = g_dir_make_tmp ("glib-file-set-contents-full-rodir-XXXXXX", &error);
g_assert_no_error (error);
file_name = g_build_filename (dir_name, "file", NULL);
fd = g_open (file_name, O_CREAT | O_RDWR, 0644);
g_assert_cmpint (fd, >=, 0);
write (fd, "a", 1);
g_assert_no_errno (g_fsync (fd));
close (fd);
g_assert_no_errno (chmod (dir_name, 0));
/* Set the file contents */
ret = g_file_set_contents_full (file_name, "b", 1, flags, 0644, &error);
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
g_assert_false (ret);
g_clear_error (&error);
g_remove (file_name);
g_unlink (dir_name);
g_free (file_name);
g_free (dir_name);
}
}
static void
test_read_link (void)
{
#ifdef HAVE_READLINK
#ifdef G_OS_UNIX
int ret;
const gchar *oldpath;
gchar *cwd;
gchar *newpath;
gchar *badpath;
gchar *path;
GError *error = NULL;
cwd = g_get_current_dir ();
oldpath = g_test_get_filename (G_TEST_DIST, "4096-random-bytes", NULL);
newpath = g_build_filename (cwd, "page-of-junk", NULL);
badpath = g_build_filename (cwd, "4097-random-bytes", NULL);
remove (newpath);
ret = symlink (oldpath, newpath);
g_assert_cmpint (ret, ==, 0);
path = g_file_read_link (newpath, &error);
g_assert_no_error (error);
g_assert_cmpstr (path, ==, oldpath);
g_free (path);
remove (newpath);
ret = symlink (badpath, newpath);
g_assert_cmpint (ret, ==, 0);
path = g_file_read_link (newpath, &error);
g_assert_no_error (error);
g_assert_cmpstr (path, ==, badpath);
g_free (path);
path = g_file_read_link (oldpath, &error);
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
g_assert_null (path);
g_error_free (error);
remove (newpath);
g_free (cwd);
g_free (newpath);
g_free (badpath);
#endif
#else
g_test_skip ("Symbolic links not supported");
#endif
}
static void
test_stdio_wrappers (void)
{
GStatBuf buf;
gchar *cwd, *path;
gint ret;
struct utimbuf ut;
GError *error = NULL;
GStatBuf path_statbuf, cwd_statbuf;
time_t now;
#ifdef G_OS_UNIX
gboolean have_cap_dac_override;
#endif
g_remove ("mkdir-test/test-create");
ret = g_rmdir ("mkdir-test");
g_assert (ret == 0 || errno == ENOENT);
ret = g_stat ("mkdir-test", &buf);
g_assert_cmpint (ret, ==, -1);
ret = g_mkdir ("mkdir-test", 0666);
g_assert_cmpint (ret, ==, 0);
ret = g_stat ("mkdir-test", &buf);
g_assert_cmpint (ret, ==, 0);
g_assert_cmpint (S_ISDIR (buf.st_mode), !=, 0);
cwd = g_get_current_dir ();
path = g_build_filename (cwd, "mkdir-test", NULL);
#ifdef G_OS_UNIX
have_cap_dac_override = check_cap_dac_override (cwd);
#endif
g_free (cwd);
/* 0666 on directories means nothing to Windows, it only obeys ACLs.
* It doesn't necessarily mean anything on Unix either: if we have
* Linux CAP_DAC_OVERRIDE or equivalent (in particular if we're root),
* then we ignore filesystem permissions. */
#ifdef G_OS_UNIX
if (have_cap_dac_override)
{
g_test_message ("Cannot test g_chdir() failing with EACCES: we "
"probably have CAP_DAC_OVERRIDE or equivalent");
}
else
{
ret = g_chdir (path);
g_assert_cmpint (ret == 0 ? 0 : errno, ==, EACCES);
g_assert_cmpint (ret, ==, -1);
}
#else
g_test_message ("Cannot test g_chdir() failing with EACCES: "
"it's Unix-specific behaviour");
#endif
ret = g_chmod (path, 0777);
g_assert_cmpint (ret, ==, 0);
ret = g_chdir (path);
g_assert_cmpint (ret, ==, 0);
cwd = g_get_current_dir ();
/* We essentially want to check that cwd == path, but we cant compare the
* paths directly since the tests might be running under a symlink (for
* example, /tmp is sometimes a symlink). Compare the inode numbers instead. */
g_assert_cmpint (g_stat (cwd, &cwd_statbuf), ==, 0);
g_assert_cmpint (g_stat (path, &path_statbuf), ==, 0);
g_assert_true (cwd_statbuf.st_dev == path_statbuf.st_dev &&
cwd_statbuf.st_ino == path_statbuf.st_ino);
g_free (cwd);
g_free (path);
ret = g_creat ("test-creat", G_TEST_DIR_MODE);
g_close (ret, &error);
g_assert_no_error (error);
ret = g_access ("test-creat", F_OK);
g_assert_cmpint (ret, ==, 0);
ret = g_rename ("test-creat", "test-create");
g_assert_cmpint (ret, ==, 0);
ret = g_open ("test-create", O_RDONLY, 0666);
g_close (ret, &error);
g_assert_no_error (error);
#ifdef G_OS_WIN32
/* On Windows the 5 permission bit results in a read-only file
* that cannot be modified in any way (attribute changes included).
* Remove the read-only attribute via chmod().
*/
ret = g_chmod ("test-create", 0666);
g_assert_cmpint (ret, ==, 0);
#endif
now = time (NULL);
ut.actime = ut.modtime = now;
ret = g_utime ("test-create", &ut);
g_assert_cmpint (ret, ==, 0);
ret = g_lstat ("test-create", &buf);
g_assert_cmpint (ret, ==, 0);
g_assert_cmpint (buf.st_atime, ==, now);
g_assert_cmpint (buf.st_mtime, ==, now);
g_chdir ("..");
g_remove ("mkdir-test/test-create");
g_rmdir ("mkdir-test");
}
/* Win32 does not support "wb+", but g_fopen() should automatically
* translate this mode to its alias "w+b".
* Also check various other file open modes for correct support across
* platforms.
* See: https://gitlab.gnome.org/GNOME/glib/merge_requests/119
*/
static void
test_fopen_modes (void)
{
char *path = g_build_filename ("temp-fopen", NULL);
gsize i;
const gchar *modes[] =
{
"w",
"r",
"a",
"w+",
"r+",
"a+",
"wb",
"rb",
"ab",
"w+b",
"r+b",
"a+b",
"wb+",
"rb+",
"ab+"
};
g_test_bug ("119");
if (g_file_test (path, G_FILE_TEST_EXISTS))
g_error ("failed, %s exists, cannot test g_fopen()", path);
for (i = 0; i < G_N_ELEMENTS (modes); i++)
{
FILE *f;
g_test_message ("Testing fopen() mode '%s'", modes[i]);
f = g_fopen (path, modes[i]);
g_assert_nonnull (f);
fclose (f);
}
g_remove (path);
g_free (path);
}
#ifdef G_OS_WIN32
#include "../gstdio-private.c"
static int
g_wcscmp0 (const gunichar2 *str1,
const gunichar2 *str2)
{
if (!str1)
return -(str1 != str2);
if (!str2)
return str1 != str2;
return wcscmp (str1, str2);
}
#define g_assert_cmpwcs(s1, cmp, s2, s1u8, s2u8) \
G_STMT_START { \
const gunichar2 *__s1 = (s1), *__s2 = (s2); \
if (g_wcscmp0 (__s1, __s2) cmp 0) ; else \
g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
#s1u8 " " #cmp " " #s2u8, s1u8, #cmp, s2u8); \
} G_STMT_END
static void
test_win32_pathstrip (void)
{
gunichar2 *buf;
gsize i;
#define IDENTITY_TEST(x) { x, x, FALSE }
struct
{
gunichar2 *in;
gunichar2 *out;
gboolean result;
} testcases[] = {
IDENTITY_TEST (L"\\\\?\\V"),
IDENTITY_TEST (L"\\\\?\\Vo"),
IDENTITY_TEST (L"\\\\?\\Volume{0700f3d3-6d24-11e3-8b2f-806e6f6e6963}\\"),
IDENTITY_TEST (L"\\??\\V"),
IDENTITY_TEST (L"\\??\\Vo"),
IDENTITY_TEST (L"\\??\\Volume{0700f3d3-6d24-11e3-8b2f-806e6f6e6963}\\"),
IDENTITY_TEST (L"\\\\?\\\x0441:\\"),
IDENTITY_TEST (L"\\??\\\x0441:\\"),
IDENTITY_TEST (L"a:\\"),
IDENTITY_TEST (L"a:\\b\\c"),
IDENTITY_TEST (L"x"),
#undef IDENTITY_TEST
{
L"\\\\?\\c:\\",
L"c:\\",
TRUE,
},
{
L"\\\\?\\C:\\",
L"C:\\",
TRUE,
},
{
L"\\\\?\\c:\\",
L"c:\\",
TRUE,
},
{
L"\\\\?\\C:\\",
L"C:\\",
TRUE,
},
{
L"\\\\?\\C:\\",
L"C:\\",
TRUE,
},
{ 0, }
};
for (i = 0; testcases[i].in; i++)
{
gsize str_len = wcslen (testcases[i].in) + 1;
gchar *in_u8 = g_utf16_to_utf8 (testcases[i].in, -1, NULL, NULL, NULL);
gchar *out_u8 = g_utf16_to_utf8 (testcases[i].out, -1, NULL, NULL, NULL);
g_assert_nonnull (in_u8);
g_assert_nonnull (out_u8);
buf = g_new0 (gunichar2, str_len);
memcpy (buf, testcases[i].in, str_len * sizeof (gunichar2));
_g_win32_strip_extended_ntobjm_prefix (buf, &str_len);
g_assert_cmpwcs (buf, ==, testcases[i].out, in_u8, out_u8);
g_free (buf);
g_free (in_u8);
g_free (out_u8);
}
/* Check for correct behaviour on non-NUL-terminated strings */
for (i = 0; testcases[i].in; i++)
{
gsize str_len = wcslen (testcases[i].in) + 1;
wchar_t old_endchar;
gchar *in_u8 = g_utf16_to_utf8 (testcases[i].in, -1, NULL, NULL, NULL);
gchar *out_u8 = g_utf16_to_utf8 (testcases[i].out, -1, NULL, NULL, NULL);
g_assert_nonnull (in_u8);
g_assert_nonnull (out_u8);
buf = g_new0 (gunichar2, str_len);
memcpy (buf, testcases[i].in, (str_len) * sizeof (gunichar2));
old_endchar = buf[wcslen (testcases[i].out)];
str_len -= 1;
if (testcases[i].result)
{
/* Given "\\\\?\\C:\\" (len 7, unterminated),
* we should get "C:\\" (len 3, unterminated).
* Put a character different from "\\" (4-th character of the buffer)
* at the end of the unterminated source buffer, into a position
* where NUL-terminator would normally be. Then later test that 4-th character
* in the buffer is still the old "\\".
* After that terminate the string and use normal g_wcscmp0().
*/
buf[str_len] = old_endchar - 1;
}
_g_win32_strip_extended_ntobjm_prefix (buf, &str_len);
g_assert_cmpuint (old_endchar, ==, buf[wcslen (testcases[i].out)]);
buf[str_len] = L'\0';
g_assert_cmpwcs (buf, ==, testcases[i].out, in_u8, out_u8);
g_free (buf);
g_free (in_u8);
g_free (out_u8);
}
}
#define g_assert_memcmp(m1, cmp, m2, memlen, m1hex, m2hex, testcase_num) \
G_STMT_START { \
if (memcmp (m1, m2, memlen) cmp 0); else \
g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
#m1hex " " #cmp " " #m2hex, m1hex, #cmp, m2hex); \
} G_STMT_END
static gchar *
to_hex (const guchar *buf,
gsize len)
{
gsize i;
GString *s = g_string_new (NULL);
if (len > 0)
g_string_append_printf (s, "%02x", buf[0]);
for (i = 1; i < len; i++)
g_string_append_printf (s, " %02x", buf[i]);
return g_string_free (s, FALSE);
}
static void
test_win32_zero_terminate_symlink (void)
{
gsize i;
#define TESTCASE(data, len_mod, use_buf, buf_size, terminate, reported_len, returned_string) \
{ (const guchar *) data, wcslen (data) * 2 + len_mod, use_buf, buf_size, terminate, reported_len, (guchar *) returned_string},
struct
{
const guchar *data;
gsize data_size;
gboolean use_buf;
gsize buf_size;
gboolean terminate;
int reported_len;
const guchar *returned_string;
} testcases[] = {
TESTCASE (L"foobar", +2, TRUE, 12 + 4, FALSE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
TESTCASE (L"foobar", +2, TRUE, 12 + 3, FALSE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
TESTCASE (L"foobar", +2, TRUE, 12 + 2, FALSE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
TESTCASE (L"foobar", +2, TRUE, 12 + 1, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", +2, TRUE, 12 + 0, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
TESTCASE (L"foobar", +2, TRUE, 12 - 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
TESTCASE (L"foobar", +2, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
TESTCASE (L"foobar", +2, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
TESTCASE (L"foobar", +1, TRUE, 12 + 4, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", +1, TRUE, 12 + 3, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", +1, TRUE, 12 + 2, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", +1, TRUE, 12 + 1, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", +1, TRUE, 12 + 0, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
TESTCASE (L"foobar", +1, TRUE, 12 - 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
TESTCASE (L"foobar", +1, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
TESTCASE (L"foobar", +1, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
TESTCASE (L"foobar", +0, TRUE, 12 + 4, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
TESTCASE (L"foobar", +0, TRUE, 12 + 3, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
TESTCASE (L"foobar", +0, TRUE, 12 + 2, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
TESTCASE (L"foobar", +0, TRUE, 12 + 1, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
TESTCASE (L"foobar", +0, TRUE, 12 + 0, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
TESTCASE (L"foobar", +0, TRUE, 12 - 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
TESTCASE (L"foobar", +0, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
TESTCASE (L"foobar", +0, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
TESTCASE (L"foobar", -1, TRUE, 12 + 3, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
TESTCASE (L"foobar", -1, TRUE, 12 + 2, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
TESTCASE (L"foobar", -1, TRUE, 12 + 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
TESTCASE (L"foobar", -1, TRUE, 12 + 0, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
TESTCASE (L"foobar", -1, TRUE, 12 - 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
TESTCASE (L"foobar", -1, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
TESTCASE (L"foobar", -1, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
TESTCASE (L"foobar", -1, TRUE, 12 - 4, FALSE, 12 - 4, "f\0o\0o\0b\0")
TESTCASE (L"foobar", -2, TRUE, 12 + 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
TESTCASE (L"foobar", -2, TRUE, 12 + 1, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
TESTCASE (L"foobar", -2, TRUE, 12 + 0, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
TESTCASE (L"foobar", -2, TRUE, 12 - 1, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
TESTCASE (L"foobar", -2, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
TESTCASE (L"foobar", -2, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
TESTCASE (L"foobar", -2, TRUE, 12 - 4, FALSE, 12 - 4, "f\0o\0o\0b\0")
TESTCASE (L"foobar", -2, TRUE, 12 - 5, FALSE, 12 - 5, "f\0o\0o\0b")
TESTCASE (L"foobar", +2, TRUE, 12 + 4, TRUE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
TESTCASE (L"foobar", +2, TRUE, 12 + 3, TRUE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
TESTCASE (L"foobar", +2, TRUE, 12 + 2, TRUE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
TESTCASE (L"foobar", +2, TRUE, 12 + 1, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", +2, TRUE, 12 + 0, TRUE, 12 + 0, "f\0o\0o\0b\0a\0\0\0")
TESTCASE (L"foobar", +2, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
TESTCASE (L"foobar", +2, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
TESTCASE (L"foobar", +2, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
TESTCASE (L"foobar", +1, TRUE, 12 + 4, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", +1, TRUE, 12 + 3, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", +1, TRUE, 12 + 2, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", +1, TRUE, 12 + 1, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", +1, TRUE, 12 + 0, TRUE, 12 + 0, "f\0o\0o\0b\0a\0\0\0")
TESTCASE (L"foobar", +1, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
TESTCASE (L"foobar", +1, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
TESTCASE (L"foobar", +1, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
TESTCASE (L"foobar", +0, TRUE, 12 + 4, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", +0, TRUE, 12 + 3, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", +0, TRUE, 12 + 2, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", +0, TRUE, 12 + 1, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", +0, TRUE, 12 + 0, TRUE, 12 + 0, "f\0o\0o\0b\0a\0\0\0")
TESTCASE (L"foobar", +0, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
TESTCASE (L"foobar", +0, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
TESTCASE (L"foobar", +0, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
TESTCASE (L"foobar", -1, TRUE, 12 + 3, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", -1, TRUE, 12 + 2, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", -1, TRUE, 12 + 1, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", -1, TRUE, 12 + 0, TRUE, 12 + 0, "f\0o\0o\0b\0a\0\0\0")
TESTCASE (L"foobar", -1, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
TESTCASE (L"foobar", -1, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
TESTCASE (L"foobar", -1, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
TESTCASE (L"foobar", -1, TRUE, 12 - 4, TRUE, 12 - 4, "f\0o\0o\0\0\0")
TESTCASE (L"foobar", -2, TRUE, 12 + 2, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
TESTCASE (L"foobar", -2, TRUE, 12 + 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
TESTCASE (L"foobar", -2, TRUE, 12 + 0, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
TESTCASE (L"foobar", -2, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
TESTCASE (L"foobar", -2, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
TESTCASE (L"foobar", -2, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
TESTCASE (L"foobar", -2, TRUE, 12 - 4, TRUE, 12 - 4, "f\0o\0o\0\0\0")
TESTCASE (L"foobar", -2, TRUE, 12 - 5, TRUE, 12 - 5, "f\0o\0o\0\0")
TESTCASE (L"foobar", +2, FALSE, 0, FALSE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
TESTCASE (L"foobar", +1, FALSE, 0, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", +0, FALSE, 0, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
TESTCASE (L"foobar", -1, FALSE, 0, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
TESTCASE (L"foobar", -2, FALSE, 0, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
TESTCASE (L"foobar", +2, FALSE, 0, TRUE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
TESTCASE (L"foobar", +1, FALSE, 0, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", +0, FALSE, 0, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", -1, FALSE, 0, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
TESTCASE (L"foobar", -2, FALSE, 0, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
TESTCASE (L"x", +2, TRUE, 2 + 4, FALSE, 2 + 2, "x\0\0\0")
TESTCASE (L"x", +2, TRUE, 2 + 3, FALSE, 2 + 2, "x\0\0\0")
TESTCASE (L"x", +2, TRUE, 2 + 2, FALSE, 2 + 2, "x\0\0\0")
TESTCASE (L"x", +2, TRUE, 2 + 1, FALSE, 2 + 1, "x\0\0")
TESTCASE (L"x", +2, TRUE, 2 + 0, FALSE, 2 + 0, "x\0")
TESTCASE (L"x", +2, TRUE, 2 - 1, FALSE, 2 - 1, "x")
TESTCASE (L"x", +2, TRUE, 2 - 2, FALSE, 2 - 2, "")
TESTCASE (L"x", +1, TRUE, 2 + 3, FALSE, 2 + 1, "x\0\0")
TESTCASE (L"x", +1, TRUE, 2 + 2, FALSE, 2 + 1, "x\0\0")
TESTCASE (L"x", +1, TRUE, 2 + 1, FALSE, 2 + 1, "x\0\0")
TESTCASE (L"x", +1, TRUE, 2 + 0, FALSE, 2 + 0, "x\0")
TESTCASE (L"x", +1, TRUE, 2 - 1, FALSE, 2 - 1, "x")
TESTCASE (L"x", +1, TRUE, 2 - 2, FALSE, 2 - 2, "")
TESTCASE (L"x", +0, TRUE, 2 + 2, FALSE, 2 + 0, "x\0")
TESTCASE (L"x", +0, TRUE, 2 + 1, FALSE, 2 + 0, "x\0")
TESTCASE (L"x", +0, TRUE, 2 + 0, FALSE, 2 + 0, "x\0")
TESTCASE (L"x", +0, TRUE, 2 - 1, FALSE, 2 - 1, "x")
TESTCASE (L"x", +0, TRUE, 2 - 2, FALSE, 2 - 2, "")
TESTCASE (L"x", -1, TRUE, 2 + 1, FALSE, 2 - 1, "x")
TESTCASE (L"x", -1, TRUE, 2 + 0, FALSE, 2 - 1, "x")
TESTCASE (L"x", -1, TRUE, 2 - 1, FALSE, 2 - 1, "x")
TESTCASE (L"x", -1, TRUE, 2 - 2, FALSE, 2 - 2, "")
TESTCASE (L"x", -2, TRUE, 2 + 0, FALSE, 2 - 2, "")
TESTCASE (L"x", -2, TRUE, 2 - 1, FALSE, 2 - 2, "")
TESTCASE (L"x", -2, TRUE, 2 - 2, FALSE, 2 - 2, "")
TESTCASE (L"x", +2, TRUE, 2 + 4, TRUE, 2 + 2, "x\0\0\0")
TESTCASE (L"x", +2, TRUE, 2 + 3, TRUE, 2 + 2, "x\0\0\0")
TESTCASE (L"x", +2, TRUE, 2 + 2, TRUE, 2 + 2, "x\0\0\0")
TESTCASE (L"x", +2, TRUE, 2 + 1, TRUE, 2 + 1, "x\0\0")
TESTCASE (L"x", +2, TRUE, 2 + 0, TRUE, 2 + 0, "\0\0")
TESTCASE (L"x", +2, TRUE, 2 - 1, TRUE, 2 - 1, "\0")
TESTCASE (L"x", +2, TRUE, 2 - 2, TRUE, 2 - 2, "")
TESTCASE (L"x", +1, TRUE, 2 + 3, TRUE, 2 + 1, "x\0\0")
TESTCASE (L"x", +1, TRUE, 2 + 2, TRUE, 2 + 1, "x\0\0")
TESTCASE (L"x", +1, TRUE, 2 + 1, TRUE, 2 + 1, "x\0\0")
TESTCASE (L"x", +1, TRUE, 2 + 0, TRUE, 2 + 0, "\0\0")
TESTCASE (L"x", +1, TRUE, 2 - 1, TRUE, 2 - 1, "\0")
TESTCASE (L"x", +1, TRUE, 2 - 2, TRUE, 2 - 2, "")
TESTCASE (L"x", +0, TRUE, 2 + 2, TRUE, 2 + 1, "x\0\0")
TESTCASE (L"x", +0, TRUE, 2 + 1, TRUE, 2 + 1, "x\0\0")
TESTCASE (L"x", +0, TRUE, 2 + 0, TRUE, 2 + 0, "\0\0")
TESTCASE (L"x", +0, TRUE, 2 - 1, TRUE, 2 - 1, "\0")
TESTCASE (L"x", +0, TRUE, 2 - 2, TRUE, 2 - 2, "")
TESTCASE (L"x", -1, TRUE, 2 + 1, TRUE, 2 + 1, "x\0\0")
TESTCASE (L"x", -1, TRUE, 2 + 0, TRUE, 2 + 0, "\0\0")
TESTCASE (L"x", -1, TRUE, 2 - 1, TRUE, 2 - 1, "\0")
TESTCASE (L"x", -1, TRUE, 2 - 2, TRUE, 2 - 2, "")
TESTCASE (L"x", -2, TRUE, 2 + 0, TRUE, 2 - 2, "")
TESTCASE (L"x", -2, TRUE, 2 - 1, TRUE, 2 - 2, "")
TESTCASE (L"x", -2, TRUE, 2 - 2, TRUE, 2 - 2, "")
TESTCASE (L"x", +2, FALSE, 0, FALSE, 2 + 2, "x\0\0\0")
TESTCASE (L"x", +1, FALSE, 0, FALSE, 2 + 1, "x\0\0")
TESTCASE (L"x", +0, FALSE, 0, FALSE, 2 + 0, "x\0")
TESTCASE (L"x", -1, FALSE, 0, FALSE, 2 - 1, "x")
TESTCASE (L"x", -2, FALSE, 0, FALSE, 2 - 2, "")
TESTCASE (L"x", +2, FALSE, 0, TRUE, 2 + 2, "x\0\0\0")
TESTCASE (L"x", +1, FALSE, 0, TRUE, 2 + 1, "x\0\0")
TESTCASE (L"x", +0, FALSE, 0, TRUE, 2 + 1, "x\0\0")
TESTCASE (L"x", -1, FALSE, 0, TRUE, 2 + 1, "x\0\0")
TESTCASE (L"x", -2, FALSE, 0, TRUE, 2 - 2, "")
{ 0, },
};
#undef TESTCASE
for (i = 0; testcases[i].data != NULL; i++)
{
gunichar2 *buf;
int result;
gchar *buf_hex, *expected_hex;
if (testcases[i].use_buf)
buf = g_malloc0 (testcases[i].buf_size + 1); /* +1 to ensure it succeeds with buf_size == 0 */
else
buf = NULL;
result = _g_win32_copy_and_maybe_terminate (testcases[i].data,
testcases[i].data_size,
testcases[i].use_buf ? buf : NULL,
testcases[i].buf_size,
testcases[i].use_buf ? NULL : &buf,
testcases[i].terminate);
if (testcases[i].reported_len != result)
g_error ("Test %" G_GSIZE_FORMAT " failed, result %d != %d", i, result, testcases[i].reported_len);
if (buf == NULL && testcases[i].buf_size != 0)
g_error ("Test %" G_GSIZE_FORMAT " failed, buf == NULL", i);
g_assert_cmpint (testcases[i].reported_len, ==, result);
if ((testcases[i].use_buf && testcases[i].buf_size != 0) ||
(!testcases[i].use_buf && testcases[i].reported_len != 0))
{
g_assert_nonnull (buf);
buf_hex = to_hex ((const guchar *) buf, result);
expected_hex = to_hex (testcases[i].returned_string, testcases[i].reported_len);
if (memcmp (buf, testcases[i].returned_string, result) != 0)
g_error ("Test %" G_GSIZE_FORMAT " failed:\n%s !=\n%s", i, buf_hex, expected_hex);
g_assert_memcmp (buf, ==, testcases[i].returned_string, testcases[i].reported_len, buf_hex, expected_hex, testcases[i].line);
g_free (buf_hex);
g_free (expected_hex);
}
g_free (buf);
}
}
#endif
int
main (int argc,
char *argv[])
{
g_setenv ("LC_ALL", "C", TRUE);
g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
g_test_bug_base ("https://gitlab.gnome.org/GNOME/glib/merge_requests/");
#ifdef G_OS_WIN32
g_test_add_func ("/fileutils/stdio-win32-pathstrip", test_win32_pathstrip);
g_test_add_func ("/fileutils/stdio-win32-zero-terminate-symlink", test_win32_zero_terminate_symlink);
#endif
g_test_add_func ("/fileutils/build-path", test_build_path);
g_test_add_func ("/fileutils/build-pathv", test_build_pathv);
g_test_add_func ("/fileutils/build-filename", test_build_filename);
g_test_add_func ("/fileutils/build-filenamev", test_build_filenamev);
g_test_add_func ("/fileutils/mkdir-with-parents", test_mkdir_with_parents);
g_test_add_func ("/fileutils/mkdir-with-parents-permission", test_mkdir_with_parents_permission);
g_test_add_func ("/fileutils/format-size-for-display", test_format_size_for_display);
g_test_add_func ("/fileutils/errors", test_file_errors);
g_test_add_func ("/fileutils/basename", test_basename);
g_test_add_func ("/fileutils/dir-make-tmp", test_dir_make_tmp);
g_test_add_func ("/fileutils/file-open-tmp", test_file_open_tmp);
g_test_add_func ("/fileutils/mkstemp", test_mkstemp);
g_test_add_func ("/fileutils/mkdtemp", test_mkdtemp);
g_test_add_func ("/fileutils/set-contents", test_set_contents);
g_test_add_func ("/fileutils/set-contents-full", test_set_contents_full);
g_test_add_func ("/fileutils/set-contents-full/read-only-file", test_set_contents_full_read_only_file);
g_test_add_func ("/fileutils/set-contents-full/read-only-directory", test_set_contents_full_read_only_directory);
g_test_add_func ("/fileutils/read-link", test_read_link);
g_test_add_func ("/fileutils/stdio-wrappers", test_stdio_wrappers);
g_test_add_func ("/fileutils/fopen-modes", test_fopen_modes);
return g_test_run ();
}