Compare commits

...

98 Commits

Author SHA1 Message Date
Jim Meyering
9aee8e78ea * src/runcon.c (main): Don't reorder arguments. Reported by
Ulrich Drepper in <http://bugzilla.redhat.com/232652>.
* tests/misc/runcon-no-reorder: New file.  Test for the above.
* tests/misc/Makefile.am (TESTS): Add runcon-no-reorder.
2007-03-18 18:15:08 +01:00
Jim Meyering
ab511a2106 * src/runcon.c (main): Remove "." at end of a diagnostic. 2007-03-18 18:15:08 +01:00
Jim Meyering
5e711ff948 Arrange for "make check-root" to run the new root-only test.
* tests/Makefile.am (t9): New target, to run tests/cp/cp-a-selinux.
(all_t): Add t9.

Use a directory on a loopback device mounted with -o context=...
* tests/cp/cp-a-selinux: Since this test now runs mount and umount,
it is a root-only one.
2007-03-18 18:15:08 +01:00
Jim Meyering
6f5700ac8a * src/runcon.c: New program.
* src/Makefile.am (bin_PROGRAMS): Add runcon.
(runcon_LDADD): Define.
* README: Add runcon to the list of programs.
* AUTHORS: Add this: runcon: Russell Coker
* tests/help-version: Add runcon as an exception.
* man/Makefile.am (dist_man_MANS): Add runcon.1.
(runcon.1): New dependency.
* po/POTFILES.in: Add src/runcon.c.
2007-03-18 18:15:08 +01:00
Jim Meyering
8daf081cd2 Regenerate .cvsignore and .gitignore files. 2007-03-18 18:15:08 +01:00
Jim Meyering
3f619c59cf mkfifo, mknod: Accept new "-Z, --context=C" option.
* src/mkfifo.c, src/mknod.c: Include <selinux/selinux.h>.
(main): Honor it.
* src/Makefile.am (mkfifo_LDADD, mknod_LDADD): Use $(LIB_SELINUX).
2007-03-18 18:15:08 +01:00
Jim Meyering
0db199df69 mkdir: Accept new "-Z, --context=C" option.
* src/mkdir.c: Include <selinux/selinux.h>.
(main): Honor it.
* src/Makefile.am (mkdir_LDADD): Use $(LIB_SELINUX).
2007-03-18 18:15:08 +01:00
Jim Meyering
beb12e09f3 * tests/cp/cp-a-selinux: New file. Test for the bug reported in
* tests/cp/Makefile.am (TESTS): Add cp-a-selinux.

* tests/selinux: New file.
* tests/Makefile.am (EXTRA_DIST): Add selinux.
* tests/misc/selinux: Source the new script, rather than open coding it.

Change how "cp -a" and "cp --preserve=context" work with SELinux.
Now, cp -a attempts to preserve context, but failure to do so does
not change cp's exit status.  However "cp --preserve=context" is
similar, but failure *does* cause cp to exit with nonzero status.
* src/copy.h (struct cp_options) [require_preserve_context]: New member.
* src/copy.c (copy_reg, copy_internal): Implement the above.
* src/mv.c (cp_option_init): Initialize the new member.
* src/install.c (cp_option_init): Likewise.
* src/cp.c (cp_option_init): Likewise.
(decode_preserve_arg): Set it or reset it.

