From: Apple <opensource@apple.com>
Date: Tue, 20 Aug 2019 09:57:28 +0000 (+0000)
Subject: file_cmds-287.11.1.tar.gz
X-Git-Tag: macos-1015^0
X-Git-Url: https://git.saurik.com/apple/file_cmds.git/commitdiff_plain/48fce60356143adc6bb8bbe808bd026c7c60606f?ds=inline

file_cmds-287.11.1.tar.gz
---

diff --git a/.gitignore b/.gitignore
index 780fbb8..196277f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-
+*~
 # /
 /build
 
diff --git a/.upstream_base_commits b/.upstream_base_commits
new file mode 100644
index 0000000..9423598
--- /dev/null
+++ b/.upstream_base_commits
@@ -0,0 +1,2 @@
+#freebsd = https://github.com/freebsd/freebsd.git
+chmod/chmod.1	freebsd	bin/chmod/chmod.1	14889ebf5bdeaead21c00f70044d9acbb923f6b0
diff --git a/chmod/chmod.1 b/chmod/chmod.1
index dccb953..0e89f26 100644
--- a/chmod/chmod.1
+++ b/chmod/chmod.1
@@ -1,3 +1,4 @@
+.\"-
 .\" Copyright (c) 1989, 1990, 1993, 1994
 .\"	The Regents of the University of California.  All rights reserved.
 .\"
@@ -12,11 +13,7 @@
 .\" 2. Redistributions in binary form must reproduce the above copyright
 .\"    notice, this list of conditions and the following disclaimer in the
 .\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"	This product includes software developed by the University of
-.\"	California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
+.\" 3. Neither the name of the University nor the names of its contributors
 .\"    may be used to endorse or promote products derived from this software
 .\"    without specific prior written permission.
 .\"
@@ -33,9 +30,9 @@
 .\" SUCH DAMAGE.
 .\"
 .\"	@(#)chmod.1	8.4 (Berkeley) 3/31/94
-.\" $FreeBSD: src/bin/chmod/chmod.1,v 1.33 2002/10/01 20:32:59 trhodes Exp $
+.\" $FreeBSD$
 .\"
-.Dd July 08, 2004
+.Dd January 7, 2017
 .Dt CHMOD 1
 .Os
 .Sh NAME
@@ -49,23 +46,23 @@
 .Ar
 .Nm chmod
 .Op Fl fv
-.Op Fl R Op Fl H | L | P 
+.Op Fl R Op Fl H | L | P
 .Op -a | +a | =a
 .Ar ACE
 .Ar
 .Nm chmod
 .Op Fl fhv
-.Op Fl R Op Fl H | L | P 
+.Op Fl R Op Fl H | L | P
 .Op Fl E
 .Ar
 .Nm chmod
 .Op Fl fhv
-.Op Fl R Op Fl H | L | P 
+.Op Fl R Op Fl H | L | P
 .Op Fl C
 .Ar
 .Nm chmod
 .Op Fl fhv
-.Op Fl R Op Fl H | L | P 
+.Op Fl R Op Fl H | L | P
 .Op Fl N
 .Ar
 .Sh DESCRIPTION
@@ -78,18 +75,19 @@ operand. It may also be used to modify the Access Control
 Lists (ACLs) associated with the listed files.
 .Pp
 The generic options are as follows:
-.Bl -tag -width Ds
+.Bl -tag -width indent
 .It Fl f
 Do not display a diagnostic message if
 .Nm chmod
 could not modify the mode for
-.Va file .
+.Va file ,
+nor modify the exit status to reflect such failures.
 .It Fl H
 If the
 .Fl R
-option is specified, symbolic links on the command line are followed.
-(Symbolic links encountered in the tree traversal are not followed by
-default.)
+option is specified, symbolic links on the command line are followed
+and hence unaffected by the command.
+(Symbolic links encountered during tree traversal are not followed.)
 .It Fl h
 If the file is a symbolic link, change the mode of the link itself
 rather than the file that the link points to.
@@ -103,8 +101,12 @@ If the
 option is specified, no symbolic links are followed.
 This is the default.
 .It Fl R
-Change the modes of the file hierarchies rooted in the files
+Change the modes of the file hierarchies rooted in the files,
 instead of just the files themselves.
+Beware of unintentionally matching the
+.Dq Pa ".."
+hard link to the parent directory when using wildcards like
+.Dq Li ".*" .
 .It Fl v
 Cause
 .Nm chmod
@@ -126,9 +128,19 @@ option is specified.
 In addition, these options override each other and the
 command's actions are determined by the last one specified.
 .Pp
+If
+.Nm chmod
+receives a
+.Dv SIGINFO
+signal (see the
+.Cm status
+argument for
+.Xr stty 1 ) ,
+then the current filename as well as the old and new modes are displayed.
+.Pp
 Only the owner of a file or the super-user is permitted to change
 the mode of a file.
-.Sh DIAGNOSTICS
+.Sh EXIT STATUS
 .Ex -std
 .Sh MODES
 Modes may be absolute or symbolic.
