diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 33cf4f072..a0ad3c2d0 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -4439,7 +4439,7 @@ gen_full_path_at (char *path_ret, int dirfd, const char *pathname, cygheap_fdget cfd (dirfd); if (cfd < 0) return -1; - if (!cfd->pc.isdir ()) + if (!cfd->pc.isdir () && !(flags & AT_EMPTY_PATH)) { set_errno (ENOTDIR); return -1; @@ -4450,6 +4450,8 @@ gen_full_path_at (char *path_ret, int dirfd, const char *pathname, { if (!*pathname) { + if (flags & AT_EMPTY_PATH) + return 0; set_errno (ENOENT); return -1; } @@ -4571,29 +4573,14 @@ fchownat (int dirfd, const char *pathname, uid_t uid, gid_t gid, int flags) __leave; } char *path = tp.c_get (); - int res = gen_full_path_at (path, dirfd, pathname); + int res = gen_full_path_at (path, dirfd, pathname, flags); if (res) + __leave; + if (!*pathname) /* Implies AT_EMPTY_PATH */ { - if (!(errno == ENOENT && (flags & AT_EMPTY_PATH))) - __leave; - /* pathname is an empty string. Operate on dirfd. */ - if (dirfd == AT_FDCWD) - { - cwdstuff::acquire_read (); - strcpy (path, cygheap->cwd.get_posix ()); - cwdstuff::release_read (); - } - else - { - cygheap_fdget cfd (dirfd); - if (cfd < 0) - __leave; - strcpy (path, cfd->get_name ()); - /* If dirfd refers to a symlink (which was necessarily - opened with O_PATH | O_NOFOLLOW), we must operate - directly on that symlink.. */ - flags = AT_SYMLINK_NOFOLLOW; - } + /* If dirfd refers to a symlink (which was necessarily opened with + O_PATH | O_NOFOLLOW), we must operate directly on that symlink. */ + flags = AT_SYMLINK_NOFOLLOW; } return chown_worker (path, (flags & AT_SYMLINK_NOFOLLOW) ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW, uid, gid); @@ -4616,21 +4603,9 @@ fstatat (int dirfd, const char *__restrict pathname, struct stat *__restrict st, __leave; } char *path = tp.c_get (); - int res = gen_full_path_at (path, dirfd, pathname); + int res = gen_full_path_at (path, dirfd, pathname, flags); if (res) - { - if (!(errno == ENOENT && (flags & AT_EMPTY_PATH))) - __leave; - /* pathname is an empty string. Operate on dirfd. */ - if (dirfd == AT_FDCWD) - { - cwdstuff::acquire_read (); - strcpy (path, cygheap->cwd.get_posix ()); - cwdstuff::release_read (); - } - else - return fstat (dirfd, st); - } + __leave; path_conv pc (path, ((flags & AT_SYMLINK_NOFOLLOW) ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW) | PC_POSIX | PC_KEEP_HANDLE, stat_suffixes);