FIXME: add an on-writable-NFS-only test
2007-03-18 18:15:08 +01:00
Jim Meyering
65ba507e17 * src/system.h (GETOPT_SELINUX_CONTEXT_OPTION_DECL): Define. 2007-03-18 18:15:06 +01:00
Jim Meyering
795c052e33 cp, mv, install: add SELinux support, but unlike with the Red Hat
patch, mv and cp do not provide the "-Z context" option.
* src/copy.c: Include <selinux/selinux.h>.
(restore_default_fscreatecon): New function.
(copy_reg): Make cp --preserve=context work for existing destination.
(copy_internal): Likewise for new destinations.
* src/copy.h (cp_options) [preserve_security_context]: New member.
* src/cp.c: Include <selinux/selinux.h>.
(selinux_enabled): New global.
(usage): Mention new --preserve=context option.
(PRESERVE_CONTEXT): Define/use.
(decode_preserve_arg): Handle PRESERVE_CONTEXT.
(main): Remove an obsolete comment.
If --preserve=context is specified on a system without SELinux
enabled, give a diagnostic and fail.
* src/mv.c: Include <selinux/selinux.h>.
Set x->preserve_security_context if SELinux is enabled.
* src/install.c: Accept new "-Z, --context=C" option.
Accept --preserve-context option (but not -P option).
Accept alternate spelling: --preserve_context, for now.
Include <selinux/selinux.h> and "quotearg.h".
(selinux_enabled, use_default_selinux_context): New globals.
(PRESERVE_CONTEXT_OPTION): Define.
(cp_option_init): Default: do not preserve security context.
(setdefaultfilecon): New function.
(main): Honor new options.
* src/Makefile.am (mv_LDADD, cp_LDADD, ginstall_LDADD):
Add $(LIB_SELINUX).
2007-03-18 18:15:06 +01:00
Jim Meyering
09ef5a443f * tests/misc/selinux [VERBOSE]: Print version info for each
of the tested tools, not just ls.
2007-03-18 18:15:06 +01:00
Jim Meyering
3765e5a26e * src/c99-to-c89.diff: Remove the ls.c patch, now that I've
temporarily removed the offending c99'ism.
2007-03-18 18:15:06 +01:00
Jim Meyering
b64a11dc76 * src/chcon.c (usage): Split a string literal that was longer than 509. 2007-03-18 18:15:06 +01:00
Jim Meyering
82d98da743 * src/ls.c (gobble_file): Don't call getfilecon unless print_scontext.
Upon failed getfilecon, accept not just ENOTSUP, but also ENODATA.
2007-03-18 18:15:06 +01:00
Jim Meyering
ecf70125f9 * src/c99-to-c89.diff: Adjust offsets. 2007-03-18 18:15:06 +01:00
Jim Meyering
1b569150c5 * AUTHORS: Add chcon. 2007-03-18 18:15:05 +01:00
Jim Meyering
4269a52c1a * src/c99-to-c89.diff: Remove trailing blanks. 2007-03-18 18:15:05 +01:00
Jim Meyering
b23de86834 * src/chcon.c: Don't include "dirname.h". system.h already includes it. 2007-03-18 18:15:05 +01:00
Jim Meyering
7782da7bf5 * gl/lib/selinux-at.c: Remove a use of HAVE_CONFIG_H. 2007-03-18 18:15:05 +01:00
Jim Meyering
2b5e4cb837 * src/c99-to-c89.diff: Handle a new c99'ism in ls.c. 2007-03-18 18:15:05 +01:00
Jim Meyering
5f997760c9 * src/id.c (main): Tweak id -Z diagnostic. 2007-03-18 18:15:05 +01:00
Jim Meyering
10ca93af8f * POTFILES.in: Add src/chcon.c. 2007-03-18 18:15:05 +01:00
Jim Meyering
0278a4d7d3 id: Add SELinux support: -Z option.
* src/id.c (main): Apply patches from Fedora, with these changes:
Remove #ifdef WITH_SELINUX.
Use error (EXIT_FAILURE, not fprintf+exit(1).
* src/Makefile.am (id_LDADD): Define, so as to add $(LIB_SELINUX).
2007-03-18 18:15:05 +01:00
Jim Meyering
2aab34d486 Keep SELinux-related ChangLog entries here. 2007-03-18 18:15:05 +01:00
Jim Meyering
2912097e82 stat: Add support for SELinux in the form of a %C format directive.
* src/stat.c (follow_links): Make this variable file-global.
(out_file_context): New function.
(print_statfs): Honor %C.
(print_stat): Honor %C.
(do_stat): Remove follow_links parameter.
(usage): Document the two %C directives.
(main): Accept -Z (though it's a no-op).
* src/Makefile.am (stat_LDADD): Define.
2007-03-18 18:15:05 +01:00
Jim Meyering
3238605998 add chcon 2007-03-18 18:15:05 +01:00
Jim Meyering
1e9098dc83 ls: Add support for SELinux and a slightly modified -Z option.
I started with the patches from Red Hat.
The entries below tell how the code evolved.

* src/ls.c (print_long_format, print_file_name_and_frills): When
there is no security context (due to getfilecon/lgetfilecon failing
with e.g. ENOTSUP), print it as "?", not "".
* src/ls.c (print_file_name_and_frills): Make -Z work without -l.
(length_of_file_name_and_frills): Likewise.

* src/ls.c: Remove the --lcontext and --scontext options.
Change the way -Z, --context work so that it no longer implies -l.
Thus, -Z -l will work like -lcontext and -Z without -l will work
like --scontext.

Adjust tests to reflect new 'ls -l' syntax -- affects only
systems with SELinux when operating on a file with no ACL.
These tests assumed that everything before the first space on
each line is the 10-byte mode string.  But there may also be a "+"
in the 11th column, just before the space.  However, note that this
is not new.  The same thing would have happened even without the
change below, when listing a file with an ACL.
* tests/chmod/equals, tests/cp/cp-parents, tests/cp/fail-perm:
* tests/cp/link-preserve, tests/install/basic-1, tests/misc/mknod:
* tests/mkdir/parents, tests/mkdir/special-1, tests/mv/partition-perm:

Don't make compilation depend on USE_ACL.  An SELinux security
context counts as an "alternate access control method", so ls
must output a "+" for each file with a security context.
* src/ls.c [struct fileinfo] (have_acl): Declare unconditionally.
(FILE_HAS_ACL): Remove macro definition.  Use f->have_acl directly.
(gobble_file): Record whether a file has a security context, and
update the condition used to determine whether to print the "+".
(gobble_file): Call getfilecon/lgetfilecon also when
format == long_format, so that we get the "+".

* src/ls.c (gobble_file): Add a comment explaining why (with a
security context option) ls doesn't exit nonzero due to e.g.,
getfilecon failing with errno == ENOTSUP.

* src/ls.c (gobble_file): Ignore failure of getfilecon if it's due
to ENOTSUP.

* src/ls.c (gobble_file): Factor out three small blocks using
getfilecon and lgetfilecon.
Don't ignore return value from getfilecon and lgetfilecon.

* src/ls.c (print_long_format): Don't use ?: (empty 2nd arg with C
ternary operator).
(print_scontext_format): Likewise.
(print_scontext): Declare to be "bool", not int.  Adjust uses.

* src/Makefile.am (dir_LDADD, ls_LDADD, vdir_LDADD): Add $(LIB_SELINUX).

* tests/misc/chcon: New file.
* tests/misc/chcon-fail: New file.
* tests/Makefile.am (check-root): Run new, root-only misc/chcon test.
* tests/misc/Makefile.am (TESTS): Add chcon and chcon-fail.

* tests/misc/Makefile.am (TESTS): Add selinux.
* tests/misc/selinux: New file.
* tests/help-version: Skip chcon.
2007-03-18 18:15:05 +01:00
Jim Meyering
27940f5d02 * man/chcon.x: New file.
* man/Makefile.am: Build chcon.1.
2007-03-18 18:15:04 +01:00
Jim Meyering
561c3a2b75 .cvsignore, .gitignore: update 2007-03-18 18:15:04 +01:00
Jim Meyering
c1fb4bcb2a New program: chcon
* gl/modules/selinux-at: New module.  Check for libselinux and set
LIB_SELINUX here, unconditionally, rather than depending on
the configure-time --enable-selinux option.
* gl/modules/selinux-h: New module.
* bootstrap.conf (gnulib_modules): Add selinux-at.
* gl/lib/selinux-at.c, gl/lib/selinux-at.h: New files.
* gl/lib/se-selinux_.h: New file.
* gl/lib/se-context_.h: New file.
* gl/m4/selinux-selinux-h.m4: New file.
* gl/m4/selinux-context-h.m4: New file.
* src/Makefile.am (bin_PROGRAMS): Add chcon.
(chcon_LDADD): Define.
* README: Add chcon to the list of programs.
* src/chcon.c: Rewrite the original (Red Hat) chcon to use fts.
2007-03-18 18:15:04 +01:00
Jim Meyering
93ff956de7 Merge branch 'master' of /cu 2007-03-18 18:14:49 +01:00
Jim Meyering
553d347d3e Fix a bug in how pr -m -s works.
* NEWS: Describe how the fix affects pr.
* src/pr.c (init_parameters): The --merge (-m) option does
not imply --expand-tabs (-e), so don't set "untabify_input".
Reported by Wis Macomson.
* tests/misc/pr: New file.  Test for the above fix.
* tests/misc/Makefile.am (TESTS): Add pr.
* THANKS: Update.
2007-03-18 16:21:26 +01:00
Jim Meyering
b1d89070f6 Fix a silly syntax error introduced in last change. 2007-03-17 13:15:17 +01:00
Jim Meyering
20bc0790a7 fix a syntax error 2007-03-17 13:01:56 +01:00
Jim Meyering
7828d1b4e2 Detect use of AC_CONFIG_AUX_DIR also when its argument is quoted.
* bootstrap: Put ""s around use of $build_aux, in case
someone uses a name containing shell meta-characters.
Reported by Alfred M. Szmidt.
2007-03-17 12:54:28 +01:00
Jim Meyering
5b3313c120 * tests/misc/tty-eof: Add shuf to the list of tested commands. 2007-03-17 12:23:14 +01:00
Jim Meyering
0edae5eee6 Avoid test failure on NFS-mounted Solaris ZFS file system.
* tests/du/basic: Skip a test if "." is on a non-local file system.
2007-03-17 11:44:42 +01:00
Jim Meyering
11f43d2e22 Avoid an obscure build failure, prefer waitpid over wait.
* src/install.c (strip): Use waitpid, not wait.  It's equivalent,
but feels less obsolescent.
2007-03-17 10:43:04 +01:00
Jim Meyering
87c54fa0ae * bootstrap: Don't use \> in grep regexp. For HP-UX. 2007-03-17 09:46:54 +01:00
Jim Meyering
3715c01f8e Begin adding support for Solaris ZFS (4 entries per trivial ACL)
* gl/lib/acl.c (ACL_NOT_WELL_SUPPORTED): New macro.
(file_has_acl, copy_acl): Use it, rather than enumerating errno values.
(is_trivial_acl): New function.  Incomplete, for now.
(file_has_acl, copy_acl): Use the new function, rather than
counting the number of entries in an ACL.
2007-03-16 22:24:09 +01:00
Jim Meyering
d2c7d7b58f * bootstrap: Update from gnulib. 2007-03-16 22:06:27 +01:00
Jim Meyering
d1e5a7af56 * .x-sc_prohibit_atoi_atof: Add TODO here, too. 2007-03-16 22:06:04 +01:00
Paul Eggert
369aaf7e5d * src/copy.c: Include filemode.h.
(overwrite_prompt): Say "try to overwrite", not "overwrite", to
make it clearer that the attempt may fail.  Problem reported by
Dan Jacobson in:
http://lists.gnu.org/archive/html/bug-coreutils/2007-03/msg00130.html
Output symbolic mode as well as numeric.
* tests/mv/i-2 (fail): Adjust to new prompt format.
2007-03-16 21:41:50 +01:00
Paul Eggert
39e85b7258 Fix manual in response to bug reports by Dan Jacobson.
* coreutils.texi (sort invocation): Explain numeric sorts better.
Compress self-congratulation into a simple "comparison is exact"
notice; the --general-numeric-sort option already explains the
tradeoffs.
(seq invocation): Add example of -f.
2007-03-16 06:30:32 +01:00
Jim Meyering
487e5317be Enforce policy: don't use *scanf functions.
* Makefile.maint (sc_prohibit_atoi_atof): Add to regexp and diagnostic.
* .x-sc_prohibit_atoi_atof: Give stty a temporary pass.
* TODO: note that stty.c needs this small clean-up.
2007-03-15 09:19:10 +01:00
Jim Meyering
112b9537dd Prepare to work on ACL-related failure when using Solaris ZFS.
* gl/lib/acl.c: New file, copied from gnulib.
2007-03-13 19:52:13 +01:00
Jim Meyering
24045feb85 Work around a failing test due to an NFS-based race condition.
* tests/cp/sparse: Accept a report that the copy is *smaller*.
2007-03-13 19:51:47 +01:00
Jim Meyering
64f972e94b * coreutils.texi (cp invocation): Mention that --preserve=timestamps
doesn't preserve time stamps on symbolic links.
Reported by Polo Talnir in <https://bugzilla.redhat.com/230866>.
2007-03-12 14:26:24 +01:00
Jim Meyering
0c1e917d6c Merge branch 'master' of /cu 2007-03-12 10:36:01 +01:00
Jim Meyering
1e7a0f088b Make bootstrap.conf a tiny bit more generic.
* bootstrap.conf (XGETTEXT_OPTIONS): Exclude gettext-related .m4
files when e.g., AM_GNU_GETTEXT([external] appears in configure.ac.
2007-03-12 09:47:36 +01:00
Jim Meyering
fd6fc97156 Try to fix today's NFS-related failure: Treat ESTALE like EACCES.
* gl/lib/savewd.c: Copy this file from gnulib, then change
"errno != EACCES" to (errno != EACCES && errno != ESTALE).
The symptom was this failure in tests/install/basic-1:
ginstall: cannot create directory `rel/a': Stale NFS file handle
2007-03-10 11:39:50 +01:00
Jim Meyering
04131454e3 The preceding change solved part of the problem. Now ginstall fails.
* tests/install/basic-1: Temporarily, don't redirect ginstall's
stderr to /dev/null, so I can see why the NFS autobuilder's NFS test
is failing.
2007-03-10 10:36:25 +01:00
Jim Meyering
bc86cb44e3 * tests/install/basic-1: When setting up an unreadable "." in an
inaccessible parent, make the parent inaccessible *after* making "."
unreadable.  Otherwise, running "chmod a-r ." in an already-
inaccessible parent would fail on NFS with "Stale NFS file handle".
Reported by Bob Proulx.
2007-03-10 09:53:49 +01:00
Jim Meyering
0a538a2488 remove trailing blanks 2007-03-10 08:17:19 +01:00
Jim Meyering
ca4f28bc83 * Makefile.maint (po-check): Exclude c99-to-c89.diff. 2007-03-10 00:43:50 +01:00
Jim Meyering
36aeb30081 Mention that both Jay Soffian and Charles Randall wrote early versions
of sort's temp-file-compression code.
2007-03-10 00:43:36 +01:00
Jim Meyering
fe3fbf2f54 * tests/chgrp/basic: Also avoid test failures on Darwin 8.8.x (MacOS X 10.4). 2007-03-09 20:09:46 +01:00
Jim Meyering
d9079b12e3 src/fs.h: git-rm a generated but already-ignored file 2007-03-09 15:19:21 +01:00
Jim Meyering
222b7c46bd Avoid test failures on Darwin 7.9.0 (MacOS X 10.3.9)
* tests/chgrp/basic: Don't let failure by chgrp to set the
group of a symlink make this test fail.  Do give a diagnostic.
In the chgrp-no-change-ctime test, add darwin7.9.0 as another
known-failing system.
When failing on some other system, print $host_triplet, too.
Reported by Peter Fales.
2007-03-09 08:47:33 +01:00
Jim Meyering
4bf9fe82c0 * src/c99-to-c89.diff: Reflect the new c99'ism, update offsets. 2007-03-08 22:09:11 +01:00
Jim Meyering
fe068c60fb Add to .cvsignore and .gitignore files. 2007-03-08 22:01:27 +01:00
Jim Meyering
e3864a430e TODO: printf: support %a even when the native *printf(3) is deficient 2007-03-08 22:01:05 +01:00
Jim Meyering
2639ed8208 rm without -f: give a better diagnostic when euidaccess fails.
* src/remove.c (write_protected_non_symlink): Return int, not bool,
so that we can indicate failure too (as a postive error number).
(prompt): If write_protected_non_symlink fails, report that error
number and fail rather than charging ahead and removing the dubious
entry.  Redo the logic of printing a diagnostic so that we need to
invoke quote (full_filename (...)) only once.  More details at:
<http://thread.gmane.org/gmane.comp.gnu.coreutils.bugs/9952/focus=9996>
2007-03-08 10:38:59 +01:00
Jim Meyering
09aab8cb41 Generalize a few more cvs-isms.
* bootstrap (checkout_only_file): Rename from CVS_only_file.
Change comments and diagnostics not to say "CVS".
2007-03-08 09:19:39 +01:00
Jim Meyering
9abd8baaaa * bootstrap: Run libtool, if necessary. 2007-03-08 01:06:41 +01:00
Jim Meyering
551bed87fa Make bootstrap a little more general.
* bootstrap (build_aux): Factor out/use this definition.
Formally require a "AC_CONFIG_AUX_DIR($build_aux)" line in configure.ac.
(insert_sorted_if_absent): Move function definition "up", to
precede new first use.
If $build_aux/ doesn't exist initially, create it, and
mark it as ignored.
2007-03-08 00:23:00 +01:00
Jim Meyering
b7a568ece8 * vasnprintf.c (VASNPRINTF): Add missing semicolon. 2007-03-04 13:03:59 +01:00
Andrew Church
2871ad3b45 Fix a bug: cp -x would fail to set mount point permissions.
* NEWS: mention cp -x bug fix
* src/copy.c (copy_internal): Don't return immediately after
copying a mount point that we do not intend to recurse under.
Based on a patch by Andrew Church.
2007-03-03 23:00:18 +01:00
Jim Meyering
f0537a71f1 pwd-unreadable-parent: Skip test on ia64/Linux, too.
* tests/misc/pwd-unreadable-parent: Also skip when $REPLACE_GETCWD.
Reported by Bob Proulx.
2007-03-03 21:38:16 +01:00
Jim Meyering
1187f011d3 Add to .cvsignore and .gitignore files. 2007-03-02 14:54:52 +01:00
Jim Meyering
c872a5f7bb * vasnprintf.c (VASNPRINTF): Remove cast of alloca return value. 2007-03-02 14:33:12 +01:00
Jim Meyering
fe4f1227a5 pwd-unreadable-parent: Skip test on non-Linux/GNU systems.
* tests/misc/pwd-unreadable-parent: Rather than trying to decide
whether this test has a chance of succeeding, run it only when
$(host_os) is linux-gnu.  It was failing on powerpc-apple-darwin8.8.0
* tests/misc/Makefile.am (TESTS_ENVIRONMENT): Add host_os=$(host_os).
2007-03-02 14:25:48 +01:00
Jim Meyering
13a4b23e79 * tests/misc/pwd-long: Also allow "+" in $PWD. 2007-03-02 13:18:43 +01:00
Jim Meyering
b655a2154e * Makefile.maint (my-distcheck): Skip the c99/c89 check if there's no such .diff file. 2007-03-02 11:13:54 +01:00
Jim Meyering
272d99e7a3 Remove another coreutils-ism. Formatting cleanup.
* Makefile.maint (my-distcheck): Update an outdated comment.
(emit_upload_commands): Use $(PACKAGE) rather than "coreutils".
2007-03-02 10:57:08 +01:00
Jim Meyering
262963212b * Makefile.maint (warn_cflags): Hoist, adding "-Dlint -O".
(my-distcheck): Use the new variable, instead of too-long literal.
2007-03-01 11:06:58 +01:00
Jim Meyering
ea42025c70 Make "make syntax-check" rules less coreutils-specific.
* Makefile.maint (sc_cast_of_x_alloc_return_value): Use CVS_LIST_EXCEPT.
(sc_cast_of_alloca_return_value): Likewise.
(sc_root_tests): Do nothing if there is no check-root target
in tests/Makefile.am.
2007-03-01 11:05:35 +01:00
Jim Meyering
7daf29845b Run the writable-files check only for release-building targets.
* Makefile.maint (local-checks-available): Remove writable-files.
(alpha beta major): Put it here, instead.
2007-03-01 11:02:25 +01:00
Jim Meyering
5703f662b7 "make syntax-check" now runs only Makefile.cfg-selected tests
* Makefile.maint (syntax-check-rules): Hoist this definition so that
it precedes the indirect use in the definition of $(local-check).
(local-check): Use :=, not just "=".
(syntax-check): Depend on $(local-check), not $(syntax-check-rules).
2007-03-01 11:00:12 +01:00
Jim Meyering
b3b6f52fad Merge in changes from gnulib:
* vasnprintf.c: Add a comment explaining why coreutils has its own
version of this file.
Include <stdint.h>.
(SIZE_MAX): Remove definition (now, stdint.h covers that).
(EOVERFLOW): Remove definition (now done via the eoverflow module).
Update some #ifdef to #if.
Use HAVE_LONG_LONG_INT, not HAVE_LONG_LONG.
* printf-parse.c: Likewise.
2007-03-01 10:41:48 +01:00
Bruno Haible
f6f2846bd8 * bootstrap.conf (gnulib_modules): Replace xreadlink with
xreadlink-with-size. Add xreadlink.
* src/copy.c (copy_internal): Update.
* src/ls.c (is_directory): Update.
* src/stat.c (print_stat): Update.
* src/readlink.c (main): Use the one-argument xreadlink function.
2007-03-01 08:06:24 +01:00
Paul Eggert
e5dbc71841 * doc/coreutils.texi (Common options): --si outputs "M", not "MB".
Problem reported by Philip Rowlands in
<http://lists.gnu.org/archive/html/bug-coreutils/2007-02/msg00283.html>.
2007-02-28 22:25:53 +01:00
Jim Meyering
b2a48ec240 * tsearch.c: Remove unused file. 2007-02-28 21:50:14 +01:00
Jim Meyering
c62a7156c5 * .x-sc_file_system: Add the new test, tests/misc/df-P, to this
list of exceptions, for the "make distcheck" sc_file_system rule.
2007-02-28 13:52:20 +01:00
Jim Meyering
195108489b * Makefile.maint (gnulib_snapshot_date): Remove now-unused definition. 2007-02-28 10:27:31 +01:00
Jim Meyering
55bc95b4d3 * tests/misc/df-P: This script *is* executable. 2007-02-28 08:11:41 +01:00
Jim Meyering
d480544281 Add a test for today's df -P fix.
* tests/misc/df-P: New file.
* tests/misc/Makefile.am (TESTS): Add df-P.
2007-02-27 19:35:27 +01:00
Paul Eggert
817d0261eb Make df -P immune to effects of e.g., the BLOCK_SIZE envvar.
* NEWS: With -P, the default block size and output format is not
affected by DF_BLOCK_SIZE, BLOCK_SIZE, or BLOCKSIZE.
* src/df.c (main): Implement this.
* doc/coreutils.texi (df invocation): With -P, the default block size
and output format is not affected by DF_BLOCK_SIZE, BLOCK_SIZE, or
BLOCKSIZE.
2007-02-27 19:33:03 +01:00
Jim Meyering
898d3df2f8 * Makefile.maint (announcement): Adjust so that it works with
announce-gen's --gnulib-snapshot-time-stamp option.
Indent one of the command lines using TAB, not 8 spaces.
2007-02-25 01:11:32 +01:00
Jim Meyering
9317cccb8f Post-release version change.
* NEWS: Add a line for 6.8+.
* configure.ac (AC_INIT): Set new version string.
2007-02-25 01:10:07 +01:00
Jim Meyering
6d8e33952a Merge branch 'master' of /cu 2007-02-01 18:03:59 +01:00
Jim Meyering
9f2adbf0be Merge branch 'master' of /cu 2007-01-29 15:32:39 +01:00
Jim Meyering
8fb6d7a9b9 Merge branch 'master' of /cu 2007-01-26 21:24:30 +01:00
Jim Meyering
cee06314e1 Merge branch 'master' of /cu 2007-01-26 14:00:36 +01:00
Jim Meyering
ebc2235bd7 merge from trunk 2007-01-26 11:15:31 +01:00
Jim Meyering
cece28a8bc merge copyright line conflict 2007-01-26 11:13:44 +01:00
Jim Meyering
94986c1d0a Merge branch 'master' of /cu 2007-01-20 16:33:20 +01:00
Jim Meyering
c12e44d891 * tests/cp/open-perm-race: Remove gdb-based test.
It would run only when compiled with -g, and besides is now
subsumed by file-perm-race.
* tests/cp/Makefile.am (TESTS): Remove open-perm-race.
2007-01-13 11:35:24 +01:00
89 changed files with 3935 additions and 1176 deletions

View File

@@ -8,6 +8,7 @@ Makefile
Makefile.in
THANKS-to-translators
aclocal.m4
chcon
config.status
configure
coreutils-*

1
.gitignore vendored
View File

@@ -13,6 +13,7 @@ Makefile.in
THANKS-to-translators
aclocal.m4
autom4te.cache
chcon
config.cache
config.h
config.hin

View File

@@ -5,3 +5,4 @@ config-log
po/
src/df.c
src/stat.c
tests/misc/df-P

View File

@@ -1,8 +1,11 @@
^configure$
ChangeLog
^TODO$
^lib/mktime\.c$
^lib/getloadavg\.c$
^lib/euidaccess\.c$
^lib/euidaccess-stat\.c$
^lib/group-member\.c$
^Makefile\.maint$
^doc/coreutils.texi$
^src/stty.c$

View File

@@ -4,6 +4,7 @@ each followed by the name(s) of its author(s).
base64: Simon Josefsson
basename: FIXME unknown
cat: Torbjorn Granlund, Richard M. Stallman
chcon: Russell Coker, Jim Meyering
chgrp: David MacKenzie, Jim Meyering
chmod: David MacKenzie, Jim Meyering
chown: David MacKenzie, Jim Meyering
@@ -60,6 +61,7 @@ pwd: Jim Meyering
readlink: Dmitry V. Levin
rm: Paul Rubin, David MacKenzie, Richard Stallman, Jim Meyering
rmdir: David MacKenzie
runcon: Russell Coker
seq: Ulrich Drepper
sha1sum: Ulrich Drepper, Scott Miller, David Madore
sha224sum: Ulrich Drepper, Scott Miller, David Madore

248
ChangeLog
View File

@@ -1,3 +1,234 @@
2007-03-18 Jim Meyering <jim@meyering.net>
Fix a bug in how pr -m -s works.
* NEWS: Describe how the fix affects pr.
* src/pr.c (init_parameters): The --merge (-m) option does
not imply --expand-tabs (-e), so don't set "untabify_input".
Reported by Wis Macomson.
* tests/misc/pr: New file. Test for the above fix.
* tests/misc/Makefile.am (TESTS): Add pr.
* THANKS: Update.
2007-03-17 Jim Meyering <jim@meyering.net>
Detect use of AC_CONFIG_AUX_DIR also when its argument is quoted.
* bootstrap: Put ""s around use of $build_aux, in case
someone uses a name containing shell meta-characters.
Reported by Alfred M. Szmidt.
* tests/misc/tty-eof: Add shuf to the list of tested commands.
Avoid test failure on NFS-mounted Solaris ZFS file system.
* tests/du/basic: Skip a test if "." is on a non-local file system.
Avoid an obscure build failure, prefer waitpid over wait.
* src/install.c (strip): Use waitpid, not wait. It's equivalent,
but feels less obsolescent.
* bootstrap: Don't use \> in grep regexp. For HP-UX.
2007-03-16 Jim Meyering <jim@meyering.net>
Begin adding support for Solaris ZFS (4 entries per trivial ACL)
* gl/lib/acl.c (ACL_NOT_WELL_SUPPORTED): New macro.
(file_has_acl, copy_acl): Use it, rather than enumerating errno values.
(is_trivial_acl): New function. Incomplete, for now.
(file_has_acl, copy_acl): Use the new function, rather than
counting the number of entries in an ACL.
* bootstrap: Update from gnulib.
* .x-sc_prohibit_atoi_atof: Add TODO here, too.
2007-03-16 Paul Eggert <eggert@cs.ucla.edu>
* src/copy.c: Include filemode.h.
(overwrite_prompt): Say "try to overwrite", not "overwrite", to
make it clearer that the attempt may fail. Problem reported by
Dan Jacobson in:
http://lists.gnu.org/archive/html/bug-coreutils/2007-03/msg00130.html
Output symbolic mode as well as numeric.
* tests/mv/i-2 (fail): Adjust to new prompt format.
2007-03-15 Jim Meyering <jim@meyering.net>
Enforce policy: don't use *scanf functions.
* Makefile.maint (sc_prohibit_atoi_atof): Add to regexp and diagnostic.
* .x-sc_prohibit_atoi_atof: Give stty a temporary pass.
* TODO: note that stty.c needs this small clean-up.
2007-03-13 Jim Meyering <jim@meyering.net>
Prepare to work on ACL-related failure when using Solaris ZFS.
* gl/lib/acl.c: New file, copied from gnulib.
Work around a failing test due to an NFS-based race condition.
* tests/cp/sparse: Accept a report that the copy is *smaller*.
2007-03-12 Jim Meyering <jim@meyering.net>
Make bootstrap.conf a tiny bit more generic.
* bootstrap.conf (XGETTEXT_OPTIONS): Exclude gettext-related .m4
files when e.g., AM_GNU_GETTEXT([external] appears in configure.ac.
2007-03-10 Jim Meyering <jim@meyering.net>
Try to fix today's NFS-related failure: Treat ESTALE like EACCES.
* gl/lib/savewd.c: Copy this file from gnulib, then change
"errno != EACCES" to (errno != EACCES && errno != ESTALE).
The symptom was this failure in tests/install/basic-1:
ginstall: cannot create directory `rel/a': Stale NFS file handle
The preceding change solved part of the problem. Now ginstall fails.
* tests/install/basic-1: Temporarily, don't redirect ginstall's
stderr to /dev/null, so I can see why the NFS autobuilder's NFS test
is failing.
* tests/install/basic-1: When setting up an unreadable "." in an
inaccessible parent, make the parent inaccessible *after* making "."
unreadable. Otherwise, running "chmod a-r ." in an already-
inaccessible parent would fail on NFS with "Stale NFS file handle".
Reported by Bob Proulx.
* Makefile.maint (po-check): Exclude c99-to-c89.diff.
2007-03-09 Jim Meyering <jim@meyering.net>
Avoid test failures on Darwin 7.9.0 (MacOS X 10.3.9)
* tests/chgrp/basic: Don't let failure by chgrp to set the
group of a symlink make this test fail. Do give a diagnostic.
In the chgrp-no-change-ctime test, add darwin7.9.0 as another
known-failing system.
When failing on some other system, print $host_triplet, too.
Also avoid test failures on Darwin 8.8.x (MacOS X 10.4).
Reported by Peter Fales.
2007-03-08 Jim Meyering <jim@meyering.net>
* src/c99-to-c89.diff: Reflect the new c99'ism, update offsets.
2007-03-08 Paul Eggert <eggert@cs.ucla.edu>
rm without -f: give a better diagnostic when euidaccess fails.
* src/remove.c (write_protected_non_symlink): Return int, not bool,
so that we can indicate failure too (as a postive error number).
(prompt): If write_protected_non_symlink fails, report that error
number and fail rather than charging ahead and removing the dubious
entry. Redo the logic of printing a diagnostic so that we need to
invoke quote (full_filename (...)) only once. More details at:
<http://thread.gmane.org/gmane.comp.gnu.coreutils.bugs/9952/focus=9996>
2007-03-08 Jim Meyering <jim@meyering.net>
Generalize a few more cvs-isms.
* bootstrap (checkout_only_file): Rename from CVS_only_file.
Change comments and diagnostics not to say "CVS".
* bootstrap: Run libtool, if necessary.
Make bootstrap a little more general.
* bootstrap (build_aux): Factor out/use this definition.
Formally require a "AC_CONFIG_AUX_DIR($build_aux)" line in configure.ac.
(insert_sorted_if_absent): Move function definition "up", to
precede new first use.
If $build_aux/ doesn't exist initially, create it, and
mark it as ignored.
2007-03-03 Andrew Church <achurch@achurch.org> (tiny change)
Paul Eggert <eggert@cs.ucla.edu>
Fix a bug: cp -x would fail to set mount point permissions.
* NEWS: mention cp -x bug fix
* src/copy.c (copy_internal): Don't return immediately after
copying a mount point that we do not intend to recurse under.
Based on a patch by Andrew Church.
2007-03-03 Jim Meyering <jim@meyering.net>
pwd-unreadable-parent: Skip test on ia64/Linux, too.
* tests/misc/pwd-unreadable-parent: Also skip when $REPLACE_GETCWD.
Reported by Bob Proulx.
2007-03-02 Jim Meyering <jim@meyering.net>
pwd-unreadable-parent: Skip test on non-Linux/GNU systems.
* tests/misc/pwd-unreadable-parent: Rather than trying to decide
whether this test has a chance of succeeding, run it only when
$(host_os) is linux-gnu. It was failing on powerpc-apple-darwin8.8.0
* tests/misc/Makefile.am (TESTS_ENVIRONMENT): Add host_os=$(host_os).
* tests/misc/pwd-long: Also allow "+" in $PWD.
Remove another coreutils-ism. Formatting cleanup.
* Makefile.maint (my-distcheck): Update an outdated comment.
(emit_upload_commands): Use $(PACKAGE) rather than "coreutils".
(my-distcheck): Skip the c99/c89 check if there's no such .diff file.
2007-03-01 Jim Meyering <jim@meyering.net>
* Makefile.maint (warn_cflags): Hoist, adding "-Dlint -O".
(my-distcheck): Use the new variable, instead of too-long literal.
Make "make syntax-check" rules less coreutils-specific.
* Makefile.maint (sc_cast_of_x_alloc_return_value): Use CVS_LIST_EXCEPT.
(sc_cast_of_alloca_return_value): Likewise.
(sc_root_tests): Do nothing if there is no check-root target
in tests/Makefile.am.
Run the writable-files check only for release-building targets.
* Makefile.maint (local-checks-available): Remove writable-files.
(alpha beta major): Put it here, instead.
"make syntax-check" now runs only Makefile.cfg-selected tests
* Makefile.maint (syntax-check-rules): Hoist this definition so that
it precedes the indirect use in the definition of $(local-check).
(local-check): Use :=, not just "=".
(syntax-check): Depend on $(local-check), not $(syntax-check-rules).
2007-02-28 Bruno Haible <bruno@clisp.org>
* bootstrap.conf (gnulib_modules): Replace xreadlink with
xreadlink-with-size. Add xreadlink.
* src/copy.c (copy_internal): Update.
* src/ls.c (is_directory): Update.
* src/stat.c (print_stat): Update.
* src/readlink.c (main): Use the one-argument xreadlink function.
2007-02-28 Paul Eggert <eggert@cs.ucla.edu>
* doc/coreutils.texi (Common options): --si outputs "M", not "MB".
Problem reported by Philip Rowlands in
<http://lists.gnu.org/archive/html/bug-coreutils/2007-02/msg00283.html>.
2007-02-28 Jim Meyering <jim@meyering.net>
* .x-sc_file_system: Add the new test, tests/misc/df-P, to this
list of exceptions, for the "make distcheck" sc_file_system rule.
* Makefile.maint (gnulib_snapshot_date): Remove now-unused definition.
2007-02-27 Paul Eggert <eggert@cs.ucla.edu>
Make df -P immune to effects of e.g., the BLOCK_SIZE envvar.
* NEWS: With -P, the default block size and output format is not
affected by DF_BLOCK_SIZE, BLOCK_SIZE, or BLOCKSIZE.
* src/df.c (main): Implement this.
2007-02-27 Jim Meyering <jim@meyering.net>
Add a test for the above.
* tests/misc/df-P: New file.
* tests/misc/Makefile.am (TESTS): Add df-P.
2007-02-25 Jim Meyering <jim@meyering.net>
* Makefile.maint (announcement): Adjust so that it works with
announce-gen's --gnulib-snapshot-time-stamp option.
Indent one of the command lines using TAB, not 8 spaces.
Post-release version change.
* NEWS: Add a line for 6.8+.
* configure.ac (AC_INIT): Set new version string.
2007-02-24 Jim Meyering <jim@meyering.net>
Version 6.8.
@@ -255,9 +486,17 @@
consistent, so this can be applied with patch -p0.
Reported by Matthew Woehlke.
Arrange for "make check-root" to run the new root-only test.
* tests/Makefile.am (t9): New target, to run tests/cp/cp-a-selinux.
(all_t): Add t9.
* Makefile.maint (patch-check): Use patch with its -p2 option,
since that makes this check slightly more strict.
Use a directory on a loopback device mounted with -o context=...
* tests/cp/cp-a-selinux: Since this test now runs mount and umount,
it is a root-only one.
2007-01-29 Jim Meyering <jim@meyering.net>
Plug a leak in ls.
@@ -420,6 +659,10 @@
Use reap_some.
(avoid_trashing_input, merge, sort, main): Adapt to mergefps.
The idea of compressing sorts temporary files was first
suggested/implemented by Jay Soffian in 1998, and again
by Charles Randall in 2001.
2007-01-20 Jim Meyering <jim@meyering.net>
* tests/misc/pwd-long: Work properly even when run from the
@@ -487,6 +730,11 @@
2007-01-13 Jim Meyering <jim@meyering.net>
* tests/cp/open-perm-race: Remove gdb-based test.
It would run only when compiled with -g, and besides is now
subsumed by file-perm-race.
* tests/cp/Makefile.am (TESTS): Remove open-perm-race.
* Transform all Makefile.am files so that when running "make check",
CU_TEST_NAME is set to the name of the test. This is so that when I
run valgrind-enabled (--log-file-qualifier=CU_TEST_NAME) "make check"

208
ChangeLog-selinux Normal file
View File

@@ -0,0 +1,208 @@
2007-03-18 Jim Meyering <jim@meyering.net>
* src/runcon.c (main): Don't reorder arguments. Reported by
Ulrich Drepper in <http://bugzilla.redhat.com/232652>.
* tests/misc/runcon-no-reorder: New file. Test for the above.
* tests/misc/Makefile.am (TESTS): Add runcon-no-reorder.
* src/runcon.c (main): Remove "." at end of a diagnostic.
2007-02-02 Jim Meyering <jim@meyering.net>
* src/runcon.c: New program.
* src/Makefile.am (bin_PROGRAMS): Add runcon.
(runcon_LDADD): Define.
* README: Add runcon to the list of programs.
* AUTHORS: Add this: runcon: Russell Coker
* tests/help-version: Add runcon as an exception.
* man/Makefile.am (dist_man_MANS): Add runcon.1.
(runcon.1): New dependency.
2007-01-31 Jim Meyering <jim@meyering.net>
mkfifo, mknod: Accept new "-Z, --context=C" option.
* src/mkfifo.c, src/mknod.c: Include <selinux/selinux.h>.
(main): Honor it.
* src/Makefile.am (mkfifo_LDADD, mknod_LDADD): Use $(LIB_SELINUX).
mkdir: Accept new "-Z, --context=C" option.
* src/mkdir.c: Include <selinux/selinux.h>.
(main): Honor it.
* src/Makefile.am (mkdir_LDADD): Use $(LIB_SELINUX).
* tests/cp/cp-a-selinux: New file. Test for the bug reported in
<http://bugzilla.redhat.com/219900>.
* tests/cp/Makefile.am (TESTS): Add cp-a-selinux.
* tests/selinux: New file.
* tests/Makefile.am (EXTRA_DIST): Add selinux.
* tests/misc/selinux: Source the new script, rather than open coding it.
Change how "cp -a" and "cp --preserve=context" work with SELinux.
Now, cp -a attempts to preserve context, but failure to do so does
not change cp's exit status. However "cp --preserve=context" is
similar, but failure *does* cause cp to exit with nonzero status.
* src/copy.h (struct cp_options) [require_preserve_context]: New member.
* src/copy.c (copy_reg, copy_internal): Implement the above.
* src/mv.c (cp_option_init): Initialize the new member.
* src/install.c (cp_option_init): Likewise.
* src/cp.c (cp_option_init): Likewise.
(decode_preserve_arg): Set it or reset it.
FIXME: add an on-writable-NFS-only test
2007-01-20 Jim Meyering <jim@meyering.net>
cp, mv, install: add SELinux support, but unlike with the Red Hat
patch, mv and cp do not provide the "-Z context" option.
* src/copy.c: Include <selinux/selinux.h>.
(restore_default_fscreatecon): New function.
(copy_reg): Make cp --preserve=context work for existing destination.
(copy_internal): Likewise for new destinations.
* src/copy.h (cp_options) [preserve_security_context]: New member.
* src/cp.c: Include <selinux/selinux.h>.
(selinux_enabled): New global.
(usage): Mention new --preserve=context option.
(PRESERVE_CONTEXT): Define/use.
(decode_preserve_arg): Handle PRESERVE_CONTEXT.
(main): Remove an obsolete comment.
If --preserve=context is specified on a system without SELinux
enabled, give a diagnostic and fail.
* src/mv.c: Include <selinux/selinux.h>.
Set x->preserve_security_context if SELinux is enabled.
* src/install.c: Accept new "-Z, --context=C" option.
Accept --preserve-context option (but not -P option).
Accept alternate spelling: --preserve_context, for now.
Include <selinux/selinux.h> and "quotearg.h".
(selinux_enabled, use_default_selinux_context): New globals.
(PRESERVE_CONTEXT_OPTION): Define.
(cp_option_init): Default: do not preserve security context.
(setdefaultfilecon): New function.
(main): Honor new options.
* src/Makefile.am (mv_LDADD, cp_LDADD, ginstall_LDADD):
Add $(LIB_SELINUX).
* src/system.h (GETOPT_SELINUX_CONTEXT_OPTION_DECL): Define.
* tests/misc/selinux [VERBOSE]: Print version info for each
of the tested tools, not just ls.
* src/c99-to-c89.diff: Remove the ls.c patch, now that I've
temporarily removed the offending c99'ism.
* src/chcon.c (usage): Split a string literal that was longer than 509.
* src/ls.c (gobble_file): Don't call getfilecon unless print_scontext.
Upon failed getfilecon, accept not just ENOTSUP, but also ENODATA.
* src/c99-to-c89.diff: Adjust offsets.
* AUTHORS: Add chcon.
* src/c99-to-c89.diff: Remove trailing blanks.
* src/chcon.c: Don't include "dirname.h". system.h already includes it.
* gl/lib/selinux-at.c: Remove a use of HAVE_CONFIG_H.
* src/c99-to-c89.diff: Handle a new c99'ism in ls.c.
* src/id.c (main): Tweak id -Z diagnostic.
id: Add SELinux support: -Z option.
* src/id.c (main): Apply patches from Fedora, with these changes:
Remove #ifdef WITH_SELINUX.
Use error (EXIT_FAILURE, not fprintf+exit(1).
* src/Makefile.am (id_LDADD): Define, so as to add $(LIB_SELINUX).
2007-01-06 Jim Meyering <jim@meyering.net>
stat: Add support for SELinux in the form of a %C format directive.
* src/stat.c (follow_links): Make this variable file-global.
(out_file_context): New function.
(print_statfs): Honor %C.
(print_stat): Honor %C.
(do_stat): Remove follow_links parameter.
(usage): Document the two %C directives.
(main): Accept -Z (though it's a no-op).
* src/Makefile.am (stat_LDADD): Define.
ls: Add support for SELinux and a slightly modified -Z option.
I started with the patches from Red Hat.
The entries below tell how the code evolved.
* src/ls.c (print_long_format, print_file_name_and_frills): When
there is no security context (due to getfilecon/lgetfilecon failing
with e.g. ENOTSUP), print it as "?", not "".
* src/ls.c (print_file_name_and_frills): Make -Z work without -l.
(length_of_file_name_and_frills): Likewise.
* src/ls.c: Remove the --lcontext and --scontext options.
Change the way -Z, --context work so that it no longer implies -l.
Thus, -Z -l will work like -lcontext and -Z without -l will work
like --scontext.
Adjust tests to reflect new 'ls -l' syntax -- affects only
systems with SELinux when operating on a file with no ACL.
These tests assumed that everything before the first space on
each line is the 10-byte mode string. But there may also be a "+"
in the 11th column, just before the space. However, note that this
is not new. The same thing would have happened even without the
change below, when listing a file with an ACL.
* tests/chmod/equals, tests/cp/cp-parents, tests/cp/fail-perm:
* tests/cp/link-preserve, tests/install/basic-1, tests/misc/mknod:
* tests/mkdir/parents, tests/mkdir/special-1, tests/mv/partition-perm:
Don't make compilation depend on USE_ACL. An SELinux security
context counts as an "alternate access control method", so ls
must output a "+" for each file with a security context.
* src/ls.c [struct fileinfo] (have_acl): Declare unconditionally.
(FILE_HAS_ACL): Remove macro definition. Use f->have_acl directly.
(gobble_file): Record whether a file has a security context, and
update the condition used to determine whether to print the "+".
(gobble_file): Call getfilecon/lgetfilecon also when
format == long_format, so that we get the "+".
* src/ls.c (gobble_file): Add a comment explaining why (with a
security context option) ls doesn't exit nonzero due to e.g.,
getfilecon failing with errno == ENOTSUP.
* src/ls.c (gobble_file): Ignore failure of getfilecon if it's due
to ENOTSUP.
* src/ls.c (gobble_file): Factor out three small blocks using
getfilecon and lgetfilecon.
Don't ignore return value from getfilecon and lgetfilecon.
* src/ls.c (print_long_format): Don't use ?: (empty 2nd arg with C
ternary operator).
(print_scontext_format): Likewise.
(print_scontext): Declare to be "bool", not int. Adjust uses.
* src/Makefile.am (dir_LDADD, ls_LDADD, vdir_LDADD): Add $(LIB_SELINUX).
* tests/misc/chcon: New file.
* tests/misc/chcon-fail: New file.
* tests/Makefile.am (check-root): Run new, root-only misc/chcon test.
* tests/misc/Makefile.am (TESTS): Add chcon and chcon-fail.
* tests/misc/Makefile.am (TESTS): Add selinux.
* tests/misc/selinux: New file.
* tests/help-version: Skip chcon.
* man/chcon.x: New file.
* man/Makefile.am: Build chcon.1.
New program: chcon
* gl/modules/selinux-at: New module. Check for libselinux and set
LIB_SELINUX here, unconditionally, rather than depending on
the configure-time --enable-selinux option.
* gl/modules/selinux-h: New module.
* bootstrap.conf (gnulib_modules): Add selinux-at.
* gl/lib/selinux-at.c, gl/lib/selinux-at.h: New files.
* gl/lib/se-selinux_.h: New file.
* gl/lib/se-context_.h: New file.
* gl/m4/selinux-selinux-h.m4: New file.
* gl/m4/selinux-context-h.m4: New file.
* src/Makefile.am (bin_PROGRAMS): Add chcon.
(chcon_LDADD): Define.
* README: Add chcon to the list of programs.
* src/chcon.c: Rewrite the original (Red Hat) chcon to use fts.

View File

@@ -69,23 +69,23 @@ export LC_ALL = C
# in system.h. E.g. today I removed from tail.c a useless definition of
# ENOSYS. It was useless because system.h ensures it's defined.
# Collect the names of rules starting with `sc_'.
syntax-check-rules := $(shell sed -n 's/^\(sc_[a-zA-Z0-9_-]*\):.*/\1/p' $(ME))
.PHONY: $(syntax-check-rules)
# Checks that don't require cvs.
# Run `changelog-check' last, as previous test may reveal problems requiring
# new ChangeLog entries.
local-checks-available = \
po-check copyright-check writable-files m4-check author_mark_check \
po-check copyright-check m4-check author_mark_check \
changelog-check patch-check strftime-check $(syntax-check-rules) \
makefile_path_separator_check \
makefile-check check-AUTHORS
.PHONY: $(local-checks-available)
local-check = $(filter-out $(local-checks-to-skip), $(local-checks-available))
local-check := $(filter-out $(local-checks-to-skip), $(local-checks-available))
# Collect the names of rules starting with `sc_'.
syntax-check-rules := $(shell sed -n 's/^\(sc_[a-zA-Z0-9_-]*\):.*/\1/p' $(ME))
.PHONY: $(syntax-check-rules)
syntax-check: $(syntax-check-rules)
syntax-check: $(local-check)
# @grep -nE '# *include <(limits|std(def|arg|bool))\.h>' \
# $$(find -type f -name '*.[chly]') && \
# { echo '$(ME): found conditional include' 1>&2; \
@@ -103,16 +103,12 @@ sc_cast_of_argument_to_free:
exit 1; } || :
sc_cast_of_x_alloc_return_value:
@grep -nE --exclude=$(srcdir)/lib/xalloc.h \
--exclude=$(srcdir)/lib/regex.c \
'\*\) *x(m|c|re)alloc\>' \
$(srcdir)/{lib,src}/*.[chy] && \
@grep -nE '\*\) *x(m|c|re)alloc\>' $$($(CVS_LIST_EXCEPT)) && \
{ echo '$(ME): don'\''t cast x*alloc return value' 1>&2; \
exit 1; } || :
sc_cast_of_alloca_return_value:
@grep -nE '\*\) *alloca\>' \
$(srcdir)/src/*.[chy] && \
@grep -nE '\*\) *alloca\>' $$($(CVS_LIST_EXCEPT)) && \
{ echo '$(ME): don'\''t cast alloca return value' 1>&2; \
exit 1; } || :
@@ -121,18 +117,18 @@ sc_space_tab:
{ echo '$(ME): found SPACE-TAB sequence; remove the SPACE' \
1>&2; exit 1; } || :
# Don't use the old ato* functions in `real' code.
# Don't use *scanf or the old ato* functions in `real' code.
# They provide no error checking mechanism.
# Instead, use strto* functions.
sc_prohibit_atoi_atof:
@grep -nE '\<ato([filq]|ll)\>' $$($(CVS_LIST_EXCEPT)) && \
{ echo '$(ME): do not use ato''f, ato''i, ato''l, ato''ll, or ato''q' \
@grep -nE '\<([fs]?scanf|ato([filq]|ll))\>' $$($(CVS_LIST_EXCEPT)) && \
{ echo '$(ME): do not use *scan''f, ato''f, ato''i, ato''l, ato''ll, or ato''q' \
1>&2; exit 1; } || :
# Using EXIT_SUCCESS as the first argument to error is misleading,
# since when that parameter is 0, error does not exit. Use `0' instead.
sc_error_exit_success:
@grep -nF 'error (EXIT_SUCCESS,' \
@grep -nF 'error (EXIT_SUCCESS,' \
$$(find -type f -name '*.[chly]') && \
{ echo '$(ME): found error (EXIT_SUCCESS' 1>&2; \
exit 1; } || :
@@ -212,7 +208,9 @@ sc_prohibit_jm_in_m4:
1>&2; exit 1; } || :
sc_root_tests:
@t1=sc-root.expected; t2=sc-root.actual; \
@if test -d tests \
&& grep check-root tests/Makefile.am>/dev/null 2>&1; then \
t1=sc-root.expected; t2=sc-root.actual; \
grep -nl '^PRIV_CHECK_ARG=require-root' \
$$($(CVS_LIST) tests) |sed s,tests,., |sort > $$t1; \
sed -n 's, cd \([^ ]*\) .*MAKE..check TESTS=\(.*\),./\1/\2,p' \
@@ -221,7 +219,8 @@ sc_root_tests:
rm -f $$t1 $$t2; \
test "$$diff" \
&& { echo 'tests/Makefile.am: missing check-root action'>&2; \
exit 1; } || :
exit 1; } || :; \
fi
headers_with_interesting_macro_defs = \
exit.h \
@@ -368,22 +367,22 @@ makefile-check:
&& { echo 'Makefile.maint: use $$(...), not @...@' 1>&2; exit 1; } || :
news-date-check: NEWS
today=`date +%Y-%m-%d`; \
if head NEWS | grep '^\*.* $(VERSION_REGEXP) ('$$today')' \
>/dev/null; then \
:; \
else \
echo "version or today's date is not in NEWS" 1>&2; \
exit 1; \
today=`date +%Y-%m-%d`; \
if head NEWS | grep '^\*.* $(VERSION_REGEXP) ('$$today')' \
>/dev/null; then \
:; \
else \
echo "version or today's date is not in NEWS" 1>&2; \
exit 1; \
fi
changelog-check:
if head ChangeLog | grep 'Version $(VERSION_REGEXP)\.$$' \
>/dev/null; then \
:; \
else \
echo "$(VERSION) not in ChangeLog" 1>&2; \
exit 1; \
if head ChangeLog | grep 'Version $(VERSION_REGEXP)\.$$' \
>/dev/null; then \
:; \
else \
echo "$(VERSION) not in ChangeLog" 1>&2; \
exit 1; \
fi
m4-check:
@@ -401,6 +400,7 @@ po-check:
for file in $$($(CVS_LIST_EXCEPT)) lib/*.[ch]; do \
case $$file in \
djgpp/* | man/*) continue;; \
*/c99-to-c89.diff) continue;; \
esac; \
case $$file in \
*.[ch]) \
@@ -470,7 +470,7 @@ copyright-check:
# Abort early if this tag has already been used.
vc-tag-check:
used=no; \
if $(VC) --help | grep CVS; then \
if $(VC) --help | grep CVS; then \
$(CVS) -n log -h README|grep -e $(this-vc-tag): >/dev/null \
&& used=yes; \
else \
@@ -514,11 +514,11 @@ null_AM_MAKEFLAGS = \
AUTOHEADER=false \
MAKEINFO=false
# Detect format-string/arg-list mismatches that would normally be obscured
# by the use of _(). The --disable-nls effectively defines away that macro,
# and building with CFLAGS='-Wformat -Werror' causes any format warning to be
# treated as a failure. Also, check for shadowing problems with -Wshadow,
# and for pointer arithmetic problems with -Wpointer-arith.
warn_cflags = -Dlint -O -Werror -Wall -Wformat -Wshadow -Wpointer-arith
# Use -Wformat -Werror to detect format-string/arg-list mismatches.
# Also, check for shadowing problems with -Wshadow, and for pointer
# arithmetic problems with -Wpointer-arith.
# These CFLAGS are pretty strict. If you build this target, you probably
# have to have a recent version of gcc and glibc headers.
TMPDIR ?= /tmp
@@ -529,7 +529,7 @@ my-distcheck: $(local-check) $(release_archive_dir)/$(prev-tgz)
GZIP=$(GZIP_ENV) $(AMTAR) -C $(t) -zxf $(distdir).tar.gz
cd $(t)/$(distdir) \
&& ./configure --disable-nls \
&& $(MAKE) CFLAGS='-Werror -Wall -Wformat -Wshadow -Wpointer-arith' \
&& $(MAKE) CFLAGS='$(warn_cflags)' \
AM_MAKEFLAGS='$(null_AM_MAKEFLAGS)' \
&& $(MAKE) dvi \
&& $(MAKE) check \
@@ -537,11 +537,13 @@ my-distcheck: $(local-check) $(release_archive_dir)/$(prev-tgz)
(cd $(t) && mv $(distdir) $(distdir).old \
&& $(AMTAR) -zxf - ) < $(distdir).tar.gz
diff -ur $(t)/$(distdir).old $(t)/$(distdir)
cd $(t)/$(distdir) \
&& (cd src && patch -V never --fuzz=0 <c99-to-c89.diff) \
&& ./configure --disable-largefile \
CFLAGS='-Werror -ansi -pedantic -Wno-long-long' \
&& $(MAKE)
if test -f $(srcdir)/src/c99-to-c89.diff; then \
cd $(t)/$(distdir) \
&& (cd src && patch -V never --fuzz=0 <c99-to-c89.diff) \
&& ./configure --disable-largefile \
CFLAGS='-Werror -ansi -pedantic -Wno-long-long' \
&& $(MAKE); \
fi
-rm -rf $(t)
@echo "========================"; \
echo "$(distdir).tar.gz is ready for distribution"; \
@@ -564,12 +566,12 @@ xd-delta = $(PACKAGE)-$(PREV_VERSION)-$(VERSION).xdelta
rel-files = $(xd-delta) $(DIST_ARCHIVES)
# Approximate date of last "update" by the date on the ChangeLog file.
gnulib_snapshot_date = \
$$(date -u --date $$(stat --printf @%Y $(gnulib_dir)/ChangeLog) \
'+%Y-%m-%d %T %z')
# Approximate the date of last gnulib "update" by the ChangeLog file's
# mtime, and provide that date in the announcement.
announcement: NEWS ChangeLog $(rel-files)
@./build-aux/announce-gen \
@cl_date=$$(stat --printf @%Y $(gnulib_dir)/ChangeLog); \
utc_date=$$(date -u --date $$cl_date '+%Y-%m-%d %T %z'); \
./build-aux/announce-gen \
--release-type=$(RELEASE_TYPE) \
--package=$(PACKAGE) \
--prev=$(PREV_VERSION) \
@@ -577,7 +579,7 @@ announcement: NEWS ChangeLog $(rel-files)
--gpg-key-id=$(gpg_key_ID) \
--news=NEWS \
--bootstrap-tools=autoconf,automake,bison,gnulib \
--gnulib-snapshot-date=$(gnulib_snapshot_date) \
--gnulib-snapshot-time-stamp="$$utc_date" \
$(addprefix --url-dir=, $(url_dir_list))
## ---------------- ##
@@ -594,7 +596,7 @@ emit_upload_commands:
@echo =====================================
@echo =====================================
@echo "$(srcdir)/build-aux/gnupload $(GNUPLOADFLAGS) \\"
@echo " --to $(gnu_rel_host):coreutils \\"
@echo " --to $(gnu_rel_host):$(PACKAGE) \\"
@echo " $(rel-files)"
@echo '# send the /tmp/announcement e-mail'
@echo =====================================
@@ -604,7 +606,7 @@ $(xd-delta): $(release_archive_dir)/$(prev-tgz) $(distdir).tar.gz
xdelta delta -9 $^ $@ || :
.PHONY: alpha beta major
alpha beta major: news-date-check changelog-check $(local-check)
alpha beta major: news-date-check changelog-check $(local-check) writable-files
test $@ = major \
&& { echo $(VERSION) | grep -E '^[0-9]+(\.[0-9]+)+$$' \
|| { echo "invalid version string: $(VERSION)" 1>&2; exit 1;};}\

