annotate lib/modechange.c @ 17632:86af85d364e1 default tip

unistd: port readlink to Mac OS X 10.3.9 * lib/unistd.in.h (_GL_INCLUDING_UNISTD_H): New macro, to work around self-include problem in Mac OS X 10.3.9 when combined with readlink module. Problem reported by Klaus Zietler in <http://bugs.gnu.org/16825>.
author Paul Eggert <eggert@penguin.cs.ucla.edu>
date Tue, 25 Feb 2014 11:16:27 -0800
parents 344018b6e5d7
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1 /* modechange.c -- file mode manipulation
4360
72f709fb8146 Remove trailing blanks.
Jim Meyering <jim@meyering.net>
parents: 4333
diff changeset
2
17587
344018b6e5d7 maint: update copyright
Eric Blake <eblake@redhat.com>
parents: 17249
diff changeset
3 Copyright (C) 1989-1990, 1997-1999, 2001, 2003-2006, 2009-2014 Free Software
12518
b5e42ef33b49 update nearly all FSF copyright year lists to include 2009
Jim Meyering <meyering@redhat.com>
parents: 12421
diff changeset
4 Foundation, Inc.
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
5
9309
bbbbbf4cd1c5 Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 7302
diff changeset
6 This program is free software: you can redistribute it and/or modify
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
7 it under the terms of the GNU General Public License as published by
9309
bbbbbf4cd1c5 Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 7302
diff changeset
8 the Free Software Foundation; either version 3 of the License, or
bbbbbf4cd1c5 Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 7302
diff changeset
9 (at your option) any later version.
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
10
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
11 This program is distributed in the hope that it will be useful,
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
14 GNU General Public License for more details.
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
15
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
9309
bbbbbf4cd1c5 Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 7302
diff changeset
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
18
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
19 /* Written by David MacKenzie <djm@ai.mit.edu> */
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
20
16235
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
21 /* The ASCII mode string is compiled into an array of 'struct
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
22 modechange', which can then be applied to each file to be changed.
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
23 We do this instead of re-parsing the ASCII string for each file
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
24 because the compiled form requires less computation to use; when
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
25 changing the mode of many files, this probably results in a
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
26 performance gain. */
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
27
7302
8a1a9361108c * _fpending.c: Include <config.h> unconditionally, since we no
Paul Eggert <eggert@cs.ucla.edu>
parents: 7056
diff changeset
28 #include <config.h>
229
Jim Meyering <jim@meyering.net>
parents: 5
diff changeset
29
1818
b2644b45e17f (make_node_op_equals, mode_compile, mode_create_from_ref, mode_adjust):
Jim Meyering <jim@meyering.net>
parents: 1769
diff changeset
30 #include "modechange.h"
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
31 #include <sys/stat.h>
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
32 #include "stat-macros.h"
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
33 #include "xalloc.h"
4666
bb2816d0923f Remove K&R cruft.
Paul Eggert <eggert@cs.ucla.edu>
parents: 4360
diff changeset
34 #include <stdlib.h>
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
35
3081
b7402f1afb7b Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents: 2950
diff changeset
36 /* The traditional octal values corresponding to each mode bit. */
b7402f1afb7b Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents: 2950
diff changeset
37 #define SUID 04000
b7402f1afb7b Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents: 2950
diff changeset
38 #define SGID 02000
b7402f1afb7b Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents: 2950
diff changeset
39 #define SVTX 01000
b7402f1afb7b Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents: 2950
diff changeset
40 #define RUSR 00400
b7402f1afb7b Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents: 2950
diff changeset
41 #define WUSR 00200
b7402f1afb7b Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents: 2950
diff changeset
42 #define XUSR 00100
b7402f1afb7b Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents: 2950
diff changeset
43 #define RGRP 00040
b7402f1afb7b Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents: 2950
diff changeset
44 #define WGRP 00020
b7402f1afb7b Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents: 2950
diff changeset
45 #define XGRP 00010
b7402f1afb7b Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents: 2950
diff changeset
46 #define ROTH 00004
b7402f1afb7b Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents: 2950
diff changeset
47 #define WOTH 00002
b7402f1afb7b Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents: 2950
diff changeset
48 #define XOTH 00001
b7402f1afb7b Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents: 2950
diff changeset
49 #define ALLM 07777 /* all octal mode bits */
b7402f1afb7b Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents: 2950
diff changeset
50
6969
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
51 /* Convert OCTAL, which uses one of the traditional octal values, to
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
52 an internal mode_t value. */
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
53 static mode_t
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
54 octal_to_mode (unsigned int octal)
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
55 {
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
56 /* Help the compiler optimize the usual case where mode_t uses
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
57 the traditional octal representation. */
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
58 return ((S_ISUID == SUID && S_ISGID == SGID && S_ISVTX == SVTX
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
59 && S_IRUSR == RUSR && S_IWUSR == WUSR && S_IXUSR == XUSR
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
60 && S_IRGRP == RGRP && S_IWGRP == WGRP && S_IXGRP == XGRP
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
61 && S_IROTH == ROTH && S_IWOTH == WOTH && S_IXOTH == XOTH)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
62 ? octal
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
63 : (mode_t) ((octal & SUID ? S_ISUID : 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
64 | (octal & SGID ? S_ISGID : 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
65 | (octal & SVTX ? S_ISVTX : 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
66 | (octal & RUSR ? S_IRUSR : 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
67 | (octal & WUSR ? S_IWUSR : 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
68 | (octal & XUSR ? S_IXUSR : 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
69 | (octal & RGRP ? S_IRGRP : 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
70 | (octal & WGRP ? S_IWGRP : 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
71 | (octal & XGRP ? S_IXGRP : 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
72 | (octal & ROTH ? S_IROTH : 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
73 | (octal & WOTH ? S_IWOTH : 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
74 | (octal & XOTH ? S_IXOTH : 0)));
6969
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
75 }
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
76
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
77 /* Special operations flags. */
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
78 enum
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
79 {
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
80 /* For the sentinel at the end of the mode changes array. */
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
81 MODE_DONE,
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
82
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
83 /* The typical case. */
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
84 MODE_ORDINARY_CHANGE,
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
85
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
86 /* In addition to the typical case, affect the execute bits if at
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
87 least one execute bit is set already, or if the file is a
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
88 directory. */
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
89 MODE_X_IF_ANY_X,
1818
b2644b45e17f (make_node_op_equals, mode_compile, mode_create_from_ref, mode_adjust):
Jim Meyering <jim@meyering.net>
parents: 1769
diff changeset
90
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
91 /* Instead of the typical case, copy some existing permissions for
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
92 u, g, or o onto the other two. Which of u, g, or o is copied
16235
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
93 is determined by which bits are set in the 'value' field. */
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
94 MODE_COPY_EXISTING
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
95 };
1818
b2644b45e17f (make_node_op_equals, mode_compile, mode_create_from_ref, mode_adjust):
Jim Meyering <jim@meyering.net>
parents: 1769
diff changeset
96
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
97 /* Description of a mode change. */
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
98 struct mode_change
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
99 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
100 char op; /* One of "=+-". */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
101 char flag; /* Special operations flag. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
102 mode_t affected; /* Set for u, g, o, or a. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
103 mode_t value; /* Bits to add/remove. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
104 mode_t mentioned; /* Bits explicitly mentioned. */
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
105 };
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
106
16235
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
107 /* Return a mode_change array with the specified "=ddd"-style
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
108 mode change operation, where NEW_MODE is "ddd" and MENTIONED
6969
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
109 contains the bits explicitly mentioned in the mode are MENTIONED. */
1769
bc0ac225f0a8 (make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents: 1760
diff changeset
110
bc0ac225f0a8 (make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents: 1760
diff changeset
111 static struct mode_change *
6969
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
112 make_node_op_equals (mode_t new_mode, mode_t mentioned)
1769
bc0ac225f0a8 (make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents: 1760
diff changeset
113 {
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
114 struct mode_change *p = xmalloc (2 * sizeof *p);
1769
bc0ac225f0a8 (make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents: 1760
diff changeset
115 p->op = '=';
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
116 p->flag = MODE_ORDINARY_CHANGE;
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
117 p->affected = CHMOD_MODE_BITS;
1769
bc0ac225f0a8 (make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents: 1760
diff changeset
118 p->value = new_mode;
6969
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
119 p->mentioned = mentioned;
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
120 p[1].flag = MODE_DONE;
1769
bc0ac225f0a8 (make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents: 1760
diff changeset
121 return p;
bc0ac225f0a8 (make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents: 1760
diff changeset
122 }
bc0ac225f0a8 (make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents: 1760
diff changeset
123
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
124 /* Return a pointer to an array of file mode change operations created from
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
125 MODE_STRING, an ASCII string that contains either an octal number
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
126 specifying an absolute mode, or symbolic mode change operations with
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
127 the form:
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
128 [ugoa...][[+-=][rwxXstugo...]...][,...]
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
129
16235
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
130 Return NULL if 'mode_string' does not contain a valid
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
131 representation of file mode change operations. */
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
132
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
133 struct mode_change *
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
134 mode_compile (char const *mode_string)
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
135 {
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
136 /* The array of mode-change directives to be returned. */
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
137 struct mode_change *mc;
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
138 size_t used = 0;
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
139 char const *p;
1769
bc0ac225f0a8 (make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents: 1760
diff changeset
140
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
141 if ('0' <= *mode_string && *mode_string < '8')
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
142 {
6969
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
143 unsigned int octal_mode = 0;
7056
db9b9e26e735 * modechange.c (mode_compile): Numeric modes now affect setuid and
Paul Eggert <eggert@cs.ucla.edu>
parents: 6969
diff changeset
144 mode_t mode;
db9b9e26e735 * modechange.c (mode_compile): Numeric modes now affect setuid and
Paul Eggert <eggert@cs.ucla.edu>
parents: 6969
diff changeset
145 mode_t mentioned;
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
146
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
147 p = mode_string;
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
148 do
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
149 {
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
150 octal_mode = 8 * octal_mode + *p++ - '0';
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
151 if (ALLM < octal_mode)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
152 return NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
153 }
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
154 while ('0' <= *p && *p < '8');
3081
b7402f1afb7b Do not assume that mode_t uses the
Jim Meyering <jim@meyering.net>
parents: 2950
diff changeset
155
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
156 if (*p)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
157 return NULL;
6527
6b31c8787689 Sync from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6259
diff changeset
158
7056
db9b9e26e735 * modechange.c (mode_compile): Numeric modes now affect setuid and
Paul Eggert <eggert@cs.ucla.edu>
parents: 6969
diff changeset
159 mode = octal_to_mode (octal_mode);
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
160 mentioned = (p - mode_string < 5
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
161 ? (mode & (S_ISUID | S_ISGID)) | S_ISVTX | S_IRWXUGO
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
162 : CHMOD_MODE_BITS);
7056
db9b9e26e735 * modechange.c (mode_compile): Numeric modes now affect setuid and
Paul Eggert <eggert@cs.ucla.edu>
parents: 6969
diff changeset
163 return make_node_op_equals (mode, mentioned);
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
164 }
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
165
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
166 /* Allocate enough space to hold the result. */
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
167 {
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
168 size_t needed = 1;
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
169 for (p = mode_string; *p; p++)
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
170 needed += (*p == '=' || *p == '+' || *p == '-');
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
171 mc = xnmalloc (needed, sizeof *mc);
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
172 }
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
173
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
174 /* One loop iteration for each
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
175 '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=][0-7]+'. */
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
176 for (p = mode_string; ; p++)
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
177 {
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
178 /* Which bits in the mode are operated on. */
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
179 mode_t affected = 0;
1769
bc0ac225f0a8 (make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents: 1760
diff changeset
180
16235
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
181 /* Turn on all the bits in 'affected' for each group given. */
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
182 for (;; p++)
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
183 switch (*p)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
184 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
185 default:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
186 goto invalid;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
187 case 'u':
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
188 affected |= S_ISUID | S_IRWXU;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
189 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
190 case 'g':
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
191 affected |= S_ISGID | S_IRWXG;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
192 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
193 case 'o':
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
194 affected |= S_ISVTX | S_IRWXO;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
195 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
196 case 'a':
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
197 affected |= CHMOD_MODE_BITS;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
198 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
199 case '=': case '+': case '-':
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
200 goto no_more_affected;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
201 }
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
202 no_more_affected:;
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
203
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
204 do
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
205 {
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
206 char op = *p++;
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
207 mode_t value;
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
208 mode_t mentioned = 0;
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
209 char flag = MODE_COPY_EXISTING;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
210 struct mode_change *change;
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
211
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
212 switch (*p)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
213 {
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
214 case '0': case '1': case '2': case '3':
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
215 case '4': case '5': case '6': case '7':
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
216 {
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
217 unsigned int octal_mode = 0;
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
218
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
219 do
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
220 {
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
221 octal_mode = 8 * octal_mode + *p++ - '0';
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
222 if (ALLM < octal_mode)
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
223 return NULL;
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
224 }
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
225 while ('0' <= *p && *p < '8');
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
226
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
227 if (affected || (*p && *p != ','))
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
228 return NULL;
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
229 affected = mentioned = CHMOD_MODE_BITS;
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
230 value = octal_to_mode (octal_mode);
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
231 flag = MODE_ORDINARY_CHANGE;
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
232 break;
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
233 }
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
234
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
235 case 'u':
16235
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
236 /* Set the affected bits to the value of the "u" bits
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
237 on the same file. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
238 value = S_IRWXU;
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
239 p++;
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
240 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
241 case 'g':
16235
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
242 /* Set the affected bits to the value of the "g" bits
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
243 on the same file. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
244 value = S_IRWXG;
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
245 p++;
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
246 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
247 case 'o':
16235
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
248 /* Set the affected bits to the value of the "o" bits
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
249 on the same file. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
250 value = S_IRWXO;
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
251 p++;
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
252 break;
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
253
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
254 default:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
255 value = 0;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
256 flag = MODE_ORDINARY_CHANGE;
1769
bc0ac225f0a8 (make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents: 1760
diff changeset
257
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
258 for (;; p++)
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
259 switch (*p)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
260 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
261 case 'r':
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
262 value |= S_IRUSR | S_IRGRP | S_IROTH;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
263 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
264 case 'w':
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
265 value |= S_IWUSR | S_IWGRP | S_IWOTH;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
266 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
267 case 'x':
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
268 value |= S_IXUSR | S_IXGRP | S_IXOTH;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
269 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
270 case 'X':
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
271 flag = MODE_X_IF_ANY_X;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
272 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
273 case 's':
16235
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
274 /* Set the setuid/gid bits if 'u' or 'g' is selected. */
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
275 value |= S_ISUID | S_ISGID;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
276 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
277 case 't':
16235
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
278 /* Set the "save text image" bit if 'o' is selected. */
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
279 value |= S_ISVTX;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
280 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
281 default:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
282 goto no_more_values;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
283 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
284 no_more_values:;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
285 }
1769
bc0ac225f0a8 (make_node_op_equals): New function.
Jim Meyering <jim@meyering.net>
parents: 1760
diff changeset
286
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
287 change = &mc[used++];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
288 change->op = op;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
289 change->flag = flag;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
290 change->affected = affected;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
291 change->value = value;
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
292 change->mentioned =
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
293 (mentioned ? mentioned : affected ? affected & value : value);
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
294 }
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
295 while (*p == '=' || *p == '+' || *p == '-');
5304
707482f5c106 (mode_compile): Don't decrement a pointer that
Paul Eggert <eggert@cs.ucla.edu>
parents: 5159
diff changeset
296
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
297 if (*p != ',')
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
298 break;
5304
707482f5c106 (mode_compile): Don't decrement a pointer that
Paul Eggert <eggert@cs.ucla.edu>
parents: 5159
diff changeset
299 }
707482f5c106 (mode_compile): Don't decrement a pointer that
Paul Eggert <eggert@cs.ucla.edu>
parents: 5159
diff changeset
300
16629
02cc478e0dc0 modechange: add notations +40, 00440, etc.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
301 if (*p == 0)
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
302 {
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
303 mc[used].flag = MODE_DONE;
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
304 return mc;
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
305 }
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
306
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
307 invalid:
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
308 free (mc);
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
309 return NULL;
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
310 }
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
311
989
c68ed1182a64 (mode_create_from_ref): Don't use umask.
Jim Meyering <jim@meyering.net>
parents: 972
diff changeset
312 /* Return a file mode change operation that sets permissions to match those
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
313 of REF_FILE. Return NULL (setting errno) if REF_FILE can't be accessed. */
972
b30f9ff1e92e (mode_create_from_ref): New function.
Jim Meyering <jim@meyering.net>
parents: 761
diff changeset
314
b30f9ff1e92e (mode_create_from_ref): New function.
Jim Meyering <jim@meyering.net>
parents: 761
diff changeset
315 struct mode_change *
1494
8b82518377ef Protoize.
Jim Meyering <jim@meyering.net>
parents: 991
diff changeset
316 mode_create_from_ref (const char *ref_file)
972
b30f9ff1e92e (mode_create_from_ref): New function.
Jim Meyering <jim@meyering.net>
parents: 761
diff changeset
317 {
b30f9ff1e92e (mode_create_from_ref): New function.
Jim Meyering <jim@meyering.net>
parents: 761
diff changeset
318 struct stat ref_stats;
b30f9ff1e92e (mode_create_from_ref): New function.
Jim Meyering <jim@meyering.net>
parents: 761
diff changeset
319
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
320 if (stat (ref_file, &ref_stats) != 0)
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
321 return NULL;
6969
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
322 return make_node_op_equals (ref_stats.st_mode, CHMOD_MODE_BITS);
972
b30f9ff1e92e (mode_create_from_ref): New function.
Jim Meyering <jim@meyering.net>
parents: 761
diff changeset
323 }
b30f9ff1e92e (mode_create_from_ref): New function.
Jim Meyering <jim@meyering.net>
parents: 761
diff changeset
324
6969
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
325 /* Return the file mode bits of OLDMODE (which is the mode of a
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
326 directory if DIR), assuming the umask is UMASK_VALUE, adjusted as
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
327 indicated by the list of change operations CHANGES. If DIR, the
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
328 type 'X' change affects the returned value even if no execute bits
7056
db9b9e26e735 * modechange.c (mode_compile): Numeric modes now affect setuid and
Paul Eggert <eggert@cs.ucla.edu>
parents: 6969
diff changeset
329 were set in OLDMODE, and set user and group ID bits are preserved
db9b9e26e735 * modechange.c (mode_compile): Numeric modes now affect setuid and
Paul Eggert <eggert@cs.ucla.edu>
parents: 6969
diff changeset
330 unless CHANGES mentioned them. If PMODE_BITS is not null, store into
6969
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
331 *PMODE_BITS a mask denoting file mode bits that are affected by
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
332 CHANGES.
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
333
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
334 The returned value and *PMODE_BITS contain only file mode bits.
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
335 For example, they have the S_IFMT bits cleared on a standard
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
336 Unix-like host. */
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
337
1818
b2644b45e17f (make_node_op_equals, mode_compile, mode_create_from_ref, mode_adjust):
Jim Meyering <jim@meyering.net>
parents: 1769
diff changeset
338 mode_t
6969
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
339 mode_adjust (mode_t oldmode, bool dir, mode_t umask_value,
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
340 struct mode_change const *changes, mode_t *pmode_bits)
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
341 {
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
342 /* The adjusted mode. */
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
343 mode_t newmode = oldmode & CHMOD_MODE_BITS;
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
344
6969
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
345 /* File mode bits that CHANGES cares about. */
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
346 mode_t mode_bits = 0;
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
347
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
348 for (; changes->flag != MODE_DONE; changes++)
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
349 {
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
350 mode_t affected = changes->affected;
6969
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
351 mode_t omit_change =
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
352 (dir ? S_ISUID | S_ISGID : 0) & ~ changes->mentioned;
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
353 mode_t value = changes->value;
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
354
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
355 switch (changes->flag)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
356 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
357 case MODE_ORDINARY_CHANGE:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
358 break;
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
359
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
360 case MODE_COPY_EXISTING:
16235
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
361 /* Isolate in 'value' the bits in 'newmode' to copy. */
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
362 value &= newmode;
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
363
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
364 /* Copy the isolated bits to the other two parts. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
365 value |= ((value & (S_IRUSR | S_IRGRP | S_IROTH)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
366 ? S_IRUSR | S_IRGRP | S_IROTH : 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
367 | (value & (S_IWUSR | S_IWGRP | S_IWOTH)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
368 ? S_IWUSR | S_IWGRP | S_IWOTH : 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
369 | (value & (S_IXUSR | S_IXGRP | S_IXOTH)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
370 ? S_IXUSR | S_IXGRP | S_IXOTH : 0));
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
371 break;
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
372
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
373 case MODE_X_IF_ANY_X:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
374 /* Affect the execute bits if execute bits are already set
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
375 or if the file is a directory. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
376 if ((newmode & (S_IXUSR | S_IXGRP | S_IXOTH)) | dir)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
377 value |= S_IXUSR | S_IXGRP | S_IXOTH;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
378 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
379 }
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
380
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
381 /* If WHO was specified, limit the change to the affected bits.
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
382 Otherwise, apply the umask. Either way, omit changes as
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
383 requested. */
6969
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
384 value &= (affected ? affected : ~umask_value) & ~ omit_change;
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
385
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
386 switch (changes->op)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
387 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
388 case '=':
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
389 /* If WHO was specified, preserve the previous values of
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
390 bits that are not affected by this change operation.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
391 Otherwise, clear all the bits. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
392 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
393 mode_t preserved = (affected ? ~affected : 0) | omit_change;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
394 mode_bits |= CHMOD_MODE_BITS & ~preserved;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
395 newmode = (newmode & preserved) | value;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
396 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
397 }
6969
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
398
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
399 case '+':
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
400 mode_bits |= value;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
401 newmode |= value;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
402 break;
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
403
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
404 case '-':
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
405 mode_bits |= value;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
406 newmode &= ~value;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
407 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9309
diff changeset
408 }
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
409 }
5813
6962b5c5069f Merge from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5304
diff changeset
410
6969
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
411 if (pmode_bits)
bbdf9204a185 Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6527
diff changeset
412 *pmode_bits = mode_bits;
5
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
413 return newmode;
41c9d08b09d7 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
414 }