@@ -137,26 +149,28 @@ one or more of the following values:
 .Pp
 .Bl -tag -width 6n -compact -offset indent
 .It Li 4000
-(the set-user-ID-on-execution bit) Executable files with this bit set
+(the setuid bit).
+Executable files with this bit set
 will run with effective uid set to the uid of the file owner.
-Directories with the set-user-id bit set will force all files and
+Directories with this bit set will force all files and
 sub-directories created in them to be owned by the directory owner
 and not by the uid of the creating process, if the underlying file
 system supports this feature: see
 .Xr chmod 2
 and the
-.Ar suiddir
+.Cm suiddir
 option to
 .Xr mount 8 .
 .It Li 2000
-(the set-group-ID-on-execution bit) Executable files with this bit set
+(the setgid bit).
+Executable files with this bit set
 will run with effective gid set to the gid of the file owner.
 .It Li 1000
-(the sticky bit)
+(the sticky bit).
 See
 .Xr chmod 2
 and
-.Xr sticky 8 .
+.Xr sticky 7 .
 .It Li 0400
 Allow read by owner.
 .It Li 0200
@@ -250,6 +264,8 @@ If no value is supplied for
 each permission bit specified in
 .Ar perm ,
 for which the corresponding bit in the file mode creation mask
+(see
+.Xr umask 2 )
 is clear, is set.
 Otherwise, the mode bits represented by the specified
 .Ar who
@@ -265,7 +281,7 @@ If no value is supplied for
 each permission bit specified in
 .Ar perm ,
 for which the corresponding bit in the file mode creation mask
-is clear, is cleared.
+is set, is cleared.
 Otherwise, the mode bits represented by the specified
 .Ar who
 and
@@ -274,7 +290,9 @@ values are cleared.
 .It =
 The mode bits specified by the
 .Ar who
-value are cleared, or, if no who value is specified, the owner, group
+value are cleared, or, if no
+.Ar who
+value is specified, the owner, group
 and other mode bits are cleared.
 Then, if no value is supplied for
 .Ar who ,
@@ -299,6 +317,10 @@ Operations upon the other permissions only (specified by the symbol
 ``o'' by itself), in combination with the
 .Ar perm
 symbols ``s'' or ``t'', are ignored.
+.Pp
+The ``w'' permission on directories will permit file creation, relocation,
+and copy into that directory.
+Files created within the directory itself will inherit its group ID.
 .Sh EXAMPLES OF VALID MODES
 .Bl -tag -width "u=rwx,go=u-w" -compact
 .It Li 644
@@ -344,7 +366,7 @@ The following permissions are applicable to all filesystem objects:
 Delete the item.  Deletion may be granted by either this permission
 on an object or the delete_child right on the containing directory.
 .It readattr
-Read an objects basic attributes.  This is implicitly granted if 
+Read an object's basic attributes.  This is implicitly granted if 
 the object can be looked up and not explicitly denied.
 .It writeattr
 Write an object's basic attributes.
@@ -536,7 +558,7 @@ Individual entries are rewritten using the =a# mode.
    1: admin allow write,chown
 .Pp
 This mode may not be used to add new entries.
-.It Fl E    
+.It Fl E
 Reads the ACL information from stdin, as a sequential list
 of ACEs, separated by newlines.  If the information parses correctly,
 the existing information is replaced.
@@ -555,17 +577,16 @@ The
 option is non-standard and its use in scripts is not recommended.
 .Sh SEE ALSO
 .Xr chflags 1 ,
-.Xr fsaclctl 1 ,
 .Xr install 1 ,
 .Xr chmod 2 ,
 .Xr stat 2 ,
 .Xr umask 2 ,
 .Xr fts 3 ,
 .Xr setmode 3 ,
+.Xr sticky 7 ,
 .Xr symlink 7 ,
 .Xr chown 8 ,
-.Xr mount 8 ,
-.Xr sticky 8
+.Xr mount 8
 .Sh STANDARDS
 The
 .Nm chmod
diff --git a/chown/chgrp.1 b/chown/chgrp.1
index 769c3d5..593c609 100644
--- a/chown/chgrp.1
+++ b/chown/chgrp.1
@@ -43,7 +43,7 @@
 .Nd change group
 .Sh SYNOPSIS
 .Nm chgrp
-.Op Fl fhv
+.Op Fl fhnv
 .Oo
 .Fl R
 .Op Fl H | Fl L | Fl P
@@ -86,6 +86,8 @@ to change the group ID of a symbolic link.
 .It Fl R
 Change the group ID for the file hierarchies rooted
 in the files instead of just the files themselves.
+.It Fl n
+Interpret the group ID as numeric, avoiding the name lookup.
 .It Fl v
 Cause
 .Nm chgrp
diff --git a/chown/chown.8 b/chown/chown.8
index a3ffa09..3455497 100644
--- a/chown/chown.8
+++ b/chown/chown.8
@@ -40,7 +40,7 @@
 .Nd change file owner and group
 .Sh SYNOPSIS
 .Nm chown