16
NEWS
View File

@@ -1,5 +1,19 @@
GNU coreutils NEWS -*- outline -*-
* Noteworthy changes in release 6.8+ (????-??-??) [not-unstable]
** Bug fixes
cp -x (--one-file-system) would fail to set mount point permissions
The default block size and output format for df -P are now unaffected by
the DF_BLOCK_SIZE, BLOCK_SIZE, and BLOCKSIZE environment variables. It
is still affected by POSIXLY_CORRECT, though.
Using pr -m -s (i.e. merging files, with TAB as the output separator)
no longer inserts extraneous spaces between output columns.
* Noteworthy changes in release 6.8 (2007-02-24) [not-unstable]
** Bug fixes
@@ -48,8 +62,6 @@ GNU coreutils NEWS -*- outline -*-
program to use when writing and reading temporary files.
This can help save both time and disk space when sorting large inputs.
** New features
sort accepts the new option -C, which acts like -c except no diagnostic
is printed. Its --check option now accepts an optional argument, and
--check=quiet and --check=silent are now aliases for -C, while

16
README
View File

@@ -7,14 +7,14 @@ arbitrary limits.
The programs that can be built with this package are:
[ base64 basename cat chgrp chmod chown chroot cksum comm cp csplit cut date
dd df dir dircolors dirname du echo env expand expr factor false fmt fold
ginstall groups head hostid hostname id join kill link ln logname ls
md5sum mkdir mkfifo mknod mv nice nl nohup od paste pathchk pinky pr
printenv printf ptx pwd readlink rm rmdir seq sha1sum sha224sum sha256sum
sha384sum sha512sum shred shuf sleep sort split stat stty su sum sync tac
tail tee test touch tr true tsort tty uname unexpand uniq unlink uptime
users vdir wc who whoami yes
[ base64 basename cat chcon chgrp chmod chown chroot cksum comm cp
csplit cut date dd df dir dircolors dirname du echo env expand expr
factor false fmt fold ginstall groups head hostid hostname id join
kill link ln logname ls md5sum mkdir mkfifo mknod mv nice nl nohup
od paste pathchk pinky pr printenv printf ptx pwd readlink rm rmdir
runcon seq sha1sum sha224sum sha256sum sha384sum sha512sum shred shuf
sleep sort split stat stty su sum sync tac tail tee test touch tr true
tsort tty uname unexpand uniq unlink uptime users vdir wc who whoami yes
See the file NEWS for a list of major changes in the current release.

1
THANKS
View File

@@ -519,6 +519,7 @@ William Bader william@nscs.fast.net
William Dowling will@franklin.com
William Lewis wiml@omnigroup.com
wiregauze wiregauze@yahoo.com
Wis Macomson wis.macomson@intel.com
Wojciech Purczynski cliph@isec.pl
Wolfram Kleff kleff@cs.uni-bonn.de
Won-kyu Park wkpark@chem.skku.ac.kr

9
TODO
View File

@@ -1,3 +1,12 @@
stty.c:
use xstrtoul, not sscanf
printf:
Now that gnulib supports *printf("%a"), import one of the
*printf-posix modules so that printf(1) will support %a even on
platforms where the native *printf(3) is deficient.
Suggestion form Eric Blake.
strip: add an option to specify the program used to strip binaries.
suggestion from Karl Berry

146
bootstrap
View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Bootstrap this package from CVS.
# Bootstrap this package from checked-out sources.
# Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
@@ -49,8 +49,8 @@ Options:
--force Attempt to bootstrap even if the sources seem
not to have been checked out.
--skip-po Do not download po files.
--cvs-user=USERNAME Set the CVS username to be used when accessing
the gnulib repository.
--cvs-user=USERNAME Set the username to use when checking out
sources from the gnulib repository.
If the file .bootstrap.conf exists in the current working directory, its
contents are read as shell variables to configure the bootstrap.
@@ -89,18 +89,20 @@ extract_package_name='
}
'
package=`sed -n "$extract_package_name" configure.ac` || exit
gnulib_name=lib$package
build_aux=build-aux
# Extra files from gnulib, which override files from other sources.
gnulib_extra_files='
build-aux/install-sh
build-aux/missing
build-aux/mdate-sh
build-aux/texinfo.tex
build-aux/depcomp
build-aux/config.guess
build-aux/config.sub
gnulib_extra_files="
$build_aux/install-sh
$build_aux/missing
$build_aux/mdate-sh
$build_aux/texinfo.tex
$build_aux/depcomp
$build_aux/config.guess
$build_aux/config.sub
doc/INSTALL
'
"
# Other locale categories that need message catalogs.
EXTRA_LOCALE_CATEGORIES=
@@ -117,7 +119,7 @@ excluded_files=
# File that should exist in the top directory of a checked out hierarchy,
# but not in a distribution tarball.
CVS_only_file=README-hacking
checkout_only_file=README-hacking
# Whether to use copies instead of symlinks.
copy=false
@@ -142,7 +144,7 @@ do
--skip-po)
SKIP_PO=t;;
--force)
CVS_only_file=;;
checkout_only_file=;;
--copy)
copy=true;;
*)
@@ -151,12 +153,42 @@ do
esac
done
if test -n "$CVS_only_file" && test ! -r "$CVS_only_file"; then
if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then
echo "$0: Bootstrapping from a non-checked-out distribution is risky." >&2
exit 1
fi
echo "$0: Bootstrapping CVS $package..."
# If $STR is not already on a line by itself in $FILE, insert it,
# sorting the new contents of the file and replacing $FILE with the result.
insert_sorted_if_absent() {
file=$1
str=$2
echo "$str" | sort -u - $file | cmp -s - $file \
|| echo "$str" | sort -u - $file -o $file \
|| exit 1
}
# Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac.
found_aux_dir=no
grep '^[ ]*AC_CONFIG_AUX_DIR(\['"$build_aux"'\])' configure.ac \
>/dev/null && found_aux_dir=yes
grep '^[ ]*AC_CONFIG_AUX_DIR('"$build_aux"')' configure.ac \
>/dev/null && found_aux_dir=yes
if test $found_aux_dir = no; then
echo "$0: expected line not found in configure.ac. Add the following:" >&2
echo " AC_CONFIG_AUX_DIR([$build_aux])" >&2.
fi
# If $build_aux doesn't exist, create it now, otherwise some bits
# below will malfunction. If creating it, also mark it as ignored.
if test ! -d $build_aux; then
mkdir $build_aux
for ig in .cvsignore .gitignore; do
test -f $ig && insert_sorted_if_absent $ig $build_aux
done
fi
echo "$0: Bootstrapping from checked-out $package sources..."
cleanup_gnulib() {
status=$?
@@ -358,16 +390,6 @@ version_controlled_file() {
test $found = yes
}
# If $STR is not already on a line by itself in $FILE, insert it,
# sorting the new contents of the file and replacing $FILE with the result.
insert_sorted_if_absent() {
file=$1
str=$2
echo "$str" | sort -u - $file | cmp -s - $file \
|| echo "$str" | sort -u - $file -o $file \
|| exit
}
slurp() {
for dir in . `(cd $1 && find * -type d -print)`; do
copied=
@@ -431,9 +453,9 @@ mkdir $bt $bt2 || exit
gnulib_tool_options="\
--import\
--no-changelog\
--aux-dir $bt/build-aux\
--aux-dir $bt/$build_aux\
--doc-base $bt/doc\
--lib lib$package\
--lib $gnulib_name\
--m4-base $bt/m4/\
--source-base $bt/lib/\
--tests-base $bt/tests\
@@ -449,23 +471,34 @@ done
# Import from gettext.
with_gettext=yes
grep '^[ ]*AM_GNU_GETTEXT_VERSION(' configure.ac >/dev/null || \
with_gettext=no
echo "$0: (cd $bt2; autopoint) ..."
cp configure.ac $bt2 &&
(cd $bt2 && autopoint && rm configure.ac) &&
slurp $bt2 $bt || exit
if test $with_gettext = yes; then
echo "$0: (cd $bt2; autopoint) ..."
cp configure.ac $bt2 &&
(cd $bt2 && autopoint && rm configure.ac) &&
slurp $bt2 $bt || exit
rm -fr $bt $bt2 || exit
rm -fr $bt $bt2 || exit
fi
# Reconfigure, getting other files.
for command in \
libtool \
'aclocal --force -I m4' \
'autoconf --force' \
'autoheader --force' \
'automake --add-missing --copy --force-missing';
do
if test "$command" = libtool; then
grep '^[ ]*AM_PROG_LIBTOOL\>' configure.ac >/dev/null ||
continue
command='libtoolize -c -f'
fi
echo "$0: $command ..."
$command || exit
done
@@ -481,36 +514,37 @@ for file in $gnulib_extra_files; do
symlink_to_gnulib $file $dst || exit
done
# Create gettext configuration.
echo "$0: Creating po/Makevars from po/Makevars.template ..."
rm -f po/Makevars
sed '
/^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '"$EXTRA_LOCALE_CATEGORIES"'/
/^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
/^XGETTEXT_OPTIONS *=/{
s/$/ \\/
a\
'"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+}
}
' po/Makevars.template >po/Makevars
if test -d runtime-po; then
# Similarly for runtime-po/Makevars, but not quite the same.
rm -f runtime-po/Makevars
if test $with_gettext = yes; then
# Create gettext configuration.
echo "$0: Creating po/Makevars from po/Makevars.template ..."
rm -f po/Makevars
sed '
/^DOMAIN *=.*/s/=.*/= '"$package"'-runtime/
/^subdir *=.*/s/=.*/= runtime-po/
/^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '"$EXTRA_LOCALE_CATEGORIES"'/
/^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
/^XGETTEXT_OPTIONS *=/{
s/$/ \\/
a\
'"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+}
'"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+}
}
' <po/Makevars.template >runtime-po/Makevars
' po/Makevars.template >po/Makevars
# Copy identical files from po to runtime-po.
(cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po)
if test -d runtime-po; then
# Similarly for runtime-po/Makevars, but not quite the same.
rm -f runtime-po/Makevars
sed '
/^DOMAIN *=.*/s/=.*/= '"$package"'-runtime/
/^subdir *=.*/s/=.*/= runtime-po/
/^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
/^XGETTEXT_OPTIONS *=/{
s/$/ \\/
a\
'"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+}
}
' <po/Makevars.template >runtime-po/Makevars
# Copy identical files from po to runtime-po.
(cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po)
fi
fi
echo "$0: done. Now you can run './configure'."

View File

@@ -60,14 +60,16 @@ gnulib_modules="
root-dev-ino
rpmatch
safe-read same
save-cwd savedir savewd settime sha1 sig2str ssize_t stat-macros
save-cwd savedir savewd
selinux-at
settime sha1 sig2str ssize_t stat-macros
stat-time stdbool stdlib-safer stpcpy strftime
strpbrk strtoimax strtoumax strverscmp sys_stat timespec tzset
unicodeio unistd-safer unlink-busy unlinkdir unlocked-io
uptime userspec utimecmp utimens vasprintf verify version-etc-fsf
wcwidth winsz-ioctl winsz-termios xalloc xgetcwd xgethostname
xmemcoll xnanosleep xreadlink xstrtod xstrtoimax xstrtol
xstrtold xstrtoumax yesno
xmemcoll xnanosleep xreadlink xreadlink-with-size xstrtod xstrtoimax
xstrtol xstrtold xstrtoumax yesno
"
# Other locale categories that need message catalogs.
@@ -81,17 +83,32 @@ XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\
--flag=wrapf:1:c-format\\\
'
# Gettext supplies these files, but we don't need them since
# we don't have an intl subdirectory.
excluded_files='
m4/glibc2.m4
m4/intdiv0.m4
m4/lcmessage.m4
m4/lock.m4
m4/printf-posix.m4
m4/size_max.m4
m4/uintmax_t.m4
m4/ulonglong.m4
m4/visibility.m4
m4/xsize.m4
'
# If "AM_GNU_GETTEXT(external" or "AM_GNU_GETTEXT([external]"
# appears in configure.ac, exclude some unnecessary files.
# Without grep's -E option (not portable enough, pre-configure),
# the following test is ugly. Also, this depends on the existence
# of configure.ac, not the obsolescent-named configure.in. But if
# you're using this infrastructure, you should care about such things.
gettext_external=0
grep '^[ ]*AM_GNU_GETTEXT(external\>' configure.ac > /dev/null &&
gettext_external=1
grep '^[ ]*AM_GNU_GETTEXT(\[external\]' configure.ac > /dev/null &&
gettext_external=1
if test $gettext_external = 1; then
# Gettext supplies these files, but we don't need them since
# we don't have an intl subdirectory.
excluded_files='
m4/glibc2.m4
m4/intdiv0.m4
m4/lcmessage.m4
m4/lock.m4
m4/printf-posix.m4
m4/size_max.m4
m4/uintmax_t.m4
m4/ulonglong.m4
m4/visibility.m4
m4/xsize.m4
'
fi

View File

@@ -20,7 +20,7 @@
dnl Written by Jim Meyering.
AC_PREREQ(2.61)
AC_INIT([GNU coreutils],[6.8],[bug-coreutils@gnu.org])
AC_INIT([GNU coreutils],[6.8+],[bug-coreutils@gnu.org])
AC_CONFIG_SRCDIR(src/ls.c)
AC_CONFIG_AUX_DIR(build-aux)

View File

@@ -1,3 +1,24 @@
2007-03-15 Paul Eggert <eggert@cs.ucla.edu>
Fix manual in response to bug reports by Dan Jacobson.
* coreutils.texi (sort invocation): Explain numeric sorts better.
Compress self-congratulation into a simple "comparison is exact"
notice; the --general-numeric-sort option already explains the
tradeoffs.
(seq invocation): Add example of -f.
2007-03-12 Jim Meyering <jim@meyering.net>
* coreutils.texi (cp invocation): Mention that --preserve=timestamps
doesn't preserve time stamps on symbolic links.
Reported by Polo Talnir in <https://bugzilla.redhat.com/230866>.
2007-02-27 Paul Eggert <eggert@cs.ucla.edu>
* coreutils.texi (df invocation): With -P, the default block size
and output format is not affected by DF_BLOCK_SIZE, BLOCK_SIZE, or
BLOCKSIZE.
2007-01-30 Paul Eggert <eggert@cs.ucla.edu>
* coreutils.texi

View File

@@ -558,8 +558,8 @@ symbolic link to a directory. @xref{Target directory}.
@itemx --si
@opindex --si
@cindex SI output
Append an SI-style abbreviation to each size, such as @samp{MB} for
megabytes. Powers of 1000 are used, not 1024; @samp{MB} stands for
Append an SI-style abbreviation to each size, such as @samp{M} for
megabytes. Powers of 1000 are used, not 1024; @samp{M} stands for
1,000,000 bytes. This option is equivalent to
@option{--block-size=si}. Use the @option{-h} or
@option{--human-readable} option if
@@ -3575,26 +3575,16 @@ can change this.
@opindex --numeric-sort
@cindex numeric sort
@vindex LC_NUMERIC
Sort numerically: the number begins each line; specifically, it consists
Sort numerically. The number begins each line and consists
of optional blanks, an optional @samp{-} sign, and zero or more
digits possibly separated by thousands separators, optionally followed
by a decimal-point character and zero or more digits. A string of
no digits is interpreted as @samp{0}. The @env{LC_NUMERIC}
by a decimal-point character and zero or more digits. An empty
number is treated as @samp{0}. The @env{LC_NUMERIC}
locale specifies the decimal-point character and thousands separator.
By default a blank is a space or a tab, but the @env{LC_CTYPE} locale
can change this.
Numeric sort uses what might be considered an unconventional method to
compare strings representing floating point numbers. Rather than first
converting each string to the C @code{double} type and then comparing
those values, @command{sort} aligns the decimal-point characters in the
two strings and compares the strings a character at a time. One benefit
of using this approach is its speed. In practice this is much more
efficient than performing the two corresponding string-to-double (or
even string-to-integer) conversions and then comparing doubles. In
addition, there is no corresponding loss of precision. Converting each
string to @code{double} before comparison would limit precision to about
16 digits on most systems.
Comparison is exact; there is no rounding error.
Neither a leading @samp{+} nor exponential notation is recognized.
To compare such strings numerically, use the
@@ -7030,7 +7020,13 @@ and ordinary users
may preserve the group ownership of a file only if they happen to be
a member of the desired group.
@itemx timestamps
Preserve the times of last access and last modification.
Preserve the times of last access and last modification, when possible.
In general, it is not possible to preserve these attributes
when the affected file is a symbolic link.
However, FreeBSD now provides the @code{lutimes} function, which makes
it possibile even for symbolic links. However, this implementation does
not yet take advantage of that.
@c FIXME: once we provide lutimes support, update the above.
@itemx links
Preserve in the destination files
any links between corresponding source files.
@@ -9481,6 +9477,13 @@ some network mounts), the columns are misaligned.
@item
The labels in the header output line are changed to conform to @acronym{POSIX}.
@item
The default block size and output format are unaffected by the
@env{DF_BLOCK_SIZE}, @env{BLOCK_SIZE} and @env{BLOCKSIZE} environment
variables. However, the default block size is still affected by
@env{POSIXLY_CORRECT}: it is 512 if @env{POSIXLY_CORRECT} is set, 1024
otherwise. @xref{Block size}.
@end enumerate
@optSi
@@ -13926,6 +13929,12 @@ Print all numbers using @var{format}.
@var{format} must contain exactly one of the @samp{printf}-style
floating point conversion specifications @samp{%a}, @samp{%e},
@samp{%f}, @samp{%g}, @samp{%A}, @samp{%E}, @samp{%F}, @samp{%G}.
The @samp{%} may be followed by zero or more flags taken from the set
@samp{-+#0 '}, then an optional width containing one or more digits,
then an optional precision consisting of a @samp{.} followed by zero
or more digits. @var{format} may also contain any number of @samp{%%}
conversion specifications. All conversion specifications have the
same meaning as with @samp{printf}.
The default format is derived from @var{first}, @var{step}, and
@var{last}. If these all use a fixed point decimal representation,
@@ -13948,6 +13957,15 @@ decimal representation.
@end table
You can get finer-grained control over output with @option{-f}:
@example
$ seq -f '(%9.2E)' -9e5 1.1e6 1.3e6
(-9.00E+05)
( 2.00E+05)
( 1.30E+06)
@end example
If you want hexadecimal integer output, you can use @command{printf}
to perform the conversion:

426
gl/lib/acl.c Normal file
View File

@@ -0,0 +1,426 @@
/* acl.c - access control lists
Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Written by Paul Eggert and Andreas Gruenbacher. */
#include <config.h>
#include "acl.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#ifndef S_ISLNK
# define S_ISLNK(Mode) 0
#endif
#ifdef HAVE_ACL_LIBACL_H
# include <acl/libacl.h>
#endif
#include "error.h"
#include "quote.h"
#include <errno.h>
#ifndef ENOSYS
# define ENOSYS (-1)
#endif
#ifndef ENOTSUP
# define ENOTSUP (-1)
#endif
#if ENABLE_NLS
# include <libintl.h>
# define _(Text) gettext (Text)
#else
# define _(Text) Text
#endif
#ifndef HAVE_FCHMOD
# define HAVE_FCHMOD false
# define fchmod(fd, mode) (-1)
#endif
/* POSIX 1003.1e (draft 17) */
#ifndef HAVE_ACL_GET_FD
# define HAVE_ACL_GET_FD false
# define acl_get_fd(fd) (NULL)
#endif
/* POSIX 1003.1e (draft 17) */
#ifndef HAVE_ACL_SET_FD
# define HAVE_ACL_SET_FD false
# define acl_set_fd(fd, acl) (-1)
#endif
/* Linux-specific */
#ifndef HAVE_ACL_EXTENDED_FILE
# define HAVE_ACL_EXTENDED_FILE false
# define acl_extended_file(name) (-1)
#endif
/* Linux-specific */
#ifndef HAVE_ACL_FROM_MODE
# define HAVE_ACL_FROM_MODE false
# define acl_from_mode(mode) (NULL)
#endif
#define ACL_NOT_WELL_SUPPORTED(Errno) \
(Errno == ENOTSUP || Errno == ENOSYS || Errno == EINVAL)
/* We detect the presence of POSIX 1003.1e (draft 17 -- abandoned) support
by checking for HAVE_ACL_GET_FILE, HAVE_ACL_SET_FILE, and HAVE_ACL_FREE.
Systems that have acl_get_file, acl_set_file, and acl_free must also
have acl_to_text, acl_from_text, and acl_delete_def_file (all defined
in the draft); systems that don't would hit #error statements here. */
#if USE_ACL && HAVE_ACL_GET_FILE && !HAVE_ACL_ENTRIES
# ifndef HAVE_ACL_TO_TEXT
# error Must have acl_to_text (see POSIX 1003.1e draft 17).
# endif
/* Return the number of entries in ACL. Linux implements acl_entries
as a more efficient extension than using this workaround. */
static int
acl_entries (acl_t acl)
{
char *text = acl_to_text (acl, NULL), *t;
int entries;
if (text == NULL)
return -1;
for (entries = 0, t = text; ; t++, entries++) {
t = strchr (t, '\n');
if (t == NULL)
break;
}
acl_free (text);
return entries;
}
#endif
/* If DESC is a valid file descriptor use fchmod to change the
file's mode to MODE on systems that have fchown. On systems
that don't have fchown and if DESC is invalid, use chown on
NAME instead. */
int
chmod_or_fchmod (const char *name, int desc, mode_t mode)
{
if (HAVE_FCHMOD && desc != -1)
return fchmod (desc, mode);
else
return chmod (name, mode);
}
#if USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_SET_FILE && HAVE_ACL_FREE
/* FIXME: use acl_trivial instead, once we have a replacement function */
static bool
is_trivial_acl (acl_t acl)
{
int n = acl_entries (acl);
if (n <= 3)
return true;
if (5 <= n)
return false;
/* Here, we know there are exactly 4 entries.
If they are for user, group, mask, and other, then return true; */
/* FIXME */
return false;
}
#endif
/* Return 1 if NAME has a nontrivial access control list, 0 if
NAME only has no or a base access control list, and -1 on
error. SB must be set to the stat buffer of FILE. */
int
file_has_acl (char const *name, struct stat const *sb)
{
#if USE_ACL && HAVE_ACL && defined GETACLCNT
/* This implementation should work on recent-enough versions of HP-UX,
Solaris, and Unixware. */
# ifndef MIN_ACL_ENTRIES
# define MIN_ACL_ENTRIES 4
# endif
if (! S_ISLNK (sb->st_mode))
{
int n = acl (name, GETACLCNT, 0, NULL);
return n < 0 ? (errno == ENOSYS ? 0 : -1) : (MIN_ACL_ENTRIES < n);
}
#elif USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_FREE
/* POSIX 1003.1e (draft 17 -- abandoned) specific version. */
if (! S_ISLNK (sb->st_mode))
{
int ret;
if (HAVE_ACL_EXTENDED_FILE)
ret = acl_extended_file (name);
else
{
acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS);
if (acl)
{
ret = !is_trivial_acl (acl);
acl_free (acl);
if (ret == 0 && S_ISDIR (sb->st_mode))
{
acl = acl_get_file (name, ACL_TYPE_DEFAULT);
if (acl)
{
ret = (0 < acl_entries (acl));
acl_free (acl);
}
else
ret = -1;
}
}
else
ret = -1;
}
if (ret < 0)
return ACL_NOT_WELL_SUPPORTED (errno) ? 0 : -1;
return ret;
}
#endif
/* FIXME: Add support for AIX, Irix, and Tru64. Please see Samba's
source/lib/sysacls.c file for fix-related ideas. */
return 0;
}
/* Copy access control lists from one file to another. If SOURCE_DESC is
a valid file descriptor, use file descriptor operations, else use
filename based operations on SRC_NAME. Likewise for DEST_DESC and
DEST_NAME.
If access control lists are not available, fchmod the target file to
MODE. Also sets the non-permission bits of the destination file
(S_ISUID, S_ISGID, S_ISVTX) to those from MODE if any are set.
System call return value semantics. */
int
copy_acl (const char *src_name, int source_desc, const char *dst_name,
int dest_desc, mode_t mode)
{
int ret;
#if USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_SET_FILE && HAVE_ACL_FREE
/* POSIX 1003.1e (draft 17 -- abandoned) specific version. */
acl_t acl;
if (HAVE_ACL_GET_FD && source_desc != -1)
acl = acl_get_fd (source_desc);
else
acl = acl_get_file (src_name, ACL_TYPE_ACCESS);
if (acl == NULL)
{
if (ACL_NOT_WELL_SUPPORTED (errno))
return set_acl (dst_name, dest_desc, mode);
else
{
error (0, errno, "%s", quote (src_name));
return -1;
}
}
if (HAVE_ACL_SET_FD && dest_desc != -1)
ret = acl_set_fd (dest_desc, acl);
else
ret = acl_set_file (dst_name, ACL_TYPE_ACCESS, acl);
if (ret != 0)
{
int saved_errno = errno;
if (ACL_NOT_WELL_SUPPORTED (errno))
{
bool trivial = is_trivial_acl (acl);
acl_free (acl);
if (trivial)
{
if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0)
saved_errno = errno;
else
return 0;
}
else
chmod_or_fchmod (dst_name, dest_desc, mode);
}
else
{
acl_free (acl);
chmod_or_fchmod (dst_name, dest_desc, mode);
}
error (0, saved_errno, _("preserving permissions for %s"),
quote (dst_name));
return -1;
}
else
acl_free (acl);
if (mode & (S_ISUID | S_ISGID | S_ISVTX))
{
/* We did not call chmod so far, so the special bits have not yet
been set. */
if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0)
{
error (0, errno, _("preserving permissions for %s"),
quote (dst_name));
return -1;
}
}
if (S_ISDIR (mode))
{
acl = acl_get_file (src_name, ACL_TYPE_DEFAULT);
if (acl == NULL)
{
error (0, errno, "%s", quote (src_name));
return -1;
}
if (acl_set_file (dst_name, ACL_TYPE_DEFAULT, acl))
{
error (0, errno, _("preserving permissions for %s"),
quote (dst_name));
acl_free (acl);
return -1;
}
else
acl_free (acl);
}
return 0;
#else
ret = chmod_or_fchmod (dst_name, dest_desc, mode);
if (ret != 0)
error (0, errno, _("preserving permissions for %s"), quote (dst_name));
return ret;
#endif
}
/* Set the access control lists of a file. If DESC is a valid file
descriptor, use file descriptor operations where available, else use
filename based operations on NAME. If access control lists are not
available, fchmod the target file to MODE. Also sets the
non-permission bits of the destination file (S_ISUID, S_ISGID, S_ISVTX)
to those from MODE if any are set. System call return value
semantics. */
int
set_acl (char const *name, int desc, mode_t mode)
{
#if USE_ACL && HAVE_ACL_SET_FILE && HAVE_ACL_FREE
/* POSIX 1003.1e draft 17 (abandoned) specific version. */
/* We must also have have_acl_from_text and acl_delete_def_file.
(acl_delete_def_file could be emulated with acl_init followed
by acl_set_file, but acl_set_file with an empty acl is
unspecified.) */
# ifndef HAVE_ACL_FROM_TEXT
# error Must have acl_from_text (see POSIX 1003.1e draft 17).
# endif
# ifndef HAVE_ACL_DELETE_DEF_FILE
# error Must have acl_delete_def_file (see POSIX 1003.1e draft 17).
# endif
acl_t acl;
int ret;
if (HAVE_ACL_FROM_MODE)
{
acl = acl_from_mode (mode);
if (!acl)
{
error (0, errno, "%s", quote (name));
return -1;
}
}
else
{
char acl_text[] = "u::---,g::---,o::---";
if (mode & S_IRUSR) acl_text[ 3] = 'r';
if (mode & S_IWUSR) acl_text[ 4] = 'w';
if (mode & S_IXUSR) acl_text[ 5] = 'x';
if (mode & S_IRGRP) acl_text[10] = 'r';
if (mode & S_IWGRP) acl_text[11] = 'w';
if (mode & S_IXGRP) acl_text[12] = 'x';
if (mode & S_IROTH) acl_text[17] = 'r';
if (mode & S_IWOTH) acl_text[18] = 'w';
if (mode & S_IXOTH) acl_text[19] = 'x';
acl = acl_from_text (acl_text);
if (!acl)
{
error (0, errno, "%s", quote (name));
return -1;
}
}
if (HAVE_ACL_SET_FD && desc != -1)
ret = acl_set_fd (desc, acl);
else
ret = acl_set_file (name, ACL_TYPE_ACCESS, acl);
if (ret != 0)
{
int saved_errno = errno;
acl_free (acl);
if (ACL_NOT_WELL_SUPPORTED (errno))
{
if (chmod_or_fchmod (name, desc, mode) != 0)
saved_errno = errno;
else
return 0;
}
error (0, saved_errno, _("setting permissions for %s"), quote (name));
return -1;
}
else
acl_free (acl);
if (S_ISDIR (mode) && acl_delete_def_file (name))
{
error (0, errno, _("setting permissions for %s"), quote (name));
return -1;
}
if (mode & (S_ISUID | S_ISGID | S_ISVTX))
{
/* We did not call chmod so far, so the special bits have not yet
been set. */
if (chmod_or_fchmod (name, desc, mode))
{
error (0, errno, _("preserving permissions for %s"), quote (name));
return -1;
}
}
return 0;
#else
int ret = chmod_or_fchmod (name, desc, mode);
if (ret)
error (0, errno, _("setting permissions for %s"), quote (name));
return ret;
#endif
}

308
gl/lib/savewd.c Normal file
View File

