From: Matthew Martin <phy1729@gmail.com>
To: dana <dana@dana.is>
Cc: zsh-workers@zsh.org
Subject: Re: Add chmod builtin
Date: Sun, 17 Mar 2019 19:44:27 -0500 [thread overview]
Message-ID: <CAGnh9tAP0eco+_qQb6nyx3QRFwqP+XMD=WmQayAXBNz5jm7zqw@mail.gmail.com> (raw)
In-Reply-To: <5A60CD98-F8E0-425F-AB77-C88DE7A9CBD2@dana.is>
[-- Attachment #1: Type: text/plain, Size: 1170 bytes --]
On Sun, Mar 17, 2019 at 6:27 AM dana <dana@dana.is> wrote:
> >+if zmodload -e zsh/files && [[ $words[1] != */* ]]; then
>
> I don't think this is reliable. It will detect any chmod as the built-in even
> if only zf_chown is loaded (with -F). And `zmodload -e` always returns 1 for
> modules loaded through selective auto-loading (-Fa), so it will *never*
> detect the built-in in that case. (Not sure if that -e behaviour is intended?)
>
> I know the $OSTYPE-$variant thing is dumb (should have passed $OSTYPE directly
> to _pick_variant), but otherwise i think the method i used for distinguishing
> the built-ins in _stat is fairly robust.
Reading the docs for _pick_variant, there's a -b option to detect
builtins. It has some issues (namely with precommands), but those can be
fixed in a separate commit. Requires some reindenting, so I've split the
patch in two.
> PS: Your patch seems to have corrupt white space
Gmail hasn't been sending mails sent via mutt for the past few months.
Not sure what's causing it, but I've had to resort to using the web
interface which seems to mangle whitespace. I've attached the patches
and they're on my github repo as well.
[-- Attachment #2: 0001-44135-_chmod-Reformat-to-minimize-next-diff.-No-func.patch --]
[-- Type: text/x-patch, Size: 4760 bytes --]
From 2f670be951b1b6e242691562a9daf06010bfce99 Mon Sep 17 00:00:00 2001
From: Matthew Martin <phy1729@gmail.com>
Date: Sun, 17 Mar 2019 19:24:56 -0500
Subject: [PATCH 1/2] 44135: _chmod: Reformat to minimize next diff. No
functional change.
---
Completion/Unix/Command/_chmod | 94 ++++++++++++++++++----------------
1 file changed, 50 insertions(+), 44 deletions(-)
diff --git a/Completion/Unix/Command/_chmod b/Completion/Unix/Command/_chmod
index af64b9eb9..6a44a4ef1 100644
--- a/Completion/Unix/Command/_chmod
+++ b/Completion/Unix/Command/_chmod
@@ -1,52 +1,58 @@
#compdef chmod gchmod
-local curcontext="$curcontext" state line expl ret=1
+local curcontext="$curcontext" state line expl ret=1 variant
local -a args privs
args=( '*: :->files' '1: :_file_modes' )
-if _pick_variant gnu=Free\ Soft unix --version; then
- args+=(
- '(-v --verbose -c --changes)'{-c,--changes}'[report changes made]'
- '(-v --verbose -c --changes)'{-v,--verbose}'[output a diagnostic for every file processed]'
- '(-f --silent --quiet)'{-f,--silent,--quiet}'[suppress most error messages]'
- '(--no-preserve-root)--preserve-root[fail to operate recursively on /]'
- "(--preserve-root)--no-preserve-root[don't treat / specially (default)]"
- '(1)--reference=[copy permissions of specified file]:file:_files'
- '(-R --recursive)'{-R,--recursive}'[change files and directories recursively]'
- '(- : *)--help[display help information]'
- '(- : *)--version[display version information]'
- )
-else
- args+=(
- '-f[suppress most error messages]'
- '-R[change files and directories recursively]'
- )
- case $OSTYPE in
- freebsd*|dragonfly*|darwin*)
- args+=( '-v[output a diagnostic for every file processed]')
+_pick_variant -r variant gnu=Free\ Soft $OSTYPE --version
+case "$variant" in
+ gnu)
+ args+=(
+ '(-v --verbose -c --changes)'{-c,--changes}'[report changes made]'
+ '(-v --verbose -c --changes)'{-v,--verbose}'[output a diagnostic for every file processed]'
+ '(-f --silent --quiet)'{-f,--silent,--quiet}'[suppress most error messages]'
+ '(--no-preserve-root)--preserve-root[fail to operate recursively on /]'
+ "(--preserve-root)--no-preserve-root[don't treat / specially (default)]"
+ '(1)--reference=[copy permissions of specified file]:file:_files'
+ '(-R --recursive)'{-R,--recursive}'[change files and directories recursively]'
+ '(- : *)--help[display help information]'
+ '(- : *)--version[display version information]'
+ )
+ ;;
+ *)
+ args+=(
+ '-f[suppress most error messages]'
+ '-R[change files and directories recursively]'
+ )
+ ;|
+ freebsd*|dragonfly*|darwin*)
+ args+=(
+ '-v[output a diagnostic for every file processed]'
+ )
;|
- freebsd*|netbsd*|darwin*|dragonfly*)
- args+=( "-h[operate on symlinks them self]" )
+ freebsd*|netbsd*|darwin*|dragonfly*)
+ args+=(
+ '-h[operate on symlinks them self]'
+ )
;|
- freebsd*|openbsd*|netbsd*|darwin*|dragonfly*)
- args+=(
- '(-H -L -P)-L[follow all symlinks]'
- '(-H -L -P)-H[follow symlinks on the command line]'
- '(-H -L -P)-P[do not follow symlinks (default)]'
- )
+ freebsd*|openbsd*|netbsd*|darwin*|dragonfly*)
+ args+=(
+ '(-H -L -P)-L[follow all symlinks]'
+ '(-H -L -P)-H[follow symlinks on the command line]'
+ '(-H -L -P)-P[do not follow symlinks (default)]'
+ )
;|
- darwin*)
- args+=(
- '(1)-C[returns false if any of the named files have ACLs]'
- '(1)-N[remove ACLs from specified files]'
- '(1)-E[read ACL info from stdin as a sequential list of ACEs]'
- '(1)-i[removes inherited bit from all entries in named files ACLs]'
- '(1)-I[removes all inherited entries from named files ACLs]'
- )
+ darwin*)
+ args+=(
+ '(1)-C[returns false if any of the named files have ACLs]'
+ '(1)-N[remove ACLs from specified files]'
+ '(1)-E[read ACL info from stdin as a sequential list of ACEs]'
+ '(1)-i[removes inherited bit from all entries in named files ACLs]'
+ '(1)-I[removes all inherited entries from named files ACLs]'
+ )
;;
- esac
-fi
+esac
_arguments -C -s "$args[@]" && ret=0
@@ -62,12 +68,12 @@ case "$state" in
local spec who op priv
local -a specs
for spec in ${(s:,:)line[1]}; do
- if [[ ${spec#*[+-=]} != [rwxst]## ]]; then
- _files && ret=0
- return ret
- fi
+ if [[ ${spec#*[+-=]} != [rwxst]## ]]; then
+ _files && ret=0
+ return ret
+ fi
- specs+=( ${${(M)spec##[+-=]*}:+a}$spec )
+ specs+=( ${${(M)spec##[+-=]*}:+a}$spec )
done
_wanted files expl file _files -g "*(-.^f:${(j.,.)specs}:)" && ret=0
fi
--
2.21.0
[-- Attachment #3: 0002-44135-Add-chmod-builtin.patch --]
[-- Type: text/x-patch, Size: 4874 bytes --]
From 8d526281e56cec6579892706c2c305246269b7eb Mon Sep 17 00:00:00 2001
From: Matthew Martin <phy1729@gmail.com>
Date: Sun, 17 Mar 2019 19:30:47 -0500
Subject: [PATCH 2/2] 44135: Add chmod builtin
---
Completion/Unix/Command/_chmod | 13 +++++++++--
Doc/Zsh/mod_files.yo | 20 +++++++++++++++++
Src/Modules/files.c | 41 ++++++++++++++++++++++++++++++++++
3 files changed, 72 insertions(+), 2 deletions(-)
diff --git a/Completion/Unix/Command/_chmod b/Completion/Unix/Command/_chmod
index 6a44a4ef1..89a7fbd43 100644
--- a/Completion/Unix/Command/_chmod
+++ b/Completion/Unix/Command/_chmod
@@ -1,12 +1,21 @@
-#compdef chmod gchmod
+#compdef chmod gchmod zf_chmod
local curcontext="$curcontext" state line expl ret=1 variant
local -a args privs
args=( '*: :->files' '1: :_file_modes' )
-_pick_variant -r variant gnu=Free\ Soft $OSTYPE --version
+_pick_variant -r variant -b zsh gnu=Free\ Soft $OSTYPE --version
case "$variant" in
+ zsh)
+ # Assign, not append because zf_chmod only supports octal modes.
+ args=(
+ '-R[change files and directories recursively]' \
+ '-s[enable paranoid behavior]' \
+ '1:octal mode:' \
+ '*: :->files'
+ )
+ ;;
gnu)
args+=(
'(-v --verbose -c --changes)'{-c,--changes}'[report changes made]'
diff --git a/Doc/Zsh/mod_files.yo b/Doc/Zsh/mod_files.yo
index 90e988474..3cf7b61e3 100644
--- a/Doc/Zsh/mod_files.yo
+++ b/Doc/Zsh/mod_files.yo
@@ -23,6 +23,26 @@ item(tt(chgrp) [ tt(-hRs) ] var(group) var(filename) ...)(
Changes group of files specified. This is equivalent to tt(chown) with
a var(user-spec) argument of `tt(:)var(group)'.
)
+findex(chmod)
+item(tt(chmod) [ tt(-Rs) ] var(mode) var(filename) ...)(
+Changes mode of files specified.
+
+The specified var(mode) must be in octal.
+
+The tt(-R) option causes tt(chmod) to recursively descend into directories,
+changing the mode of all files in the directory after
+changing the mode of the directory itself.
+
+The tt(-s) option is a zsh extension to tt(chmod) functionality. It enables
+paranoid behaviour, intended to avoid security problems involving
+a tt(chmod) being tricked into affecting files other than the ones
+intended. It will refuse to follow symbolic links, so that (for example)
+``tt(chmod 600 /tmp/foo/passwd)'' can't accidentally chmod tt(/etc/passwd)
+if tt(/tmp/foo) happens to be a link to tt(/etc). It will also check
+where it is after leaving directories, so that a recursive chmod of
+a deep directory tree can't end up recursively chmoding tt(/usr) as
+a result of directories being moved up the tree.
+)
findex(chown)
item(tt(chown) [ tt(-hRs) ] var(user-spec) var(filename) ...)(
Changes ownership and group of files specified.
diff --git a/Src/Modules/files.c b/Src/Modules/files.c
index 6f816bac0..85764d55e 100644
--- a/Src/Modules/files.c
+++ b/Src/Modules/files.c
@@ -619,6 +619,45 @@ bin_rm(char *nam, char **args, Options ops, UNUSED(int func))
return OPT_ISSET(ops,'f') ? 0 : err;
}
+/* chmod builtin */
+
+struct chmodmagic {
+ char *nam;
+ mode_t mode;
+};
+
+/**/
+static int
+chmod_dochmod(char *arg, char *rp, UNUSED(struct stat const *sp), void *magic)
+{
+ struct chmodmagic *chm = magic;
+
+ if(chmod(rp, chm->mode)) {
+ zwarnnam(chm->nam, "%s: %e", arg, errno);
+ return 1;
+ }
+ return 0;
+}
+
+/**/
+static int
+bin_chmod(char *nam, char **args, Options ops, int func)
+{
+ struct chmodmagic chm;
+ char *str = args[0], *ptr;
+
+ chm.nam = nam;
+
+ chm.mode = zstrtol(str, &ptr, 8);
+ if(!*str || *ptr) {
+ zwarnnam(nam, "invalid mode `%s'", str);
+ return 1;
+ }
+
+ return recursivecmd(nam, 0, OPT_ISSET(ops,'R'), OPT_ISSET(ops,'s'),
+ args + 1, chmod_dochmod, recurse_donothing, chmod_dochmod, &chm);
+}
+
/* chown builtin */
struct chownmagic {
@@ -754,6 +793,7 @@ static struct builtin bintab[] = {
/* The names which overlap commands without necessarily being
* fully compatible. */
BUILTIN("chgrp", 0, bin_chown, 2, -1, BIN_CHGRP, "hRs", NULL),
+ BUILTIN("chmod", 0, bin_chmod, 2, -1, 0, "Rs", NULL),
BUILTIN("chown", 0, bin_chown, 2, -1, BIN_CHOWN, "hRs", NULL),
BUILTIN("ln", 0, bin_ln, 1, -1, BIN_LN, LN_OPTS, NULL),
BUILTIN("mkdir", 0, bin_mkdir, 1, -1, 0, "pm:", NULL),
@@ -763,6 +803,7 @@ static struct builtin bintab[] = {
BUILTIN("sync", 0, bin_sync, 0, 0, 0, NULL, NULL),
/* The "safe" zsh-only names */
BUILTIN("zf_chgrp", 0, bin_chown, 2, -1, BIN_CHGRP, "hRs", NULL),
+ BUILTIN("zf_chmod", 0, bin_chmod, 2, -1, 0, "Rs", NULL),
BUILTIN("zf_chown", 0, bin_chown, 2, -1, BIN_CHOWN, "hRs", NULL),
BUILTIN("zf_ln", 0, bin_ln, 1, -1, BIN_LN, LN_OPTS, NULL),
BUILTIN("zf_mkdir", 0, bin_mkdir, 1, -1, 0, "pm:", NULL),
--
2.21.0
next prev parent reply other threads:[~2019-03-18 0:45 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-03-17 3:08 Matthew Martin
2019-03-17 11:27 ` dana
2019-03-18 0:44 ` Matthew Martin [this message]
2019-03-18 1:28 ` dana
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAGnh9tAP0eco+_qQb6nyx3QRFwqP+XMD=WmQayAXBNz5jm7zqw@mail.gmail.com' \
--to=phy1729@gmail.com \
--cc=dana@dana.is \
--cc=zsh-workers@zsh.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).