-.Op Fl fhv
+.Op Fl fhnv
 .Oo
 .Fl R
 .Op Fl H | Fl L | Fl P
@@ -48,7 +48,7 @@
 .Ar owner Ns Op : Ns Ar group
 .Ar
 .Nm chown
-.Op Fl fhv
+.Op Fl fhnv
 .Oo
 .Fl R
 .Op Fl H | Fl L | Fl P
@@ -91,6 +91,8 @@ to change the user ID and/or the group of symbolic links.
 .It Fl R
 Change the user ID and/or the group ID for the file hierarchies rooted
 in the files instead of just the files themselves.
+.It Fl n
+Interpret user ID and group ID as numeric, avoiding name lookups.
 .It Fl v
 Cause
 .Nm chown
diff --git a/chown/chown.c b/chown/chown.c
index 74f1759..708a6c5 100644
--- a/chown/chown.c
+++ b/chown/chown.c
@@ -76,6 +76,9 @@ void	usage(void);
 uid_t uid;
 gid_t gid;
 int ischown;
+#ifdef __APPLE__
+int isnumeric = 0;
+#endif
 const char *gname;
 
 int
@@ -96,7 +99,11 @@ main(int argc, char **argv)
 	ischown = (strcmp(cp, "chown") == 0);
 
 	Hflag = Lflag = Pflag = Rflag = fflag = hflag = vflag = 0;
+#ifdef __APPLE__
+	while ((ch = getopt(argc, argv, "HLPRfhnv")) != -1)
+#else
 	while ((ch = getopt(argc, argv, "HLPRfhv")) != -1)
+#endif
 		switch (ch) {
 		case 'H':
 			Hflag = 1;
@@ -119,6 +126,11 @@ main(int argc, char **argv)
 		case 'h':
 			hflag = 1;
 	 		break;
+#ifdef __APPLE__
+		case 'n':
+			isnumeric = 1;
+			break;
+#endif
 		case 'v':
 			vflag = 1;
 			break;
@@ -246,7 +258,11 @@ a_gid(const char *s)
 	if (*s == '\0')			/* Argument was "uid[:.]". */
 		return;
 	gname = s;
+#ifdef __APPLE__
+	gid = (!isnumeric && ((gr = getgrnam(s)) != NULL)) ? gr->gr_gid : id(s, "group");
+#else
 	gid = ((gr = getgrnam(s)) != NULL) ? gr->gr_gid : id(s, "group");
+#endif
 }
 
 void
@@ -256,7 +272,11 @@ a_uid(const char *s)
 
 	if (*s == '\0')			/* Argument was "[:.]gid". */
 		return;
+#ifdef __APPLE__
+	uid = (!isnumeric && ((pw = getpwnam(s)) != NULL)) ? pw->pw_uid : id(s, "user");
+#else
 	uid = ((pw = getpwnam(s)) != NULL) ? pw->pw_uid : id(s, "user");
+#endif
 }
 
 static uid_t
@@ -305,11 +325,21 @@ usage(void)
 
 	if (ischown)
 		(void)fprintf(stderr, "%s\n%s\n",
+#ifdef __APPLE__
+		    "usage: chown [-fhnv] [-R [-H | -L | -P]] owner[:group]"
+		    " file ...",
+		    "       chown [-fhnv] [-R [-H | -L | -P]] :group file ...");
+#else
 		    "usage: chown [-fhv] [-R [-H | -L | -P]] owner[:group]"
 		    " file ...",
 		    "       chown [-fhv] [-R [-H | -L | -P]] :group file ...");
+#endif
 	else
 		(void)fprintf(stderr, "%s\n",
+#ifdef __APPLE__
+		    "usage: chgrp [-fhnv] [-R [-H | -L | -P]] group file ...");
+#else
 		    "usage: chgrp [-fhv] [-R [-H | -L | -P]] group file ...");
+#endif
 	exit(1);
 }
diff --git a/compress/compress.c b/compress/compress.c
index 17d100f..26da7fa 100644
--- a/compress/compress.c
+++ b/compress/compress.c
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD: src/usr.bin/compress/compress.c,v 1.23 2010/12/11 08:32:16 j
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <locale.h>
 
 #include "zopen.h"
 
@@ -412,14 +413,23 @@ int
 permission(const char *fname)
 {
 	int ch, first;
+	char resp[] = {'\0', '\0'};
 
 	if (!isatty(fileno(stderr)))
 		return (0);
 	(void)fprintf(stderr, "overwrite %s? ", fname);
+
+	/* Load user specified locale */
+	setlocale(LC_MESSAGES, "");
+
 	first = ch = getchar();
 	while (ch != '\n' && ch != EOF)
 		ch = getchar();
-	return (first == 'y');
+
+	/* only care about first character */
+	resp[0] = first;
+
+	return (rpmatch(resp) == 1);
 }
 
 void