@@ -0,0 +1,308 @@
/* Save and restore the working directory, possibly using a child process.
Copyright (C) 2006, 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* Written by Paul Eggert. */
#include <config.h>
#include "savewd.h"
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "dirname.h"
#include "fcntl-safer.h"
/* Save the working directory into *WD, if it hasn't been saved
already. Return true if a child has been forked to do the real
work. */
static bool
savewd_save (struct savewd *wd)
{
switch (wd->state)
{
case INITIAL_STATE:
/* Save the working directory, or prepare to fall back if possible. */
{
int fd = open_safer (".", O_RDONLY);
if (0 <= fd)
{
wd->state = FD_STATE;
wd->val.fd = fd;
break;
}
if (errno != EACCES && errno != ESTALE)
{
wd->state = ERROR_STATE;
wd->val.errnum = errno;
break;
}
}
wd->state = FORKING_STATE;
wd->val.child = -1;
/* Fall through. */
case FORKING_STATE:
if (wd->val.child < 0)
{
/* "Save" the initial working directory by forking a new
subprocess that will attempt all the work from the chdir
until until the next savewd_restore. */
wd->val.child = fork ();
if (wd->val.child != 0)
{
if (0 < wd->val.child)
return true;
wd->state = ERROR_STATE;
wd->val.errnum = errno;
}
}
break;
case FD_STATE:
case FD_POST_CHDIR_STATE:
case ERROR_STATE:
case FINAL_STATE:
break;
default:
assert (false);
}
return false;
}
int
savewd_chdir (struct savewd *wd, char const *dir, int options,
int open_result[2])
{
int fd = -1;
int result = 0;
/* Open the directory if requested, or if avoiding a race condition
is requested and possible. */
if (open_result
|| (options & (HAVE_WORKING_O_NOFOLLOW ? SAVEWD_CHDIR_NOFOLLOW : 0)))
{
fd = open (dir,
(O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
| (options & SAVEWD_CHDIR_NOFOLLOW ? O_NOFOLLOW : 0)));
if (open_result)
{
open_result[0] = fd;
open_result[1] = errno;
}
if (fd < 0 && ((errno != EACCES && errno != ESTALE)
|| (options & SAVEWD_CHDIR_READABLE)))
result = -1;
}
if (result == 0 && ! (0 <= fd && options & SAVEWD_CHDIR_SKIP_READABLE))
{
if (savewd_save (wd))
{
open_result = NULL;
result = -2;
}
else
{
result = (fd < 0 ? chdir (dir) : fchdir (fd));
if (result == 0)
switch (wd->state)
{
case FD_STATE:
wd->state = FD_POST_CHDIR_STATE;
break;
case ERROR_STATE:
case FD_POST_CHDIR_STATE:
case FINAL_STATE:
break;
case FORKING_STATE:
assert (wd->val.child == 0);
break;
default:
assert (false);
}
}
}
if (0 <= fd && ! open_result)
{
int e = errno;
close (fd);
errno = e;
}
return result;
}
int
savewd_restore (struct savewd *wd, int status)
{
switch (wd->state)
{
case INITIAL_STATE:
case FD_STATE:
/* The working directory is the desired directory, so there's no
work to do. */
break;
case FD_POST_CHDIR_STATE:
/* Restore the working directory using fchdir. */
if (fchdir (wd->val.fd) == 0)
{
wd->state = FD_STATE;
break;
}
else
{
int chdir_errno = errno;
close (wd->val.fd);
wd->state = ERROR_STATE;
wd->val.errnum = chdir_errno;
}
/* Fall through. */
case ERROR_STATE:
/* Report an error if asked to restore the working directory. */
errno = wd->val.errnum;
return -1;
case FORKING_STATE:
/* "Restore" the working directory by waiting for the subprocess
to finish. */
{
pid_t child = wd->val.child;
if (child == 0)
_exit (status);
if (0 < child)
{
int child_status;
while (waitpid (child, &child_status, 0) < 0)
assert (errno == EINTR);
wd->val.child = -1;
if (! WIFEXITED (child_status))
raise (WTERMSIG (child_status));
return WEXITSTATUS (child_status);
}
}
break;
default:
assert (false);
}
return 0;
}
void
savewd_finish (struct savewd *wd)
{
switch (wd->state)
{
case INITIAL_STATE:
case ERROR_STATE:
break;
case FD_STATE:
case FD_POST_CHDIR_STATE:
close (wd->val.fd);
break;
case FORKING_STATE:
assert (wd->val.child < 0);
break;
default:
assert (false);
}
wd->state = FINAL_STATE;
}
/* Return true if the actual work is currently being done by a
subprocess.
A true return means that the caller and the subprocess should
resynchronize later with savewd_restore, using only their own
memory to decide when to resynchronize; they should not consult the
file system to decide, because that might lead to race conditions.
This is why savewd_chdir is broken out into another function;
savewd_chdir's callers _can_ inspect the file system to decide
whether to call savewd_chdir. */
static inline bool
savewd_delegating (struct savewd const *wd)
{
return wd->state == FORKING_STATE && 0 < wd->val.child;
}
int
savewd_process_files (int n_files, char **file,
int (*act) (char *, struct savewd *, void *),
void *options)
{
int i = 0;
int last_relative;
int exit_status = EXIT_SUCCESS;
struct savewd wd;
savewd_init (&wd);
for (last_relative = n_files - 1; 0 <= last_relative; last_relative--)
if (! IS_ABSOLUTE_FILE_NAME (file[last_relative]))
break;
for (; i < last_relative; i++)
{
if (! savewd_delegating (&wd))
{
int s = act (file[i], &wd, options);
if (exit_status < s)
exit_status = s;
}
if (! IS_ABSOLUTE_FILE_NAME (file[i + 1]))
{
int r = savewd_restore (&wd, exit_status);
if (exit_status < r)
exit_status = r;
}
}
savewd_finish (&wd);
for (; i < n_files; i++)
{
int s = act (file[i], &wd, options);
if (exit_status < s)
exit_status = s;
}
return exit_status;
}

31
gl/lib/se-context_.h Normal file
View File

@@ -0,0 +1,31 @@
#ifndef SELINUX_CONTEXT_H
# define SELINUX_CONTEXT_H
# include <errno.h>
/* Some systems don't have ENOSYS. */
# ifndef ENOSYS
# ifdef ENOTSUP
# define ENOSYS ENOTSUP
# else
/* Some systems don't have ENOTSUP either. */
# define ENOSYS EINVAL
# endif
# endif
typedef int context_t;
static inline context_t context_new (char const *s)
{ errno = ENOTSUP; return 0; }
static inline char *context_str (context_t con)
{ errno = ENOTSUP; return (void *) 0; }
static inline void context_free (context_t c) {}
static inline int context_user_set (context_t sc, char const *s)
{ errno = ENOTSUP; return -1; }
static inline int context_role_set (context_t sc, char const *s)
{ errno = ENOTSUP; return -1; }
static inline int context_range_set (context_t sc, char const *s)
{ errno = ENOTSUP; return -1; }
static inline int context_type_set (context_t sc, char const *s)
{ errno = ENOTSUP; return -1; }
#endif

54
gl/lib/se-selinux_.h Normal file
View File

@@ -0,0 +1,54 @@
#ifndef SELINUX_SELINUX_H
# define SELINUX_SELINUX_H
# include <sys/types.h>
# include <errno.h>
/* Some systems don't have ENOSYS. */
# ifndef ENOSYS
# ifdef ENOTSUP
# define ENOSYS ENOTSUP
# else
/* Some systems don't have ENOTSUP either. */
# define ENOSYS EINVAL
# endif
# endif
typedef unsigned short security_class_t;
# define security_context_t char*
# define is_selinux_enabled() 0
static inline int getcon (security_context_t *con) { errno = ENOTSUP; return -1; }
static inline void freecon (security_context_t con) {}
static inline int getfscreatecon (security_context_t *con)
{ errno = ENOTSUP; return -1; }
static inline int setfscreatecon (security_context_t con)
{ errno = ENOTSUP; return -1; }
static inline int matchpathcon (char const *s, mode_t m,
security_context_t *con)
{ errno = ENOTSUP; return -1; }
static inline int getfilecon (char const *s, security_context_t *con)
{ errno = ENOTSUP; return -1; }
static inline int lgetfilecon (char const *s, security_context_t *con)
{ errno = ENOTSUP; return -1; }
static inline int setfilecon (char const *s, security_context_t con)
{ errno = ENOTSUP; return -1; }
static inline int lsetfilecon (char const *s, security_context_t con)
{ errno = ENOTSUP; return -1; }
static inline int fsetfilecon (int fd, security_context_t con)
{ errno = ENOTSUP; return -1; }
static inline int security_check_context (security_context_t con)
{ errno = ENOTSUP; return -1; }
static inline int security_check_context_raw (security_context_t con)
{ errno = ENOTSUP; return -1; }
static inline int setexeccon (security_context_t con)
{ errno = ENOTSUP; return -1; }
static inline int security_compute_create (security_context_t scon,
security_context_t tcon,
security_class_t tclass,
security_context_t *newcon)
{ errno = ENOTSUP; return -1; }
#endif

92
gl/lib/selinux-at.c Normal file
View File

@@ -0,0 +1,92 @@
/* openat-style fd-relative functions for SE Linux
Copyright (C) 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* written by Jim Meyering */
#include <config.h>
#include "selinux-at.h"
#include "openat.h"
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
#include "save-cwd.h"
#include "gettext.h"
#define _(msgid) gettext (msgid)
#include "openat-priv.h"
#define AT_FUNC_NAME getfileconat
#define AT_FUNC_F1 getfilecon
#define AT_FUNC_F2 getfilecon
#define AT_FUNC_USE_F1_COND 1
#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t *con
#define AT_FUNC_POST_FILE_ARGS , con
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_F2
#undef AT_FUNC_USE_F1_COND
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
#define AT_FUNC_NAME lgetfileconat
#define AT_FUNC_F1 lgetfilecon
#define AT_FUNC_F2 lgetfilecon
#define AT_FUNC_USE_F1_COND 1
#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t *con
#define AT_FUNC_POST_FILE_ARGS , con
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_F2
#undef AT_FUNC_USE_F1_COND
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
#define AT_FUNC_NAME setfileconat
#define AT_FUNC_F1 setfilecon
#define AT_FUNC_F2 setfilecon
#define AT_FUNC_USE_F1_COND 1
#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t con
#define AT_FUNC_POST_FILE_ARGS , con
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_F2
#undef AT_FUNC_USE_F1_COND
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
#define AT_FUNC_NAME lsetfileconat
#define AT_FUNC_F1 lsetfilecon
#define AT_FUNC_F2 lsetfilecon
#define AT_FUNC_USE_F1_COND 1
#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t con
#define AT_FUNC_POST_FILE_ARGS , con
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_F2
#undef AT_FUNC_USE_F1_COND
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS

24
gl/lib/selinux-at.h Normal file
View File

