OpenCoverage

chown-core.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/coreutils/src/src/chown-core.c
Source codeSwitch to Preprocessed file
LineSourceCount
1/* chown-core.c -- core functions for changing ownership.-
2 Copyright (C) 2000-2018 Free Software Foundation, Inc.-
3-
4 This program is free software: you can redistribute it and/or modify-
5 it under the terms of the GNU General Public License as published by-
6 the Free Software Foundation, either version 3 of the License, or-
7 (at your option) any later version.-
8-
9 This program is distributed in the hope that it will be useful,-
10 but WITHOUT ANY WARRANTY; without even the implied warranty of-
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the-
12 GNU General Public License for more details.-
13-
14 You should have received a copy of the GNU General Public License-
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */-
16-
17/* Extracted from chown.c/chgrp.c and librarified by Jim Meyering. */-
18-
19#include <config.h>-
20#include <stdio.h>-
21#include <sys/types.h>-
22#include <pwd.h>-
23#include <grp.h>-
24-
25#include "system.h"-
26#include "chown-core.h"-
27#include "error.h"-
28#include "ignore-value.h"-
29#include "root-dev-ino.h"-
30#include "xfts.h"-
31-
32#define FTSENT_IS_DIRECTORY(E) \-
33 ((E)->fts_info == FTS_D \-
34 || (E)->fts_info == FTS_DC \-
35 || (E)->fts_info == FTS_DP \-
36 || (E)->fts_info == FTS_DNR)-
37-
38enum RCH_status-
39 {-
40 /* we called fchown and close, and both succeeded */-
41 RC_ok = 2,-
42-
43 /* required_uid and/or required_gid are specified, but don't match */-
44 RC_excluded,-
45-
46 /* SAME_INODE check failed */-
47 RC_inode_changed,-
48-
49 /* open/fchown isn't needed, isn't safe, or doesn't work due to-
50 permissions problems; fall back on chown */-
51 RC_do_ordinary_chown,-
52-
53 /* open, fstat, fchown, or close failed */-
54 RC_error-
55 };-
56-
57extern void-
58chopt_init (struct Chown_option *chopt)-
59{-
60 chopt->verbosity = V_off;-
61 chopt->root_dev_ino = NULL;-
62 chopt->affect_symlink_referent = true;-
63 chopt->recurse = false;-
64 chopt->force_silent = false;-
65 chopt->user_name = NULL;-
66 chopt->group_name = NULL;-
67}
executed 144 times by 2 tests: end of block
Executed by:
  • chgrp
  • chown