diff --git a/cp/utils.c b/cp/utils.c
index afc525a..af05cc3 100644
--- a/cp/utils.c
+++ b/cp/utils.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD: src/bin/cp/utils.c,v 1.46 2005/09/05 04:36:08 csjp Exp $");
 #include <stdlib.h>
 #include <sysexits.h>
 #include <unistd.h>
+#include <locale.h>
 
 #ifdef __APPLE__
 #include <sys/time.h>
@@ -79,6 +80,7 @@ copy_file(const FTSENT *entp, int dne)
 	size_t wresid;
 	off_t wtotal;
 	char *bufp;
+	char resp[] = {'\0', '\0'};
 #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
 	char *p;
 #endif
@@ -110,10 +112,18 @@ copy_file(const FTSENT *entp, int dne)
 		} else if (iflag) {
 			(void)fprintf(stderr, "overwrite %s? %s", 
 					to.p_path, YESNO);
+
+			/* Load user specified locale */
+			setlocale(LC_MESSAGES, "");
+
 			checkch = ch = getchar();
 			while (ch != '\n' && ch != EOF)
 				ch = getchar();
-			if (checkch != 'y' && checkch != 'Y') {
+
+			/* only care about the first character */
+			resp[0] = checkch;
+
+			if (rpmatch(resp) != 1) {
 				(void)close(from_fd);
 				(void)fprintf(stderr, "not overwritten\n");
 				return (1);
diff --git a/du/du.c b/du/du.c
index c49d901..1bf6bc5 100644
--- a/du/du.c
+++ b/du/du.c
@@ -70,6 +70,7 @@ __FBSDID("$FreeBSD: src/usr.bin/du/du.c,v 1.38 2005/04/09 14:31:40 stefanf Exp $
 
 #ifdef __APPLE__
 #include <get_compat.h>
+#include <sys/sysctl.h>
 #else
 #define COMPAT_MODE(func, mode) (1)
 #endif
@@ -255,6 +256,13 @@ main(int argc, char *argv[])
 	(void) getbsize(&notused, &blocksize);
 	blocksize /= 512;
 
+#ifdef __APPLE__
+	// "du" should not have any side effect on disk usage,
+	// so prevent materializing dataless directories upon traversal
+	rval = 1;
+	(void) sysctlbyname("vfs.nspace.prevent_materialization", NULL, NULL, &rval, sizeof(rval));
+#endif /* __APPLE__ */
+
 	rval = 0;
 
 	if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL)
diff --git a/file_cmds.xcodeproj/project.pbxproj b/file_cmds.xcodeproj/project.pbxproj
index be7b451..c6e9610 100644
--- a/file_cmds.xcodeproj/project.pbxproj
+++ b/file_cmds.xcodeproj/project.pbxproj
@@ -7,6 +7,18 @@
 	objects = {
 
 /* Begin PBXAggregateTarget section */
+		3E966CE71FB2211F0019F7A1 /* tests */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = 3E966CE91FB2211F0019F7A1 /* Build configuration list for PBXAggregateTarget "tests" */;
+			buildPhases = (
+				3E966CED1FB2215C0019F7A1 /* CopyFiles */,
+				3E966CEF1FB221740019F7A1 /* CopyFiles */,
+			);
+			dependencies = (
+			);
+			name = tests;
+			productName = tests;
+		};
 		FC8A8C3C14B64A9D001B97AD /* shar */ = {
 			isa = PBXAggregateTarget;
 			buildConfigurationList = FC8A8C3D14B64A9D001B97AD /* Build configuration list for PBXAggregateTarget "shar" */;
@@ -186,6 +198,8 @@
 
 /* Begin PBXBuildFile section */
 		3E59B9311D4A767600D3128C /* futimens.c in Sources */ = {isa = PBXBuildFile; fileRef = 3E59B9301D4A767600D3128C /* futimens.c */; };
+		3E966CEE1FB2216F0019F7A1 /* file_cmds.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3E966CEC1FB2214F0019F7A1 /* file_cmds.plist */; };
+		3E966CF01FB2218A0019F7A1 /* chgrp.sh in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3E966CEB1FB2214F0019F7A1 /* chgrp.sh */; };
 		FC8A8A2814B6486E001B97AD /* chflags.c in Sources */ = {isa = PBXBuildFile; fileRef = FCB1BDCC14B6460C0070FACB /* chflags.c */; };
 		FC8A8BE414B6494B001B97AD /* chflags.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FCB1BDCB14B6460C0070FACB /* chflags.1 */; };
 		FC8A8BE514B64958001B97AD /* chmod.c in Sources */ = {isa = PBXBuildFile; fileRef = FCB1BDD014B6460C0070FACB /* chmod.c */; };
@@ -200,7 +214,6 @@
 		FC8A8BEF14B6497A001B97AD /* sum1.c in Sources */ = {isa = PBXBuildFile; fileRef = FCB1BDE114B6460C0070FACB /* sum1.c */; };
 		FC8A8BF014B6497D001B97AD /* sum2.c in Sources */ = {isa = PBXBuildFile; fileRef = FCB1BDE214B6460C0070FACB /* sum2.c */; };
 		FC8A8BF114B64982001B97AD /* compress.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FCB1BDE414B6460C0070FACB /* compress.1 */; };