@@ -0,0 +1,24 @@
/* Prototypes for openat-style fd-relative SELinux functions
Copyright (C) 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <selinux/selinux.h>
#include <selinux/context.h>
int getfileconat (int fd, char const *file, security_context_t *con);
int lgetfileconat (int fd, char const *file, security_context_t *con);
int setfileconat (int fd, char const *file, security_context_t con);
int lsetfileconat (int fd, char const *file, security_context_t con);

View File

@@ -0,0 +1,18 @@
# serial 1 -*- Autoconf -*-
# Copyright (C) 2006 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# From Jim Meyering
# Provide <selinux/context.h>, if necessary.
AC_DEFUN([gl_HEADERS_SELINUX_CONTEXT_H],
[
AC_LIBSOURCES([se-context_.h])
# Check for <selinux/context.h>,
AC_CHECK_HEADERS([selinux/context.h],
[SELINUX_CONTEXT_H=],
[SELINUX_CONTEXT_H=selinux/context.h])
AC_SUBST([SELINUX_CONTEXT_H])
])

View File

@@ -0,0 +1,18 @@
# serial 1 -*- Autoconf -*-
# Copyright (C) 2006 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# From Jim Meyering
# Provide <selinux/selinux.h>, if necessary.
AC_DEFUN([gl_HEADERS_SELINUX_SELINUX_H],
[
AC_LIBSOURCES([se-selinux_.h])
# Check for <selinux/selinux.h>,
AC_CHECK_HEADERS([selinux/selinux.h],
[SELINUX_SELINUX_H=],
[SELINUX_SELINUX_H=selinux/selinux.h])
AC_SUBST([SELINUX_SELINUX_H])
])

32
gl/modules/selinux-at Normal file
View File

@@ -0,0 +1,32 @@
Description:
openat-style fd-relative functions for SE Linux
Files:
lib/selinux-at.c
lib/selinux-at.h
Depends-on:
selinux-h
configure.ac:
# FIXME: put this in an .m4 file?
# For runcon.
AC_CHECK_HEADERS([selinux/flask.h])
AC_LIBOBJ([selinux-at])
ac_save_LIBS="$LIBS"
AC_SEARCH_LIBS(setfilecon, selinux,
[test "$ac_cv_search_setfilecon" = "none required" ||
LIB_SELINUX=$ac_cv_search_setfilecon])
AC_SUBST(LIB_SELINUX)
LIBS="$ac_save_LIBS"
Makefile.am:
Include:
selinux-at.h
License:
LGPL
Maintainer:
Jim Meyering

54
gl/modules/selinux-h Normal file
View File

@@ -0,0 +1,54 @@
Description:
SELinux-related headers for systems that lack them.
Files:
lib/se-context_.h
lib/se-selinux_.h
m4/selinux-context-h.m4
m4/selinux-selinux-h.m4
Depends-on:
configure.ac:
gl_HEADERS_SELINUX_SELINUX_H
gl_HEADERS_SELINUX_CONTEXT_H
Makefile.am:
BUILT_SOURCES += $(SELINUX_SELINUX_H)
selinux/selinux.h: se-selinux_.h
mkdir -p selinux
cp $(srcdir)/se-selinux_.h $@-t
chmod a-x $@-t
mv $@-t $@
MOSTLYCLEANFILES += selinux/selinux.h selinux/selinux.h-t
BUILT_SOURCES += $(SELINUX_CONTEXT_H)
selinux/context.h: se-context_.h
mkdir -p selinux
cp $(srcdir)/se-context_.h $@-t
chmod a-x $@-t
mv $@-t $@
MOSTLYCLEANFILES += selinux/context.h selinux/context.h-t
MOSTLYCLEANDIRS += selinux
Include:
#include <selinux/selinux.h>
#include <selinux/context.h>
License:
LGPL
Maintainer:
Jim Meyering
# lib/selinux-at.c
#
# # For runcon.
# AC_CHECK_HEADERS([selinux/flask.h])
#
# ac_save_LIBS="$LIBS"
# AC_SEARCH_LIBS(setfilecon, selinux,
# [test "$ac_cv_search_setfilecon" = "none required" ||
# LIB_SELINUX=$ac_cv_search_setfilecon])
# AC_SUBST(LIB_SELINUX)
# LIBS="$ac_save_LIBS"

View File

@@ -219,6 +219,8 @@ mountlist.h
mpsort.c
mpsort.h
nanosleep.c
netinet_in.h
netinet_in_.h
obstack.c
obstack.h
offtostr.c
@@ -284,7 +286,14 @@ savedir.c
savedir.h
savewd.c
savewd.h
se-context.h
se-context_.h
se-selinux.h
se-selinux_.h
search.h
selinux
selinux-at.c
selinux-at.h
setenv.c
setenv.h
settime.c
@@ -389,6 +398,7 @@ xmemcoll.c
xmemcoll.h
xnanosleep.c
xnanosleep.h
xreadlink-with-size.c
xreadlink.c
xreadlink.h
xstrndup.c

10
lib/.gitignore vendored
View File

@@ -213,6 +213,8 @@ mountlist.h
mpsort.c
mpsort.h
nanosleep.c
netinet_in.h
netinet_in_.h
obstack.c
obstack.h
offtostr.c
@@ -277,6 +279,13 @@ savedir.c
savedir.h
savewd.c
savewd.h
se-context.h
se-context_.h
se-selinux.h
se-selinux_.h
selinux
selinux-at.c
selinux-at.h
setenv.c
setenv.h
settime.c
@@ -380,6 +389,7 @@ xmemcoll.c
xmemcoll.h
xnanosleep.c
xnanosleep.h
xreadlink-with-size.c
xreadlink.c
xreadlink.h
xstrndup.c

View File

@@ -1,3 +1,27 @@
2007-03-04 Jim Meyering <jim@meyering.net>
* vasnprintf.c (VASNPRINTF): Add missing semicolon.
2007-03-02 Jim Meyering <jim@meyering.net>
* vasnprintf.c (VASNPRINTF): Remove cast of alloca return value.
2007-03-01 Jim Meyering <jim@meyering.net>
Merge in changes from gnulib:
* vasnprintf.c: Add a comment explaining why coreutils has its own
version of this file.
Include <stdint.h>.
(SIZE_MAX): Remove definition (now, stdint.h covers that).
(EOVERFLOW): Remove definition (now done via the eoverflow module).
Update some #ifdef to #if.
Use HAVE_LONG_LONG_INT, not HAVE_LONG_LONG.
* printf-parse.c: Likewise.
2007-02-28 Jim Meyering <jim@meyering.net>
* tsearch.c: Remove unused file.
2007-02-23 Jim Meyering <jim@meyering.net>
* randperm.c (randperm_new): Comment: say that this function

View File

@@ -1,5 +1,8 @@
/* Formatted output to strings.
Copyright (C) 1999-2000, 2002-2004, 2006 Free Software Foundation, Inc.
This file is intended to provide exactly the same functionality
as the version in gnulib, but without the need for the xsize module.
Copyright (C) 1999-2000, 2002-2003, 2006-2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -27,21 +30,12 @@
/* Get size_t, NULL. */
#include <stddef.h>
/* Get intmax_t. */
#if HAVE_STDINT_H_WITH_UINTMAX
# include <stdint.h>
#endif
#if HAVE_INTTYPES_H_WITH_UINTMAX
# include <inttypes.h>
#endif
/* Get intmax_t, SIZE_MAX. */
#include <stdint.h>
/* malloc(), realloc(), free(). */
#include <stdlib.h>
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif
#if WIDE_CHAR_VERSION
# define PRINTF_PARSE wprintf_parse
# define CHAR_T wchar_t
@@ -329,7 +323,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
flags += 8;
cp++;
}
#ifdef HAVE_INTMAX_T
#if HAVE_INTMAX_T
else if (*cp == 'j')
{
if (sizeof (intmax_t) > sizeof (long))
@@ -385,11 +379,14 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
switch (c)
{
case 'd': case 'i':
#ifdef HAVE_LONG_LONG
#if HAVE_LONG_LONG_INT
/* If 'long long' exists and is larger than 'long': */
if (flags >= 16 || (flags & 4))
type = TYPE_LONGLONGINT;
else
#endif
/* If 'long long' exists and is the same as 'long', we parse
"lld" into TYPE_LONGINT. */
if (flags >= 8)
type = TYPE_LONGINT;
else if (flags & 2)
@@ -400,11 +397,14 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
type = TYPE_INT;
break;
case 'o': case 'u': case 'x': case 'X':
#ifdef HAVE_LONG_LONG
#if HAVE_LONG_LONG_INT
/* If 'long long' exists and is larger than 'long': */
if (flags >= 16 || (flags & 4))
type = TYPE_ULONGLONGINT;
else
#endif
/* If 'unsigned long long' exists and is the same as
'unsigned long', we parse "llu" into TYPE_ULONGINT. */
if (flags >= 8)
type = TYPE_ULONGINT;
else if (flags & 2)
@@ -416,7 +416,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
break;
case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
case 'a': case 'A':
#ifdef HAVE_LONG_DOUBLE
#if HAVE_LONG_DOUBLE
if (flags >= 16 || (flags & 4))
type = TYPE_LONGDOUBLE;
else
@@ -425,7 +425,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
break;
case 'c':
if (flags >= 8)
#ifdef HAVE_WINT_T
#if HAVE_WINT_T
type = TYPE_WIDE_CHAR;
#else
goto error;
@@ -433,7 +433,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
else
type = TYPE_CHAR;
break;
#ifdef HAVE_WINT_T
#if HAVE_WINT_T
case 'C':
type = TYPE_WIDE_CHAR;
c = 'c';
@@ -441,7 +441,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
#endif
case 's':
if (flags >= 8)
#ifdef HAVE_WCHAR_T
#if HAVE_WCHAR_T
type = TYPE_WIDE_STRING;
#else
goto error;
@@ -449,7 +449,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
else
type = TYPE_STRING;
break;
#ifdef HAVE_WCHAR_T
#if HAVE_WCHAR_T
case 'S':
type = TYPE_WIDE_STRING;
c = 's';
@@ -459,11 +459,14 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
type = TYPE_POINTER;
break;
case 'n':
#ifdef HAVE_LONG_LONG
#if HAVE_LONG_LONG_INT
/* If 'long long' exists and is larger than 'long': */
if (flags >= 16 || (flags & 4))
type = TYPE_COUNT_LONGLONGINT_POINTER;
else
#endif
/* If 'long long' exists and is the same as 'long', we parse
"lln" into TYPE_COUNT_LONGINT_POINTER. */
if (flags >= 8)
type = TYPE_COUNT_LONGINT_POINTER;
else if (flags & 2)

View File

@@ -1,698 +0,0 @@
/* Copyright (C) 1995, 1996, 1997, 2000, 2005, 2006 Free Software
Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>, 1997.
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, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA. */
/* Tree search for red/black trees.
The algorithm for adding nodes is taken from one of the many "Algorithms"
books by Robert Sedgewick, although the implementation differs.
The algorithm for deleting nodes can probably be found in a book named
"Introduction to Algorithms" by Cormen/Leiserson/Rivest. At least that's
the book that my professor took most algorithms from during the "Data
Structures" course...
Totally public domain. */
/* Red/black trees are binary trees in which the edges are colored either red
or black. They have the following properties:
1. The number of black edges on every path from the root to a leaf is
constant.
2. No two red edges are adjacent.
Therefore there is an upper bound on the length of every path, it's
O(log n) where n is the number of nodes in the tree. No path can be longer
than 1+2*P where P is the length of the shortest path in the tree.
Useful for the implementation:
3. If one of the children of a node is NULL, then the other one is red
(if it exists).
In the implementation, not the edges are colored, but the nodes. The color
interpreted as the color of the edge leading to this node. The color is
meaningless for the root node, but we color the root node black for
convenience. All added nodes are red initially.
Adding to a red/black tree is rather easy. The right place is searched
with a usual binary tree search. Additionally, whenever a node N is
reached that has two red successors, the successors are colored black and
the node itself colored red. This moves red edges up the tree where they
pose less of a problem once we get to really insert the new node. Changing
N's color to red may violate rule 2, however, so rotations may become
necessary to restore the invariants. Adding a new red leaf may violate
the same rule, so afterwards an additional check is run and the tree
possibly rotated.
Deleting is hairy. There are mainly two nodes involved: the node to be
deleted (n1), and another node that is to be unchained from the tree (n2).
If n1 has a successor (the node with a smallest key that is larger than
n1), then the successor becomes n2 and its contents are copied into n1,
otherwise n1 becomes n2.
Unchaining a node may violate rule 1: if n2 is black, one subtree is
missing one black edge afterwards. The algorithm must try to move this
error upwards towards the root, so that the subtree that does not have
enough black edges becomes the whole tree. Once that happens, the error
has disappeared. It may not be necessary to go all the way up, since it
is possible that rotations and recoloring can fix the error before that.
Although the deletion algorithm must walk upwards through the tree, we
do not store parent pointers in the nodes. Instead, delete allocates a
small array of parent pointers and fills it while descending the tree.
Since we know that the length of a path is O(log n), where n is the number
of nodes, this is likely to use less memory. */
/* Tree rotations look like this:
A C
/ \ / \
B C A G
/ \ / \ --> / \
D E F G B F
/ \
D E
In this case, A has been rotated left. This preserves the ordering of the
binary tree. */
#include <config.h>
#if __GNUC__
# define alloca __builtin_alloca
#else
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
# pragma alloca
# else
char *alloca ();
# endif
# endif
#endif
#include <stdlib.h>
#include <string.h>
#include <search.h>
#ifndef weak_alias
# define __tsearch tsearch
# define __tfind tfind
# define __tdelete tdelete
# define __twalk twalk
# define __tdestroy tdestroy
#endif
#ifndef _LIBC
# define weak_alias(f,g)
# define internal_function
#endif
typedef struct node_t
{
/* Callers expect this to be the first element in the structure - do not
move! */
const void *key;
struct node_t *left;
struct node_t *right;
unsigned int red:1;
} *node;
typedef const struct node_t *const_node;
#undef DEBUGGING
#ifdef DEBUGGING
/* Routines to check tree invariants. */
# include <assert.h>
# define CHECK_TREE(a) check_tree(a)
static void
check_tree_recurse (node p, int d_sofar, int d_total)
{
if (p == NULL)
{
assert (d_sofar == d_total);
return;
}
check_tree_recurse (p->left, d_sofar + (p->left && !p->left->red), d_total);
check_tree_recurse (p->right, d_sofar + (p->right && !p->right->red), d_total);
if (p->left)
assert (!(p->left->red && p->red));
if (p->right)
assert (!(p->right->red && p->red));
}
static void
check_tree (node root)
{
int cnt = 0;
node p;
if (root == NULL)
return;
root->red = 0;
for(p = root->left; p; p = p->left)
cnt += !p->red;
check_tree_recurse (root, 0, cnt);
}
#else
# define CHECK_TREE(a)
#endif
/* Possibly "split" a node with two red successors, and/or fix up two red
edges in a row. ROOTP is a pointer to the lowest node we visited, PARENTP
and GPARENTP pointers to its parent/grandparent. P_R and GP_R contain the
comparison values that determined which way was taken in the tree to reach
ROOTP. MODE is 1 if we need not do the split, but must check for two red
edges between GPARENTP and ROOTP. */
static void
maybe_split_for_insert (node *rootp, node *parentp, node *gparentp,
int p_r, int gp_r, int mode)
{
node root = *rootp;
node *rp, *lp;
rp = &(*rootp)->right;
lp = &(*rootp)->left;
/* See if we have to split this node (both successors red). */
if (mode == 1
|| ((*rp) != NULL && (*lp) != NULL && (*rp)->red && (*lp)->red))
{
/* This node becomes red, its successors black. */
root->red = 1;
if (*rp)
(*rp)->red = 0;
if (*lp)
(*lp)->red = 0;
/* If the parent of this node is also red, we have to do
rotations. */
if (parentp != NULL && (*parentp)->red)
{
node gp = *gparentp;
node p = *parentp;
/* There are two main cases:
1. The edge types (left or right) of the two red edges differ.
2. Both red edges are of the same type.
There exist two symmetries of each case, so there is a total of
4 cases. */
if ((p_r > 0) != (gp_r > 0))
{
/* Put the child at the top of the tree, with its parent
and grandparent as successors. */
p->red = 1;
gp->red = 1;
root->red = 0;
if (p_r < 0)
{
/* Child is left of parent. */
p->left = *rp;
*rp = p;
gp->right = *lp;
*lp = gp;
}
else
{
/* Child is right of parent. */
p->right = *lp;
*lp = p;
gp->left = *rp;
*rp = gp;
}
*gparentp = root;
}
else
{
*gparentp = *parentp;
/* Parent becomes the top of the tree, grandparent and
child are its successors. */
p->red = 0;
gp->red = 1;
if (p_r < 0)
{
/* Left edges. */
gp->left = p->right;
p->right = gp;
}
else
{
/* Right edges. */
gp->right = p->left;
p->left = gp;
}
}
}
}
}
/* Find or insert datum into search tree.
KEY is the key to be located, ROOTP is the address of tree root,
COMPAR the ordering function. */
void *
__tsearch (const void *key, void **vrootp, __compar_fn_t compar)
{
node q;
node *parentp = NULL, *gparentp = NULL;
node *rootp = (node *) vrootp;
node *nextp;
int r = 0, p_r = 0, gp_r = 0; /* No they might not, Mr Compiler. */
if (rootp == NULL)
return NULL;
/* This saves some additional tests below. */
if (*rootp != NULL)
(*rootp)->red = 0;
CHECK_TREE (*rootp);
nextp = rootp;
while (*nextp != NULL)
{
node root = *rootp;
r = (*compar) (key, root->key);
if (r == 0)
return root;
maybe_split_for_insert (rootp, parentp, gparentp, p_r, gp_r, 0);
/* If that did any rotations, parentp and gparentp are now garbage.
That doesn't matter, because the values they contain are never
used again in that case. */
nextp = r < 0 ? &root->left : &root->right;
if (*nextp == NULL)
break;
gparentp = parentp;
parentp = rootp;
rootp = nextp;
gp_r = p_r;
p_r = r;
}
q = (struct node_t *) malloc (sizeof (struct node_t));
if (q != NULL)
{
*nextp = q; /* link new node to old */
q->key = key; /* initialize new node */
q->red = 1;
q->left = q->right = NULL;
}
if (nextp != rootp)
/* There may be two red edges in a row now, which we must avoid by
rotating the tree. */
maybe_split_for_insert (nextp, rootp, parentp, r, p_r, 1);
return q;
}
#ifdef weak_alias
weak_alias (__tsearch, tsearch)
#endif
/* Find datum in search tree.
KEY is the key to be located, ROOTP is the address of tree root,
COMPAR the ordering function. */
void *
__tfind (key, vrootp, compar)
const void *key;
void *const *vrootp;
__compar_fn_t compar;
{
node *rootp = (node *) vrootp;
if (rootp == NULL)
return NULL;
CHECK_TREE (*rootp);
while (*rootp != NULL)
{
node root = *rootp;
int r;
r = (*compar) (key, root->key);
if (r == 0)
return root;
rootp = r < 0 ? &root->left : &root->right;
}
return NULL;
}
#ifdef weak_alias
weak_alias (__tfind, tfind)
#endif
/* Delete node with given key.
KEY is the key to be deleted, ROOTP is the address of the root of tree,
COMPAR the comparison function. */
void *
__tdelete (const void *key, void **vrootp, __compar_fn_t compar)
{
node p, q, r, retval;
int cmp;
node *rootp = (node *) vrootp;
node root, unchained;
/* Stack of nodes so we remember the parents without recursion. It's
_very_ unlikely that there are paths longer than 40 nodes. The tree
would need to have around 250.000 nodes. */
int stacksize = 40;
int sp = 0;
node **nodestack = (node **) alloca (sizeof (node *) * stacksize);
if (rootp == NULL)
return NULL;
p = *rootp;
if (p == NULL)
return NULL;
CHECK_TREE (p);
while ((cmp = (*compar) (key, (*rootp)->key)) != 0)
{
if (sp == stacksize)
{
node **newstack;
stacksize += 20;
newstack = (node **) alloca (sizeof (node *) * stacksize);
nodestack = memcpy (newstack, nodestack, sp * sizeof (node *));
}
nodestack[sp++] = rootp;
p = *rootp;
rootp = ((cmp < 0)
? &(*rootp)->left
: &(*rootp)->right);
if (*rootp == NULL)
return NULL;
}
/* This is bogus if the node to be deleted is the root... this routine
really should return an integer with 0 for success, -1 for failure
and errno = ESRCH or something. */
retval = p;
/* We don't unchain the node we want to delete. Instead, we overwrite
it with its successor and unchain the successor. If there is no
successor, we really unchain the node to be deleted. */
root = *rootp;
r = root->right;
q = root->left;
if (q == NULL || r == NULL)
unchained = root;
else
{
node *parent = rootp, *up = &root->right;
for (;;)
{
if (sp == stacksize)
{
node **newstack;
stacksize += 20;
newstack = (node **) alloca (sizeof (node *) * stacksize);
nodestack = memcpy (newstack, nodestack, sp * sizeof (node *));
}
nodestack[sp++] = parent;
parent = up;
if ((*up)->left == NULL)
break;
up = &(*up)->left;
}
unchained = *up;
}
/* We know that either the left or right successor of UNCHAINED is NULL.
R becomes the other one, it is chained into the parent of UNCHAINED. */
r = unchained->left;
if (r == NULL)
r = unchained->right;
if (sp == 0)
*rootp = r;
else
{
q = *nodestack[sp-1];
if (unchained == q->right)
q->right = r;
else
q->left = r;
}
if (unchained != root)
root->key = unchained->key;
if (!unchained->red)
{
/* Now we lost a black edge, which means that the number of black
edges on every path is no longer constant. We must balance the
tree. */
/* NODESTACK now contains all parents of R. R is likely to be NULL
in the first iteration. */
/* NULL nodes are considered black throughout - this is necessary for
correctness. */
while (sp > 0 && (r == NULL || !r->red))
{
node *pp = nodestack[sp - 1];
p = *pp;
/* Two symmetric cases. */
if (r == p->left)
{
/* Q is R's brother, P is R's parent. The subtree with root
R has one black edge less than the subtree with root Q. */
q = p->right;
if (q != NULL && q->red)
{
/* If Q is red, we know that P is black. We rotate P left
so that Q becomes the top node in the tree, with P below
it. P is colored red, Q is colored black.
This action does not change the black edge count for any
leaf in the tree, but we will be able to recognize one
of the following situations, which all require that Q
is black. */
q->red = 0;
p->red = 1;
/* Left rotate p. */
p->right = q->left;
q->left = p;
*pp = q;
/* Make sure pp is right if the case below tries to use
it. */
nodestack[sp++] = pp = &q->left;
q = p->right;
}
/* We know that Q can't be NULL here. We also know that Q is
black. */
if ((q->left == NULL || !q->left->red)
&& (q->right == NULL || !q->right->red))
{
/* Q has two black successors. We can simply color Q red.
The whole subtree with root P is now missing one black
edge. Note that this action can temporarily make the
tree invalid (if P is red). But we will exit the loop
in that case and set P black, which both makes the tree
valid and also makes the black edge count come out
right. If P is black, we are at least one step closer
to the root and we'll try again the next iteration. */
q->red = 1;
r = p;
}
else
{
/* Q is black, one of Q's successors is red. We can
repair the tree with one operation and will exit the
loop afterwards. */
if (q->right == NULL || !q->right->red)
{
/* The left one is red. We perform the same action as
in maybe_split_for_insert where two red edges are
adjacent but point in different directions:
Q's left successor (let's call it Q2) becomes the
top of the subtree we are looking at, its parent (Q)
and grandparent (P) become its successors. The former
successors of Q2 are placed below P and Q.
P becomes black, and Q2 gets the color that P had.
This changes the black edge count only for node R and
its successors. */
node q2 = q->left;
q2->red = p->red;
p->right = q2->left;
q->left = q2->right;
q2->right = q;
q2->left = p;
*pp = q2;
p->red = 0;
}
else
{
/* It's the right one. Rotate P left. P becomes black,
and Q gets the color that P had. Q's right successor
also becomes black. This changes the black edge
count only for node R and its successors. */
q->red = p->red;
p->red = 0;
q->right->red = 0;
/* left rotate p */
p->right = q->left;
q->left = p;
*pp = q;
}
/* We're done. */
sp = 1;
r = NULL;
}
}
else
{
/* Comments: see above. */
q = p->left;
if (q != NULL && q->red)
{
q->red = 0;
p->red = 1;
p->left = q->right;
q->right = p;
*pp = q;
nodestack[sp++] = pp = &q->right;
q = p->left;
}
if ((q->right == NULL || !q->right->red)
&& (q->left == NULL || !q->left->red))
{
q->red = 1;
r = p;
}
else
{
if (q->left == NULL || !q->left->red)
{
node q2 = q->right;
q2->red = p->red;
p->left = q2->right;
q->right = q2->left;
q2->left = q;
q2->right = p;
*pp = q2;
p->red = 0;
}
else
{
q->red = p->red;
p->red = 0;
q->left->red = 0;
p->left = q->right;
q->right = p;
*pp = q;
}
sp = 1;
r = NULL;
}
}
--sp;
}
if (r != NULL)
r->red = 0;
}
free (unchained);
return retval;
}
#ifdef weak_alias
weak_alias (__tdelete, tdelete)
#endif
/* Walk the nodes of a tree.
ROOT is the root of the tree to be walked, ACTION the function to be
called at each node. LEVEL is the level of ROOT in the whole tree. */
static void
internal_function
trecurse (const void *vroot, __action_fn_t action, int level)
{
const_node root = (const_node) vroot;
if (root->left == NULL && root->right == NULL)
(*action) (root, leaf, level);
else
{
(*action) (root, preorder, level);
if (root->left != NULL)
trecurse (root->left, action, level + 1);
(*action) (root, postorder, level);
if (root->right != NULL)
trecurse (root->right, action, level + 1);
(*action) (root, endorder, level);
}
}
/* Walk the nodes of a tree.
ROOT is the root of the tree to be walked, ACTION the function to be
called at each node. */
void
__twalk (const void *vroot, __action_fn_t action)
{
const_node root = (const_node) vroot;
CHECK_TREE (root);
if (root != NULL && action != NULL)
trecurse (root, action, 0);
}
#ifdef weak_alias
weak_alias (__twalk, twalk)
#endif
/* The standardized functions miss an important functionality: the
tree cannot be removed easily. We provide a function to do this. */
static void
internal_function
tdestroy_recurse (node root, void (*freefct)(void *))
{
if (root->left != NULL)
tdestroy_recurse (root->left, freefct);
if (root->right != NULL)
tdestroy_recurse (root->right, freefct);
(*freefct) ((void *) root->key);
/* Free the node itself. */
free (root);
}
void
__tdestroy (void *vroot, void (*freefct)(void *))
{
node root = (node) vroot;
CHECK_TREE (root);
if (root != NULL)
tdestroy_recurse (root, freefct);
}
#ifdef weak_alias
weak_alias (__tdestroy, tdestroy)
#endif

View File

@@ -1,5 +1,8 @@
/* vsprintf with automatic memory allocation.
Copyright (C) 1999, 2002-2006 Free Software Foundation, Inc.
This file is intended to provide exactly the same functionality
as the version in gnulib, but without the need for the xsize module.
Copyright (C) 1999, 2002-2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -23,7 +26,6 @@
#endif
#include <config.h>
#ifndef IN_LIBINTL
# include <alloca.h>
#endif
@@ -37,6 +39,7 @@
#include <stdio.h> /* snprintf(), sprintf() */
#include <stdlib.h> /* abort(), malloc(), realloc(), free() */
#include <stdint.h> /* SIZE_MAX */
#include <string.h> /* memcpy(), strlen() */
#include <errno.h> /* errno */
#include <limits.h> /* CHAR_BIT, INT_MAX */
@@ -47,17 +50,8 @@
# include "printf-parse.h"
#endif
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif
/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */
#ifndef EOVERFLOW
# define EOVERFLOW E2BIG
#endif
#ifdef HAVE_WCHAR_T
# ifdef HAVE_WCSLEN
#if HAVE_WCHAR_T
# if HAVE_WCSLEN
# define local_wcslen wcslen
# else
/* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
@@ -152,7 +146,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
#if HAVE_ALLOCA
if (buf_neededlength < 4000 / sizeof (CHAR_T))
{
buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T));
buf = alloca (buf_neededlength * sizeof (CHAR_T));
buf_malloced = NULL;
}
else
@@ -254,7 +248,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
case TYPE_COUNT_LONGINT_POINTER:
*a.arg[dp->arg_index].a.a_count_longint_pointer = length;
break;
#ifdef HAVE_LONG_LONG
#if HAVE_LONG_LONG_INT
case TYPE_COUNT_LONGLONGINT_POINTER:
*a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
break;
@@ -338,7 +332,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
{
case 'd': case 'i': case 'u':
# ifdef HAVE_LONG_LONG
# if HAVE_LONG_LONG_INT
if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
tmp_length =
(unsigned int) (sizeof (unsigned long long) * CHAR_BIT
@@ -369,7 +363,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
break;
case 'o':
# ifdef HAVE_LONG_LONG
# if HAVE_LONG_LONG_INT
if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
tmp_length =
(unsigned int) (sizeof (unsigned long long) * CHAR_BIT
@@ -397,7 +391,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
break;
case 'x': case 'X':
# ifdef HAVE_LONG_LONG
# if HAVE_LONG_LONG_INT
if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
tmp_length =
(unsigned int) (sizeof (unsigned long long) * CHAR_BIT
@@ -426,7 +420,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
break;
case 'f': case 'F':
# ifdef HAVE_LONG_DOUBLE
# if HAVE_LONG_DOUBLE
if (type == TYPE_LONGDOUBLE)
tmp_length =
(unsigned int) (LDBL_MAX_EXP
@@ -450,7 +444,6 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
break;
case 'e': case 'E': case 'g': case 'G':
case 'a': case 'A':
tmp_length =
12; /* sign, decimal point, exponent etc. */
tmp_length += precision;
@@ -458,8 +451,31 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
goto out_of_memory;
break;
case 'a': case 'A':
# if HAVE_LONG_DOUBLE
if (type == TYPE_LONGDOUBLE)
tmp_length =
(unsigned int) (LDBL_DIG
* 0.831 /* decimal -> hexadecimal */
)
+ 1; /* turn floor into ceil */
else
# endif
tmp_length =
(unsigned int) (DBL_DIG
* 0.831 /* decimal -> hexadecimal */
)
+ 1; /* turn floor into ceil */
if (tmp_length < precision)
tmp_length = precision;
/* Account for sign, decimal point etc. */
tmp_length += 12;
if (tmp_length < 12)
goto out_of_memory;
break;
case 'c':
# if defined HAVE_WINT_T && !WIDE_CHAR_VERSION
# if HAVE_WINT_T && !WIDE_CHAR_VERSION
if (type == TYPE_WIDE_CHAR)
tmp_length = MB_CUR_MAX;
else
@@ -468,7 +484,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
break;
case 's':
# ifdef HAVE_WCHAR_T
# if HAVE_WCHAR_T
if (type == TYPE_WIDE_STRING)
{
tmp_length =
@@ -551,7 +567,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
switch (type)
{
#ifdef HAVE_LONG_LONG
#if HAVE_LONG_LONG_INT
case TYPE_LONGLONGINT:
case TYPE_ULONGLONGINT:
*p++ = 'l';
@@ -559,15 +575,15 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
#endif
case TYPE_LONGINT:
case TYPE_ULONGINT:
#ifdef HAVE_WINT_T
#if HAVE_WINT_T
case TYPE_WIDE_CHAR:
#endif
#ifdef HAVE_WCHAR_T
#if HAVE_WCHAR_T
case TYPE_WIDE_STRING:
#endif
*p++ = 'l';
break;
#ifdef HAVE_LONG_DOUBLE
#if HAVE_LONG_DOUBLE
case TYPE_LONGDOUBLE:
*p++ = 'L';
break;
@@ -705,7 +721,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
SNPRINTF_BUF (arg);
}
break;
#ifdef HAVE_LONG_LONG
#if HAVE_LONG_LONG_INT
case TYPE_LONGLONGINT:
{
long long int arg = a.arg[dp->arg_index].a.a_longlongint;
@@ -725,7 +741,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
SNPRINTF_BUF (arg);
}
break;
#ifdef HAVE_LONG_DOUBLE
#if HAVE_LONG_DOUBLE
case TYPE_LONGDOUBLE:
{
long double arg = a.arg[dp->arg_index].a.a_longdouble;
@@ -739,7 +755,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
SNPRINTF_BUF (arg);
}
break;
#ifdef HAVE_WINT_T
#if HAVE_WINT_T
case TYPE_WIDE_CHAR:
{
wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
@@ -753,7 +769,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
SNPRINTF_BUF (arg);
}
break;
#ifdef HAVE_WCHAR_T
#if HAVE_WCHAR_T
case TYPE_WIDE_STRING:
{
const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;

View File

@@ -175,6 +175,8 @@ same.m4
save-cwd.m4
savedir.m4
savewd.m4
selinux-context-h.m4
selinux-selinux-h.m4
setenv.m4
settime.m4
sha1.m4

2
m4/.gitignore vendored
View File

@@ -168,6 +168,8 @@ same.m4
save-cwd.m4
savedir.m4
savewd.m4
selinux-context-h.m4
selinux-selinux-h.m4
setenv.m4
settime.m4
sha1.m4

View File

@@ -18,14 +18,15 @@
# 02110-1301, USA.
dist_man_MANS = \
base64.1 basename.1 cat.1 chgrp.1 chmod.1 chown.1 cksum.1 comm.1 \
base64.1 basename.1 cat.1 chcon.1 chgrp.1 chmod.1 chown.1 cksum.1 comm.1 \
cp.1 csplit.1 cut.1 date.1 dd.1 df.1 dir.1 dircolors.1 dirname.1 du.1 \
echo.1 env.1 expand.1 expr.1 factor.1 false.1 fmt.1 fold.1 groups.1 \
head.1 hostname.1 id.1 install.1 join.1 kill.1 \
link.1 ln.1 logname.1 \
ls.1 md5sum.1 mkdir.1 mkfifo.1 mknod.1 mv.1 nl.1 nohup.1 od.1 \
paste.1 pathchk.1 pr.1 printenv.1 printf.1 ptx.1 pwd.1 readlink.1 \
rm.1 rmdir.1 seq.1 sha1sum.1 sha224sum.1 sha256sum.1 sha384sum.1 sha512sum.1 \
rm.1 rmdir.1 runcon.1 seq.1 \
sha1sum.1 sha224sum.1 sha256sum.1 sha384sum.1 sha512sum.1 \
shred.1 shuf.1 sleep.1 sort.1 split.1 stat.1 \
su.1 sum.1 sync.1 tac.1 tail.1 tee.1 test.1 touch.1 tr.1 true.1 tsort.1 \
tty.1 unexpand.1 uniq.1 unlink.1 vdir.1 wc.1 \
@@ -45,6 +46,7 @@ common_dep = $(top_srcdir)/configure.ac
base64.1: $(common_dep) $(srcdir)/base64.x ../src/base64.c
basename.1: $(common_dep) $(srcdir)/basename.x ../src/basename.c
cat.1: $(common_dep) $(srcdir)/cat.x ../src/cat.c
chcon.1: $(common_dep) $(srcdir)/chcon.x ../src/chcon.c
chgrp.1: $(common_dep) $(srcdir)/chgrp.x ../src/chgrp.c
chmod.1: $(common_dep) $(srcdir)/chmod.x ../src/chmod.c
chown.1: $(common_dep) $(srcdir)/chown.x ../src/chown.c
@@ -104,6 +106,7 @@ pwd.1: $(common_dep) $(srcdir)/pwd.x ../src/pwd.c
readlink.1: $(common_dep) $(srcdir)/readlink.x ../src/readlink.c
rm.1: $(common_dep) $(srcdir)/rm.x ../src/rm.c
rmdir.1: $(common_dep) $(srcdir)/rmdir.x ../src/rmdir.c
runcon.1: $(common_dep) $(srcdir)/runcon.x ../src/runcon.c
seq.1: $(common_dep) $(srcdir)/seq.x ../src/seq.c
sha1sum.1: $(common_dep) $(srcdir)/sha1sum.x ../src/md5sum.c
sha224sum.1: $(common_dep) $(srcdir)/sha224sum.x ../src/md5sum.c

4
man/chcon.x Normal file
View File

@@ -0,0 +1,4 @@
[NAME]
chcon \- change file security context
[DESCRIPTION]
.\" Add any additional description here

14
man/runcon.x Normal file
View File

@@ -0,0 +1,14 @@
[NAME]
runcon \- run command with specified security context
[DESCRIPTION]
Run COMMAND with completely-specified CONTEXT, or with current or
transitioned security context modified by one or more of LEVEL,
ROLE, TYPE, and USER.
.PP
If none of \fI-c\fR, \fI-t\fR, \fI-u\fR, \fI-r\fR, or \fI-l\fR, is specified,
the first argument is used as the complete context. Any additional
arguments after \fICOMMAND\fR are interpreted as arguments to the
command.
.PP
Note that only carefully-chosen contexts are likely to successfully
run.

View File

@@ -1,3 +1,11 @@
2007-02-02 Jim Meyering <jim@meyering.net>
* POTFILES.in: Add src/runcon.c.
2007-01-13 Jim Meyering <jim@meyering.net>
* POTFILES.in: Add src/chcon.c.
2006-10-19 Jim Meyering <jim@meyering.net>
* POTFILES.in: Also include lib/regcomp.c, since it too uses gettext.

View File

@@ -1,5 +1,5 @@
# List of files which contain translatable strings.
# Copyright (C) 1996-2006 Free Software Foundation, Inc.
# Copyright (C) 1996-2007 Free Software Foundation, Inc.
# These are nominally temporary...
lib/acl.c
@@ -33,6 +33,7 @@ lib/xstrtol.h
src/base64.c
src/basename.c
src/cat.c
src/chcon.c
src/chgrp.c
src/chmod.c
src/chown-core.c
@@ -90,6 +91,7 @@ src/readlink.c
src/remove.c
src/rm.c
src/rmdir.c
src/runcon.c
src/seq.c
src/setuidgid.c
src/shred.c

View File

@@ -19,14 +19,15 @@
EXTRA_PROGRAMS = chroot df hostid nice pinky stty su uname uptime users who
bin_SCRIPTS = groups
bin_PROGRAMS = [ chgrp chown chmod cp dd dircolors du \
bin_PROGRAMS = [ chcon chgrp chown chmod cp dd dircolors du \
ginstall link ln dir vdir ls mkdir \
mkfifo mknod mv nohup readlink rm rmdir shred stat sync touch unlink \
cat cksum comm csplit cut expand fmt fold head join md5sum \
nl od paste pr ptx sha1sum sha224sum sha256sum sha384sum sha512sum \
shuf sort split sum tac tail tr tsort unexpand uniq wc \
basename date dirname echo env expr factor false \
hostname id kill logname pathchk printenv printf pwd seq sleep tee \
hostname id kill logname pathchk printenv printf pwd \
runcon seq sleep tee \
test true tty whoami yes \
base64 \
$(OPTIONAL_BIN_PROGS) $(DF_PROG)
@@ -60,9 +61,14 @@ AM_CPPFLAGS = -I$(top_srcdir)/lib
LDADD = ../lib/libcoreutils.a $(LIBINTL) ../lib/libcoreutils.a
# for eaccess in lib/euidaccess.c.
cp_LDADD = $(LDADD) $(LIB_EACCESS)
ginstall_LDADD = $(LDADD) $(LIB_EACCESS)
mv_LDADD = $(LDADD) $(LIB_EACCESS)
chcon_LDADD = $(LDADD) $(LIB_SELINUX)
cp_LDADD = $(LDADD) $(LIB_EACCESS) $(LIB_SELINUX)
ginstall_LDADD = $(LDADD) $(LIB_EACCESS) $(LIB_SELINUX)
mkdir_LDADD = $(LDADD) $(LIB_SELINUX)
mkfifo_LDADD = $(LDADD) $(LIB_SELINUX)
mknod_LDADD = $(LDADD) $(LIB_SELINUX)
mv_LDADD = $(LDADD) $(LIB_EACCESS) $(LIB_SELINUX)
runcon_LDADD = $(LDADD) $(LIB_SELINUX)
pathchk_LDADD = $(LDADD) $(LIB_EACCESS)
rm_LDADD = $(LDADD) $(LIB_EACCESS)
test_LDADD = $(LDADD) $(LIB_EACCESS)
@@ -71,12 +77,13 @@ __LDADD = $(LDADD) $(LIB_EACCESS)
# for clock_gettime and fdatasync
dd_LDADD = $(LDADD) $(LIB_GETHRXTIME) $(LIB_FDATASYNC)
dir_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
ls_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
dir_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_SELINUX)
id_LDADD = $(LDADD) $(LIB_SELINUX)
ls_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_SELINUX)
pr_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
shred_LDADD = $(LDADD) $(LIB_GETHRXTIME) $(LIB_FDATASYNC)
shuf_LDADD = $(LDADD) $(LIB_GETHRXTIME)
vdir_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
vdir_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_SELINUX)
## If necessary, add -lm to resolve use of pow in lib/strtod.c.
sort_LDADD = $(LDADD) $(POW_LIB) $(LIB_GETHRXTIME)
@@ -111,6 +118,8 @@ cp_LDADD += $(LIB_ACL)
mv_LDADD += $(LIB_ACL)
ginstall_LDADD += $(LIB_ACL)
stat_LDADD = $(LDADD) $(LIB_SELINUX)
$(PROGRAMS): ../lib/libcoreutils.a
SUFFIXES = .sh

View File

@@ -31,7 +31,24 @@ index 4728bdd..7477da5 100644
if (top->unremovable)
hash_free (top->unremovable);
obstack_blank (&ds->Active_dir, -(int) sizeof (struct AD_ent));
@@ -1481,6 +1483,7 @@ rm_1 (Dirstack_state *ds, char const *fi
@@ -815,6 +817,7 @@ prompt (int fd_cwd, Dirstack_state const *ds, char const *filename,
if (write_protected || x->interactive == RMI_ALWAYS)
{
+ char const *quoted_name = quote (full_filename (filename));
if (write_protected <= 0
&& cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) != 0)
{
@@ -832,8 +835,6 @@ prompt (int fd_cwd, Dirstack_state const *ds, char const *filename,
write_protected = EISDIR;
}
- char const *quoted_name = quote (full_filename (filename));
-
if (0 < write_protected)
{
error (0, write_protected, _("cannot remove %s"), quoted_name);
@@ -1487,6 +1488,7 @@ rm_1 (Dirstack_state *ds, char const *filename,
return RM_ERROR;
}
@@ -39,7 +56,7 @@ index 4728bdd..7477da5 100644
struct stat st;
cache_stat_init (&st);
cycle_check_init (&ds->cycle_check_state);
@@ -1503,6 +1506,7 @@ rm_1 (Dirstack_state *ds, char const *fi
@@ -1509,6 +1511,7 @@ rm_1 (Dirstack_state *ds, char const *filename,
AD_push_initial (ds);
AD_INIT_OTHER_MEMBERS ();
@@ -47,7 +64,7 @@ index 4728bdd..7477da5 100644
enum RM_status status = remove_entry (AT_FDCWD, ds, filename, &st, x, NULL);
if (status == RM_NONEMPTY_DIR)
{
@@ -1519,6 +1523,8 @@ rm_1 (Dirstack_state *ds, char const *fi
@@ -1525,6 +1528,8 @@ rm_1 (Dirstack_state *ds, char const *filename,
ds_clear (ds);
return status;

590
src/chcon.c Normal file
View File

@@ -0,0 +1,590 @@
/* chcon -- change security context of files
Copyright (C) 2005-2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <getopt.h>
#include "system.h"
#include "dev-ino.h"
#include "error.h"
#include "openat.h"
#include "quote.h"
#include "quotearg.h"
#include "root-dev-ino.h"
#include "selinux-at.h"
#include "xfts.h"
/* The official name of this program (e.g., no `g' prefix). */
#define PROGRAM_NAME "chcon"
#define AUTHORS "Russell Coker", "Jim Meyering"
enum Change_status
{
CH_NOT_APPLIED,
CH_SUCCEEDED,
CH_FAILED,
CH_NO_CHANGE_REQUESTED
};
enum Verbosity
{
/* Print a message for each file that is processed. */
V_high,
/* Print a message for each file whose attributes we change. */
V_changes_only,
/* Do not be verbose. This is the default. */
V_off
};
/* The name the program was run with. */
char *program_name;
/* If nonzero, and the systems has support for it, change the context
of symbolic links rather than any files they point to. */
static bool affect_symlink_referent;
/* If true, change the modes of directories recursively. */
static bool recurse;
/* Level of verbosity. */
static bool verbose;
/* Pointer to the device and inode numbers of `/', when --recursive.
Otherwise NULL. */
static struct dev_ino *root_dev_ino;
/* The name of the context file is being given. */
static char const *specified_context;
/* Specific components of the context */
static char const *specified_user;
static char const *specified_role;
static char const *specified_range;
static char const *specified_type;
/* For long options that have no equivalent short option, use a
non-character as a pseudo short option, starting with CHAR_MAX + 1. */
enum
{
DEREFERENCE_OPTION = CHAR_MAX + 1,
NO_PRESERVE_ROOT,
PRESERVE_ROOT,
REFERENCE_FILE_OPTION
};
static struct option const long_options[] =
{
{"recursive", no_argument, NULL, 'R'},
{"dereference", no_argument, NULL, DEREFERENCE_OPTION},
{"no-dereference", no_argument, NULL, 'h'},
{"no-preserve-root", no_argument, NULL, NO_PRESERVE_ROOT},
{"preserve-root", no_argument, NULL, PRESERVE_ROOT},
{"reference", required_argument, NULL, REFERENCE_FILE_OPTION},
{"user", required_argument, NULL, 'u'},
{"role", required_argument, NULL, 'r'},
{"type", required_argument, NULL, 't'},
{"range", required_argument, NULL, 'l'},
{"verbose", no_argument, NULL, 'v'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
};
/* Given a security context, CONTEXT, derive a context_t (*RET),
setting any portions selected via the global variables, specified_user,
specified_role, etc. */
static int
compute_context_from_mask (security_context_t context, context_t *ret)
{
bool ok = true;
context_t new_context = context_new (context);
if (!new_context)
{
error (0, errno, _("failed to create security context: %s"),
quotearg_colon (context));
return 1;
}
#define SET_COMPONENT(C, comp) \
do \
{ \
if (specified_ ## comp \
&& context_ ## comp ## _set ((C), specified_ ## comp)) \
{ \
error (0, errno, \
_("failed to set %s security context component to %s"), \
#comp, quote (specified_ ## comp)); \
ok = false; \
} \
} \
while (0)
SET_COMPONENT (new_context, user);
SET_COMPONENT (new_context, range);
SET_COMPONENT (new_context, role);
SET_COMPONENT (new_context, type);
if (!ok)
{
int saved_errno = errno;
context_free (new_context);
errno = saved_errno;
return 1;
}
*ret = new_context;
return 0;
}
/* Change the context of FILE, using specified components.
If it is a directory and -R is given, recurse.
Return 0 if successful, 1 if errors occurred. */
static int
change_file_context (int fd, char const *file)
{
security_context_t file_context = NULL;
context_t context;
security_context_t context_string;
int errors = 0;
if (specified_context == NULL)
{
int status = (affect_symlink_referent
? getfileconat (fd, file, &file_context)
: lgetfileconat (fd, file, &file_context));
if (status < 0 && errno != ENODATA)
{
error (0, errno, _("failed to get security context of %s"),
quote (file));
return 1;
}
/* If the file doesn't have a context, and we're not setting all of
the context components, there isn't really an obvious default.
Thus, we just give up. */
if (file_context == NULL)
{
error (0, 0, _("can't apply partial context to unlabeled file %s"),
quote (file));
return 1;
}
if (compute_context_from_mask (file_context, &context))
return 1;
}
else
{
/* FIXME: this should be done exactly once, in main. */
context = context_new (specified_context);
if (!context)
abort ();
}
context_string = context_str (context);
if (file_context == NULL || ! STREQ (context_string, file_context))
{
int fail = (affect_symlink_referent
? setfileconat (fd, file, context_string)
: lsetfileconat (fd, file, context_string));
if (fail)
{
errors = 1;
error (0, errno, _("failed to change context of %s to %s"),
quote_n (0, file), quote_n (1, context_string));
}
}
context_free (context);
freecon (file_context);
return errors;
}
/* Change the context of FILE.
Return true if successful. This function is called
once for every file system object that fts encounters. */
static bool
process_file (FTS *fts, FTSENT *ent)
{
char const *file_full_name = ent->fts_path;
char const *file = ent->fts_accpath;
const struct stat *file_stats = ent->fts_statp;
bool ok = true;
switch (ent->fts_info)
{
case FTS_D:
if (recurse)
{
if (ROOT_DEV_INO_CHECK (root_dev_ino, ent->fts_statp))
{
/* This happens e.g., with "chcon -R --preserve-root ... /"
and with "chcon -RH --preserve-root ... symlink-to-root". */
ROOT_DEV_INO_WARN (file_full_name);
/* Tell fts not to traverse into this hierarchy. */
fts_set (fts, ent, FTS_SKIP);
/* Ensure that we do not process "/" on the second visit. */
ent = fts_read (fts);
return false;
}
return true;
}
break;
case FTS_DP:
if (! recurse)
return true;
break;
case FTS_NS:
/* For a top-level file or directory, this FTS_NS (stat failed)
indicator is determined at the time of the initial fts_open call.
With programs like chmod, chown, and chgrp, that modify
permissions, it is possible that the file in question is
accessible when control reaches this point. So, if this is
the first time we've seen the FTS_NS for this file, tell
fts_read to stat it "again". */
if (ent->fts_level == 0 && ent->fts_number == 0)
{
ent->fts_number = 1;
fts_set (fts, ent, FTS_AGAIN);
return true;
}
error (0, ent->fts_errno, _("cannot access %s"), quote (file_full_name));
ok = false;
break;
case FTS_ERR:
error (0, ent->fts_errno, _("%s"), quote (file_full_name));
ok = false;
break;
case FTS_DNR:
error (0, ent->fts_errno, _("cannot read directory %s"),
quote (file_full_name));
ok = false;
break;
default:
break;
}
if (ent->fts_info == FTS_DP
&& ok && ROOT_DEV_INO_CHECK (root_dev_ino, file_stats))
{
ROOT_DEV_INO_WARN (file_full_name);
ok = false;
}
if (ok)
{
if (verbose)
printf (_("changing security context of %s"),
quote (file_full_name));
if (change_file_context (fts->fts_cwd_fd, file) != 0)
ok = false;
}
if ( ! recurse)
fts_set (fts, ent, FTS_SKIP);
return ok;
}
/* Recursively operate on the specified FILES (the last entry
of which is NULL). BIT_FLAGS controls how fts works.
Return true if successful. */
static bool
process_files (char **files, int bit_flags)
{
bool ok = true;
FTS *fts = xfts_open (files, bit_flags, NULL);
while (1)
{
FTSENT *ent;
ent = fts_read (fts);
if (ent == NULL)
{
if (errno != 0)
{
/* FIXME: try to give a better message */
error (0, errno, _("fts_read failed"));
ok = false;
}
break;
}
ok &= process_file (fts, ent);
}
/* Ignore failure, since the only way it can do so is in failing to
return to the original directory, and since we're about to exit,
that doesn't matter. */
fts_close (fts);
return ok;
}
void
usage (int status)
{
if (status != EXIT_SUCCESS)
fprintf (stderr, _("Try `%s --help' for more information.\n"),
program_name);
else
{
printf (_("\
Usage: %s [OPTION]... CONTEXT FILE...\n\
or: %s [OPTION]... [-u USER] [-r ROLE] [-l RANGE] [-t TYPE] FILE...\n\
or: %s [OPTION]... --reference=RFILE FILE...\n\
"),
program_name, program_name, program_name);
fputs (_("\
Change the security context of each FILE to CONTEXT.\n\
With --reference, change the security context of each FILE to that of RFILE.\n\
\n\
-c, --changes like verbose but report only when a change is made\n\
-h, --no-dereference affect symbolic links instead of any referenced file\n\
(available only on systems with lchown system call)\n\
"), stdout);
fputs (_("\
--reference=RFILE use RFILE's security context rather than specifying\n\
a CONTEXT value\n\
-R, --recursive operate on files and directories recursively\n\
-v, --verbose output a diagnostic for every file processed\n\
"), stdout);
fputs (_("\
-u, --user=USER set user USER in the target security context\n\
-r, --role=ROLE set role ROLE in the target security context\n\
-t, --type=TYPE set type TYPE in the target security context\n\
-l, --range=RANGE set range RANGE in the target security context\n\
\n\
"), stdout);
fputs (_("\
The following options modify how a hierarchy is traversed when the -R\n\
option is also specified. If more than one is specified, only the final\n\
one takes effect.\n\
\n\
-H if a command line argument is a symbolic link\n\
to a directory, traverse it\n\
-L traverse every symbolic link to a directory\n\
encountered\n\
-P do not traverse any symbolic links (default)\n\
\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
}
exit (status);
}
int
main (int argc, char **argv)
{
security_context_t ref_context = NULL;
/* Bit flags that control how fts works. */
int bit_flags = FTS_PHYSICAL;
/* 1 if --dereference, 0 if --no-dereference, -1 if neither has been
specified. */
int dereference = -1;
bool ok;
bool preserve_root = false;
bool component_specified = false;
char *reference_file = NULL;
int optc;
initialize_main (&argc, &argv);
program_name = argv[0];
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
atexit (close_stdout);
while ((optc = getopt_long (argc, argv, "HLPRchvu:r:t:l:", long_options, NULL))
!= -1)
{
switch (optc)
{
case 'H': /* Traverse command-line symlinks-to-directories. */
bit_flags = FTS_COMFOLLOW | FTS_PHYSICAL;
break;
case 'L': /* Traverse all symlinks-to-directories. */
bit_flags = FTS_LOGICAL;
break;
case 'P': /* Traverse no symlinks-to-directories. */
bit_flags = FTS_PHYSICAL;
break;
case 'h': /* --no-dereference: affect symlinks */
dereference = 0;
break;
case DEREFERENCE_OPTION: /* --dereference: affect the referent
of each symlink */
dereference = 1;
break;
case NO_PRESERVE_ROOT:
preserve_root = false;
break;
case PRESERVE_ROOT:
preserve_root = true;
break;
case REFERENCE_FILE_OPTION:
reference_file = optarg;
break;
case 'R':
recurse = true;
break;
case 'f':
/* ignore */
break;
case 'v':
verbose = true;
break;
case 'u':
specified_user = optarg;
component_specified = true;
break;
case 'r':
specified_role = optarg;
component_specified = true;
break;
case 't':
specified_type = optarg;
component_specified = true;
break;
case 'l':
specified_range = optarg;
component_specified = true;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
usage (EXIT_FAILURE);
}
}
if (recurse)
{
if (bit_flags == FTS_PHYSICAL)
{
if (dereference == 1)
error (EXIT_FAILURE, 0,
_("-R --dereference requires either -H or -L"));
affect_symlink_referent = false;
}
else
{
if (dereference == 0)
error (EXIT_FAILURE, 0, _("-R -h requires -P"));
affect_symlink_referent = true;
}
}
else
{
bit_flags = FTS_PHYSICAL;
affect_symlink_referent = (dereference != 0);
}
if (argc - optind < (reference_file || component_specified ? 1 : 2))
{
if (argc <= optind)
error (0, 0, _("missing operand"));
else
error (0, 0, _("missing operand after %s"), quote (argv[argc - 1]));
usage (EXIT_FAILURE);
}
if (reference_file)
{
if (getfilecon (reference_file, &ref_context) < 0)
error (EXIT_FAILURE, errno, _("failed to get security context of %s"),
quote (reference_file));
specified_context = ref_context;
}
else if (component_specified)
{
/* FIXME: it's already null, so this is a no-op. */
specified_context = NULL;
}
else
{
context_t context;
specified_context = argv[optind++];
context = context_new (specified_context);
if (!context)
error (EXIT_FAILURE, 0, _("invalid context: %s"),
quotearg_colon (specified_context));
context_free (context);
}
if (reference_file && component_specified)
{
error (0, 0, _("conflicting security context specifiers given"));
usage (1);
}
if (recurse & preserve_root)
{
static struct dev_ino dev_ino_buf;
root_dev_ino = get_root_dev_ino (&dev_ino_buf);
if (root_dev_ino == NULL)
error (EXIT_FAILURE, errno, _("failed to get attributes of %s"),
quote ("/"));
}
else
{
root_dev_ino = NULL;
}
ok = process_files (argv + optind, bit_flags | FTS_NOSTAT);
exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
}

View File

@@ -21,6 +21,7 @@
#include <stdio.h>
#include <assert.h>
#include <sys/types.h>
#include <selinux/selinux.h>
#if HAVE_HURD_H
# include <hurd.h>
@@ -38,6 +39,7 @@
#include "euidaccess.h"
#include "error.h"
#include "fcntl--.h"
#include "filemode.h"
#include "filenamecat.h"
#include "full-write.h"
#include "getpagesize.h"
@@ -301,6 +303,42 @@ copy_reg (char const *src_name, char const *dst_name,
{
dest_desc = open (dst_name, O_WRONLY | O_TRUNC | O_BINARY);
/* When using cp --preserve=context to copy to an existing destination,
use the default context rather than that of the source. Why?
1) the src context may prohibit writing, and
2) because it's more consistent to use the same context
that is used when the destination file doesn't already exist. */
if (x->preserve_security_context && 0 <= dest_desc)
{
security_context_t con;
if (getfscreatecon (&con) < 0)
{
error (0, errno, _("failed to get file system create context"));
if (x->require_preserve_context)
{
return_val = false;
goto close_src_desc;
}
}
if (con)
{
if (fsetfilecon (dest_desc, con) < 0)
{
error (0, errno,
_("failed to set the security context of %s to %s"),
quote_n (0, dst_name), quote_n (1, con));
if (x->require_preserve_context)
{
return_val = false;
freecon (con);
goto close_src_desc;
}
}
freecon(con);
}
}
if (dest_desc < 0 && x->unlink_dest_after_failed_open)
{
if (unlink (dst_name) != 0)
@@ -797,10 +835,14 @@ overwrite_prompt (char const *dst_name, struct stat const *dst_sb)
{
if (euidaccess (dst_name, W_OK) != 0)
{
char perms[12]; /* "-rwxrwxrwx " ls-style modes. */
strmode (dst_sb->st_mode, perms);
perms[10] = '\0';
fprintf (stderr,
_("%s: overwrite %s, overriding mode %04lo? "),
_("%s: try to overwrite %s, overriding mode %04lo (%s)? "),
program_name, quote (dst_name),
(unsigned long int) (dst_sb->st_mode & CHMOD_MODE_BITS));
(unsigned long int) (dst_sb->st_mode & CHMOD_MODE_BITS),
&perms[1]);
}
else
{
@@ -990,6 +1032,15 @@ emit_verbose (char const *src, char const *dst, char const *backup_dst_name)
putchar ('\n');
}
/* A wrapper around "setfscreatecon (NULL)" that exits upon failure. */
static void
restore_default_fscreatecon_or_die (void)
{
if (setfscreatecon (NULL) != 0)
error (EXIT_FAILURE, errno,
_("failed to restore the default file creation context"));
}
/* Copy the file SRC_NAME to the file DST_NAME. The files may be of
any type. NEW_DST should be true if the file DST_NAME cannot
exist because its parent directory was just created; NEW_DST should
@@ -1338,7 +1389,7 @@ copy_internal (char const *src_name, char const *dst_name,
if (x->move_mode && src_sb.st_nlink == 1)
{
earlier_file = src_to_dest_lookup (src_sb.st_ino, src_sb.st_dev);
earlier_file = src_to_dest_lookup (src_sb.st_ino, src_sb.st_dev);
}
else if ((x->preserve_links
&& (1 < src_sb.st_nlink
@@ -1528,6 +1579,38 @@ copy_internal (char const *src_name, char const *dst_name,
delayed_ok = true;
if (x->preserve_security_context)
{
security_context_t con;
if (0 <= lgetfilecon (src_name, &con))
{
if (setfscreatecon (con) < 0)
{
error (0, errno,
_("failed to set default file creation context to %s"),
quote (con));
if (x->require_preserve_context)
{
freecon (con);
return false;
}
}
freecon (con);
}
else
{
if (errno != ENOTSUP && errno != ENODATA)
{
error (0, errno,
_("failed to get security context of %s"),
quote (src_name));
if (x->require_preserve_context)
return false;
}
}
}
/* In certain modes (cp's --symbolic-link), and for certain file types
(symlinks and hard links) it doesn't make sense to preserve metadata,
or it's possible to preserve only some of it.
@@ -1604,19 +1687,20 @@ copy_internal (char const *src_name, char const *dst_name,
emit_verbose (src_name, dst_name, NULL);
}
/* Are we crossing a file system boundary? */
/* Decide whether to copy the contents of the directory. */
if (x->one_file_system && device != 0 && device != src_sb.st_dev)
return true;
/* Copy the contents of the directory. */
if (! copy_dir (src_name, dst_name, new_dst, &src_sb, dir, x,
copy_into_self))
{
/* Don't just return here -- otherwise, the failure to read a
single file in a source directory would cause the containing
destination directory not to have owner/perms set properly. */
delayed_ok = false;
/* Here, we are crossing a file system boundary and cp's -x option
is in effect: so don't copy the contents of this directory. */
}
else
{
/* Copy the contents of the directory. Don't just return if
this fails -- otherwise, the failure to read a single file
in a source directory would cause the containing destination
directory not to have owner/perms set properly. */
delayed_ok = copy_dir (src_name, dst_name, new_dst, &src_sb, dir, x,
copy_into_self);
}
}
else if (x->symbolic_link)
@@ -1720,7 +1804,7 @@ copy_internal (char const *src_name, char const *dst_name,
}
else if (S_ISLNK (src_mode))
{
char *src_link_val = xreadlink (src_name, src_sb.st_size);
char *src_link_val = xreadlink_with_size (src_name, src_sb.st_size);
if (src_link_val == NULL)
{
error (0, errno, _("cannot read symbolic link %s"), quote (src_name));
@@ -1740,7 +1824,8 @@ copy_internal (char const *src_name, char const *dst_name,
FIXME: This behavior isn't documented, and seems wrong
in some cases, e.g., if the destination symlink has the
wrong ownership, permissions, or time stamps. */
char *dest_link_val = xreadlink (dst_name, dst_sb.st_size);
char *dest_link_val =
xreadlink_with_size (dst_name, dst_sb.st_size);
if (STREQ (dest_link_val, src_link_val))
same_link = true;
free (dest_link_val);
@@ -1755,6 +1840,9 @@ copy_internal (char const *src_name, char const *dst_name,
}
}
if (x->preserve_security_context)
restore_default_fscreatecon_or_die ();
/* There's no need to preserve timestamps or permissions. */
preserve_metadata = false;
@@ -1888,6 +1976,9 @@ copy_internal (char const *src_name, char const *dst_name,
un_backup:
if (x->preserve_security_context)
restore_default_fscreatecon_or_die ();
/* We have failed to create the destination file.
If we've just added a dev/ino entry via the remember_copied
call above (i.e., unless we've just failed to create a hard link),

View File

@@ -1,5 +1,5 @@
/* core functions for copying files and directories
Copyright (C) 89, 90, 91, 1995-2005 Free Software Foundation.
Copyright (C) 89, 90, 91, 1995-2007 Free Software Foundation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -142,10 +142,25 @@ struct cp_options
/* If true and any of the above (for preserve) file attributes cannot
be applied to a destination file, treat it as a failure and return
nonzero immediately. E.g. cp -p requires this be nonzero, mv requires
it be zero. */
nonzero immediately. E.g. for cp -p this must be true, for mv it
must be false. */
bool require_preserve;
/* If true, attempt to preserve the SELinux security context, too.
Set this only if the kernel is SELinux enabled. */
bool preserve_security_context;
/* Useful only when preserve_security_context is true.
If true, a failed attempt to preserve a file's security context
propagates failure "out" to the caller. If false, a failure to
preserve a file's security context does not change the invoking
application's exit status. Give diagnostics for failed syscalls
regardless of this setting. For example, with "cp --preserve=context"
this flag is "true", while with "cp -a", it is false. That means
"cp -a" attempts to preserve any security context, but does not
fail if it is unable to do so. */
bool require_preserve_context;
/* If true, copy directories recursively and copy special files
as themselves rather than copying their contents. */
bool recursive;

View File

@@ -21,6 +21,7 @@
#include <stdio.h>
#include <sys/types.h>
#include <getopt.h>
#include <selinux/selinux.h>
#include "system.h"
#include "argmatch.h"
@@ -85,6 +86,9 @@ enum
/* The invocation name of this program. */
char *program_name;
/* True if the kernel is SELinux enabled. */
static bool selinux_enabled;
/* If true, the command "cp x/e_file e_dir" uses "e_dir/x/e_file"
as its destination instead of the usual "e_dir/e_file." */
static bool parents_option = false;
@@ -191,7 +195,7 @@ Mandatory arguments to long options are mandatory for short options too.\n\
-p same as --preserve=mode,ownership,timestamps\n\
--preserve[=ATTR_LIST] preserve the specified attributes (default:\n\
mode,ownership,timestamps), if possible\n\
additional attributes: links, all\n\
additional attributes: context, links, all\n\
"), stdout);
fputs (_("\
--no-preserve=ATTR_LIST don't preserve the specified attributes\n\
@@ -749,6 +753,8 @@ cp_option_init (struct cp_options *x)
x->preserve_links = false;
x->preserve_mode = false;
x->preserve_timestamps = false;
x->preserve_security_context = false;
x->require_preserve_context = false;
x->require_preserve = false;
x->recursive = false;
@@ -777,18 +783,19 @@ decode_preserve_arg (char const *arg, struct cp_options *x, bool on_off)
PRESERVE_TIMESTAMPS,
PRESERVE_OWNERSHIP,
PRESERVE_LINK,
PRESERVE_CONTEXT,
PRESERVE_ALL
};
static enum File_attribute const preserve_vals[] =
{
PRESERVE_MODE, PRESERVE_TIMESTAMPS,
PRESERVE_OWNERSHIP, PRESERVE_LINK, PRESERVE_ALL
PRESERVE_OWNERSHIP, PRESERVE_LINK, PRESERVE_CONTEXT, PRESERVE_ALL
};
/* Valid arguments to the `--preserve' option. */
static char const* const preserve_args[] =
{
"mode", "timestamps",
"ownership", "links", "all", NULL
"ownership", "links", "context", "all", NULL
};
ARGMATCH_VERIFY (preserve_args, preserve_vals);
@@ -824,11 +831,18 @@ decode_preserve_arg (char const *arg, struct cp_options *x, bool on_off)
x->preserve_links = on_off;
break;
case PRESERVE_CONTEXT:
x->preserve_security_context = on_off;
x->require_preserve_context = on_off;
break;
case PRESERVE_ALL:
x->preserve_mode = on_off;
x->preserve_timestamps = on_off;
x->preserve_ownership = on_off;
x->preserve_links = on_off;
if (selinux_enabled)
x->preserve_security_context = on_off;
break;
default:
@@ -862,6 +876,7 @@ main (int argc, char **argv)
atexit (close_stdout);
selinux_enabled = (0 < is_selinux_enabled ());
cp_option_init (&x);
/* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
@@ -1048,9 +1063,6 @@ main (int argc, char **argv)
x.dereference = DEREF_ALWAYS;
}
/* The key difference between -d (--no-dereference) and not is the version
of `stat' to call. */
if (x.recursive)
x.copy_as_regular = copy_contents;
@@ -1059,6 +1071,14 @@ main (int argc, char **argv)
if (x.unlink_dest_after_failed_open & (x.hard_link | x.symbolic_link))
x.unlink_dest_before_opening = true;
if (x.preserve_security_context)
{
if (!selinux_enabled)
error (EXIT_FAILURE, 0,
_("cannot preserve security context "
"without an SELinux-enabled kernel"));
}
/* Allocate space for remembering copied and created files. */
hash_init ();

View File

@@ -796,10 +796,7 @@ main (int argc, char **argv)
inode_format = false;
show_all_fs = false;
show_listed_fs = false;
human_output_opts = human_options (getenv ("DF_BLOCK_SIZE"), false,
&output_block_size);
human_output_opts = -1;
print_type = false;
file_systems_processed = false;
posix_format = false;
@@ -876,6 +873,18 @@ main (int argc, char **argv)
}
}
if (human_output_opts == -1)
{
if (posix_format)
{
human_output_opts = 0;
output_block_size = (getenv ("POSIXLY_CORRECT") ? 512 : 1024);
}
else
human_output_opts = human_options (getenv ("DF_BLOCK_SIZE"), false,
&output_block_size);
}
/* Fail if the same file system type was both selected and excluded. */
{
bool match = false;

View File

@@ -1,43 +0,0 @@
/* Define the magic numbers as given by statfs(2).
Please send additions to bug-coreutils@gnu.org and meskes@debian.org.
This file is generated automatically from ./stat.c. */
#if defined __linux__
# define S_MAGIC_AFFS 0xADFF
# define S_MAGIC_DEVPTS 0x1CD1
# define S_MAGIC_EXT 0x137D
# define S_MAGIC_EXT2_OLD 0xEF51
# define S_MAGIC_EXT2 0xEF53
# define S_MAGIC_JFS 0x3153464a
# define S_MAGIC_XFS 0x58465342
# define S_MAGIC_HPFS 0xF995E849
# define S_MAGIC_ISOFS 0x9660
# define S_MAGIC_ISOFS_WIN 0x4000
# define S_MAGIC_ISOFS_R_WIN 0x4004
# define S_MAGIC_MINIX 0x137F
# define S_MAGIC_MINIX_30 0x138F
# define S_MAGIC_MINIX_V2 0x2468
# define S_MAGIC_MINIX_V2_30 0x2478
# define S_MAGIC_MSDOS 0x4d44
# define S_MAGIC_FAT 0x4006
# define S_MAGIC_NCP 0x564c
# define S_MAGIC_NFS 0x6969
# define S_MAGIC_PROC 0x9fa0
# define S_MAGIC_SMB 0x517B
# define S_MAGIC_XENIX 0x012FF7B4
# define S_MAGIC_SYSV4 0x012FF7B5
# define S_MAGIC_SYSV2 0x012FF7B6
# define S_MAGIC_COH 0x012FF7B7
# define S_MAGIC_UFS 0x00011954
# define S_MAGIC_XIAFS 0x012FD16D
# define S_MAGIC_NTFS 0x5346544e
# define S_MAGIC_TMPFS 0x1021994
# define S_MAGIC_REISERFS 0x52654973
# define S_MAGIC_CRAMFS 0x28cd3d45
# define S_MAGIC_ROMFS 0x7275
# define S_MAGIC_RAMFS 0x858458f6
# define S_MAGIC_SQUASHFS 0x73717368
# define S_MAGIC_SYSFS 0x62656572
#elif defined __GNU__
# include <hurd/hurd_types.h>
#endif

View File

@@ -1,5 +1,5 @@
/* id -- print real and effective UIDs and GIDs
Copyright (C) 1989-2005 Free Software Foundation, Inc.
Copyright (C) 1989-2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
#include <pwd.h>
#include <grp.h>
#include <getopt.h>
#include <selinux/selinux.h>
#include "system.h"
#include "error.h"
@@ -37,6 +38,9 @@
int getugroups ();
/* If nonzero, output only the SELinux context. -Z */
static int just_context = 0;
static void print_user (uid_t uid);
static void print_group (gid_t gid);
static void print_group_list (const char *username);
@@ -55,8 +59,13 @@ static gid_t rgid, egid;
/* True unless errors have been encountered. */
static bool ok = true;
/* The SELinux context. Start with a known invalid value so print_full_info
knows when `context' has not been set to a meaningful value. */
static security_context_t context = NULL;
static struct option const longopts[] =
{
{"context", no_argument, NULL, 'Z'},
{"group", no_argument, NULL, 'g'},
{"groups", no_argument, NULL, 'G'},
{"name", no_argument, NULL, 'n'},
@@ -80,6 +89,7 @@ usage (int status)
Print information for USERNAME, or the current user.\n\
\n\
-a ignore, for compatibility with other versions\n\
-Z, --context print only the security context of the current user\n\
-g, --group print only the effective group ID\n\
-G, --groups print all group IDs\n\
-n, --name print a name instead of a number, for -ugG\n\
@@ -101,6 +111,7 @@ int
main (int argc, char **argv)
{
int optc;
int selinux_enabled = (is_selinux_enabled () > 0);
/* If true, output the list of all group IDs. -G */
bool just_group_list = false;
@@ -119,13 +130,22 @@ main (int argc, char **argv)
atexit (close_stdout);
while ((optc = getopt_long (argc, argv, "agnruG", longopts, NULL)) != -1)
while ((optc = getopt_long (argc, argv, "agnruGZ", longopts, NULL)) != -1)
{
switch (optc)
{
case 'a':
/* Ignore -a, for compatibility with SVR4. */
break;
case 'Z':
/* politely decline if we're not on a selinux-enabled kernel. */
if (!selinux_enabled)
error (EXIT_FAILURE, 0,
_("--context (-Z) works only on an SELinux-enabled kernel"));
just_context = 1;
break;
case 'g':
just_group = true;
break;
@@ -148,19 +168,38 @@ main (int argc, char **argv)
}
}
if (just_user + just_group + just_group_list > 1)
error (EXIT_FAILURE, 0, _("cannot print only user and only group"));
if (just_user + just_group + just_group_list == 0 && (use_real | use_name))
error (EXIT_FAILURE, 0,
_("cannot print only names or real IDs in default format"));
if (argc - optind > 1)
if (1 < argc - optind)
{
error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
usage (EXIT_FAILURE);
}
if (argc - optind == 1 && just_context)
error (EXIT_FAILURE, 0,
_("cannot print security context when user specified"));
if (just_context && !selinux_enabled)
error (EXIT_FAILURE, 0, _("\
cannot display context when selinux not enabled or when displaying the id\n\
of a different user"));
/* If we are on a selinux-enabled kernel, get our context.
Otherwise, leave the context variable alone - it has
been initialized known invalid value; if we see this invalid
value later, we will know we are on a non-selinux kernel. */
if (selinux_enabled)
{
if (getcon (&context) && just_context)
error (EXIT_FAILURE, 0, _("can't get process context"));
}
if (just_user + just_group + just_group_list + just_context > 1)
error (EXIT_FAILURE, 0, _("cannot print \"only\" of more than one choice"));
if (just_user + just_group + just_group_list == 0 && (use_real | use_name))
error (EXIT_FAILURE, 0,
_("cannot print only names or real IDs in default format"));
if (argc - optind == 1)
{
struct passwd *pwd = getpwnam (argv[optind]);
@@ -183,6 +222,8 @@ main (int argc, char **argv)
print_group (use_real ? rgid : egid);
else if (just_group_list)
print_group_list (argv[optind]);
else if (just_context)
fputs (context, stdout);
else
print_full_info (argv[optind]);
putchar ('\n');
@@ -385,4 +426,6 @@ print_full_info (const char *username)
free (groups);
}
#endif /* HAVE_GETGROUPS */
if (context != NULL)
printf (" context=%s", context);
}

View File

@@ -24,6 +24,7 @@
#include <signal.h>
#include <pwd.h>
#include <grp.h>
#include <selinux/selinux.h>
#include "system.h"
#include "backupfile.h"
@@ -35,6 +36,7 @@
#include "mkdir-p.h"
#include "modechange.h"
#include "quote.h"
#include "quotearg.h"
#include "savewd.h"
#include "stat-time.h"
#include "utimens.h"
@@ -49,6 +51,9 @@
# include <sys/wait.h>
#endif
static int selinux_enabled = 0;
static bool use_default_selinux_context = true;
#if ! HAVE_ENDGRENT
# define endgrent() ((void) 0)
#endif
@@ -121,15 +126,28 @@ static bool strip_files;
/* If true, install a directory instead of a regular file. */
static bool dir_arg;
/* For long options that have no equivalent short option, use a
non-character as a pseudo short option, starting with CHAR_MAX + 1. */
enum
{
PRESERVE_CONTEXT_OPTION = CHAR_MAX + 1
};
static struct option const long_options[] =
{
{"backup", optional_argument, NULL, 'b'},
{GETOPT_SELINUX_CONTEXT_OPTION_DECL},
{"directory", no_argument, NULL, 'd'},
{"group", required_argument, NULL, 'g'},
{"mode", required_argument, NULL, 'm'},
{"no-target-directory", no_argument, NULL, 'T'},
{"owner", required_argument, NULL, 'o'},
{"preserve-timestamps", no_argument, NULL, 'p'},
{"preserve-context", no_argument, NULL, PRESERVE_CONTEXT_OPTION},
/* Continue silent support for --preserve_context until Jan 2008. FIXME-obs
After that, FIXME-obs: warn in, say, late 2008, and disable altogether
a year or two later. */
{"preserve_context", no_argument, NULL, PRESERVE_CONTEXT_OPTION},
{"strip", no_argument, NULL, 's'},
{"suffix", required_argument, NULL, 'S'},
{"target-directory", required_argument, NULL, 't'},
@@ -156,6 +174,7 @@ cp_option_init (struct cp_options *x)
x->preserve_mode = false;
x->preserve_timestamps = false;
x->require_preserve = false;
x->require_preserve_context = false;
x->recursive = false;
x->sparse_mode = SPARSE_AUTO;
x->symbolic_link = false;
@@ -169,11 +188,47 @@ cp_option_init (struct cp_options *x)
x->stdin_tty = false;
x->update = false;
x->preserve_security_context = false;
x->verbose = false;
x->dest_info = NULL;
x->src_info = NULL;
}
/* Modify file context to match the specified policy.
If an error occurs the file will remain with the default directory
context. */
static void
setdefaultfilecon (char const *file)
{
struct stat st;
security_context_t scontext = NULL;
if (selinux_enabled != 1)
{
/* Indicate no context found. */
return;
}
if (lstat (file, &st) != 0)
return;
/* If there's an error determining the context, or it has none,
return to allow default context */
if ((matchpathcon (file, st.st_mode, &scontext) != 0) ||
(strcmp (scontext, "<<none>>") == 0))
{
if (scontext != NULL)
freecon (scontext);
return;
}
if (lsetfilecon (file, scontext) < 0 && errno != ENOTSUP)
error (0, errno,
_("warning: %s: failed to change context to %s"),
quotearg_colon (file), scontext);
freecon (scontext);
return;
}
/* FILE is the last operand of this command. Return true if FILE is a
directory. But report an error there is a problem accessing FILE,
or if FILE does not exist but would have to refer to an existing
@@ -222,6 +277,9 @@ main (int argc, char **argv)
bool no_target_directory = false;
int n_files;
char **file;
security_context_t scontext = NULL;
/* set iff kernel has extra selinux system calls */
selinux_enabled = (0 < is_selinux_enabled ());
initialize_main (&argc, &argv);
program_name = argv[0];
@@ -243,7 +301,7 @@ main (int argc, char **argv)
we'll actually use backup_suffix_string. */
backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
while ((optc = getopt_long (argc, argv, "bcsDdg:m:o:pt:TvS:", long_options,
while ((optc = getopt_long (argc, argv, "bcsDdg:m:o:pt:TvS:Z:", long_options,
NULL)) != -1)
{
switch (optc)
@@ -305,6 +363,27 @@ main (int argc, char **argv)
case 'T':
no_target_directory = true;
break;
case PRESERVE_CONTEXT_OPTION:
if ( ! selinux_enabled)
{
error (0, 0, _("Warning: ignoring --preserve-context; "
"this kernel is not SELinux-enabled."));
break;
}
x.preserve_security_context = true;
use_default_selinux_context = false;
break;
case 'Z':
if ( ! selinux_enabled)
{
error (0, 0, _("Warning: ignoring --context (-Z); "
"this kernel is not SELinux-enabled."));
break;
}
scontext = optarg;
use_default_selinux_context = false;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
@@ -320,6 +399,11 @@ main (int argc, char **argv)
error (EXIT_FAILURE, 0,
_("target directory not allowed when installing a directory"));
if (x.preserve_security_context && scontext != NULL)
error (EXIT_FAILURE, 0,
_("cannot force target context to %s and preserve it"),
quote (scontext));
if (backup_suffix_string)
simple_backup_suffix = xstrdup (backup_suffix_string);
@@ -328,6 +412,11 @@ main (int argc, char **argv)
version_control_string)
: no_backups);
if (scontext && setfscreatecon (scontext) < 0)
error (EXIT_FAILURE, errno,
_("failed to set default file creation context to %s"),
quote (scontext));
n_files = argc - optind;
file = argv + optind;
@@ -503,6 +592,7 @@ copy_file (const char *from, const char *to, const struct cp_options *x)
static bool
change_attributes (char const *name)
{
bool ok = false;
/* chown must precede chmod because on some systems,
chown clears the set[ug]id bits for non-superusers,
resulting in incorrect permissions.
@@ -521,9 +611,12 @@ change_attributes (char const *name)
else if (chmod (name, mode) != 0)
error (0, errno, _("cannot change permissions of %s"), quote (name));
else
return true;
ok = true;
return false;
if (use_default_selinux_context)
setdefaultfilecon (name);
return ok;
}
/* Set the timestamps of file TO to match those of file FROM.
@@ -566,11 +659,10 @@ strip (char const *name)
error (EXIT_FAILURE, errno, _("cannot run strip"));
break;
default: /* Parent. */
/* Parent process. */
while (pid != wait (&status)) /* Wait for kid to finish. */
/* Do nothing. */ ;
if (status)
error (EXIT_FAILURE, 0, _("strip failed"));
if (waitpid (pid, &status, 0) < 0)
error (EXIT_FAILURE, errno, _("waiting for strip"));
else if (! WIFEXITED (status) || WEXITSTATUS (status))
error (EXIT_FAILURE, 0, _("strip process terminated abnormally"));
break;
}
}
@@ -688,6 +780,11 @@ Mandatory arguments to long options are mandatory for short options too.\n\
-T, --no-target-directory treat DEST as a normal file\n\
-v, --verbose print the name of each directory as it is created\n\
"), stdout);
fputs (_("\
--preserve-context preserve SELinux security context\n\
-Z, --context=CONTEXT set SELinux security context of files and directories\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
fputs (_("\

View File

@@ -61,6 +61,7 @@
#include <pwd.h>
#include <getopt.h>
#include <signal.h>
#include <selinux/selinux.h>
/* Use SA_NOCLDSTOP as a proxy for whether the sigaction machinery is
present. */
@@ -167,24 +168,20 @@ struct fileinfo
zero. */
mode_t linkmode;
/* SELinux security context. */
security_context_t scontext;
bool stat_ok;
/* For symbolic link and color printing, true if linked-to file
exists, otherwise false. */
bool linkok;
#if USE_ACL
/* For long listings, true if the file has an access control list. */
/* For long listings, true if the file has an access control list,
or an SELinux security context. */
bool have_acl;
#endif
};
#if USE_ACL
# define FILE_HAS_ACL(F) ((F)->have_acl)
#else
# define FILE_HAS_ACL(F) 0
#endif
#define LEN_STR_PAIR(s) sizeof (s) - 1, s
/* Null is a valid character in a color indicator (think about Epson
@@ -320,14 +317,12 @@ static struct pending *pending_dirs;
static time_t current_time = TYPE_MINIMUM (time_t);
static int current_time_ns = -1;
static bool print_scontext;
/* Whether any of the files has an ACL. This affects the width of the
mode column. */
#if USE_ACL
static bool any_has_acl;
#else
enum { any_has_acl = false };
#endif
/* The number of columns to use for columns containing inode numbers,
block sizes, link counts, owners, groups, authors, major device
@@ -336,6 +331,7 @@ enum { any_has_acl = false };
static int inode_number_width;
static int block_size_width;
static int nlink_width;
static int scontext_width;
static int owner_width;
static int group_width;
static int author_width;
@@ -787,6 +783,7 @@ static struct option const long_options[] =
{"time-style", required_argument, NULL, TIME_STYLE_OPTION},
{"color", optional_argument, NULL, COLOR_OPTION},
{"block-size", required_argument, NULL, BLOCK_SIZE_OPTION},
{"context", no_argument, 0, 'Z'},
{"author", no_argument, NULL, AUTHOR_OPTION},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
@@ -1246,6 +1243,7 @@ main (int argc, char **argv)
format_needs_stat = sort_type == sort_time || sort_type == sort_size
|| format == long_format
|| print_scontext
|| print_block_size;
format_needs_type = (! format_needs_stat
&& (recursive
@@ -1439,6 +1437,7 @@ decode_switches (int argc, char **argv)
ignore_mode = IGNORE_DEFAULT;
ignore_patterns = NULL;
hide_patterns = NULL;
print_scontext = false;
/* FIXME: put this in a function. */
{
@@ -1514,7 +1513,7 @@ decode_switches (int argc, char **argv)
}
while ((c = getopt_long (argc, argv,
"abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UX1",
"abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UXZ1",
long_options, NULL)) != -1)
{
switch (c)
@@ -1813,6 +1812,10 @@ decode_switches (int argc, char **argv)
file_output_block_size = output_block_size = 1;
break;
case 'Z':
print_scontext = true;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
@@ -2516,18 +2519,22 @@ clear_files (void)
struct fileinfo *f = sorted_file[i];
free (f->name);
free (f->linkname);
if (f->scontext)
{
freecon (f->scontext);
f->scontext = NULL;
}
}
cwd_n_used = 0;
#if USE_ACL
any_has_acl = false;
#endif
inode_number_width = 0;
block_size_width = 0;
nlink_width = 0;
owner_width = 0;
group_width = 0;
author_width = 0;
scontext_width = 0;
major_device_number_width = 0;
minor_device_number_width = 0;
file_size_width = 0;
@@ -2589,9 +2596,11 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
)))))
{
/* FIXME-c99: move this decl "down", once ls.c stabilizes. */
bool file_has_security_context = false;
/* Absolute name of this file. */
char *absolute_name;
bool do_deref;
int err;
if (name[0] == '/' || dirname[0] == 0)
@@ -2606,6 +2615,7 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
{
case DEREF_ALWAYS:
err = stat (absolute_name, &f->stat);
do_deref = true;
break;
case DEREF_COMMAND_LINE_ARGUMENTS:
@@ -2614,6 +2624,7 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
{
bool need_lstat;
err = stat (absolute_name, &f->stat);
do_deref = true;
if (dereference == DEREF_COMMAND_LINE_ARGUMENTS)
break;
@@ -2632,9 +2643,26 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
default: /* DEREF_NEVER */
err = lstat (absolute_name, &f->stat);
do_deref = false;
break;
}
if (err == 0 && print_scontext)
{
int attr_len = (do_deref
? getfilecon (absolute_name, &f->scontext)
: lgetfilecon (absolute_name, &f->scontext));
err = (attr_len < 0);
file_has_security_context = (err == 0);
/* When requesting security context information, don't make
ls fail just because the file (even a command line argument)
isn't on the right type of file system. I.e., a getfilecon
failure isn't in the same class as a stat failure. */
if (err && (errno == ENOTSUP || errno == ENODATA))
err = 0;
}
if (err != 0)
{
/* Failure to stat a command line argument leads to
@@ -2653,16 +2681,14 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
f->stat_ok = true;
#if USE_ACL
if (format == long_format)
{
int n = file_has_acl (absolute_name, &f->stat);
f->have_acl = (0 < n);
f->have_acl = (0 < n || file_has_security_context);
any_has_acl |= f->have_acl;
if (n < 0)
error (0, errno, "%s", quotearg_colon (absolute_name));
}
#endif
if (S_ISLNK (f->stat.st_mode)
&& (format == long_format || check_symlink_color))
@@ -2738,6 +2764,13 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
author_width = len;
}
if (print_scontext)
{
int len = f->scontext ? strlen (f->scontext) : 0;
if (scontext_width < len)
scontext_width = len;
}
{
char buf[INT_BUFSIZE_BOUND (uintmax_t)];
int len = strlen (umaxtostr (f->stat.st_nlink, buf));
@@ -2798,7 +2831,7 @@ is_directory (const struct fileinfo *f)
static void
get_link_name (char const *filename, struct fileinfo *f, bool command_line_arg)
{
f->linkname = xreadlink (filename, f->stat.st_size);
f->linkname = xreadlink_with_size (filename, f->stat.st_size);
if (f->linkname == NULL)
file_failure (command_line_arg, _("cannot read symbolic link %s"),
filename);
@@ -3387,7 +3420,7 @@ print_long_format (const struct fileinfo *f)
struct tm *when_local;
/* Compute the mode string, except remove the trailing space if no
files in this directory have ACLs. */
file in this directory has an ACL or SELinux security context. */
if (f->stat_ok)
filemodestring (&f->stat, modebuf);
else
@@ -3398,7 +3431,7 @@ print_long_format (const struct fileinfo *f)
}
if (! any_has_acl)
modebuf[10] = '\0';
else if (FILE_HAS_ACL (f))
else if (f->have_acl)
modebuf[10] = '+';
switch (time_type)
@@ -3463,7 +3496,7 @@ print_long_format (const struct fileinfo *f)
DIRED_INDENT ();
if (print_owner | print_group | print_author)
if (print_owner | print_group | print_author | print_scontext)
{
DIRED_FPUTS (buf, stdout, p - buf);
@@ -3476,6 +3509,10 @@ print_long_format (const struct fileinfo *f)
if (print_author)
format_user (f->stat.st_author, author_width, f->stat_ok);
if (print_scontext)
format_user_or_group ((f->scontext ? f->scontext : "?"),
0, scontext_width);
p = buf;
}
@@ -3812,6 +3849,10 @@ print_file_name_and_frills (const struct fileinfo *f)
human_readable (ST_NBLOCKS (f->stat), buf, human_output_opts,
ST_NBLOCKSIZE, output_block_size));
if (print_scontext)
printf ("%*s ", format == with_commas ? 0 : scontext_width,
(f->scontext ? f->scontext : "?"));
print_name_with_quoting (f->name, FILE_OR_LINK_MODE (f), f->linkok,
f->stat_ok, f->filetype, NULL);
@@ -3975,6 +4016,9 @@ length_of_file_name_and_frills (const struct fileinfo *f)
output_block_size))
: block_size_width);
if (print_scontext)
len += 1 + (format == with_commas ? strlen (f->scontext) : scontext_width);
quote_name (NULL, f->name, filename_quoting_options, &name_width);
len += name_width;
@@ -4403,6 +4447,7 @@ Mandatory arguments to long options are mandatory for short options too.\n\
-w, --width=COLS assume screen width instead of current value\n\
-x list entries by lines instead of by columns\n\
-X sort alphabetically by entry extension\n\
-Z, --context print any SELinux security context of each file\n\
-1 list one file per line\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);

View File

@@ -1,5 +1,5 @@
/* mkdir -- make directories
Copyright (C) 90, 1995-2002, 2004, 2005, 2006 Free Software Foundation, Inc.
Copyright (C) 90, 1995-2002, 2004-2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <getopt.h>
#include <sys/types.h>
#include <selinux/selinux.h>
#include "system.h"
#include "error.h"
@@ -40,6 +41,7 @@ char *program_name;
static struct option const longopts[] =
{
{GETOPT_SELINUX_CONTEXT_OPTION_DECL},
{"mode", required_argument, NULL, 'm'},
{"parents", no_argument, NULL, 'p'},
{"verbose", no_argument, NULL, 'v'},
@@ -68,6 +70,8 @@ Mandatory arguments to long options are mandatory for short options too.\n\
-m, --mode=MODE set file mode (as in chmod), not a=rwx - umask\n\
-p, --parents no error if existing, make parent directories as needed\n\
-v, --verbose print a message for each created directory\n\
-Z, --context=CTX set the SELinux security context of each created\n\
directory to CTX\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
@@ -140,7 +144,9 @@ main (int argc, char **argv)
{
const char *specified_mode = NULL;
int optc;
security_context_t scontext = NULL;
struct mkdir_options options;
options.make_ancestor_function = NULL;
options.mode = S_IRWXUGO;
options.mode_bits = 0;
@@ -154,7 +160,7 @@ main (int argc, char **argv)
atexit (close_stdout);
while ((optc = getopt_long (argc, argv, "pm:v", longopts, NULL)) != -1)
while ((optc = getopt_long (argc, argv, "pm:vZ:", longopts, NULL)) != -1)
{
switch (optc)
{
@@ -167,6 +173,9 @@ main (int argc, char **argv)
case 'v': /* --verbose */
options.created_directory_format = _("created directory %s");
break;
case 'Z':
scontext = optarg;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
@@ -180,6 +189,11 @@ main (int argc, char **argv)
usage (EXIT_FAILURE);
}
if (scontext && setfscreatecon (scontext) < 0)
error (EXIT_FAILURE, errno,
_("failed to set default file creation context to %s"),
quote (optarg));
if (options.make_ancestor_function || specified_mode)
{
mode_t umask_value = umask (0);

View File

@@ -1,5 +1,5 @@
/* mkfifo -- make fifo's (named pipes)
Copyright (C) 90, 91, 1995-2006 Free Software Foundation, Inc.
Copyright (C) 90, 91, 1995-2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <getopt.h>
#include <sys/types.h>
#include <selinux/selinux.h>
#include "system.h"
#include "error.h"
@@ -37,6 +38,7 @@ char *program_name;
static struct option const longopts[] =
{
{GETOPT_SELINUX_CONTEXT_OPTION_DECL},
{"mode", required_argument, NULL, 'm'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
@@ -55,6 +57,9 @@ usage (int status)
fputs (_("\
Create named pipes (FIFOs) with the given NAMEs.\n\
\n\
"), stdout);
fputs (_("\
-Z, --context=CTX set the SELinux security context of each NAME to CTX\n\
"), stdout);
fputs (_("\
Mandatory arguments to long options are mandatory for short options too.\n\
@@ -76,6 +81,7 @@ main (int argc, char **argv)
char const *specified_mode = NULL;
int exit_status = EXIT_SUCCESS;
int optc;
security_context_t scontext = NULL;
initialize_main (&argc, &argv);
program_name = argv[0];
@@ -85,13 +91,16 @@ main (int argc, char **argv)
atexit (close_stdout);
while ((optc = getopt_long (argc, argv, "m:", longopts, NULL)) != -1)
while ((optc = getopt_long (argc, argv, "m:Z:", longopts, NULL)) != -1)
{
switch (optc)
{
case 'm':
specified_mode = optarg;
break;
case 'Z':
scontext = optarg;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
@@ -105,6 +114,11 @@ main (int argc, char **argv)
usage (EXIT_FAILURE);
}
if (scontext && setfscreatecon (scontext) < 0)
error (EXIT_FAILURE, errno,
_("failed to set default file creation context to %s"),
quote (optarg));
newmode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (specified_mode)
{

View File

@@ -1,5 +1,5 @@
/* mknod -- make special files
Copyright (C) 90, 91, 1995-2006 Free Software Foundation, Inc.
Copyright (C) 90, 91, 1995-2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <getopt.h>
#include <sys/types.h>
#include <selinux/selinux.h>
#include "system.h"
#include "error.h"
@@ -38,6 +39,7 @@ char *program_name;
static struct option const longopts[] =
{
{GETOPT_SELINUX_CONTEXT_OPTION_DECL},
{"mode", required_argument, NULL, 'm'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
@@ -57,6 +59,9 @@ usage (int status)
fputs (_("\
Create the special file NAME of the given TYPE.\n\
\n\
"), stdout);
fputs(_("\
-Z, --context=CTX set the SELinux security context of NAME to CTX\n\
"), stdout);
fputs (_("\
Mandatory arguments to long options are mandatory for short options too.\n\
@@ -92,6 +97,7 @@ main (int argc, char **argv)
int optc;
int expected_operands;
mode_t node_type;
security_context_t scontext = NULL;
initialize_main (&argc, &argv);
program_name = argv[0];
@@ -101,13 +107,16 @@ main (int argc, char **argv)
atexit (close_stdout);
while ((optc = getopt_long (argc, argv, "m:", longopts, NULL)) != -1)
while ((optc = getopt_long (argc, argv, "m:Z:", longopts, NULL)) != -1)
{
switch (optc)
{
case 'm':
specified_mode = optarg;
break;
case 'Z':
scontext = optarg;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
@@ -157,6 +166,11 @@ main (int argc, char **argv)
usage (EXIT_FAILURE);
}
if (scontext && setfscreatecon (scontext) < 0)
error (EXIT_FAILURE, errno,
_("failed to set default file creation context to %s"),
quote (optarg));
/* Only check the first character, to allow mnemonic usage like
`mknod /dev/rst0 character 18 0'. */

View File

@@ -22,6 +22,7 @@
#include <getopt.h>
#include <sys/types.h>
#include <assert.h>
#include <selinux/selinux.h>
#include "system.h"
#include "argmatch.h"
@@ -113,6 +114,8 @@ rm_option_init (struct rm_options *x)
static void
cp_option_init (struct cp_options *x)
{
bool selinux_enabled = (0 < is_selinux_enabled ());
x->copy_as_regular = false; /* FIXME: maybe make this an option */
x->dereference = DEREF_NEVER;
x->unlink_dest_before_opening = false;
@@ -126,7 +129,9 @@ cp_option_init (struct cp_options *x)
x->preserve_links = true;
x->preserve_mode = true;
x->preserve_timestamps = true;
x->preserve_security_context = selinux_enabled;
x->require_preserve = false; /* FIXME: maybe make this an option */
x->require_preserve_context = false;
x->recursive = true;
x->sparse_mode = SPARSE_AUTO; /* FIXME: maybe make this an option */
x->symbolic_link = false;

View File

@@ -1,5 +1,5 @@
/* pr -- convert text files for printing.
Copyright (C) 88, 91, 1995-2006 Free Software Foundation, Inc.
Copyright (C) 88, 91, 1995-2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1265,7 +1265,6 @@ init_parameters (int number_of_files)
col_sep_string = column_separator;
truncate_lines = true;
untabify_input = true;
tabify_output = true;
}
else

View File

@@ -1,5 +1,5 @@
/* readlink -- display value of a symbolic link.
Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -159,7 +159,7 @@ main (int argc, char **argv)
value = (can_mode != -1
? canonicalize_filename_mode (fname, can_mode)
: xreadlink (fname, 1024));
: xreadlink (fname));
if (value)
{
printf ("%s%s", value, (no_newline ? "" : "\n"));

View File

@@ -704,20 +704,21 @@ is_empty_dir (int fd_cwd, char const *dir)
return saved_errno == 0 ? true : false;
}
/* Return true if FILE is determined to be an unwritable non-symlink.
Otherwise, return false (including when lstat'ing it fails).
/* Return -1 if FILE is an unwritable non-symlink,
0 if it is writable or some other type of file,
a positive error number if there is some problem in determining the answer.
Set *BUF to the file status.
This is to avoid calling euidaccess when FILE is a symlink. */
static bool
static int
write_protected_non_symlink (int fd_cwd,
char const *file,
Dirstack_state const *ds,
struct stat *buf)
{
if (cache_fstatat (fd_cwd, file, buf, AT_SYMLINK_NOFOLLOW) != 0)
return false;
return errno;
if (S_ISLNK (buf->st_mode))
return false;
return 0;
/* Here, we know FILE is not a symbolic link. */
/* In order to be reentrant -- i.e., to avoid changing the working
@@ -771,9 +772,16 @@ write_protected_non_symlink (int fd_cwd,
size_t file_name_len
= obstack_object_size (&ds->dir_stack) + strlen (file);
return (file_name_len < MIN (PATH_MAX, 8192)
? euidaccess (full_filename (file), W_OK) != 0 && errno == EACCES
: euidaccess_stat (buf, W_OK) != 0);
if (MIN (PATH_MAX, 8192) <= file_name_len)
return - euidaccess_stat (buf, W_OK);
if (euidaccess (full_filename (file), W_OK) == 0)
return 0;
if (errno == EACCES)
return -1;
/* Perhaps some other process has removed the file, or perhaps this
is a buggy NFS client. */
return errno;
}
}
@@ -794,75 +802,73 @@ prompt (int fd_cwd, Dirstack_state const *ds, char const *filename,
struct rm_options const *x, enum Prompt_action mode,
Ternary *is_empty)
{
bool write_protected = false;
int write_protected = 0;
*is_empty = T_UNKNOWN;
if (x->interactive == RMI_NEVER)
return RM_OK;
if (((!x->ignore_missing_files & ((x->interactive == RMI_ALWAYS)
| x->stdin_tty))
&& (write_protected = write_protected_non_symlink (fd_cwd, filename,
ds, sbuf)))
|| x->interactive == RMI_ALWAYS)
if (!x->ignore_missing_files
& ((x->interactive == RMI_ALWAYS) | x->stdin_tty))
write_protected = write_protected_non_symlink (fd_cwd, filename, ds, sbuf);
if (write_protected || x->interactive == RMI_ALWAYS)
{
if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) != 0)
if (write_protected <= 0
&& cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) != 0)
{
/* This happens, e.g., with `rm '''. */
error (0, errno, _("cannot remove %s"),
quote (full_filename (filename)));
return RM_ERROR;
write_protected = errno;
}
if (S_ISDIR (sbuf->st_mode) && !x->recursive)
if (write_protected <= 0)
{
error (0, EISDIR, _("cannot remove %s"),
quote (full_filename (filename)));
return RM_ERROR;
}
/* Using permissions doesn't make sense for symlinks. */
if (S_ISLNK (sbuf->st_mode))
{
if (x->interactive != RMI_ALWAYS)
/* Using permissions doesn't make sense for symlinks. */
if (S_ISLNK (sbuf->st_mode) && x->interactive != RMI_ALWAYS)
return RM_OK;
write_protected = false;
if (S_ISDIR (sbuf->st_mode) && !x->recursive)
write_protected = EISDIR;
}
char const *quoted_name = quote (full_filename (filename));
if (0 < write_protected)
{
error (0, write_protected, _("cannot remove %s"), quoted_name);
return RM_ERROR;
}
/* Issue the prompt. */
{
char const *quoted_name = quote (full_filename (filename));
/* FIXME: use a variant of error (instead of fprintf) that doesn't
append a newline. Then we won't have to declare program_name in
this file. */
if (S_ISDIR (sbuf->st_mode)
&& x->recursive
&& mode == PA_DESCEND_INTO_DIR
&& ((*is_empty = (is_empty_dir (fd_cwd, filename) ? T_YES : T_NO))
== T_NO))
/* FIXME: use a variant of error (instead of fprintf) that doesn't
append a newline. Then we won't have to declare program_name in
this file. */
if (S_ISDIR (sbuf->st_mode)
&& x->recursive
&& mode == PA_DESCEND_INTO_DIR
&& ((*is_empty = (is_empty_dir (fd_cwd, filename) ? T_YES : T_NO))
== T_NO))
fprintf (stderr,
(write_protected
? _("%s: descend into write-protected directory %s? ")
: _("%s: descend into directory %s? ")),
program_name, quoted_name);
else
{
/* TRANSLATORS: You may find it more convenient to translate
the equivalent of _("%s: remove %s (write-protected) %s? ").
It should avoid grammatical problems with the output
of file_type. */
fprintf (stderr,
(write_protected
? _("%s: descend into write-protected directory %s? ")
: _("%s: descend into directory %s? ")),
program_name, quoted_name);
else
{
/* TRANSLATORS: You may find it more convenient to translate
the equivalent of _("%s: remove %s (write-protected) %s? ").
It should avoid grammatical problems with the output
of file_type. */
fprintf (stderr,
(write_protected
? _("%s: remove write-protected %s %s? ")
: _("%s: remove %s %s? ")),
program_name, file_type (sbuf), quoted_name);
}
? _("%s: remove write-protected %s %s? ")
: _("%s: remove %s %s? ")),
program_name, file_type (sbuf), quoted_name);
}
if (!yesno ())
return RM_USER_DECLINED;
}
if (!yesno ())
return RM_USER_DECLINED;
}
return RM_OK;
}

249
src/runcon.c Normal file
View File

@@ -0,0 +1,249 @@
/*
* runcon [ context |
* ( [ -c ] [ -r role ] [-t type] [ -u user ] [ -l levelrange ] )
* command [arg1 [arg2 ...] ]
*
* attempt to run the specified command with the specified context.
*
* -r role : use the current context with the specified role
* -t type : use the current context with the specified type
* -u user : use the current context with the specified user
* -l level : use the current context with the specified level range
* -c : compute process transition context before modifying
*
* Contexts are interpreted as follows:
*
* Number of MLS
* components system?
*
* 1 - type
* 2 - role:type
* 3 Y role:type:range
* 3 N user:role:type
* 4 Y user:role:type:range
* 4 N error
*/
#include <config.h>
#include <stdio.h>
#include <getopt.h>
#include <selinux/selinux.h>
#include <selinux/context.h>
#ifdef HAVE_SELINUX_FLASK_H
# include <selinux/flask.h>
#else
# define SECCLASS_PROCESS 0
#endif
#include <sys/types.h>
#include "system.h"
#include "error.h"
#include "quote.h"
#include "quotearg.h"
/* The official name of this program (e.g., no `g' prefix). */
#define PROGRAM_NAME "runcon"
#define AUTHORS "Russell Coker"
static struct option long_options[] = {
{"role", required_argument, NULL, 'r'},
{"type", required_argument, NULL, 't'},
{"user", required_argument, NULL, 'u'},
{"range", required_argument, NULL, 'l'},
{"compute", no_argument, NULL, 'c'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
};
/* The name the program was run with. */
char *program_name;
void
usage (int status)
{
if (status != EXIT_SUCCESS)
fprintf (stderr, _("Try `%s --help' for more information.\n"),
program_name);
else
{
printf (_("\
Usage: %s CONTEXT COMMAND [args]\n\
or: %s [ -c ] [-u USER] [-r ROLE] [-t TYPE] [-l RANGE] COMMAND [args]\n\
"), program_name, program_name);
fputs (_("\
Run a program in a different security context.\n\
With neither CONTEXT nor COMMAND, print the current security context.\n\
\n\
CONTEXT Complete security context\n\
-c, --compute compute process transition context before modifying\n\
-t, --type=TYPE type (for same role as parent)\n\
-u, --user=USER user identity\n\
-r, --role=ROLE role\n\
-l, --range=RANGE levelrange\n\
\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
}
exit (status);
}
int
main (int argc, char **argv, char **envp)
{
char *role = NULL;
char *range = NULL;
char *user = NULL;
char *type = NULL;
char *context = NULL;
security_context_t cur_context = NULL;
security_context_t file_context = NULL;
security_context_t new_context = NULL;
bool compute_trans = false;
context_t con;
initialize_main (&argc, &argv);
program_name = argv[0];
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
atexit (close_stdout);
while (1)
{
int option_index = 0;
int c = getopt_long (argc, argv, "+r:t:u:l:c", long_options,
&option_index);
if (c == -1)
break;
switch (c)
{
case 'r':
if (role)
error (EXIT_FAILURE, 0, _("multiple roles"));
role = optarg;
break;
case 't':
if (type)
error (EXIT_FAILURE, 0, _("multiple types"));
type = optarg;
break;
case 'u':
if (user)
error (EXIT_FAILURE, 0, _("multiple users"));
user = optarg;
break;
case 'l':
if (range)
error (EXIT_FAILURE, 0, _("multiple levelranges"));
range = optarg;
break;
case 'c':
compute_trans = true;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
usage (EXIT_FAILURE);
break;
}
}
if (argc - optind == 0)
{
if (getcon (&cur_context) < 0)
error (EXIT_FAILURE, errno, _("failed to get current context"));
fputs (cur_context, stdout);
fputc ('\n', stdout);
exit (EXIT_SUCCESS);
}
if (!(user || role || type || range || compute_trans))
{
if (optind >= argc)
{
error (0, 0, _("you must specify -c, -t, -u, -l, -r, or context"));
usage (1);
}
context = argv[optind++];
}
if (optind >= argc)
{
error (0, 0, _("no command specified"));
usage (1);
}
if (is_selinux_enabled () != 1)
error (EXIT_FAILURE, 0,
_("runcon may be used only on a SELinux kernel"));
if (context)
{
con = context_new (context);
if (!con)
error (EXIT_FAILURE, errno, _("failed to create security context: %s"),
quotearg_colon (context));
}
else
{
if (getcon (&cur_context) < 0)
error (EXIT_FAILURE, errno, _("failed to get current context"));
/* We will generate context based on process transition */
if (compute_trans)
{
/* Get context of file to be executed */
if (getfilecon (argv[optind], &file_context) == -1)
error (EXIT_FAILURE, errno,
_("failed to get security context of %s"),
quote (argv[optind]));
/* compute result of process transition */
if (security_compute_create (cur_context, file_context,
SECCLASS_PROCESS, &new_context) != 0)
error (EXIT_FAILURE, errno,
_("failed to compute a new context"));
/* free contexts */
freecon (file_context);
freecon (cur_context);
/* set cur_context equal to new_context */
cur_context = new_context;
}
con = context_new (cur_context);
if (!con)
error (EXIT_FAILURE, errno, _("failed to create security context: %s"),
quotearg_colon (cur_context));
if (user && context_user_set (con, user))
error (EXIT_FAILURE, errno, _("failed to set new user %s"), user);
if (type && context_type_set (con, type))
error (EXIT_FAILURE, errno, _("failed to set new type %s"), type);
if (range && context_range_set (con, range))
error (EXIT_FAILURE, errno, _("failed to set new range %s"), range);
if (role && context_role_set (con, role))
error (EXIT_FAILURE, errno, _("failed to set new role %s"), role);
}
if (security_check_context (context_str (con)) < 0)
error (EXIT_FAILURE, errno, _("invalid context: %s"),
quotearg_colon (context_str (con)));
if (setexeccon (context_str (con)) != 0)
error (EXIT_FAILURE, errno, _("unable to set security context %s"),
quote (context_str (con)));
if (cur_context != NULL)
freecon (cur_context);
execvp (argv[optind], argv + optind);
{
int exit_status = (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
error (0, errno, "%s", argv[optind]);
exit (exit_status);
}
}

View File

@@ -1,5 +1,5 @@
/* stat.c -- display file or file system status
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation.
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -54,6 +54,7 @@
#elif HAVE_OS_H /* BeOS */
# include <fs_info.h>
#endif
#include <selinux/selinux.h>
#include "system.h"
@@ -158,6 +159,7 @@ enum
};
static struct option const long_options[] = {
{"context", no_argument, 0, 'Z'},
{"dereference", no_argument, NULL, 'L'},
{"file-system", no_argument, NULL, 'f'},
{"filesystem", no_argument, NULL, 'f'}, /* obsolete and undocumented alias */
@@ -171,6 +173,9 @@ static struct option const long_options[] = {
char *program_name;
/* Whether to follow symbolic links; True for --dereference (-L). */
static bool follow_links;
/* Whether to interpret backslash-escape sequences.
True for --printf=FMT, not for --format=FMT (-c). */
static bool interpret_backslash_escapes;
@@ -394,6 +399,26 @@ out_uint_x (char *pformat, size_t prefix_len, uintmax_t arg)
printf (pformat, arg);
}
/* Very specialized function (modifies FORMAT), just so as to avoid
duplicating this code between both print_statfs and print_stat. */
static void
out_file_context (char const *filename, char *pformat, size_t prefix_len)
{
char *scontext;
if ((follow_links
? getfilecon (filename, &scontext)
: lgetfilecon (filename, &scontext)) < 0)
{
error (0, errno, _("failed to get security context of %s"),
quote (filename));
scontext = NULL;
}
strcpy (pformat + prefix_len, "s");
printf (pformat, (scontext ? scontext : "?"));
if (scontext)
freecon (scontext);
}
/* print statfs info */
static void
print_statfs (char *pformat, size_t prefix_len, char m, char const *filename,
@@ -472,7 +497,9 @@ print_statfs (char *pformat, size_t prefix_len, char m, char const *filename,
case 'd':
out_int (pformat, prefix_len, statfsbuf->f_ffree);
break;
case 'C':
out_file_context (filename, pformat, prefix_len);
break;
default:
fputc ('?', stdout);
break;
@@ -497,7 +524,7 @@ print_stat (char *pformat, size_t prefix_len, char m,
out_string (pformat, prefix_len, quote (filename));
if (S_ISLNK (statbuf->st_mode))
{
char *linkname = xreadlink (filename, statbuf->st_size);
char *linkname = xreadlink_with_size (filename, statbuf->st_size);
if (linkname == NULL)
{
error (0, errno, _("cannot read symbolic link %s"),
@@ -595,6 +622,9 @@ print_stat (char *pformat, size_t prefix_len, char m,
else
out_uint (pformat, prefix_len, statbuf->st_ctime);
break;
case 'C':
out_file_context (filename, pformat, prefix_len);
break;
default:
fputc ('?', stdout);
break;
@@ -774,8 +804,7 @@ do_statfs (char const *filename, bool terse, char const *format)
/* stat the file and print what we find */
static bool
do_stat (char const *filename, bool follow_links, bool terse,
char const *format)
do_stat (char const *filename, bool terse, char const *format)
{
struct stat statbuf;
@@ -853,6 +882,7 @@ The valid format sequences for files (without --file-system):\n\
%A Access rights in human readable form\n\
%b Number of blocks allocated (see %B)\n\
%B The size in bytes of each block reported by %b\n\
%C SELinux security context string\n\
"), stdout);
fputs (_("\
%d Device number in decimal\n\
@@ -892,6 +922,7 @@ Valid format sequences for file systems:\n\
%c Total file nodes in file system\n\
%d Free file nodes in file system\n\
%f Free blocks in file system\n\
%C SELinux security context string\n\
"), stdout);
fputs (_("\
%i File System ID in hex\n\
@@ -913,7 +944,6 @@ main (int argc, char *argv[])
{
int c;
int i;
bool follow_links = false;
bool fs = false;
bool terse = false;
char *format = NULL;
@@ -927,7 +957,7 @@ main (int argc, char *argv[])
atexit (close_stdout);
while ((c = getopt_long (argc, argv, "c:fLt", long_options, NULL)) != -1)
while ((c = getopt_long (argc, argv, "c:fLtZ", long_options, NULL)) != -1)
{
switch (c)
{
@@ -955,6 +985,11 @@ main (int argc, char *argv[])
terse = true;
break;
case 'Z': /* FIXME: remove in 2008, warn in 2007 */
/* Ignored, for compatibility with distributions
that implemented this before upstream. */
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
@@ -973,7 +1008,7 @@ main (int argc, char *argv[])
for (i = optind; i < argc; i++)
ok &= (fs
? do_statfs (argv[i], terse, format)
: do_stat (argv[i], follow_links, terse, format));
: do_stat (argv[i], terse, format));
exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
}

View File

@@ -399,6 +399,8 @@ enum
"help", no_argument, NULL, GETOPT_HELP_CHAR
#define GETOPT_VERSION_OPTION_DECL \
"version", no_argument, NULL, GETOPT_VERSION_CHAR
#define GETOPT_SELINUX_CONTEXT_OPTION_DECL \
"context", required_argument, NULL, 'Z'
#define case_GETOPT_HELP_CHAR \
case GETOPT_HELP_CHAR: \

View File

@@ -18,7 +18,7 @@ EXTRA_DIST = \
$(TESTS) Coreutils.pm Makefile.am.in README acl envvar-check \
expensive group-names input-tty lang-default mk-script \
other-fs-tmpdir priv-check \
rwx-to-mode sample-test setgid-check sparse-file \
rwx-to-mode sample-test selinux setgid-check sparse-file \
umask-check very-expensive
## N O T E :: Please do not add new tests/ directories.
@@ -30,7 +30,7 @@ SUBDIRS = \
tsort unexpand uniq wc
## N O T E :: Please do not add new directories.
all_t = t1 t2 t3 t4 t5 t6 t7
all_t = t1 t2 t3 t4 t5 t6 t7 t8 t9
.PHONY: check-root $(all_t)
check-root: $(all_t)
@@ -48,6 +48,10 @@ t6:
cd rm && $(MAKE) check TESTS=one-file-system
t7:
cd ls && $(MAKE) check TESTS=nameless-uid
t8:
cd misc && $(MAKE) check TESTS=chcon
t9:
cd cp && $(MAKE) check TESTS=cp-a-selinux
check-recursive: root-hint

View File

@@ -1,8 +1,7 @@
#!/bin/sh
# make sure chgrp is reasonable
# Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006 Free Software
# Foundation, Inc.
# Copyright (C) 2000-2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -79,7 +78,11 @@ test `stat --printf=%g f` = $g1 || fail=1
# This should not change the group of f.
chgrp -h $g2 symlink
test `stat --printf=%g f` = $g1 || fail=1
test `stat --printf=%g symlink` = $g2 || fail=1
# Don't fail if chgrp failed to set the group of a symlink.
# Some systems don't support that.
test `stat --printf=%g symlink` = $g2 ||
echo 'info: failed to set group of symlink' 1>&2
chown --from=:$g1 :$g2 f; test `stat --printf=%g f` = $g2 || fail=1
@@ -110,15 +113,19 @@ sleep 1
chgrp $g1 f
# The following no-change chgrp command is supposed to update f's ctime,
# but on OpenBSD, it appears to be a no-op for some file system types
# (at least NFS) so g's ctime is more recent. This is not a big deal;
# but on OpenBSD and Darwin 7.9.0 and 8.8.0 (aka MacOS X 10.3.9 and 10.4),
# it appears to be a no-op for some file system types (at least NFS) so g's
# ctime is more recent. This is not a big deal;
# this test works fine when the files are on a local file system (/tmp).
chgrp '' f
test "`ls -C -c -t f g`" = 'f g' || \
{
case $host_triplet in
*openbsd*) echo ignoring known OpenBSD-specific chgrp failure 1>&2 ;;
*) echo no-change chgrp failed to update ctime 1>&2; fail=1 ;;
*openbsd*) echo ignoring known OpenBSD-specific chgrp failure 1>&2 ;;
*darwin7.9.*|*darwin8.8.*)
echo ignoring known MacOS X-specific chgrp failure 1>&2 ;;
*) echo $host_triplet: no-change chgrp failed to update ctime 1>&2;
fail=1 ;;
esac
}

View File

@@ -51,7 +51,7 @@ for src in u g o; do
for dest in u g o; do
test $dest = $src && continue
chmod a=,$src=rwx,$dest=$src,$src= f || fail=1
set _ `ls -l f`; shift; actual_perms=$1
actual_perms=`ls -l f|cut -b-10`
expected_perms=`eval 'echo \$expected_'$dest`
test "$actual_perms" = "$expected_perms" || fail=1
done
@@ -59,7 +59,7 @@ done
umask 027
chmod a=,u=rwx,=u f || fail=1
set _ `ls -l f`; shift; actual_perms=$1
actual_perms=`ls -l f|cut -b-10`
test "$actual_perms" = "-rwxr-x---" || fail=1
(exit $fail); exit $fail

View File

@@ -18,6 +18,7 @@
# 02110-1301, USA.
TESTS = \
cp-a-selinux \
file-perm-race parent-perm-race \
backup-dir \
src-base-dot \

94
tests/cp/cp-a-selinux Executable file
View File

@@ -0,0 +1,94 @@
#!/bin/sh
# Ensure that cp -a and cp --preserve=context work properly.
# In particular, test on a writable NFS partition.
# Copyright (C) 2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program 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 General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
if test "$VERBOSE" = yes; then
set -x
cp --version
fi
. $srcdir/../envvar-check
. $srcdir/../lang-default
. $srcdir/../selinux
PRIV_CHECK_ARG=require-root . $srcdir/../priv-check
pwd=`pwd`
t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
trap 'status=$?; cd "$pwd"; umount $tmp/mnt; chmod -R u+rwx $t0 && rm -rf $t0 && exit $status' 0
trap '(exit $?); exit $?' 1 2 13 15
framework_failure=0
mkdir -p $tmp || framework_failure=1
cd $tmp || framework_failure=1
# Create a file system, then mount it with the context=... option.
dd if=/dev/zero of=blob bs=8192 count=200 > /dev/null 2>&1 \
|| framework_failure=1
mkdir mnt || framework_failure=1
mkfs -t ext2 -F blob > /dev/null 2>&1 || framework_failure=1
mount -oloop,context=system_u:object_r:removable_t blob mnt \
|| framework_failure=1
cd mnt || framework_failure=1
echo > f || framework_failure=1
echo > g || framework_failure=1
if test $framework_failure = 1; then
echo "$0: failure in testing framework" 1>&2
(exit 1); exit 1
fi
fail=0
# /bin/cp from coreutils-6.7-3.fc7 would fail this test by letting cp
# succeed (giving no diagnostics), yet leaving the destination file empty.
cp -a f g 2>err || fail=1
test -s g || fail=1 # The destination file must not be empty.
test -s err && fail=1 # There must be no stderr output.
rm -f g err
echo > g
# =====================================================
# Here, we expect cp to fail, because it cannot set the SELinux
# security context through NFS or a mount with fixed context.
cp --preserve=context f g 2> out && fail=1
# Here, we *do* expect the destination to be empty.
test -s g && fail=1
# An alternative to the current approach would be to run in a confined
# domain (maybe creating/loading it) that lacks the required permissions
# to the file type.
# Note: this test could also be run by a regular (non-root) user in an
# NFS mounted directory. When doing that, I get this diagnostic:
# cp: failed to set the security context of `g' to `system_u:object_r:nfs_t': \
# Operation not supported
sed "s/ .g' to .*//" out > k
mv k out
cat <<\EOF > exp || fail=1
cp: failed to set the security context of
EOF
cmp out exp || fail=1
test $fail = 1 && diff out exp 2> /dev/null
(exit $fail); exit $fail

View File

@@ -75,8 +75,8 @@ test -d d/f && fail=1
# Check that re_protect works.
chmod go=w d/a
cp -a --parents d/a/b/c e || fail=1
p=`ls -ld e/d|sed 's/ .*//'`; case $p in drwxr-xr-x);; *) fail=1;; esac
p=`ls -ld e/d/a|sed 's/ .*//'`; case $p in drwx-w--w-);; *) fail=1;; esac
p=`ls -ld e/d/a/b/c|sed 's/ .*//'`; case $p in drwxr-xr-x);; *) fail=1;; esac
p=`ls -ld e/d|cut -b-10`; case $p in drwxr-xr-x);; *) fail=1;; esac
p=`ls -ld e/d/a|cut -b-10`; case $p in drwx-w--w-);; *) fail=1;; esac
p=`ls -ld e/d/a/b/c|cut -b-10`; case $p in drwxr-xr-x);; *) fail=1;; esac
(exit $fail); exit $fail

View File

@@ -52,9 +52,8 @@ cp -pR D DD > /dev/null 2>&1 && fail=1
# Permissions on DD must be `dr-x------'
set X `ls -ld DD`
shift
test "$1" = dr-x------ || fail=1
mode=`ls -ld DD|cut -b-10`
test "$mode" = dr-x------ || fail=1
chmod 0 D
ln -s D/D symlink

View File

@@ -98,7 +98,7 @@ rm -rf a b c d
touch a; chmod 731 a
umask 077
cp -a --no-preserve=mode a b
set _ `ls -l b`; shift; mode=$1
mode=`ls -l b|cut -b-10`
test "$mode" = "-rwx------" || fail=1
umask 022
# --------------------------------------

View File

@@ -52,6 +52,6 @@ fail=0
cp --sparse=always sparse copy || fail=1
# Ensure that the copy has the same block count as the original.
test `stat --printf %b sparse` = `stat --printf %b copy` || fail=1
test `stat --printf %b copy` -le `stat --printf %b sparse` || fail=1
(exit $fail); exit $fail

View File

@@ -1,7 +1,7 @@
#!/bin/sh
# Compare actual numbers from du, assuming block size matches mine.
# Copyright (C) 2003, 2006 Free Software Foundation, Inc.
# Copyright (C) 2003, 2006-2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -80,20 +80,23 @@ EOF
cmp out exp || fail=1
test $fail = 1 && diff -u out exp 2> /dev/null
rm -f out exp
du --block-size=$B -a d | sort -r -k2,2 > out || fail=1
echo === >> out
du --block-size=$B -S d | sort -r -k2,2 >> out || fail=1
# Perform this test only if "." is on a local file system.
# Otherwise, it would fail e.g., on an NFS-mounted Solaris ZFS file system.
if df --local . >/dev/null 2>&1; then
rm -f out exp
du --block-size=$B -a d | sort -r -k2,2 > out || fail=1
echo === >> out
du --block-size=$B -S d | sort -r -k2,2 >> out || fail=1
t2=`stat --format=%b d/sub/2`
ts=`stat --format=%b d/sub`
t1=`stat --format=%b d/1`
td=`stat --format=%b d`
tot=`expr $t1 + $t2 + $ts + $td`
d1=`expr $td + $t1`
s2=`expr $ts + $t2`
t2=`stat --format=%b d/sub/2`
ts=`stat --format=%b d/sub`
t1=`stat --format=%b d/1`
td=`stat --format=%b d`
tot=`expr $t1 + $t2 + $ts + $td`
d1=`expr $td + $t1`
s2=`expr $ts + $t2`
cat <<EOF | sed 's/ *#.*//' > exp
cat <<EOF | sed 's/ *#.*//' > exp
$t2 d/sub/2
$s2 d/sub
$t1 d/1
@@ -103,7 +106,8 @@ $s2 d/sub
$d1 d # d + d/1; don't count the dir. entry for d/sub
EOF
cmp out exp || fail=1
test $fail = 1 && diff out exp 2> /dev/null
cmp out exp || fail=1
test $fail = 1 && diff out exp 2> /dev/null
fi
(exit $fail); exit $fail

View File

@@ -2,8 +2,7 @@
# Make sure all these programs work properly
# when invoked with --help or --version.
# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
# Foundation, Inc.
# Copyright (C) 2000-2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -72,6 +71,8 @@ for lang in C fr da; do
# Skip `test'; it doesn't accept --help or --version.
test $i = test && continue;
test $i = chcon && continue;
test $i = runcon && continue;
# false fails even when invoked with --help or --version.
if test $i = false; then
@@ -197,7 +198,7 @@ lbracket_args=": ]"
for i in $all_programs; do
# Skip these.
case $i in chroot|stty|tty|false) continue;; esac
case $i in chroot|stty|tty|false|chcon|runcon) continue;; esac
rm -rf $tmp_in $tmp_in2 $tmp_dir $tmp_out
echo > $tmp_in

View File

@@ -1,8 +1,7 @@
#! /bin/sh
# Basic tests for "install".
# Copyright (C) 1998, 2000, 2001, 2002, 2004, 2005, 2006 Free Software
# Foundation, Inc.
# Copyright (C) 1998, 2000-2002, 2004-2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -99,9 +98,8 @@ ginstall -s -c -m 555 $dd $dir || fail=1
test -f $dd || fail=1
# Make sure that the destination file has the requested permissions.
set X `ls -l $dir/$dd`
shift
test "$1" = -r-xr-xr-x || fail=1
mode=`ls -l $dir/$dd|cut -b-10`
test "$mode" = -r-xr-xr-x || fail=1
# These failed in coreutils CVS from 2004-06-25 to 2004-08-11.
ginstall -d . || fail=1
@@ -131,8 +129,8 @@ test -d xx/rel && fail=1
# Test that we can install from an unreadable directory with an
# inaccessible parent. coreutils 5.97 fails this test.
mkdir -p sub1/d || fail=1
(cd sub1/d && chmod a-rx .. && chmod a-r . &&
ginstall -d "$abs/xx/zz" rel/a rel/b 2> /dev/null) || fail=1
(cd sub1/d && chmod a-r . && chmod a-rx .. &&
ginstall -d "$abs/xx/zz" rel/a rel/b) || fail=1
chmod 755 sub1 sub1/d || fail=1
test -d xx/zz || fail=1
test -d sub1/d/rel/a || fail=1

View File

@@ -1,6 +1,6 @@
# Make miscellaneous coreutils tests. -*-Makefile-*-
# Copyright (C) 200-2007 Free Software Foundation, Inc.
# Copyright (C) 2001-2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -30,6 +30,7 @@ TESTS_ENVIRONMENT = \
PATH="$(VG_PATH_PREFIX)`pwd`/../../src$(PATH_SEPARATOR)$$PATH" \
CONFIG_HEADER=$(CONFIG_HEADER) \
REPLACE_GETCWD=$(REPLACE_GETCWD) \
host_os=$(host_os) \
PROG=`../../src/basename -- "$$tst"`
# Do not choose a name that is a shell keyword like 'if', or a
@@ -39,7 +40,12 @@ TESTS_ENVIRONMENT = \
# will execute the test script rather than the standard utility.
TESTS = \
pr \
df-P \
pwd-unreadable-parent \
chcon \
chcon-fail \
selinux \
cut \
wc-files0-from \
wc-files0 \
@@ -67,6 +73,7 @@ TESTS = \
printf \
printf-hex \
pwd-long \
runcon-no-reorder \
sha224sum \
sha256sum \
sha384sum \

73
tests/misc/chcon Executable file
View File

@@ -0,0 +1,73 @@
#!/bin/sh
# exercise chcon
if test "$VERBOSE" = yes; then
set -x
chcon --version
fi
. $srcdir/../lang-default
PRIV_CHECK_ARG=require-root . $srcdir/../priv-check
pwd=`pwd`
t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
trap 'status=$?; cd $pwd; chmod -R u+rwx $t0; rm -rf $t0 && exit $status' 0
trap '(exit $?); exit $?' 1 2 13 15
framework_failure=0
mkdir -p $tmp || framework_failure=1
cd $tmp || framework_failure=1
mkdir -p d/sub/s2 || framework_failure=1
touch f g d/sub/1 d/sub/2 || framework_failure=1
if test $framework_failure = 1; then
echo "$0: failure in testing framework" 1>&2
(exit 1); exit 1
fi
fail=0
# Set to a specified context.
u1=root
r1=object_r
t1=tmp_t
ctx=$u1:$r1:$t1
chcon $ctx f || fail=1
stat --printf='f|%C\n' f > out || fail=1
# Use --reference.
chcon --ref=f g || fail=1
stat --printf='g|%C\n' g >> out || fail=1
# Change the individual parts of the context, one by one.
u2=user_u
r2=object_r
t2=file_t
l2=SystemLow-SystemHigh
for i in --user=$u2 --role=$r2 --type=$t2 --range=$l2; do
chcon $i f || fail=1
stat --printf="f|$i|"'%C\n' f >> out || fail=1
done
# Same, but change back using the short-named options.
for i in -u$u1 -r$r1 -t$t1; do
chcon $i f || fail=1
stat --printf="f|$i|"'%C\n' f >> out || fail=1
done
cat <<EOF > exp || fail=1
f|$ctx
g|$ctx
f|--user=$u2|$u2:$r1:$t1
f|--role=$r2|$u2:$r2:$t1
f|--type=$t2|$u2:$r2:$t2
f|--range=$l2|$u2:$r2:$t2:$l2
f|-uroot|root:object_r:file_t:SystemLow-SystemHigh
f|-robject_r|root:object_r:file_t:SystemLow-SystemHigh
f|-ttmp_t|root:object_r:tmp_t:SystemLow-SystemHigh
EOF
cmp out exp || fail=1
test $fail = 1 && diff out exp 2> /dev/null
(exit $fail); exit $fail

41
tests/misc/chcon-fail Executable file
View File

@@ -0,0 +1,41 @@
#!/bin/sh
# Ensure that chcon fails when it should.
# These tests don't use any actual SE Linux syscalls.
if test "$VERBOSE" = yes; then
set -x
chcon --version
fi
. $srcdir/../lang-default
pwd=`pwd`
t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
trap 'status=$?; cd $pwd; chmod -R u+rwx $t0; rm -rf $t0 && exit $status' 0
trap '(exit $?); exit $?' 1 2 13 15
framework_failure=0
mkdir -p $tmp || framework_failure=1
cd $tmp || framework_failure=1
if test $framework_failure = 1; then
echo "$0: failure in testing framework" 1>&2
(exit 1); exit 1
fi
fail=0
# neither context nor file
chcon 2> /dev/null && fail=1
# No file
chcon CON 2> /dev/null && fail=1
# No file
touch f
chcon --reference=f 2> /dev/null && fail=1
# No file
chcon -u anyone 2> /dev/null && fail=1
(exit $fail); exit $fail

60
tests/misc/df-P Executable file
View File

@@ -0,0 +1,60 @@
#!/bin/sh
# Ensure that df -P is not affected by BLOCK_SIZE settings
# Copyright (C) 2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program 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 General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
if test "$VERBOSE" = yes; then
set -x
df --version
fi
. $srcdir/../envvar-check
. $srcdir/../lang-default
pwd=`pwd`
t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
trap 'status=$?; cd "$pwd" && chmod -R u+rwx $t0 && rm -rf $t0 && exit $status' 0
trap '(exit $?); exit $?' 1 2 13 15
framework_failure=0
mkdir -p $tmp || framework_failure=1
cd $tmp || framework_failure=1
if test $framework_failure = 1; then
echo "$0: failure in testing framework" 1>&2
(exit 1); exit 1
fi
fail=0
df -P . > t1 || fail=1
BLOCK_SIZE=1M df -P . > t2 || fail=1
# Since disk utilization may be changing, compare only df's header line.
# That records the block size. E.g., for "1M", it would be:
# Filesystem 1048576-blocks Used Available Capacity Mounted on
# while for 1K, it would be
# Filesystem 1024-blocks Used Available Capacity Mounted on
head -n1 t1 > exp || fail=1
head -n1 t2 > out || fail=1
cmp out exp || fail=1
test $fail = 1 && diff out exp 2> /dev/null
(exit $fail); exit $fail

View File

@@ -42,15 +42,15 @@ fail=0
umask 777
mknod -m 734 f1 p || fail=1
set _ `ls -dgo f1`; shift; mode=$1
mode=`ls -dgo f1|cut -b-10`
test $mode = prwx-wxr-- || fail=1
mkfifo -m 734 f2 || fail=1
set _ `ls -dgo f2`; shift; mode=$1
mode=`ls -dgo f2|cut -b-10`
test $mode = prwx-wxr-- || fail=1
mkdir -m 734 f3 || fail=1
set _ `ls -dgo f3`; shift; mode=$1
mode=`ls -dgo f3|cut -b-10`
test $mode = drwx-wxr-- || test $mode = drwx-wsr-- || fail=1
(exit $fail); exit $fail

61
tests/misc/pr Executable file
View File

@@ -0,0 +1,61 @@
#!/bin/sh
# -*- perl -*-
# Exercise a bug with pr -m -s
# Copyright (C) 2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program 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 General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
: ${PERL=perl}
: ${srcdir=.}
. $srcdir/../envvar-check
$PERL -e 1 > /dev/null 2>&1 || {
echo 1>&2 "$0: configure didn't find a usable version of Perl," \
"so can't run this test"
exit 77
}
exec $PERL -w -I$srcdir/.. -MCoreutils -- - <<\EOF
#/
require 5.003;
use strict;
(my $program_name = $0) =~ s|.*/||;
$ENV{PROG} = 'pr';
my $ME = $ENV{PROG};
# Turn off localization of executable's ouput.
@ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
my @Tests =
(
['merge-w-tabs', '-m -s -t',
{IN=>{1=>"a\tb\tc\n"}},
{IN=>{2=>"m\tn\to\n"}},
{IN=>{3=>"x\ty\tz\n"}},
{OUT=>join("\t", qw(a b c m n o x y z)) . "\n"} ],
);
my $save_temps = $ENV{DEBUG};
my $verbose = $ENV{VERBOSE};
my $prog = $ENV{PROG} || die "$0: \$PROG not specified in environment\n";
my $fail = run_tests ($program_name, $prog, \@Tests, $save_temps, $verbose);
exit $fail;
EOF

View File

@@ -97,7 +97,7 @@ until (++$i == $n);
my $build_src_dir = $ENV{BUILD_SRC_DIR};
$build_src_dir
or die "$ME: envvar BUILD_SRC_DIR not defined\n";
if ($build_src_dir !~ m!^([-.:/\w]+)$!)
if ($build_src_dir !~ m!^([-+.:/\w]+)$!)
{
warn "$0: skipping this test; odd build source directory name:\n"
. "$build_src_dir\n";

View File

@@ -26,17 +26,17 @@ if test "$VERBOSE" = yes; then
readlink --version
fi
skip=1
# Run this test IFF:
# if REPLACE_GETCWD is 0 (system getcwd is good enough)
# or HAVE_PARTLY_WORKING_GETCWD is defined
test $REPLACE_GETCWD = 0 && skip=0
test $skip = 1 &&
grep '^#define HAVE_PARTLY_WORKING_GETCWD ' $CONFIG_HEADER > /dev/null &&
skip=0
test $skip = 1 &&
test $host_os != linux-gnu &&
{
echo 1>&2 "$0: inadequate system getcwd; skipping this test"
echo 1>&2 "$0: vendor getcwd may be inadequate; skipping this test"
(exit 77); exit 77
}
# Linux ia64 has the gl_FUNC_GETCWD_ABORT_BUG, so we can't use
# the system getcwd.
test $REPLACE_GETCWD = 1 &&
{
echo 1>&2 "$0: can't use buggy system getcwd; skipping this test"
(exit 77); exit 77
}

57
tests/misc/runcon-no-reorder Executable file
View File

@@ -0,0 +1,57 @@
#!/bin/sh
# Ensure that runcon does not reorder its arguments.
# Copyright (C) 2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program 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 General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
if test "$VERBOSE" = yes; then
set -x
runcon --version
fi
. $srcdir/../lang-default
pwd=`pwd`
t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
trap 'status=$?; cd "$pwd" && chmod -R u+rwx $t0 && rm -rf $t0 && exit $status' 0
trap '(exit $?); exit $?' 1 2 13 15
framework_failure=0
mkdir -p $tmp || framework_failure=1
cd $tmp || framework_failure=1
cat <<\EOF > exp || framework_failure=1
runcon: runcon may be used only on a SELinux kernel
EOF
if test $framework_failure = 1; then
echo "$0: failure in testing framework" 1>&2
(exit 1); exit 1
fi
fail=0
# This test works even on systems without SELinux.
# On such a system it fails with the above diagnostic, which is fine.
# Before the no-reorder change, it would have failed with a diagnostic
# about -j being an invalid option.
runcon -t unconfined_t true -j 2> out && : > exp
cmp out exp || fail=1
test $fail = 1 && diff out exp 2> /dev/null
(exit $fail); exit $fail

61
tests/misc/selinux Executable file
View File

@@ -0,0 +1,61 @@
#!/bin/sh
# Test SELinux-related options.
if test "$VERBOSE" = yes; then
set -x
chcon --version
cp --version
ls --version
mv --version
stat --version
fi
. $srcdir/../envvar-check
. $srcdir/../lang-default
. $srcdir/../selinux
PRIV_CHECK_ARG=require-non-root . $srcdir/../priv-check
pwd=`pwd`
t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
trap 'status=$?; cd $pwd; chmod -R u+rwx $t0; rm -rf $t0 && exit $status' 0
trap '(exit $?); exit $?' 1 2 13 15
framework_failure=0
mkdir -p $tmp || framework_failure=1
cd $tmp || framework_failure=1
# Create a regular file, dir, fifo.
touch f || framework_failure=1
mkdir d s1 s2 || framework_failure=1
mkfifo p || framework_failure=1
if test $framework_failure = 1; then
echo "$0: failure in testing framework" 1>&2
(exit 1); exit 1
fi
fail=0
ctx=root:object_r:tmp_t
# FIXME, what if $ctx is no different from the default. Not likely.
# give each a different context, via chcon
chcon $ctx f d p || fail=1
# inspect that context with both ls -Z and stat.
for i in d f p; do
c=`ls -dogZ $i|cut -d' ' -f3`; test x$c = x$ctx || fail=1
c=`stat --printf %C $i`; test x$c = x$ctx || fail=1
done
# Copy each to a new directory and ensure that context is preserved.
cp -r --preserve=all d f p s1 || fail=1
for i in d f p; do
c=`stat --printf %C s1/$i`; test x$c = x$ctx || fail=1
done
# Now, move each to a new directory and ensure that context is preserved.
mv d f p s2 || fail=1
for i in d f p; do
c=`stat --printf %C s2/$i`; test x$c = x$ctx || fail=1
done
(exit $fail); exit $fail

View File

@@ -67,6 +67,7 @@ $@ and (warn "$ME: this script requires Perl's Expect package >=1.11\n"),
sha256sum
sha384sum
sha512sum
shuf
sort
sum
tac

View File

@@ -65,12 +65,12 @@ d_mode_arg=`"$abs_srcdir/../rwx-to-mode" $d_mode_str`
mkdir -p -m $d_mode_arg a/b/c/d
# Make sure the permissions of `a' haven't been changed.
p=`ls -ld a|sed 's/ .*//'`; case $p in $mode_str);; *) fail=1;; esac
p=`ls -ld a|cut -b-10`; case $p in $mode_str);; *) fail=1;; esac
# `b's and `c's should reflect the umask
p=`ls -ld a/b|sed 's/ .*//'`; case $p in drwx------);; *) fail=1;; esac
p=`ls -ld a/b/c|sed 's/ .*//'`; case $p in drwx------);; *) fail=1;; esac
p=`ls -ld a/b|cut -b-10`; case $p in drwx------);; *) fail=1;; esac
p=`ls -ld a/b/c|cut -b-10`; case $p in drwx------);; *) fail=1;; esac
# `d's perms are determined by the -m argument.
p=`ls -ld a/b/c/d|sed 's/ .*//'`; case $p in $d_mode_str);; *) fail=1;; esac
p=`ls -ld a/b/c/d|cut -b-10`; case $p in $d_mode_str);; *) fail=1;; esac
(exit $fail); exit $fail

