/* The file descriptor for the directory containing "path" */
int parent_fd = 0;
+ /* dirname() and basename() mangle their arguments, so we need
+ to make copies of "path" before using them. */
+ char* dirname_path_copy = NULL;
+ char* basename_path_copy = NULL;
+
/* Get the parent directory of "path" with dirname(), which happens
* to murder its argument and necessitates a path_copy. */
- char* path_copy = strdup(path);
- if (path_copy == NULL) {
+ dirname_path_copy = strdup(path);
+ if (dirname_path_copy == NULL) {
perror("apply_default_acl_ex (strdup)");
return ACL_ERROR;
}
- char* parent = dirname(path_copy);
+ char* parent = dirname(dirname_path_copy);
parent_fd = safe_open(parent, O_DIRECTORY | O_NOFOLLOW);
if (parent_fd == OPEN_ERROR) {
if (errno == ELOOP || errno == ENOTDIR) {
goto cleanup;
}
- fd = safe_open(path, O_NOFOLLOW);
+ /* We already obtained the parent fd safely, so if we use the
+ basename of path here instead of the full thing, then we can get
+ away with using openat() and spare ourselves the slowness of
+ another safe_open(). */
+ basename_path_copy = strdup(path);
+ if (basename_path_copy == NULL) {
+ perror("apply_default_acl_ex (strdup)");
+ return ACL_ERROR;
+ }
+ fd = openat(parent_fd, basename(basename_path_copy), O_NOFOLLOW);
if (fd == OPEN_ERROR) {
if (errno == ELOOP || errno == ENOTDIR) {
/* We hit a symlink, either in the last path component (ELOOP)
}
/* There's a good reason why we saved the ACL above, even though
- * we're about tto read it back into memory and mess with it on the
+ * we're about to read it back into memory and mess with it on the
* next line. The acl_copy_xattr() function is already a hack to let
* us copy default ACLs without resorting to path names; we simply
* have no way to read the parent's default ACL into memory using
*/
/* Now we potentially need to mask the execute permissions in the
- ACL on fd; or maybe now. */
+ ACL on fd; or maybe not. */
if (allow_exec) {
goto cleanup;
}
}
cleanup:
- free(path_copy);
+ free(dirname_path_copy);
+ free(basename_path_copy);
if (new_acl != (acl_t)NULL) {
acl_free(new_acl);
}