From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2210) id A792F3938C08; Mon, 1 Mar 2021 14:02:16 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A792F3938C08 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Ken Brown To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin] Cygwin: simplify linkat with AT_EMPTY_PATH X-Act-Checkin: newlib-cygwin X-Git-Author: Ken Brown X-Git-Refname: refs/heads/master X-Git-Oldrev: 425203384a6c3e19af782c86570740464423eb4d X-Git-Newrev: 182ba1f022fb42b22fd2c7d925bf687227b2b3c7 Message-Id: <20210301140216.A792F3938C08@sourceware.org> Date: Mon, 1 Mar 2021 14:02:16 +0000 (GMT) X-BeenThere: cygwin-cvs@cygwin.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Cygwin core component git logs List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 01 Mar 2021 14:02:16 -0000 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=182ba1f022fb42b22fd2c7d925bf687227b2b3c7 commit 182ba1f022fb42b22fd2c7d925bf687227b2b3c7 Author: Ken Brown Date: Thu Feb 25 07:54:10 2021 -0500 Cygwin: simplify linkat with AT_EMPTY_PATH linkat(olddirfd, oldpath, oldname, newdirfd, newname, AT_EMPTY_PATH) is supposed to create a link to the file referenced by olddirfd if oldname is the empty string. Currently this is done via the /proc filesystem by converting the call to linkat(AT_FDCWD, "/proc/self/fd/", newdirfd, newname, AT_SYMLINK_FOLLOW), which ultimately leads to a call to the appropriate fhandler's link method. Simplify this by using cygheap_fdget to obtain the fhandler directly. Diff: --- winsup/cygwin/syscalls.cc | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 460fe6801..6ba4f10f7 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -4962,6 +4962,8 @@ linkat (int olddirfd, const char *oldpathname, int flags) { tmp_pathbuf tp; + fhandler_base *fh = NULL; + __try { if (flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) @@ -4970,21 +4972,25 @@ linkat (int olddirfd, const char *oldpathname, __leave; } char *oldpath = tp.c_get (); - /* AT_EMPTY_PATH with an empty oldpathname is equivalent to - - linkat(AT_FDCWD, "/proc/self/fd/", newdirfd, - newname, AT_SYMLINK_FOLLOW); - - Convert the request accordingly. */ if ((flags & AT_EMPTY_PATH) && oldpathname && oldpathname[0] == '\0') { + /* Operate directly on olddirfd, which can be anything + except a directory. */ if (olddirfd == AT_FDCWD) { set_errno (EPERM); __leave; } - __small_sprintf (oldpath, "/proc/%d/fd/%d", myself->pid, olddirfd); - flags = AT_SYMLINK_FOLLOW; + cygheap_fdget cfd (olddirfd); + if (cfd < 0) + __leave; + if (cfd->pc.isdir ()) + { + set_errno (EPERM); + __leave; + } + fh = cfd; + flags = 0; /* In case AT_SYMLINK_FOLLOW was set. */ } else if (gen_full_path_at (oldpath, olddirfd, oldpathname)) __leave; @@ -5003,6 +5009,8 @@ linkat (int olddirfd, const char *oldpathname, } strcpy (oldpath, old_name.get_posix ()); } + if (fh) + return fh->link (newpath); return link (oldpath, newpath); } __except (EFAULT) {}