/* 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)
}
cleanup:
- free(path_copy);
+ free(dirname_path_copy);
+ free(basename_path_copy);
if (new_acl != (acl_t)NULL) {
acl_free(new_acl);
}