-		FC8A8BF214B64984001B97AD /* uncompress.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FCB1BDEB14B6460C0070FACB /* uncompress.1 */; };
 		FC8A8BF314B64988001B97AD /* compress.c in Sources */ = {isa = PBXBuildFile; fileRef = FCB1BDE514B6460C0070FACB /* compress.c */; };
 		FC8A8BF414B6498A001B97AD /* zopen.c in Sources */ = {isa = PBXBuildFile; fileRef = FCB1BDEE14B6460C0070FACB /* zopen.c */; };
 		FC8A8BF514B64995001B97AD /* cp.c in Sources */ = {isa = PBXBuildFile; fileRef = FCB1BDF214B6460C0070FACB /* cp.c */; };
@@ -798,6 +811,26 @@
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXCopyFilesBuildPhase section */
+		3E966CED1FB2215C0019F7A1 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = /AppleInternal/CoreOS/BATS/unit_tests;
+			dstSubfolderSpec = 0;
+			files = (
+				3E966CEE1FB2216F0019F7A1 /* file_cmds.plist in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		3E966CEF1FB221740019F7A1 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = /AppleInternal/Tests/file_cmds;
+			dstSubfolderSpec = 0;
+			files = (
+				3E966CF01FB2218A0019F7A1 /* chgrp.sh in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		FC8A8B0F14B648D7001B97AD /* CopyFiles */ = {
 			isa = PBXCopyFilesBuildPhase;
 			buildActionMask = 2147483647;
@@ -834,7 +867,6 @@
 			dstPath = /usr/share/man/man1/;
 			dstSubfolderSpec = 0;
 			files = (
-				FC8A8BF214B64984001B97AD /* uncompress.1 in CopyFiles */,
 				FC8A8BF114B64982001B97AD /* compress.1 in CopyFiles */,
 			);
 			runOnlyForDeploymentPostprocessing = 1;
@@ -1146,6 +1178,8 @@
 /* Begin PBXFileReference section */
 		0773099A1A3A4DFE00E9B4EA /* dd.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = dd.entitlements; sourceTree = "<group>"; };
 		3E59B9301D4A767600D3128C /* futimens.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = futimens.c; sourceTree = "<group>"; };
+		3E966CEB1FB2214F0019F7A1 /* chgrp.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = chgrp.sh; sourceTree = "<group>"; };
+		3E966CEC1FB2214F0019F7A1 /* file_cmds.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = file_cmds.plist; sourceTree = "<group>"; };
 		FC8A8B1214B648D7001B97AD /* chmod */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = chmod; sourceTree = BUILT_PRODUCTS_DIR; };
 		FC8A8B1A14B648E0001B97AD /* chown */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = chown; sourceTree = BUILT_PRODUCTS_DIR; };
 		FC8A8B2214B648E3001B97AD /* cksum */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = cksum; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1235,7 +1269,7 @@
 		FCB1BE1D14B6460C0070FACB /* symlink.7 */ = {isa = PBXFileReference; lastKnownFileType = text; path = symlink.7; sourceTree = "<group>"; };
 		FCB1BE1F14B6460C0070FACB /* cmp.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = cmp.c; sourceTree = "<group>"; };
 		FCB1BE2014B6460C0070FACB /* extern.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = extern.h; sourceTree = "<group>"; };
-		FCB1BE2114B6460C0070FACB /* ls.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = ls.1; sourceTree = "<group>"; };
+		FCB1BE2114B6460C0070FACB /* ls.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; lineEnding = 0; path = ls.1; sourceTree = "<group>"; };
 		FCB1BE2214B6460C0070FACB /* ls.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ls.c; sourceTree = "<group>"; };
 		FCB1BE2314B6460C0070FACB /* ls.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ls.h; sourceTree = "<group>"; };
 		FCB1BE2514B6460C0070FACB /* print.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = print.c; sourceTree = "<group>"; };
@@ -1528,9 +1562,19 @@
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+		3E966CEA1FB221330019F7A1 /* tests */ = {
+			isa = PBXGroup;
+			children = (
+				3E966CEB1FB2214F0019F7A1 /* chgrp.sh */,
+				3E966CEC1FB2214F0019F7A1 /* file_cmds.plist */,
+			);
+			path = tests;
+			sourceTree = "<group>";
+		};
 		FCB1BDAD14B645D00070FACB = {
 			isa = PBXGroup;
 			children = (
+				3E966CEA1FB221330019F7A1 /* tests */,
 				FCB1BDCA14B6460C0070FACB /* chflags */,
 				FCB1BDCE14B6460C0070FACB /* chmod */,
 				FCB1BDD414B6460C0070FACB /* chown */,
@@ -2448,12 +2492,19 @@
 			attributes = {
 				LastUpgradeCheck = 0610;
 				ORGANIZATIONNAME = "Apple Inc.";
+				TargetAttributes = {
+					3E966CE71FB2211F0019F7A1 = {
+						CreatedOnToolsVersion = 9.2;
+						ProvisioningStyle = Automatic;
+					};
+				};
 			};
 			buildConfigurationList = FCB1BDB214B645D00070FACB /* Build configuration list for PBXProject "file_cmds" */;
 			compatibilityVersion = "Xcode 3.2";
 			developmentRegion = English;
 			hasScannedForEncodings = 0;
 			knownRegions = (
+				English,
 				en,
 			);
 			mainGroup = FCB1BDAD14B645D00070FACB;
@@ -2496,6 +2547,7 @@
 				FC8A8BCC14B648F0001B97AD /* touch */,
 				FC8A8CC814B65F92001B97AD /* uncompress */,
 				FC8A8C5014B650CF001B97AD /* unlink */,
+				3E966CE71FB2211F0019F7A1 /* tests */,
 			);
 		};
 /* End PBXProject section */
