New upstream version 2017.3
This commit is contained in:
commit
057de00126
134 files changed
+7527
-2384
No files matched your search
+107
-86
@@ -1,13 +1,14 @@
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the library GPL. It is
|
||||
numbered 2 because it goes with version 2 of the ordinary GPL.]
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
@@ -16,97 +17,109 @@ freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Library General Public License, applies to some
|
||||
specially designated Free Software Foundation software, and to any
|
||||
other libraries whose authors decide to use it. You can use it for
|
||||
your libraries, too.
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if
|
||||
you distribute copies of the library, or if you modify it.
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link a program with the library, you must provide
|
||||
complete object files to the recipients so that they can relink them
|
||||
with the library, after making changes to the library and recompiling
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
Our method of protecting your rights has two steps: (1) copyright
|
||||
the library, and (2) offer you this license which gives you legal
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
Also, for each distributor's protection, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
library. If the library is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original
|
||||
version, so that any problems introduced by others will not reflect on
|
||||
the original authors' reputations.
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that companies distributing free
|
||||
software will individually obtain patent licenses, thus in effect
|
||||
transforming the program into proprietary software. To prevent this,
|
||||
we have made it clear that any patent must be licensed for everyone's
|
||||
free use or not licensed at all.
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the ordinary
|
||||
GNU General Public License, which was designed for utility programs. This
|
||||
license, the GNU Library General Public License, applies to certain
|
||||
designated libraries. This license is quite different from the ordinary
|
||||
one; be sure to read it in full, and don't assume that anything in it is
|
||||
the same as in the ordinary license.
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
The reason we have a separate public license for some libraries is that
|
||||
they blur the distinction we usually make between modifying or adding to a
|
||||
program and simply using it. Linking a program with a library, without
|
||||
changing the library, is in some sense simply using the library, and is
|
||||
analogous to running a utility program or application program. However, in
|
||||
a textual and legal sense, the linked executable is a combined work, a
|
||||
derivative of the original library, and the ordinary General Public License
|
||||
treats it as such.
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
Because of this blurred distinction, using the ordinary General
|
||||
Public License for libraries did not effectively promote software
|
||||
sharing, because most developers did not use the libraries. We
|
||||
concluded that weaker conditions might promote sharing better.
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
However, unrestricted linking of non-free programs would deprive the
|
||||
users of those programs of all benefit from the free status of the
|
||||
libraries themselves. This Library General Public License is intended to
|
||||
permit developers of non-free programs to use free libraries, while
|
||||
preserving your freedom as a user of such programs to change the free
|
||||
libraries that are incorporated in them. (We have not seen how to achieve
|
||||
this as regards changes in header files, but we have achieved it as regards
|
||||
changes in the actual functions of the Library.) The hope is that this
|
||||
will lead to faster development of free libraries.
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, while the latter only
|
||||
works together with the library.
|
||||
|
||||
Note that it is possible for a library to be covered by the ordinary
|
||||
General Public License rather than by this special one.
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library which
|
||||
contains a notice placed by the copyright holder or other authorized
|
||||
party saying it may be distributed under the terms of this Library
|
||||
General Public License (also called "this License"). Each licensee is
|
||||
addressed as "you".
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
@@ -133,7 +146,7 @@ such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
@@ -255,7 +268,7 @@ distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also compile or
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
@@ -282,23 +295,31 @@ of these things:
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Accompany the work with a written offer, valid for at
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
c) If distribution of the work is made by offering access to copy
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
d) Verify that the user has already received a copy of these
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the source code distributed need not include anything that is normally
|
||||
distributed (in either source or binary form) with the major
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
@@ -347,7 +368,7 @@ Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
@@ -390,7 +411,7 @@ excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Library General Public License from time to time.
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
@@ -453,16 +474,16 @@ convey the exclusion of warranty; and each file should have at least the
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This 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
|
||||
Library General Public License for more details.
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
@@ -51,3 +51,10 @@ libglnx_la_SOURCES = \
|
||||
libglnx_la_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags)
|
||||
libglnx_la_LDFLAGS = -avoid-version -Bsymbolic-functions -export-symbols-regex "^glnx_" -no-undefined -export-dynamic
|
||||
libglnx_la_LIBADD = $(libglnx_libs)
|
||||
|
||||
TESTS += test-libglnx-xattrs
|
||||
|
||||
check_PROGRAMS += test-libglnx-xattrs
|
||||
test_libglnx_xattrs_SOURCES = $(libglnx_srcpath)/tests/test-libglnx-xattrs.c
|
||||
test_libglnx_xattrs_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags)
|
||||
test_libglnx_xattrs_LDADD = $(libglnx_libs) libglnx.la
|
||||
@@ -51,3 +51,10 @@ libglnx_la_SOURCES = \
|
||||
libglnx_la_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags)
|
||||
libglnx_la_LDFLAGS = -avoid-version -Bsymbolic-functions -export-symbols-regex "^glnx_" -no-undefined -export-dynamic
|
||||
libglnx_la_LIBADD = $(libglnx_libs)
|
||||
|
||||
TESTS += test-libglnx-xattrs
|
||||
|
||||
check_PROGRAMS += test-libglnx-xattrs
|
||||
test_libglnx_xattrs_SOURCES = libglnx/tests/test-libglnx-xattrs.c
|
||||
test_libglnx_xattrs_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags)
|
||||
test_libglnx_xattrs_LDADD = $(libglnx_libs) libglnx.la
|
||||
+4
-26
@@ -293,13 +293,10 @@ glnx_gen_temp_name (gchar *tmpl)
|
||||
{
|
||||
size_t len;
|
||||
char *XXXXXX;
|
||||
int count;
|
||||
int i;
|
||||
static const char letters[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
static const int NLETTERS = sizeof (letters) - 1;
|
||||
glong value;
|
||||
GTimeVal tv;
|
||||
static int counter = 0;
|
||||
|
||||
g_return_if_fail (tmpl != NULL);
|
||||
len = strlen (tmpl);
|
||||
@@ -307,27 +304,8 @@ glnx_gen_temp_name (gchar *tmpl)
|
||||
|
||||
XXXXXX = tmpl + (len - 6);
|
||||
|
||||
/* Get some more or less random data. */
|
||||
g_get_current_time (&tv);
|
||||
value = (tv.tv_usec ^ tv.tv_sec) + counter++;
|
||||
|
||||
for (count = 0; count < 100; value += 7777, ++count)
|
||||
{
|
||||
glong v = value;
|
||||
|
||||
/* Fill in the random bits. */
|
||||
XXXXXX[0] = letters[v % NLETTERS];
|
||||
v /= NLETTERS;
|
||||
XXXXXX[1] = letters[v % NLETTERS];
|
||||
v /= NLETTERS;
|
||||
XXXXXX[2] = letters[v % NLETTERS];
|
||||
v /= NLETTERS;
|
||||
XXXXXX[3] = letters[v % NLETTERS];
|
||||
v /= NLETTERS;
|
||||
XXXXXX[4] = letters[v % NLETTERS];
|
||||
v /= NLETTERS;
|
||||
XXXXXX[5] = letters[v % NLETTERS];
|
||||
}
|
||||
for (i = 0; i < 6; i++)
|
||||
XXXXXX[i] = letters[g_random_int_range(0, NLETTERS)];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+50
-68
@@ -83,19 +83,22 @@ read_xattr_name_array (const char *path,
|
||||
|
||||
funcstr = fd != -1 ? "fgetxattr" : "lgetxattr";
|
||||
|
||||
p = xattrs;
|
||||
while (p < xattrs+len)
|
||||
for (p = xattrs; p < xattrs+len; p = p + strlen (p) + 1)
|
||||
{
|
||||
ssize_t bytes_read;
|
||||
char *buf;
|
||||
GBytes *bytes = NULL;
|
||||
g_autofree char *buf = NULL;
|
||||
g_autoptr(GBytes) bytes = NULL;
|
||||
|
||||
again:
|
||||
if (fd != -1)
|
||||
bytes_read = fgetxattr (fd, p, NULL, 0);
|
||||
else
|
||||
bytes_read = lgetxattr (path, p, NULL, 0);
|
||||
if (bytes_read < 0)
|
||||
{
|
||||
if (errno == ENODATA)
|
||||
continue;
|
||||
|
||||
glnx_set_prefix_error_from_errno (error, "%s", funcstr);
|
||||
goto out;
|
||||
}
|
||||
@@ -103,26 +106,30 @@ read_xattr_name_array (const char *path,
|
||||
continue;
|
||||
|
||||
buf = g_malloc (bytes_read);
|
||||
bytes = g_bytes_new_take (buf, bytes_read);
|
||||
if (fd != -1)
|
||||
r = fgetxattr (fd, p, buf, bytes_read);
|
||||
else
|
||||
r = lgetxattr (path, p, buf, bytes_read);
|
||||
if (r < 0)
|
||||
{
|
||||
g_bytes_unref (bytes);
|
||||
if (errno == ERANGE)
|
||||
{
|
||||
g_free (g_steal_pointer (&buf));
|
||||
goto again;
|
||||
}
|
||||
else if (errno == ENODATA)
|
||||
continue;
|
||||
|
||||
glnx_set_prefix_error_from_errno (error, "%s", funcstr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
bytes = g_bytes_new_take (g_steal_pointer (&buf), bytes_read);
|
||||
g_variant_builder_add (builder, "(@ay@ay)",
|
||||
g_variant_new_bytestring (p),
|
||||
variant_new_ay_bytes (bytes));
|
||||
|
||||
p = p + strlen (p) + 1;
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
@@ -130,22 +137,29 @@ read_xattr_name_array (const char *path,
|
||||
|
||||
static gboolean
|
||||
get_xattrs_impl (const char *path,
|
||||
int fd,
|
||||
GVariant **out_xattrs,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
ssize_t bytes_read;
|
||||
ssize_t bytes_read, real_size;
|
||||
glnx_free char *xattr_names = NULL;
|
||||
glnx_free char *xattr_names_canonical = NULL;
|
||||
GVariantBuilder builder;
|
||||
gboolean builder_initialized = FALSE;
|
||||
g_autoptr(GVariant) ret_xattrs = NULL;
|
||||
|
||||
g_assert (path != NULL || fd != -1);
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ayay)"));
|
||||
builder_initialized = TRUE;
|
||||
|
||||
bytes_read = llistxattr (path, NULL, 0);
|
||||
again:
|
||||
if (path)
|
||||
bytes_read = llistxattr (path, NULL, 0);
|
||||
else
|
||||
bytes_read = flistxattr (fd, NULL, 0);
|
||||
|
||||
if (bytes_read < 0)
|
||||
{
|
||||
@@ -158,15 +172,27 @@ get_xattrs_impl (const char *path,
|
||||
else if (bytes_read > 0)
|
||||
{
|
||||
xattr_names = g_malloc (bytes_read);
|
||||
if (llistxattr (path, xattr_names, bytes_read) < 0)
|
||||
if (path)
|
||||
real_size = llistxattr (path, xattr_names, bytes_read);
|
||||
else
|
||||
real_size = flistxattr (fd, xattr_names, bytes_read);
|
||||
if (real_size < 0)
|
||||
{
|
||||
if (errno == ERANGE)
|
||||
{
|
||||
g_free (xattr_names);
|
||||
goto again;
|
||||
}
|
||||
glnx_set_prefix_error_from_errno (error, "%s", "llistxattr");
|
||||
goto out;
|
||||
}
|
||||
xattr_names_canonical = canonicalize_xattrs (xattr_names, bytes_read);
|
||||
|
||||
if (!read_xattr_name_array (path, -1, xattr_names_canonical, bytes_read, &builder, error))
|
||||
goto out;
|
||||
else if (real_size > 0)
|
||||
{
|
||||
xattr_names_canonical = canonicalize_xattrs (xattr_names, real_size);
|
||||
|
||||
if (!read_xattr_name_array (path, fd, xattr_names_canonical, real_size, &builder, error))
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret_xattrs = g_variant_builder_end (&builder);
|
||||
@@ -201,52 +227,8 @@ glnx_fd_get_all_xattrs (int fd,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
ssize_t bytes_read;
|
||||
glnx_free char *xattr_names = NULL;
|
||||
glnx_free char *xattr_names_canonical = NULL;
|
||||
GVariantBuilder builder;
|
||||
gboolean builder_initialized = FALSE;
|
||||
g_autoptr(GVariant) ret_xattrs = NULL;
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ayay)"));
|
||||
builder_initialized = TRUE;
|
||||
|
||||
bytes_read = flistxattr (fd, NULL, 0);
|
||||
|
||||
if (bytes_read < 0)
|
||||
{
|
||||
if (errno != ENOTSUP)
|
||||
{
|
||||
glnx_set_prefix_error_from_errno (error, "%s", "flistxattr");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else if (bytes_read > 0)
|
||||
{
|
||||
xattr_names = g_malloc (bytes_read);
|
||||
if (flistxattr (fd, xattr_names, bytes_read) < 0)
|
||||
{
|
||||
glnx_set_prefix_error_from_errno (error, "%s", "flistxattr");
|
||||
goto out;
|
||||
}
|
||||
xattr_names_canonical = canonicalize_xattrs (xattr_names, bytes_read);
|
||||
|
||||
if (!read_xattr_name_array (NULL, fd, xattr_names_canonical, bytes_read, &builder, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_xattrs = g_variant_builder_end (&builder);
|
||||
builder_initialized = FALSE;
|
||||
g_variant_ref_sink (ret_xattrs);
|
||||
|
||||
ret = TRUE;
|
||||
if (out_xattrs)
|
||||
*out_xattrs = g_steal_pointer (&ret_xattrs);
|
||||
out:
|
||||
if (!builder_initialized)
|
||||
g_variant_builder_clear (&builder);
|
||||
return ret;
|
||||
return get_xattrs_impl (NULL, fd, out_xattrs,
|
||||
cancellable, error);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -269,7 +251,7 @@ glnx_dfd_name_get_all_xattrs (int dfd,
|
||||
{
|
||||
if (dfd == AT_FDCWD || dfd == -1)
|
||||
{
|
||||
return get_xattrs_impl (name, out_xattrs, cancellable, error);
|
||||
return get_xattrs_impl (name, -1, out_xattrs, cancellable, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -278,7 +260,7 @@ glnx_dfd_name_get_all_xattrs (int dfd,
|
||||
* https://mail.gnome.org/archives/ostree-list/2014-February/msg00017.html
|
||||
*/
|
||||
snprintf (buf, sizeof (buf), "/proc/self/fd/%d/%s", dfd, name);
|
||||
return get_xattrs_impl (buf, out_xattrs, cancellable, error);
|
||||
return get_xattrs_impl (buf, -1, out_xattrs, cancellable, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2017 Red Hat, Inc.
|
||||
*
|
||||
* This 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 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This 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 this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "libglnx.h"
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define XATTR_THREAD_RUN_TIME_USECS (5 * G_USEC_PER_SEC)
|
||||
|
||||
struct XattrWorker {
|
||||
int dfd;
|
||||
gboolean is_writer;
|
||||
guint n_attrs_read;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
WRITE_RUN_MUTATE,
|
||||
WRITE_RUN_CREATE,
|
||||
} WriteType;
|
||||
|
||||
static gboolean
|
||||
set_random_xattr_value (int fd, const char *name, GError **error)
|
||||
{
|
||||
const guint8 randxattrbyte = g_random_int_range (0, 256);
|
||||
const guint32 randxattrvalue_len = (g_random_int () % 256) + 1; /* Picked to be not too small or large */
|
||||
g_autofree char *randxattrvalue = g_malloc (randxattrvalue_len);
|
||||
|
||||
memset (randxattrvalue, randxattrbyte, randxattrvalue_len);
|
||||
|
||||
if (fsetxattr (fd, name, randxattrvalue, randxattrvalue_len, 0) < 0)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
add_random_xattrs (int fd, GError **error)
|
||||
{
|
||||
const guint nattrs = MIN (2, g_random_int () % 16);
|
||||
|
||||
for (guint i = 0; i < nattrs; i++)
|
||||
{
|
||||
guint32 randxattrname_v = g_random_int ();
|
||||
g_autofree char *randxattrname = g_strdup_printf ("user.test%u", randxattrname_v);
|
||||
|
||||
if (!set_random_xattr_value (fd, randxattrname, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_write_run (GLnxDirFdIterator *dfd_iter, GError **error)
|
||||
{
|
||||
WriteType wtype = g_random_int () % 2;
|
||||
|
||||
if (wtype == WRITE_RUN_CREATE)
|
||||
{
|
||||
guint32 randname_v = g_random_int ();
|
||||
g_autofree char *randname = g_strdup_printf ("file%u", randname_v);
|
||||
glnx_fd_close int fd = -1;
|
||||
|
||||
again:
|
||||
fd = openat (dfd_iter->fd, randname, O_CREAT | O_EXCL, 0644);
|
||||
if (fd < 0)
|
||||
{
|
||||
if (errno == EEXIST)
|
||||
{
|
||||
g_printerr ("Congratulations! I suggest purchasing a lottery ticket today!\n");
|
||||
goto again;
|
||||
}
|
||||
else
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!add_random_xattrs (fd, error))
|
||||
return FALSE;
|
||||
}
|
||||
else if (wtype == WRITE_RUN_MUTATE)
|
||||
{
|
||||
while (TRUE)
|
||||
{
|
||||
g_autoptr(GVariant) current_xattrs = NULL;
|
||||
glnx_fd_close int fd = -1;
|
||||
|
||||
struct dirent *dent;
|
||||
if (!glnx_dirfd_iterator_next_dent (dfd_iter, &dent, NULL, error))
|
||||
return FALSE;
|
||||
if (!dent)
|
||||
break;
|
||||
|
||||
fd = openat (dfd_iter->fd, dent->d_name, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!glnx_fd_get_all_xattrs (fd, ¤t_xattrs, NULL, error))
|
||||
return FALSE;
|
||||
|
||||
for (int i = 0; i < g_variant_n_children (current_xattrs); i++)
|
||||
{
|
||||
const char *name, *value;
|
||||
g_variant_get_child (current_xattrs, i, "(^&ay^&ay)", &name, &value);
|
||||
|
||||
/* We don't want to potentially test/change xattrs like security.selinux
|
||||
* that were injected by the system.
|
||||
*/
|
||||
if (!g_str_has_prefix (name, "user.test"))
|
||||
continue;
|
||||
|
||||
if (!set_random_xattr_value (fd, name, error))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_read_run (GLnxDirFdIterator *dfd_iter,
|
||||
guint *out_n_read,
|
||||
GError **error)
|
||||
{
|
||||
guint nattrs = 0;
|
||||
while (TRUE)
|
||||
{
|
||||
g_autoptr(GVariant) current_xattrs = NULL;
|
||||
glnx_fd_close int fd = -1;
|
||||
|
||||
struct dirent *dent;
|
||||
if (!glnx_dirfd_iterator_next_dent (dfd_iter, &dent, NULL, error))
|
||||
return FALSE;
|
||||
if (!dent)
|
||||
break;
|
||||
|
||||
fd = openat (dfd_iter->fd, dent->d_name, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!glnx_fd_get_all_xattrs (fd, ¤t_xattrs, NULL, error))
|
||||
return FALSE;
|
||||
|
||||
/* We don't actually care about the values, just use the variable
|
||||
* to avoid compiler warnings.
|
||||
*/
|
||||
nattrs += g_variant_n_children (current_xattrs);
|
||||
}
|
||||
|
||||
*out_n_read = nattrs;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
xattr_thread (gpointer data)
|
||||
{
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
GError **error = &local_error;
|
||||
struct XattrWorker *worker = data;
|
||||
guint64 end_time = g_get_monotonic_time () + XATTR_THREAD_RUN_TIME_USECS;
|
||||
guint n_read = 0;
|
||||
|
||||
while (g_get_monotonic_time () < end_time)
|
||||
{
|
||||
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
|
||||
|
||||
if (!glnx_dirfd_iterator_init_at (worker->dfd, ".", TRUE, &dfd_iter, error))
|
||||
goto out;
|
||||
|
||||
if (worker->is_writer)
|
||||
{
|
||||
if (!do_write_run (&dfd_iter, error))
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!do_read_run (&dfd_iter, &n_read, error))
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
g_assert_no_error (local_error);
|
||||
|
||||
return GINT_TO_POINTER (n_read);
|
||||
}
|
||||
|
||||
static void
|
||||
test_xattr_races (void)
|
||||
{
|
||||
/* If for some reason we're built in a VM which only has one vcpu, let's still
|
||||
* at least make the test do something.
|
||||
*/
|
||||
/* FIXME - this deadlocks for me on 4.9.4-201.fc25.x86_64, whether
|
||||
* using overlayfs or xfs as source/dest.
|
||||
*/
|
||||
const guint nprocs = MAX (4, g_get_num_processors ());
|
||||
struct XattrWorker wdata[nprocs];
|
||||
GThread *threads[nprocs];
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
GError **error = &local_error;
|
||||
glnx_fd_close int dfd = -1;
|
||||
g_autofree char *tmpdir = g_strdup_printf ("%s/libglnx-xattrs-XXXXXX",
|
||||
getenv ("TMPDIR") ?: "/var/tmp");
|
||||
guint nread = 0;
|
||||
|
||||
if (!glnx_mkdtempat (AT_FDCWD, tmpdir, 0700, error))
|
||||
goto out;
|
||||
|
||||
if (!glnx_opendirat (AT_FDCWD, tmpdir, TRUE, &dfd, error))
|
||||
goto out;
|
||||
|
||||
for (guint i = 0; i < nprocs; i++)
|
||||
{
|
||||
struct XattrWorker *worker = &wdata[i];
|
||||
worker->dfd = dfd;
|
||||
worker->is_writer = i % 2 == 0;
|
||||
threads[i] = g_thread_new (NULL, xattr_thread, worker);
|
||||
}
|
||||
|
||||
for (guint i = 0; i < nprocs; i++)
|
||||
{
|
||||
if (wdata[i].is_writer)
|
||||
(void) g_thread_join (threads[i]);
|
||||
else
|
||||
nread += GPOINTER_TO_UINT (g_thread_join (threads[i]));
|
||||
}
|
||||
|
||||
g_print ("Read %u xattrs race free!\n", nread);
|
||||
|
||||
(void) glnx_shutil_rm_rf_at (AT_FDCWD, tmpdir, NULL, NULL);
|
||||
|
||||
out:
|
||||
g_assert_no_error (local_error);
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/xattr-races", test_xattr_races);
|
||||
|
||||
ret = g_test_run();
|
||||
|
||||
return ret;
|
||||
}
|
||||
Reference in new issue
Block a user