2020-02-25 15:15:30 +00:00
|
|
|
/* Test --no-hard-links option to localedef.
|
2024-01-01 18:12:26 +00:00
|
|
|
Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
2020-02-25 15:15:30 +00:00
|
|
|
This file is part of the GNU C Library.
|
|
|
|
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Lesser General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
The GNU C Library 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. See the GNU
|
|
|
|
Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
|
|
License along with the GNU C Library; if not, see
|
|
|
|
<https://www.gnu.org/licenses/>. */
|
|
|
|
|
|
|
|
/* The test is designed to run in a container and execute localedef
|
|
|
|
once without --no-hard-links, verify that there are 2 hard links to
|
|
|
|
LC_CTYPE, and then run again *with* --no-hard-links and verify there
|
|
|
|
are no hard links and link counts remain at 1. The expectation here
|
|
|
|
is that LC_CTYPE is identical for both locales because they are same
|
|
|
|
empty locale but with a different name. We use tests-container in
|
|
|
|
this test because the hard link optimziation is only carried out for
|
|
|
|
the default locale installation directory, and to write to that we
|
|
|
|
need write access to that directory, enabled by 'su' via
|
|
|
|
tests-container framework. */
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
|
|
|
|
#include <support/check.h>
|
|
|
|
#include <support/support.h>
|
|
|
|
#include <support/xunistd.h>
|
|
|
|
#include <support/capture_subprocess.h>
|
|
|
|
|
|
|
|
/* Each test compiles a locale to output, and has an expected link count
|
|
|
|
for LC_CTYPE. This test expects that localedef removes the existing
|
|
|
|
files before installing new copies of the files, and we do not
|
|
|
|
cleanup between localedef runs. We can't cleanup between each pair
|
|
|
|
of runs since localedef must see the existing locale in order to
|
|
|
|
determine that space could be saved by using a hardlink. */
|
|
|
|
struct test_data
|
|
|
|
{
|
|
|
|
/* Arguments to localedef for this step. */
|
|
|
|
const char * argv[16];
|
|
|
|
/* Expected output file generated by running localedef. */
|
|
|
|
const char *output;
|
|
|
|
/* Expected st_nlink count for the output. */
|
|
|
|
int st_nlink;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Check for link count. */
|
|
|
|
void
|
|
|
|
check_link (struct test_data step)
|
|
|
|
{
|
|
|
|
struct stat64 locale;
|
|
|
|
char *output;
|
|
|
|
|
|
|
|
output = xasprintf ("%s/%s", support_complocaledir_prefix, step.output);
|
2024-08-16 14:05:20 +00:00
|
|
|
xstat64 (output, &locale);
|
2020-02-25 15:15:30 +00:00
|
|
|
free (output);
|
|
|
|
TEST_COMPARE (locale.st_nlink, step.st_nlink);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
run_localedef (void *step)
|
|
|
|
{
|
|
|
|
const char *prog = xasprintf ("%s/localedef", support_bindir_prefix);
|
|
|
|
struct test_data *one = (struct test_data *) step;
|
|
|
|
|
|
|
|
one->argv[0] = prog;
|
|
|
|
execv (prog, (char * const *) one->argv);
|
|
|
|
FAIL_EXIT1 ("execv: %m");
|
|
|
|
}
|
|
|
|
|
|
|
|
#define TEST1DIR "test1_locale.dir"
|
|
|
|
#define TEST2DIR "test2_locale.dir"
|
|
|
|
|
|
|
|
/* The whole test has 4 steps described below. Note the argv[0] NULL
|
|
|
|
will be filled in at runtime by run_localedef. */
|
|
|
|
static struct test_data step[4] = {
|
|
|
|
{ .argv = { NULL, "--no-archive", "-i", "/test1_locale", TEST1DIR, NULL },
|
|
|
|
.output = TEST1DIR "/LC_CTYPE",
|
|
|
|
.st_nlink = 1 },
|
|
|
|
{ .argv = { NULL, "--no-archive", "-i", "/test2_locale", TEST2DIR, NULL },
|
|
|
|
.output = TEST2DIR "/LC_CTYPE",
|
|
|
|
.st_nlink = 2 },
|
|
|
|
{ .argv = { NULL, "--no-archive", "--no-hard-links", "-i", "/test1_locale",
|
|
|
|
TEST1DIR, NULL },
|
|
|
|
.output = TEST1DIR "/LC_CTYPE",
|
|
|
|
.st_nlink = 1 },
|
|
|
|
{ .argv = { NULL, "--no-archive", "--no-hard-links", "-i", "/test2_locale",
|
|
|
|
TEST1DIR, NULL },
|
|
|
|
.output = TEST2DIR "/LC_CTYPE",
|
|
|
|
.st_nlink = 1 },
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
do_test (void)
|
|
|
|
{
|
|
|
|
struct support_capture_subprocess result;
|
|
|
|
|
|
|
|
printf ("INFO: $complocaledir is %s\n", support_complocaledir_prefix);
|
|
|
|
/* Compile the first locale. */
|
|
|
|
result = support_capture_subprocess (run_localedef, (void *) &step[0]);
|
|
|
|
support_capture_subprocess_check (&result, "execv", 1, sc_allow_stderr);
|
|
|
|
check_link (step[0]);
|
|
|
|
|
|
|
|
/* This time around we should have link counts of 2 for the second
|
|
|
|
linked locale since categories are identical. */
|
|
|
|
result = support_capture_subprocess (run_localedef, (void *) &step[1]);
|
|
|
|
support_capture_subprocess_check (&result, "execv", 1, sc_allow_stderr);
|
|
|
|
check_link (step[1]);
|
|
|
|
|
|
|
|
/* Again with --no-hard-links (link count is always one). */
|
|
|
|
result = support_capture_subprocess (run_localedef, (void *) &step[2]);
|
|
|
|
support_capture_subprocess_check (&result, "execv", 1, sc_allow_stderr);
|
|
|
|
check_link (step[2]);
|
|
|
|
|
|
|
|
/* Again with --no-hard-links, and the link count must remain 1. */
|
|
|
|
result = support_capture_subprocess (run_localedef, (void *) &step[3]);
|
|
|
|
support_capture_subprocess_check (&result, "execv", 1, sc_allow_stderr);
|
|
|
|
check_link (step[3]);
|
|
|
|
|
|
|
|
/* Tested without and with --no-hard-links and link counts were
|
|
|
|
consistent. */
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include <support/test-driver.c>
|