@@ -3268,6 +3320,14 @@
 /* End PBXTargetDependency section */
 
 /* Begin XCBuildConfiguration section */
+		3E966CE81FB2211F0019F7A1 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CODE_SIGN_STYLE = Automatic;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
 		FC8A8B1114B648D7001B97AD /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
@@ -3563,6 +3623,14 @@
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
+		3E966CE91FB2211F0019F7A1 /* Build configuration list for PBXAggregateTarget "tests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				3E966CE81FB2211F0019F7A1 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 		FC8A8B1014B648D7001B97AD /* Build configuration list for PBXNativeTarget "chmod" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
diff --git a/install/xinstall.c b/install/xinstall.c
index 05b6500..5e6bcec 100644
--- a/install/xinstall.c
+++ b/install/xinstall.c
@@ -529,11 +529,7 @@ install(from_name, to_name, fset, flags)
 	if (!devnull)
 		(void)close(from_fd);
 }
-#if TARGET_OS_EMBEDDED
-#define BUFFER_SIZE 128*1024
-#else  /* !TARGET_OS_EMBEDDED */
-#define BUFFER_SIZE MAXBSIZE
-#endif	/* TARGET_OS_EMBEDDED */
+
 /*
  * compare --
  *	compare two files; non-zero means files differ
@@ -569,8 +565,8 @@ compare(int from_fd, const char *from_name, size_t from_len,
 		}
 	out:
 		if (!done_compare) {
-			char buf1[BUFFER_SIZE];
-			char buf2[BUFFER_SIZE];
+			char buf1[MAXBSIZE];
+			char buf2[MAXBSIZE];
 			int n1, n2;
 
 			rv = 0;
@@ -673,7 +669,8 @@ copy(from_fd, from_name, to_fd, to_name, size)
 {
 	register int nr, nw;
 	int serrno;
-	char *p, buf[BUFFER_SIZE];
+	char *p;
+	char buf[MAXBSIZE];
 	int done_copy;
 
 	/* Rewind file descriptors. */
diff --git a/ls/ls.1 b/ls/ls.1
index 12e8af5..b75c1ae 100644
--- a/ls/ls.1
+++ b/ls/ls.1
@@ -43,7 +43,7 @@
 .Nd list directory contents
 .Sh SYNOPSIS
 .Nm ls
-.Op Fl ABCFGHLOPRSTUW@abcdefghiklmnopqrstuwx1
+.Op Fl ABCFGHLOPRSTUW@abcdefghiklmnopqrstuwx1%
 .Op Ar
 .Sh DESCRIPTION
 For each operand that names a
@@ -188,7 +188,7 @@ option.
 .Dq ell . )
 List in long format.
 (See below.)
-If the output is to a terminal, a total sum for all the file
+A total sum for all the file
 sizes is output on a line before the long listing.
 .It Fl m
 Stream output format; list files across the page, separated by commas.
@@ -278,6 +278,10 @@ The same as
 .Fl C ,
 except that the multi-column output is produced with entries sorted
 across, rather than down, the columns.
+.It Fl %
+Distinguish dataless files and directories with a '%' character in long
+.Pq Fl l
+output, and don't materialize dataless directories when listing them.
 .El
 .Pp
 The
@@ -349,6 +353,11 @@ Otherwise, if the file or directory has extended security information
 the permissions field printed by the 
 .Fl l
 option is followed by a '+' character.
+If the
+.Fl %
+option is given, a '%' character follows the permissions field
+for dataless files and directories,
+possibly replacing the '@' or '+' character.
 .Pp
 If the modification time of the file
 is more than 6 months in the past or future,
diff --git a/ls/ls.c b/ls/ls.c
index ab8b756..7823b55 100644
--- a/ls/ls.c
+++ b/ls/ls.c
@@ -74,6 +74,8 @@ __RCSID("$FreeBSD: src/bin/ls/ls.c,v 1.66 2002/09/21 01:28:36 wollman Exp $");
 #include <sys/xattr.h>
 #include <sys/param.h>
 #include <get_compat.h>