View File

@@ -33,8 +33,8 @@ output_mode_string=drwxr-x-wT
mkdir -m$set_mode_string $tmp || fail=1
test -d $tmp || fail=1
set -- `ls -ld $tmp`
case "$1" in
mode=`ls -ld $tmp|cut -b-10`
case "$mode" in
$output_mode_string) ;;
*) fail=1 ;;
esac
@@ -49,8 +49,8 @@ mkdir -m$set_mode_string $tmp2 2> /dev/null && fail=1
mkdir --parents -m$set_mode_string $tmp2 || fail=1
test -d $tmp2 || fail=1
set -- `ls -ld $tmp2`
case "$1" in
mode=`ls -ld $tmp2|cut -b-10`
case "$mode" in
$output_mode_string) ;;
*) fail=1 ;;
esac

View File

@@ -2,7 +2,7 @@
# Test both cp and mv for their behavior with -if and -fi
# The standards (POSIX and SuS) dictate annoyingly inconsistent behavior.
# Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc.
# Copyright (C) 2000, 2001, 2006, 2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -61,7 +61,7 @@ cp -if e f < y > out 2>&1 || fail=1
# Make sure out contains the prompt.
case "`cat out`" in
"cp: overwrite \`f', overriding mode 0000?"*) ;;
"cp: try to overwrite \`f', overriding mode 0000 (---------)?"*) ;;
*) fail=1 ;;
esac

View File

@@ -49,7 +49,7 @@ test -f file && fail=1
test -f $other_partition_tmpdir/file || fail=1
# This would have failed with the mv from fileutils-4.0i.
set _ `ls -l $other_partition_tmpdir/file`; shift; mode=$1
mode=`ls -l $other_partition_tmpdir/file|cut -b-10`
test "$mode" = "-rwxrwxrwx" || fail=1
exit $fail

24
tests/selinux Normal file
View File

@@ -0,0 +1,24 @@
# Is a test expensive?
# Copyright (C) 2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program 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 General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
test "`ls -Zd .`" = '? .' &&
{
echo "$0: skipping this test; this system (or maybe just" 1>&2
echo " the current file system) lacks SELinux support" 1>&2
(exit 77); exit 77
}