144
68-
69extern void-
70chopt_free (struct Chown_option *chopt _GL_UNUSED)-
71{-
72 /* Deliberately do not free chopt->user_name or ->group_name.-
73 They're not always allocated. */-
74}-
75-
76/* Convert the numeric group-id, GID, to a string stored in xmalloc'd memory,-
77 and return it. If there's no corresponding group name, use the decimal-
78 representation of the ID. */-
79-
80extern char *-
81gid_to_name (gid_t gid)-
82{-
83 char buf[INT_BUFSIZE_BOUND (intmax_t)];-
84 struct group *grp = getgrgid (gid);-
85 return xstrdup (grp ? grp->gr_name
executed 1 time by 1 test: return xstrdup (grp ? grp->gr_name : (! ((gid_t) 0 < (gid_t) -1)) ? imaxtostr (gid, buf) : umaxtostr (gid, buf));
Executed by:
  • chgrp
1
86 : TYPE_SIGNED (gid_t) ? imaxtostr (gid, buf)
executed 1 time by 1 test: return xstrdup (grp ? grp->gr_name : (! ((gid_t) 0 < (gid_t) -1)) ? imaxtostr (gid, buf) : umaxtostr (gid, buf));
Executed by:
  • chgrp
1
87 : umaxtostr (gid, buf));
executed 1 time by 1 test: return xstrdup (grp ? grp->gr_name : (! ((gid_t) 0 < (gid_t) -1)) ? imaxtostr (gid, buf) : umaxtostr (gid, buf));
Executed by:
  • chgrp
1
88}-
89-
90/* Convert the numeric user-id, UID, to a string stored in xmalloc'd memory,-
91 and return it. If there's no corresponding user name, use the decimal-
92 representation of the ID. */-
93-
94extern char *-
95uid_to_name (uid_t uid)-
96{-
97 char buf[INT_BUFSIZE_BOUND (intmax_t)];-
98 struct passwd *pwd = getpwuid (uid);-
99 return xstrdup (pwd ? pwd->pw_name
never executed: return xstrdup (pwd ? pwd->pw_name : (! ((uid_t) 0 < (uid_t) -1)) ? imaxtostr (uid, buf) : umaxtostr (uid, buf));
0
100 : TYPE_SIGNED (uid_t) ? imaxtostr (uid, buf)
never executed: return xstrdup (pwd ? pwd->pw_name : (! ((uid_t) 0 < (uid_t) -1)) ? imaxtostr (uid, buf) : umaxtostr (uid, buf));
0
101 : umaxtostr (uid, buf));
never executed: return xstrdup (pwd ? pwd->pw_name : (! ((uid_t) 0 < (uid_t) -1)) ? imaxtostr (uid, buf) : umaxtostr (uid, buf));
0
102}-
103-
104/* Allocate a string representing USER and GROUP. */-
105-
106static char *-
107user_group_str (char const *user, char const *group)-
108{-
109 char *spec = NULL;-
110-
111 if (user)
userDescription
TRUEnever evaluated
FALSEnever evaluated
0
112 {-
113 if (group)
groupDescription
TRUEnever evaluated
FALSEnever evaluated
0
114 {-
115 spec = xmalloc (strlen (user) + 1 + strlen (group) + 1);-
116 stpcpy (stpcpy (stpcpy (spec, user), ":"), group);-
117 }
never executed: end of block
0
118 else-
119 {-
120 spec = xstrdup (user);-
121 }
never executed: end of block
0
122 }-
123 else if (group)
groupDescription
TRUEnever evaluated
FALSEnever evaluated
0
124 {-
125 spec = xstrdup (group);-
126 }
never executed: end of block
0
127-
128 return spec;
never executed: return spec;
0
129}-
130-
131/* Tell the user how/if the user and group of FILE have been changed.-
132 If USER is NULL, give the group-oriented messages.-
133 CHANGED describes what (if anything) has happened. */-
134-
135static void-
136describe_change (const char *file, enum Change_status changed,-
137 char const *old_user, char const *old_group,-
138 char const *user, char const *group)-
139{-
140 const char *fmt;-
141 char *old_spec;-
142 char *spec;-
143-
144 if (changed == CH_NOT_APPLIED)
changed == CH_NOT_APPLIEDDescription
TRUEnever evaluated
FALSEnever evaluated
0
145 {-
146 printf (_("neither symbolic link %s nor referent has been changed\n"),-
147 quoteaf (file));-
148 return;
never executed: return;
0
149 }-
150-
151 spec = user_group_str (user, group);-
152 old_spec = user_group_str (user ? old_user : NULL, group ? old_group : NULL);-
153-
154 switch (changed)-
155 {-
156 case CH_SUCCEEDED:
never executed: case CH_SUCCEEDED:
0
157 fmt = (user ? _("changed ownership of %s from %s to %s\n")
userDescription
TRUEnever evaluated
FALSEnever evaluated
0
158 : group ? _("changed group of %s from %s to %s\n")
groupDescription
TRUEnever evaluated
FALSEnever evaluated
0
159 : _("no change to ownership of %s\n"));-
160 break;
never executed: break;
0
161 case CH_FAILED:
never executed: case CH_FAILED:
0
162 if (old_spec)
old_specDescription
TRUEnever evaluated
FALSEnever evaluated
0
163 {-
164 fmt = (user ? _("failed to change ownership of %s from %s to %s\n")
userDescription
TRUEnever evaluated
FALSEnever evaluated
0
165 : group ? _("failed to change group of %s from %s to %s\n")
groupDescription
TRUEnever evaluated
FALSEnever evaluated
0
166 : _("failed to change ownership of %s\n"));-
167 }
never executed: end of block
0
168 else-
169 {-
170 fmt = (user ? _("failed to change ownership of %s to %s\n")
userDescription
TRUEnever evaluated
FALSEnever evaluated
0
171 : group ? _("failed to change group of %s to %s\n")
groupDescription
TRUEnever evaluated
FALSEnever evaluated
0
172 : _("failed to change ownership of %s\n"));-
173 free (old_spec);-
174 old_spec = spec;-
175 spec = NULL;-
176 }
never executed: end of block
0
177 break;
never executed: break;
0
178 case CH_NO_CHANGE_REQUESTED:
never executed: case CH_NO_CHANGE_REQUESTED:
0
179 fmt = (user ? _("ownership of %s retained as %s\n")
userDescription
TRUEnever evaluated
FALSEnever evaluated
0
180 : group ? _("group of %s retained as %s\n")
groupDescription
TRUEnever evaluated
FALSEnever evaluated
0
181 : _("ownership of %s retained\n"));-
182 break;
never executed: break;
0
183 default:
never executed: default:
0
184 abort ();
never executed: abort ();
0
185 }-
186-
187 printf (fmt, quoteaf (file), old_spec, spec);-
188-
189 free (old_spec);-
190 free (spec);-
191}
never executed: end of block
0
192-
193/* Change the owner and/or group of the FILE to UID and/or GID (safely)-
194 only if REQUIRED_UID and REQUIRED_GID match the owner and group IDs-
195 of FILE. ORIG_ST must be the result of 'stat'ing FILE.-
196-
197 The 'safely' part above means that we can't simply use chown(2),-
198 since FILE might be replaced with some other file between the time-
199 of the preceding stat/lstat and this chown call. So here we open-
200 FILE and do everything else via the resulting file descriptor.-
201 We first call fstat and verify that the dev/inode match those from-
202 the preceding stat call, and only then, if appropriate (given the-
203 required_uid and required_gid constraints) do we call fchown.-
204-
205 Return RC_do_ordinary_chown if we can't open FILE, or if FILE is a-
206 special file that might have undesirable side effects when opening.-
207 In this case the caller can use the less-safe ordinary chown.-
208-
209 Return one of the RCH_status values. */-
210-
211static enum RCH_status-
212restricted_chown (int cwd_fd, char const *file,-
213 struct stat const *orig_st,-
214 uid_t uid, gid_t gid,-
215 uid_t required_uid, gid_t required_gid)-
216{-
217 enum RCH_status status = RC_ok;-
218 struct stat st;-
219 int open_flags = O_NONBLOCK | O_NOCTTY;-
220 int fd;-
221-
222 if (required_uid == (uid_t) -1 && required_gid == (gid_t) -1)
required_uid == (uid_t) -1Description
TRUEevaluated 60 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEnever evaluated
required_gid == (gid_t) -1Description
TRUEevaluated 55 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 5 times by 1 test
Evaluated by:
  • chown
0-60
223 return RC_do_ordinary_chown;
executed 55 times by 2 tests: return RC_do_ordinary_chown;
Executed by:
  • chgrp
  • chown
55
224-
225 if (! S_ISREG (orig_st->st_mode))
! (((( orig_st... == (0100000))Description
TRUEnever evaluated
FALSEevaluated 5 times by 1 test
Evaluated by:
  • chown
0-5
226 {-
227 if (S_ISDIR (orig_st->st_mode))
(((( orig_st->... == (0040000))Description
TRUEnever evaluated
FALSEnever evaluated
0
228 open_flags |= O_DIRECTORY;
never executed: open_flags |= 0200000 ;
0
229 else-
230 return RC_do_ordinary_chown;
never executed: return RC_do_ordinary_chown;
0
231 }-
232-
233 fd = openat (cwd_fd, file, O_RDONLY | open_flags);-
234 if (! (0 <= fd
0 <= fdDescription
TRUEevaluated 3 times by 1 test
Evaluated by:
  • chown
FALSEevaluated 2 times by 1 test
Evaluated by:
  • chown
2-3
235 || (errno == EACCES && S_ISREG (orig_st->st_mode)
(*__errno_location ()) == 13Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • chown
FALSEnever evaluated
(((( orig_st->... == (0100000))Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • chown
FALSEnever evaluated
0-2
236 && 0 <= (fd = openat (cwd_fd, file, O_WRONLY | open_flags)))))
0 <= (fd = ope...| open_flags))Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • chown
FALSEevaluated 1 time by 1 test
Evaluated by:
  • chown
1
237 return (errno == EACCES ? RC_do_ordinary_chown : RC_error);
executed 1 time by 1 test: return ( (*__errno_location ()) == 13 ? RC_do_ordinary_chown : RC_error);
Executed by:
  • chown
1
238-
239 if (fstat (fd, &st) != 0)
fstat (fd, &st) != 0Description
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • chown
0-4
240 status = RC_error;
never executed: status = RC_error;
0
241 else if (! SAME_INODE (*orig_st, st))
(*orig_st).st_...== (st).st_inoDescription
TRUEevaluated 4 times by 1 test
Evaluated by:
  • chown
FALSEnever evaluated
(*orig_st).st_...== (st).st_devDescription
TRUEevaluated 4 times by 1 test
Evaluated by:
  • chown
FALSEnever evaluated
0-4
242 status = RC_inode_changed;
never executed: status = RC_inode_changed;
0
243 else if ((required_uid == (uid_t) -1 || required_uid == st.st_uid)
required_uid == (uid_t) -1Description
TRUEevaluated 4 times by 1 test
Evaluated by:
  • chown
FALSEnever evaluated
required_uid == st.st_uidDescription
TRUEnever evaluated
FALSEnever evaluated
0-4
244 && (required_gid == (gid_t) -1 || required_gid == st.st_gid))
required_gid == (gid_t) -1Description
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • chown
required_gid == st.st_gidDescription
TRUEevaluated 4 times by 1 test
Evaluated by:
  • chown
FALSEnever evaluated
0-4
245 {-
246 if (fchown (fd, uid, gid) == 0)
fchown (fd, uid, gid) == 0Description
TRUEevaluated 4 times by 1 test
Evaluated by:
  • chown
FALSEnever evaluated
0-4
247 {-
248 status = (close (fd) == 0
close (fd) == 0Description
TRUEevaluated 4 times by 1 test
Evaluated by:
  • chown
FALSEnever evaluated
0-4
249 ? RC_ok : RC_error);-
250 return status;
executed 4 times by 1 test: return status;
Executed by:
  • chown
4
251 }-
252 else-
253 {-
254 status = RC_error;-
255 }
never executed: end of block
0
256 }-
257-
258 int saved_errno = errno;-
259 close (fd);-
260 errno = saved_errno;-
261 return status;
never executed: return status;
0
262}-
263-
264/* Change the owner and/or group of the file specified by FTS and ENT-
265 to UID and/or GID as appropriate.-
266 If REQUIRED_UID is not -1, then skip files with any other user ID.-
267 If REQUIRED_GID is not -1, then skip files with any other group ID.-
268 CHOPT specifies additional options.-
269 Return true if successful. */-
270static bool-
271change_file_owner (FTS *fts, FTSENT *ent,-
272 uid_t uid, gid_t gid,-
273 uid_t required_uid, gid_t required_gid,-
274 struct Chown_option const *chopt)-
275{-
276 char const *file_full_name = ent->fts_path;-
277 char const *file = ent->fts_accpath;-
278 struct stat const *file_stats;-
279 struct stat stat_buf;-
280 bool ok = true;-
281 bool do_chown;-
282 bool symlink_changed = true;-
283-
284 switch (ent->fts_info)-
285 {-
286 case FTS_D:
executed 44 times by 2 tests: case 1:
Executed by:
  • chgrp
  • chown
44
287 if (chopt->recurse)
chopt->recurseDescription
TRUEevaluated 26 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 18 times by 2 tests
Evaluated by:
  • chgrp
  • chown
18-26
288 {-
289 if (ROOT_DEV_INO_CHECK (chopt->root_dev_ino, ent->fts_statp))
chopt->root_dev_inoDescription
TRUEevaluated 10 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 16 times by 1 test
Evaluated by:
  • chgrp
(*ent->fts_sta...ev_ino).st_inoDescription
TRUEevaluated 4 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 6 times by 2 tests
Evaluated by:
  • chgrp
  • chown
(*ent->fts_sta...ev_ino).st_devDescription
TRUEevaluated 4 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEnever evaluated
0-16
290 {-
291 /* This happens e.g., with "chown -R --preserve-root 0 /"-
292 and with "chown -RH --preserve-root 0 symlink-to-root". */-
293 ROOT_DEV_INO_WARN (file_full_name);
never executed: __result = (((const unsigned char *) (const char *) ( file_full_name ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
never executed: __result = (((const unsigned char *) (const char *) ( "/" ))[3] - __s2[3]);
never executed: end of block
executed 2 times by 2 tests: end of block
Executed by:
  • chgrp
  • chown
executed 2 times by 2 tests: error (0, 0, dcgettext (((void *)0), "it is dangerous to operate recursively on %s" , 5) , quotearg_style (shell_escape_always_quoting_style, file_full_name));
Executed by:
  • chgrp
  • chown
executed 2 times by 2 tests: error (0, 0, dcgettext (((void *)0), "it is dangerous to operate recursively on %s (same as %s)" , 5) , quotearg_n_style (0, shell_escape_always_quoting_style, file_full_name), quotearg_n_style (1, shell_escape_always_quoting_style, "/"));
Executed by:
  • chgrp
  • chown
( __extension_...)))); }) == 0)Description
TRUEevaluated 2 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 2 times by 2 tests
Evaluated by:
  • chgrp
  • chown
__s1_len > 0Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 0Description
TRUEevaluated 4 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEnever evaluated
__result == 0Description
TRUEevaluated 2 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 2 times by 2 tests
Evaluated by:
  • chgrp
  • chown
__s2_len > 1Description
TRUEnever evaluated
FALSEevaluated 2 times by 2 tests
Evaluated by:
  • chgrp
  • chown
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
0-4
294 /* Tell fts not to traverse into this hierarchy. */-
295 fts_set (fts, ent, FTS_SKIP);-
296 /* Ensure that we do not process "/" on the second visit. */-
297 ignore_value (fts_read (fts));-
298 return false;
executed 4 times by 2 tests: return 0 ;
Executed by:
  • chgrp
  • chown
4
299 }-
300 return true;
executed 22 times by 2 tests: return 1 ;
Executed by:
  • chgrp
  • chown
22
301 }-
302 break;
executed 18 times by 2 tests: break;
Executed by:
  • chgrp
  • chown
18
303-
304 case FTS_DP:
executed 40 times by 2 tests: case 6:
Executed by:
  • chgrp
  • chown
40
305 if (! chopt->recurse)
! chopt->recurseDescription
TRUEevaluated 18 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 22 times by 2 tests
Evaluated by:
  • chgrp
  • chown
18-22
306 return true;
executed 18 times by 2 tests: return 1 ;
Executed by:
  • chgrp
  • chown
18
307 break;
executed 22 times by 2 tests: break;
Executed by:
  • chgrp
  • chown
22
308-
309 case FTS_NS:
executed 5 times by 2 tests: case 10:
Executed by:
  • chgrp
  • chown
5
310 /* For a top-level file or directory, this FTS_NS (stat failed)-
311 indicator is determined at the time of the initial fts_open call.-
312 With programs like chmod, chown, and chgrp, that modify-
313 permissions, it is possible that the file in question is-
314 accessible when control reaches this point. So, if this is-
315 the first time we've seen the FTS_NS for this file, tell-
316 fts_read to stat it "again". */-
317 if (ent->fts_level == 0 && ent->fts_number == 0)
ent->fts_level == 0Description
TRUEevaluated 4 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 1 time by 1 test
Evaluated by:
  • chgrp
ent->fts_number == 0Description
TRUEevaluated 2 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 2 times by 2 tests
Evaluated by:
  • chgrp
  • chown
1-4
318 {-
319 ent->fts_number = 1;-
320 fts_set (fts, ent, FTS_AGAIN);-
321 return true;
executed 2 times by 2 tests: return 1 ;
Executed by:
  • chgrp
  • chown
2
322 }-
323 if (! chopt->force_silent)
! chopt->force_silentDescription
TRUEevaluated 1 time by 1 test
Evaluated by:
  • chgrp
FALSEevaluated 2 times by 2 tests
Evaluated by:
  • chgrp
  • chown
1-2
324 error (0, ent->fts_errno, _("cannot access %s"),
executed 1 time by 1 test: error (0, ent->fts_errno, dcgettext (((void *)0), "cannot access %s" , 5) , quotearg_style (shell_escape_always_quoting_style, file_full_name));
Executed by:
  • chgrp
1
325 quoteaf (file_full_name));
executed 1 time by 1 test: error (0, ent->fts_errno, dcgettext (((void *)0), "cannot access %s" , 5) , quotearg_style (shell_escape_always_quoting_style, file_full_name));
Executed by:
  • chgrp
1
326 ok = false;-
327 break;
executed 3 times by 2 tests: break;
Executed by:
  • chgrp
  • chown
3
328-
329 case FTS_ERR:
never executed: case 7:
0
330 if (! chopt->force_silent)
! chopt->force_silentDescription
TRUEnever evaluated
FALSEnever evaluated
0
331 error (0, ent->fts_errno, "%s", quotef (file_full_name));
never executed: error (0, ent->fts_errno, "%s", quotearg_n_style_colon (0, shell_escape_quoting_style, file_full_name));
0
332 ok = false;-
333 break;
never executed: break;
0
334-
335 case FTS_DNR:
never executed: case 4:
0
336 if (! chopt->force_silent)
! chopt->force_silentDescription
TRUEnever evaluated
FALSEnever evaluated
0
337 error (0, ent->fts_errno, _("cannot read directory %s"),
never executed: error (0, ent->fts_errno, dcgettext (((void *)0), "cannot read directory %s" , 5) , quotearg_style (shell_escape_always_quoting_style, file_full_name));
0
338 quoteaf (file_full_name));
never executed: error (0, ent->fts_errno, dcgettext (((void *)0), "cannot read directory %s" , 5) , quotearg_style (shell_escape_always_quoting_style, file_full_name));
0
339 ok = false;-
340 break;
never executed: break;
0
341-
342 case FTS_DC: /* directory that causes cycles */
never executed: case 2:
0
343 if (cycle_warning_required (fts, ent))
cycle_warning_...red (fts, ent)Description
TRUEnever evaluated
FALSEnever evaluated
0
344 {-
345 emit_cycle_warning (file_full_name);-
346 return false;
never executed: return 0 ;
0
347 }-
348 break;
never executed: break;
0
349-
350 default:
executed 59 times by 2 tests: default:
Executed by:
  • chgrp
  • chown
59
351 break;
executed 59 times by 2 tests: break;
Executed by:
  • chgrp
  • chown
59
352 }-
353-
354 if (!ok)
!okDescription
TRUEevaluated 3 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 99 times by 2 tests
Evaluated by:
  • chgrp
  • chown
3-99
355 {-
356 do_chown = false;-
357 file_stats = NULL;-
358 }
executed 3 times by 2 tests: end of block
Executed by:
  • chgrp
  • chown
3
359 else if (required_uid == (uid_t) -1 && required_gid == (gid_t) -1
required_uid == (uid_t) -1Description
TRUEevaluated 99 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEnever evaluated
required_gid == (gid_t) -1Description
TRUEevaluated 94 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 5 times by 1 test
Evaluated by:
  • chown
0-99
360 && chopt->verbosity == V_off
chopt->verbosity == V_offDescription
TRUEevaluated 94 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEnever evaluated
0-94
361 && ! chopt->root_dev_ino
! chopt->root_dev_inoDescription
TRUEevaluated 83 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 11 times by 2 tests
Evaluated by:
  • chgrp
  • chown
11-83
362 && ! chopt->affect_symlink_referent)
! chopt->affec...mlink_referentDescription
TRUEevaluated 32 times by 1 test
Evaluated by:
  • chgrp
FALSEevaluated 51 times by 2 tests
Evaluated by:
  • chgrp
  • chown
32-51
363 {-
364 do_chown = true;-
365 file_stats = ent->fts_statp;-
366 }
executed 32 times by 1 test: end of block
Executed by:
  • chgrp
32
367 else-
368 {-
369 file_stats = ent->fts_statp;-
370-
371 /* If this is a symlink and we're dereferencing them,-
372 stat it to get info on the referent. */-
373 if (chopt->affect_symlink_referent && S_ISLNK (file_stats->st_mode))
chopt->affect_symlink_referentDescription
TRUEevaluated 61 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 6 times by 2 tests
Evaluated by:
  • chgrp
  • chown
(((( file_stat... == (0120000))Description
TRUEevaluated 6 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 55 times by 2 tests
Evaluated by:
  • chgrp
  • chown
6-61
374 {-
375 if (fstatat (fts->fts_cwd_fd, file, &stat_buf, 0) != 0)
fstatat (fts->...t_buf, 0) != 0Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • chown
FALSEevaluated 5 times by 1 test
Evaluated by:
  • chgrp
1-5
376 {-
377 if (! chopt->force_silent)
! chopt->force_silentDescription
TRUEevaluated 1 time by 1 test
Evaluated by:
  • chown
FALSEnever evaluated
0-1
378 error (0, errno, _("cannot dereference %s"),
executed 1 time by 1 test: error (0, (*__errno_location ()) , dcgettext (((void *)0), "cannot dereference %s" , 5) , quotearg_style (shell_escape_always_quoting_style, file_full_name));
Executed by:
  • chown
1
379 quoteaf (file_full_name));
executed 1 time by 1 test: error (0, (*__errno_location ()) , dcgettext (((void *)0), "cannot dereference %s" , 5) , quotearg_style (shell_escape_always_quoting_style, file_full_name));
Executed by:
  • chown
1
380 ok = false;-
381 }
executed 1 time by 1 test: end of block
Executed by:
  • chown
1
382-
383 file_stats = &stat_buf;-
384 }
executed 6 times by 2 tests: end of block
Executed by:
  • chgrp
  • chown
6
385-
386 do_chown = (ok
okDescription
TRUEevaluated 66 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 1 time by 1 test
Evaluated by:
  • chown
1-66
387 && (required_uid == (uid_t) -1
required_uid == (uid_t) -1Description
TRUEevaluated 66 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEnever evaluated
0-66
388 || required_uid == file_stats->st_uid)
required_uid =..._stats->st_uidDescription
TRUEnever evaluated
FALSEnever evaluated
0
389 && (required_gid == (gid_t) -1
required_gid == (gid_t) -1Description
TRUEevaluated 61 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 5 times by 1 test
Evaluated by:
  • chown
5-61
390 || required_gid == file_stats->st_gid));
required_gid =..._stats->st_gidDescription
TRUEevaluated 5 times by 1 test
Evaluated by:
  • chown
FALSEnever evaluated
0-5
391 }
executed 67 times by 2 tests: end of block
Executed by:
  • chgrp
  • chown
67
392-
393 /* This happens when chown -LR --preserve-root encounters a symlink-to-/. */-
394 if (ok
okDescription
TRUEevaluated 98 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 4 times by 2 tests
Evaluated by:
  • chgrp
  • chown
4-98
395 && FTSENT_IS_DIRECTORY (ent)
(ent)->fts_info == 1Description
TRUEevaluated 18 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 80 times by 2 tests
Evaluated by:
  • chgrp
  • chown
(ent)->fts_info == 2Description
TRUEnever evaluated
FALSEevaluated 80 times by 2 tests
Evaluated by:
  • chgrp
  • chown
(ent)->fts_info == 6Description
TRUEevaluated 22 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 58 times by 2 tests
Evaluated by:
  • chgrp
  • chown
(ent)->fts_info == 4Description
TRUEnever evaluated
FALSEevaluated 58 times by 2 tests
Evaluated by:
  • chgrp
  • chown
0-80
396 && ROOT_DEV_INO_CHECK (chopt->root_dev_ino, file_stats))
chopt->root_dev_inoDescription
TRUEevaluated 6 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 34 times by 2 tests
Evaluated by:
  • chgrp
  • chown
(*file_stats)....ev_ino).st_inoDescription
TRUEnever evaluated
FALSEevaluated 6 times by 2 tests
Evaluated by:
  • chgrp
  • chown
(*file_stats)....ev_ino).st_devDescription
TRUEnever evaluated
FALSEnever evaluated
0-34
397 {-
398 ROOT_DEV_INO_WARN (file_full_name);
never executed: __result = (((const unsigned char *) (const char *) ( file_full_name ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
never executed: __result = (((const unsigned char *) (const char *) ( "/" ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
never executed: error (0, 0, dcgettext (((void *)0), "it is dangerous to operate recursively on %s" , 5) , quotearg_style (shell_escape_always_quoting_style, file_full_name));
never executed: error (0, 0, dcgettext (((void *)0), "it is dangerous to operate recursively on %s (same as %s)" , 5) , quotearg_n_style (0, shell_escape_always_quoting_style, file_full_name), quotearg_n_style (1, shell_escape_always_quoting_style, "/"));
( __extension_...)))); }) == 0)Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 0Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 0Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
399 return false;
never executed: return 0 ;
0
400 }-
401-
402 if (do_chown)
do_chownDescription
TRUEevaluated 98 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 4 times by 2 tests
Evaluated by:
  • chgrp
  • chown
4-98
403 {-
404 if ( ! chopt->affect_symlink_referent)
! chopt->affec...mlink_referentDescription
TRUEevaluated 38 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 60 times by 2 tests
Evaluated by:
  • chgrp
  • chown
38-60
405 {-
406 ok = (lchownat (fts->fts_cwd_fd, file, uid, gid) == 0);-
407-
408 /* Ignore any error due to lack of support; POSIX requires-
409 this behavior for top-level symbolic links with -h, and-
410 implies that it's required for all symbolic links. */-
411 if (!ok && errno == EOPNOTSUPP)
!okDescription
TRUEnever evaluated
FALSEevaluated 38 times by 2 tests
Evaluated by:
  • chgrp
  • chown
(*__errno_location ()) == 95Description
TRUEnever evaluated
FALSEnever evaluated
0-38
412 {-
413 ok = true;-
414 symlink_changed = false;-
415 }
never executed: end of block
0
416 }
executed 38 times by 2 tests: end of block
Executed by:
  • chgrp
  • chown
38
417 else-
418 {-
419 /* If possible, avoid a race condition with --from=O:G and without the-
420 (-h) --no-dereference option. If fts's stat call determined-
421 that the uid/gid of FILE matched the --from=O:G-selected-
422 owner and group IDs, blindly using chown(2) here could lead-
423 chown(1) or chgrp(1) mistakenly to dereference a *symlink*-
424 to an arbitrary file that an attacker had moved into the-
425 place of FILE during the window between the stat and-
426 chown(2) calls. If FILE is a regular file or a directory-
427 that can be opened, this race condition can be avoided safely. */-
428-
429 enum RCH_status err-
430 = restricted_chown (fts->fts_cwd_fd, file, file_stats, uid, gid,-
431 required_uid, required_gid);-
432 switch (err)-
433 {-
434 case RC_ok:
executed 4 times by 1 test: case RC_ok:
Executed by:
  • chown
4
435 break;
executed 4 times by 1 test: break;
Executed by:
  • chown
4
436-
437 case RC_do_ordinary_chown:
executed 56 times by 2 tests: case RC_do_ordinary_chown:
Executed by:
  • chgrp
  • chown
56
438 ok = (chownat (fts->fts_cwd_fd, file, uid, gid) == 0);-
439 break;
executed 56 times by 2 tests: break;
Executed by:
  • chgrp
  • chown
56
440-
441 case RC_error:
never executed: case RC_error:
0
442 ok = false;-
443 break;
never executed: break;
0
444-
445 case RC_inode_changed:
never executed: case RC_inode_changed:
0
446 /* FIXME: give a diagnostic in this case? */-
447 case RC_excluded:
never executed: case RC_excluded:
0
448 do_chown = false;-
449 ok = false;-
450 break;
never executed: break;
0
451-
452 default:
never executed: default:
0
453 abort ();
never executed: abort ();
0
454 }-
455 }-
456-
457 /* On some systems (e.g., GNU/Linux 2.4.x),-
458 the chown function resets the 'special' permission bits.-
459 Do *not* restore those bits; doing so would open a window in-
460 which a malicious user, M, could subvert a chown command run-
461 by some other user and operating on files in a directory-
462 where M has write access. */-
463-
464 if (do_chown && !ok && ! chopt->force_silent)
do_chownDescription
TRUEevaluated 98 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEnever evaluated
!okDescription
TRUEnever evaluated
FALSEevaluated 98 times by 2 tests
Evaluated by:
  • chgrp
  • chown
! chopt->force_silentDescription
TRUEnever evaluated
FALSEnever evaluated
0-98
465 error (0, errno, (uid != (uid_t) -1
never executed: error (0, (*__errno_location ()) , (uid != (uid_t) -1 ? dcgettext (((void *)0), "changing ownership of %s" , 5) : dcgettext (((void *)0), "changing group of %s" , 5) ), quotearg_style (shell_escape_always_quoting_style, file_full_name));
0
466 ? _("changing ownership of %s")
never executed: error (0, (*__errno_location ()) , (uid != (uid_t) -1 ? dcgettext (((void *)0), "changing ownership of %s" , 5) : dcgettext (((void *)0), "changing group of %s" , 5) ), quotearg_style (shell_escape_always_quoting_style, file_full_name));
0
467 : _("changing group of %s")),
never executed: error (0, (*__errno_location ()) , (uid != (uid_t) -1 ? dcgettext (((void *)0), "changing ownership of %s" , 5) : dcgettext (((void *)0), "changing group of %s" , 5) ), quotearg_style (shell_escape_always_quoting_style, file_full_name));
0
468 quoteaf (file_full_name));
never executed: error (0, (*__errno_location ()) , (uid != (uid_t) -1 ? dcgettext (((void *)0), "changing ownership of %s" , 5) : dcgettext (((void *)0), "changing group of %s" , 5) ), quotearg_style (shell_escape_always_quoting_style, file_full_name));
0
469 }
executed 98 times by 2 tests: end of block
Executed by:
  • chgrp
  • chown
98
470-
471 if (chopt->verbosity != V_off)
chopt->verbosity != V_offDescription
TRUEnever evaluated
FALSEevaluated 102 times by 2 tests
Evaluated by:
  • chgrp
  • chown
0-102
472 {-
473 bool changed =-
474 ((do_chown && ok && symlink_changed)
do_chownDescription
TRUEnever evaluated
FALSEnever evaluated
okDescription
TRUEnever evaluated
FALSEnever evaluated
symlink_changedDescription
TRUEnever evaluated
FALSEnever evaluated
0
475 && ! ((uid == (uid_t) -1 || uid == file_stats->st_uid)
uid == (uid_t) -1Description
TRUEnever evaluated
FALSEnever evaluated
uid == file_stats->st_uidDescription
TRUEnever evaluated
FALSEnever evaluated
0
476 && (gid == (gid_t) -1 || gid == file_stats->st_gid)));
gid == (gid_t) -1Description
TRUEnever evaluated
FALSEnever evaluated
gid == file_stats->st_gidDescription
TRUEnever evaluated
FALSEnever evaluated
0
477-
478 if (changed || chopt->verbosity == V_high)
changedDescription
TRUEnever evaluated
FALSEnever evaluated
chopt->verbosity == V_highDescription
TRUEnever evaluated
FALSEnever evaluated
0
479 {-
480 enum Change_status ch_status =-
481 (!ok ? CH_FAILED
!okDescription
TRUEnever evaluated
FALSEnever evaluated
0
482 : !symlink_changed ? CH_NOT_APPLIED
!symlink_changedDescription
TRUEnever evaluated
FALSEnever evaluated
0
483 : !changed ? CH_NO_CHANGE_REQUESTED
!changedDescription
TRUEnever evaluated
FALSEnever evaluated
0
484 : CH_SUCCEEDED);-
485 char *old_usr = file_stats ? uid_to_name (file_stats->st_uid) : NULL;
file_statsDescription
TRUEnever evaluated
FALSEnever evaluated
0
486 char *old_grp = file_stats ? gid_to_name (file_stats->st_gid) : NULL;
file_statsDescription
TRUEnever evaluated
FALSEnever evaluated
0
487 describe_change (file_full_name, ch_status,-
488 old_usr, old_grp,-
489 chopt->user_name, chopt->group_name);-
490 free (old_usr);-
491 free (old_grp);-
492 }
never executed: end of block
0
493 }
never executed: end of block
0
494-
495 if ( ! chopt->recurse)
! chopt->recurseDescription
TRUEevaluated 54 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 48 times by 2 tests
Evaluated by:
  • chgrp
  • chown
48-54
496 fts_set (fts, ent, FTS_SKIP);
executed 54 times by 2 tests: fts_set (fts, ent, 4);
Executed by:
  • chgrp
  • chown
54
497-
498 return ok;
executed 102 times by 2 tests: return ok;
Executed by:
  • chgrp
  • chown
102
499}-
500-
501/* Change the owner and/or group of the specified FILES.-
502 BIT_FLAGS specifies how to treat each symlink-to-directory-
503 that is encountered during a recursive traversal.-
504 CHOPT specifies additional options.-
505 If UID is not -1, then change the owner id of each file to UID.-
506 If GID is not -1, then change the group id of each file to GID.-
507 If REQUIRED_UID and/or REQUIRED_GID is not -1, then change only-
508 files with user ID and group ID that match the non-(-1) value(s).-
509 Return true if successful. */-
510extern bool-
511chown_files (char **files, int bit_flags,-
512 uid_t uid, gid_t gid,-
513 uid_t required_uid, gid_t required_gid,-
514 struct Chown_option const *chopt)-
515{-
516 bool ok = true;-
517-
518 /* Use lstat and stat only if they're needed. */-
519 int stat_flags = ((required_uid != (uid_t) -1 || required_gid != (gid_t) -1
required_uid != (uid_t) -1Description
TRUEnever evaluated
FALSEevaluated 73 times by 2 tests
Evaluated by:
  • chgrp
  • chown
required_gid != (gid_t) -1Description
TRUEevaluated 5 times by 1 test
Evaluated by:
  • chown
FALSEevaluated 68 times by 2 tests
Evaluated by:
  • chgrp
  • chown
0-73
520 || chopt->affect_symlink_referent
chopt->affect_symlink_referentDescription
TRUEevaluated 46 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 22 times by 2 tests
Evaluated by:
  • chgrp
  • chown
22-46
521 || chopt->verbosity != V_off)
chopt->verbosity != V_offDescription
TRUEnever evaluated
FALSEevaluated 22 times by 2 tests
Evaluated by:
  • chgrp
  • chown
0-22
522 ? 0-
523 : FTS_NOSTAT);-
524-
525 FTS *fts = xfts_open (files, bit_flags | stat_flags, NULL);-
526-
527 while (1)-
528 {-
529 FTSENT *ent;-
530-
531 ent = fts_read (fts);-
532 if (ent == NULL)
ent == ((void *)0)Description
TRUEevaluated 73 times by 2 tests
Evaluated by:
  • chgrp
  • chown
FALSEevaluated 148 times by 2 tests
Evaluated by:
  • chgrp
  • chown
73-148
533 {-
534 if (errno != 0)
(*__errno_location ()) != 0Description
TRUEnever evaluated
FALSEevaluated 73 times by 2 tests
Evaluated by:
  • chgrp
  • chown
0-73
535 {-
536 /* FIXME: try to give a better message */-
537 if (! chopt->force_silent)
! chopt->force_silentDescription
TRUEnever evaluated
FALSEnever evaluated
0
538 error (0, errno, _("fts_read failed"));
never executed: error (0, (*__errno_location ()) , dcgettext (((void *)0), "fts_read failed" , 5) );
0
539 ok = false;-
540 }
never executed: end of block
0
541 break;
executed 73 times by 2 tests: break;
Executed by:
  • chgrp
  • chown
73
542 }-
543-
544 ok &= change_file_owner (fts, ent, uid, gid,-
545 required_uid, required_gid, chopt);-
546 }
executed 148 times by 2 tests: end of block
Executed by:
  • chgrp
  • chown
148
547-
548 if (fts_close (fts) != 0)
fts_close (fts) != 0Description
TRUEnever evaluated
FALSEevaluated 73 times by 2 tests
Evaluated by:
  • chgrp
  • chown
0-73
549 {-
550 error (0, errno, _("fts_close failed"));-
551 ok = false;-
552 }
never executed: end of block
0
553-
554 return ok;
executed 73 times by 2 tests: return ok;
Executed by:
  • chgrp
  • chown
73
555}-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.1.2