+#include <sys/sysctl.h>
+#include <System/sys/fsctl.h>
 #else
 #define COMPAT_MODE(a,b) (1)
 #endif /* __APPLE__ */
@@ -131,6 +133,8 @@ static int f_whiteout;		/* show whiteout entries */
        int f_xattr;		/* show extended attributes in long listing */
        int f_group;		/* show group */
        int f_owner;		/* show owner */
+       int f_dataless;          /* distinguish dataless files in long listing,
+				   and don't materialize dataless directories. */
 #ifdef COLORLS
        int f_color;		/* add type in color for non-regular files */
 
@@ -182,7 +186,7 @@ main(int argc, char *argv[])
 		f_listdot = 1;
 
 	fts_options = FTS_PHYSICAL;
- 	while ((ch = getopt(argc, argv, "1@ABCFGHLOPRSTUWabcdefghiklmnopqrstuvwx")) 
+	while ((ch = getopt(argc, argv, "1@ABCFGHLOPRSTUWabcdefghiklmnopqrstuvwx%"))
 	    != -1) {
 		switch (ch) {
 		/*
@@ -364,6 +368,9 @@ main(int argc, char *argv[])
 		case 'O':
 			f_flags = 1;
 			break;
+		case '%':
+			f_dataless = 1;
+			break;
 		default:
 		case '?':
 			usage();
@@ -484,6 +491,17 @@ main(int argc, char *argv[])
 	else
 		printfcn = printcol;
 
+#ifdef __APPLE__
+	if (f_dataless) {
+		// don't materialize dataless directories from the cloud
+		// (particularly usefull when listing recursively)
+		int state = 1;
+		if (sysctlbyname("vfs.nspace.prevent_materialization", NULL, NULL, &state, sizeof(state)) < 0) {
+			err(1, "prevent_materialization");
+		}
+	}
+#endif /* __APPLE__ */
+
 	if (argc)
 		traverse(argc, argv, fts_options);
 	else
@@ -833,6 +851,9 @@ display(FTSENT *p, FTSENT *list)
 				} else {
 					np->mode_suffix = ' ';
 				}
+				if (f_dataless && (sp->st_flags & SF_DATALESS)) {
+					np->mode_suffix = '%';
+				}
 				if (!f_acl) {
 					acl_free(np->acl);
 					np->acl = NULL;
diff --git a/ls/ls.h b/ls/ls.h
index 14babbb..5b4769b 100644
--- a/ls/ls.h
+++ b/ls/ls.h
@@ -97,7 +97,7 @@ typedef struct {
 	int	*xattr_sizes;
 	acl_t	acl;		/* f_acl */
         int	xattr_count;
-	char	mode_suffix;	/* @ | + | <space> */
+	char	mode_suffix;	/* @ | + | % | <space> */
 #endif /* __APPLE__ */
 	char data[1];
 } NAMES;
diff --git a/ls/util.c b/ls/util.c
index de79f13..1aae3f1 100644
--- a/ls/util.c
+++ b/ls/util.c
@@ -222,9 +222,9 @@ usage(void)
 {
 	(void)fprintf(stderr,
 #ifdef COLORLS
-	"usage: ls [-ABCFGHLOPRSTUWabcdefghiklmnopqrstuwx1]"
+	"usage: ls [-@ABCFGHLOPRSTUWabcdefghiklmnopqrstuwx1%%]"
 #else
-	"usage: ls [-ABCFHLOPRSTUWabcdefghiklmnopqrstuwx1]"
+	"usage: ls [-@ABCFHLOPRSTUWabcdefghiklmnopqrstuwx1%%]"
 #endif
 		      " [file ...]\n");
 	exit(1);
diff --git a/mv/mv.c b/mv/mv.c
index 0576c43..52a2938 100644
--- a/mv/mv.c
+++ b/mv/mv.c
@@ -67,6 +67,7 @@ __RCSID("$FreeBSD: src/bin/mv/mv.c,v 1.39 2002/07/09 17:45:13 johan Exp $");
 #include <string.h>
 #include <sysexits.h>
 #include <unistd.h>
+#include <locale.h>
 
 #ifdef __APPLE__
 #include <copyfile.h>
@@ -240,6 +241,7 @@ do_move(char *from, char *to)
 	struct stat sb;
 	int ask, ch, first;
 	char modep[15];
+	char resp[] = {'\0', '\0'};
 
 	/*
 	 * Check access.  If interactive and file exists, ask user if it
@@ -272,10 +274,17 @@ do_move(char *from, char *to)
 			ask = 1;
 		}
 		if (ask) {
+			/* Load user specified locale */
+			setlocale(LC_MESSAGES, "");
+
 			first = ch = getchar();
 			while (ch != '\n' && ch != EOF)
 				ch = getchar();
-			if (first != 'y' && first != 'Y') {
+
+			/* only care about the first character */
+			resp[0] = first;
+
+			if (rpmatch(resp) != 1) {
 				(void)fprintf(stderr, "not overwritten\n");
 				return (0);
 			}
diff --git a/rm/rm.c b/rm/rm.c
index 9022802..956c245 100644
--- a/rm/rm.c
+++ b/rm/rm.c
@@ -60,12 +60,17 @@ __used static const char rcsid[] =
 #include <string.h>
 #include <sysexits.h>
 #include <unistd.h>
+#include <locale.h>
 
 #ifdef __APPLE__
 #include <removefile.h>
 #include <pwd.h>
 #include <grp.h>
 #include "get_compat.h"
+
+#ifndef AT_REMOVEDIR_DATALESS
+#define AT_REMOVEDIR_DATALESS   0x0100  /* Remove a dataless directory without materializing first */
+#endif
 #else
 #define COMPAT_MODE(func, mode) 1
 #endif
@@ -280,7 +285,15 @@ rm_tree(argv)
 			switch (p->fts_info) {
 			case FTS_DP:
 			case FTS_DNR:
+#if __APPLE__
+				if (p->fts_statp != NULL && (p->fts_statp->st_flags & SF_DATALESS) != 0)
+					rval = unlinkat(AT_FDCWD, p->fts_accpath, AT_REMOVEDIR_DATALESS);
+				else
+					rval = rmdir(p->fts_accpath);
+#else
+
 				rval = rmdir(p->fts_accpath);
+#endif
 				if (rval == 0 || (fflag && errno == ENOENT)) {
 					if (rval == 0 && vflag)
 						(void)printf("%s\n",
@@ -465,12 +478,21 @@ int
 yes_or_no()
 {
 	int ch, first;
+	char resp[] = {'\0', '\0'};
+
 	(void)fflush(stderr);
 
+	/* Load user specified locale */
+	setlocale(LC_MESSAGES, "");
+
 	first = ch = getchar();
 	while (ch != '\n' && ch != EOF)
 		ch = getchar();
-	return (first == 'y' || first == 'Y');
+
+	/* only care about the first character */
+	resp[0] = first;
+
+	return (rpmatch(resp) == 1);
 }
 
 int
diff --git a/stat/stat.c b/stat/stat.c
index 095900e..610eff9 100644
--- a/stat/stat.c
+++ b/stat/stat.c
@@ -731,7 +731,14 @@ format1(const struct stat *st,
 		small = (sizeof(st->st_flags) == 4);
 		data = st->st_flags;
 		sdata = NULL;
-		formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX;
+		formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX |
+			FMTF_STRING;
+		if (ofmt == FMTF_STRING) {
+			small = 0;
+			data = 0;
+			snprintf(path, sizeof(path), "%s", fflagstostr(st->st_flags));
+			sdata = path;
+		}
 		if (ofmt == 0)
 			ofmt = FMTF_UNSIGNED;
 		break;
diff --git a/tests/chgrp.sh b/tests/chgrp.sh
new file mode 100644
index 0000000..503fbf1
--- /dev/null
+++ b/tests/chgrp.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+GROUPID=31337
+
+dscl /Local/Default -read /Groups/$GROUPID > /dev/null 2>&1
+if [ $? != "0" ]; then
+	dscl /Local/Default -create /Groups/$GROUPID 
+	dscl /Local/Default -create /Groups/$GROUPID PrimaryGroupID 9999
+fi
+
+mkdir /tmp/$$
+chgrp $GROUPID /tmp/$$
+gid=`/usr/bin/stat -f '%g' /tmp/$$`
+if [ "$gid" != "9999" ]; then
+	echo "chgrp $GROUPID, expected group 9999, is $gid"
+	exit 1
+fi
+
+chgrp -n $GROUPID /tmp/$$
+gid=`/usr/bin/stat -f '%g' /tmp/$$`
+if [ "$gid" != "$GROUPID" ]; then
+	echo "chgrp -n $GROUPID, expected group $GROUPID, is $gid"
+	exit 1
+fi
+
+exit 0
diff --git a/tests/file_cmds.plist b/tests/file_cmds.plist
new file mode 100644
index 0000000..4e4d135
--- /dev/null
+++ b/tests/file_cmds.plist
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>Project</key>
+	<string>file_cmds</string>
+	<key>IgnoreOutput</key>
+	<true/>
+	<key>Tests</key>
+	<array>
+		<dict>
+			<key>Command</key>
+			<array>
+				<string>/bin/sh</string>
+				<string>chgrp.sh</string>
+			</array>
+			<key>AsRoot</key>
+			<true/>
+			<key>TestName</key>
+			<string>chgrp</string>
+			<key>WhenToRun</key>
+			<array>
+				<string>PRESUBMISSION</string>
+				<string>NIGHTLY</string>
+			</array>
+			<key>WorkingDirectory</key>
+			<string>/AppleInternal/Tests/file_cmds</string>
+		</dict>
+	</array>
+	<key>Timeout</key>
+	<integer>30</integer>
+</dict>
+</plist>