Return true if copy of file SRC_NAME to file DEST_NAME aka DEST_DIRFD+DEST_RELNAME is necessary. */
| 166 | /* Return true if copy of file SRC_NAME to file DEST_NAME aka |
| 167 | DEST_DIRFD+DEST_RELNAME is necessary. */ |
| 168 | static bool |
| 169 | need_copy (char const *src_name, char const *dest_name, |
| 170 | int dest_dirfd, char const *dest_relname, |
| 171 | const struct cp_options *x) |
| 172 | { |
| 173 | if (extra_mode (mode)) |
| 174 | return true; |
| 175 | |
| 176 | /* compare files using stat */ |
| 177 | struct stat src_sb; |
| 178 | if (stat (src_name, &src_sb) != 0) |
| 179 | return true; |
| 180 | |
| 181 | struct stat dest_sb; |
| 182 | if (fstatat (dest_dirfd, dest_relname, &dest_sb, AT_SYMLINK_NOFOLLOW) != 0) |
| 183 | return true; |
| 184 | |
| 185 | if (!S_ISREG (src_sb.st_mode) || !S_ISREG (dest_sb.st_mode) |
| 186 | || extra_mode (src_sb.st_mode) || extra_mode (dest_sb.st_mode)) |
| 187 | return true; |
| 188 | |
| 189 | if (src_sb.st_size != dest_sb.st_size |
| 190 | || (dest_sb.st_mode & CHMOD_MODE_BITS) != mode) |
| 191 | return true; |
| 192 | |
| 193 | if (owner_id == (uid_t) -1) |
| 194 | { |
| 195 | errno = 0; |
| 196 | uid_t ruid = getuid (); |
| 197 | if ((ruid == (uid_t) -1 && errno) || dest_sb.st_uid != ruid) |
| 198 | return true; |
| 199 | } |
| 200 | else if (dest_sb.st_uid != owner_id) |
| 201 | return true; |
| 202 | |
| 203 | if (group_id == (uid_t) -1) |
| 204 | { |
| 205 | errno = 0; |
| 206 | gid_t rgid = getgid (); |
| 207 | if ((rgid == (uid_t) -1 && errno) || dest_sb.st_gid != rgid) |
| 208 | return true; |
| 209 | } |
| 210 | else if (dest_sb.st_gid != group_id) |
| 211 | return true; |
| 212 | |
| 213 | /* compare SELinux context if preserving */ |
| 214 | if (selinux_enabled && x->preserve_security_context) |
| 215 | { |
| 216 | char *file_scontext_raw = NULL; |
| 217 | if (getfilecon_raw (src_name, &file_scontext_raw) == -1) |
| 218 | return true; |
| 219 | |
| 220 | char *to_scontext_raw = NULL; |
| 221 | if (getfilecon_raw (dest_name, &to_scontext_raw) == -1) |
| 222 | { |
| 223 | freecon (file_scontext_raw); |
| 224 | return true; |
| 225 | } |
no test coverage detected