From patchwork Thu Sep 10 15:19:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 40393 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 996173972437; Thu, 10 Sep 2020 15:19:28 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 996173972437 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1599751168; bh=zNjoCyV0nHdZ185LY1n+WORtjEv6Oir9KZEn4YIvXXk=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=Y1dUy1b2M69gceOclCwe0CwtIkT5Qn09dDpqQadVF9+aR5Hq1iP1O+HePpAWsIYnI q0Cnv4HoxYdiztzHSE8q1O4+/cuL4ZOfyrv0hexEcElv7b0CuM5BwctF2Ke+Ydi2UN 84lWBhEEgMyw9H13DWSsUm/NEzIXfq/fDIjk3oY0= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qk1-x744.google.com (mail-qk1-x744.google.com [IPv6:2607:f8b0:4864:20::744]) by sourceware.org (Postfix) with ESMTPS id 9B5763857C50 for ; Thu, 10 Sep 2020 15:19:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 9B5763857C50 Received: by mail-qk1-x744.google.com with SMTP id g72so6397382qke.8 for ; Thu, 10 Sep 2020 08:19:25 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=zNjoCyV0nHdZ185LY1n+WORtjEv6Oir9KZEn4YIvXXk=; b=PsMn4SigADjeleetrQ54qyxztIeygIwHisTGNfYB9fsbgWAOxq6wlAEnG+MIb/g3ls shSWi6C+8cNb2CWpjN3f0vbBXLLI2RnaVeF8HIWxMK3GKAuKNq1i55WHeKFl6ObWz4EP rftu3NUT+YwusQx0ycXIr+tItCHDLabe2h30Hzts5fjuhp7fK7ZMuQYV9B8sjNZnxoZM GRSCKETtndzVYae6xESije9Jxo8gZ0oa4b1+SvgAkIptw1T85SIlAu/mm5LznlIkhCZU Sy9ViPCBeaAammd+ntr2y9YU1QEL+FyDLW7LOW+USXLt2jLjwSyx+iHPUNkTJPb8mjw0 QRwQ== X-Gm-Message-State: AOAM532TylYgNazcQ5ftU/BE8ToHy3Hyr1atsvB7mmGj9U8/6fLwHL8M nrjlHL0dBVbdIu3sloB+w0Qi+b4YgiZwJA== X-Google-Smtp-Source: ABdhPJyCInZf909bbT9CudJYIHY7jjy28pzSR8RKCwb+NeuCJa5+BocFJ4Q9Nx7+KEx33vuc9oU6uw== X-Received: by 2002:a37:897:: with SMTP id 145mr8622524qki.82.1599751164525; Thu, 10 Sep 2020 08:19:24 -0700 (PDT) Received: from localhost.localdomain ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id z37sm7851090qtz.67.2020.09.10.08.19.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Sep 2020 08:19:24 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH 4/4] stdlib: Remove lstat usage from realpath [BZ #24970] Date: Thu, 10 Sep 2020 12:19:15 -0300 Message-Id: <20200910151915.1982465-4-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200910151915.1982465-1-adhemerval.zanella@linaro.org> References: <20200910151915.1982465-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-13.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" The readlink already tells whether the file is a symlink, so there is no need to call lstat to check it. However for '..' it requires an extra readlink check if the previous component can be really accessed, otherwise the next iteration will check a possible valid path and end early. It should performance-wise acceptable and a gain over lstat, afaik symlink should not update any inode information. Checked on x86_64-linux-gnu and i686-linux-gnu. --- stdlib/canonicalize.c | 52 ++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c index 44a25a9a59..952f4dca41 100644 --- a/stdlib/canonicalize.c +++ b/stdlib/canonicalize.c @@ -55,6 +55,7 @@ __realpath (const char *name, char *resolved) const char *start, *end, *rpath_limit; const size_t path_max = PATH_MAX; int num_links = 0; + char buf[PATH_MAX]; char extra_buf[PATH_MAX]; if (name == NULL) @@ -104,12 +105,6 @@ __realpath (const char *name, char *resolved) for (end = start; *start; start = end) { -#ifdef _LIBC - struct stat64 st; -#else - struct stat st; -#endif - /* Skip sequence of multiple path-separators. */ while (*start == '/') ++start; @@ -118,12 +113,25 @@ __realpath (const char *name, char *resolved) for (end = start; *end && *end != '/'; ++end) /* Nothing. */; - if (end - start == 0) - break; - else if (end - start == 1 && start[0] == '.') + if (end - start == 1 && start[0] == '.') /* nothing */; else if (end - start == 2 && start[0] == '.' && start[1] == '.') { + ssize_t n; + + if (dest[-1] != '/') + *dest++ = '/'; + *dest = '\0'; + + n = __readlink (rpath, buf, path_max - 1); + if (n == -1) + { + if (errno == ENOTDIR && dest[-1] == '/') + dest[-1] = '\0'; + if (errno != EINVAL) + goto error; + } + /* Back up to previous component, ignore if at root already. */ if (dest > rpath + 1) for (--dest; dest > rpath && dest[-1] != '/'; --dest) @@ -132,6 +140,7 @@ __realpath (const char *name, char *resolved) else { size_t new_size; + ssize_t n; if (dest[-1] != '/') *dest++ = '/'; @@ -166,25 +175,23 @@ __realpath (const char *name, char *resolved) dest = __mempcpy (dest, start, end - start); *dest = '\0'; - if (__lxstat64 (_STAT_VER, rpath, &st) < 0) - goto error; - - if (S_ISLNK (st.st_mode)) + n = __readlink (rpath, buf, path_max - 1); + if (n < 0) + { + if (errno == ENOTDIR && dest[-1] == '/') + dest[-1] = '\0'; + if (errno != EINVAL) + goto error; + } + else { - char buf[PATH_MAX]; size_t len; - ssize_t n; if (++num_links > __eloop_threshold ()) { __set_errno (ELOOP); goto error; } - n = __readlink (rpath, buf, path_max - 1); - if (n < 0) - goto error; - buf[n] = '\0'; - len = strlen (end); /* Check that n + len + 1 doesn't overflow and is <= path_max. */ if (n >= SIZE_MAX - len || n + len >= path_max) @@ -211,11 +218,6 @@ __realpath (const char *name, char *resolved) continue; } } - else if (!S_ISDIR (st.st_mode) && *end != '\0') - { - __set_errno (ENOTDIR); - goto error; - } } } if (dest > rpath + 1 && dest[-1] == '/')