From patchwork Tue Jul 20 10:33:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= X-Patchwork-Id: 12388007 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 28863C07E9B for ; Tue, 20 Jul 2021 10:34:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1102F610D2 for ; Tue, 20 Jul 2021 10:34:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236973AbhGTJxc (ORCPT ); Tue, 20 Jul 2021 05:53:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45418 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237640AbhGTJw5 (ORCPT ); Tue, 20 Jul 2021 05:52:57 -0400 Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A372FC061762 for ; Tue, 20 Jul 2021 03:33:35 -0700 (PDT) Received: by mail-wm1-x329.google.com with SMTP id n4so12008374wms.1 for ; Tue, 20 Jul 2021 03:33:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=4uz2KKn5sd/2X6wmQeTEAAQoEddd4k3jyWOUDlQXlFI=; b=d9ZHTEVSfA/VpvAQmJwHTH9RqX2cv8O9wGMlqVjIT1YTtbSPM4VAVKD72Bq0SYfbm0 1x9AkUoicD2dV1IURoXkoRJqeq221/YK+HDX9bIhnU3rYUJxC8UHtVm3HUyoGVDm+Fp5 tXHrzkQpvFmHyNZ2F+AvsbVRD6XuWBsdx5na4g14qnlk/DmlSndEfcG9EDtGzi/d1tlF cWchq4DAatAKQ/RTGuLzWClrKuH9WMMCe685F5eqZNP0fooOnYXhFAjyQN2Fg0JIZiDN Zehw5zyhgoIXX79GFnrErujyvnfjxVLSuzV6Vek2ohhpKX4XBWtnmVzn2GmaLy4SdXmD IAVQ== 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=4uz2KKn5sd/2X6wmQeTEAAQoEddd4k3jyWOUDlQXlFI=; b=MbK3vNfSfrL8l2MPmAdBeRQKJikSDA3OaQKo1O7tfz0OOWY5O5jIB6ZnEZpzyqM1+N v9HC2HMC+h8WLatCeQU0S9P/dssqtuLBq0XK+9sVhFdQ6Yll/GvouIiymTWrgySy9ft7 KDyMNlGr10pUemwJFE7GeeKgGv0igNtaN2Iyj4nkIJn0odzmPiE4Ns2z6HWzus3jeyaV fz9f+Ort5RTbf/LnjCGNoHr6vGOA9LJ80fFBBSeh1q8p0Bn11hJmEs1o9RvUSXRhbj8s YxQQkRBLiECJg9tSIEAtHqsJ+mEARYrrOoNTBBQyNihFZwD1VR8XkvmTiLxKEAPydeWE 8bfg== X-Gm-Message-State: AOAM533ay81kcFA/qt1ybokA0+Qj5W5dvyvRs09QfxuUlvCMSul5jRRM udzdHVfP2ZYGXcA2JgnjAyM8DrcOjYhSIg== X-Google-Smtp-Source: ABdhPJwLfTczEwPqSSgobvaNl351Z4Ie2h1Mf5BeCh8EcinEThLxML/xt9U3Y69u1U1h6xuL1/3mXw== X-Received: by 2002:a1c:9d16:: with SMTP id g22mr30732154wme.152.1626777213965; Tue, 20 Jul 2021 03:33:33 -0700 (PDT) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id l14sm22179852wrs.22.2021.07.20.03.33.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Jul 2021 03:33:33 -0700 (PDT) From: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= To: git@vger.kernel.org Cc: Junio C Hamano , Jeff King , Han-Wen Nienhuys , Michael Haggerty , Jonathan Tan , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBC?= =?utf-8?b?amFybWFzb24=?= Subject: [PATCH v9 1/7] refs file backend: move raceproof_create_file() here Date: Tue, 20 Jul 2021 12:33:24 +0200 Message-Id: X-Mailer: git-send-email 2.32.0.874.ge7a9d58bfcf In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Move the raceproof_create_file() API added to cache.h and object-file.c in 177978f56ad (raceproof_create_file(): new function, 2017-01-06) to its only user, refs/files-backend.c. Signed-off-by: Ævar Arnfjörð Bjarmason --- cache.h | 43 ----------------- object-file.c | 68 --------------------------- refs/files-backend.c | 109 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 111 deletions(-) diff --git a/cache.h b/cache.h index ba04ff8bd36..eb4dfe6381f 100644 --- a/cache.h +++ b/cache.h @@ -1202,49 +1202,6 @@ enum scld_error safe_create_leading_directories(char *path); enum scld_error safe_create_leading_directories_const(const char *path); enum scld_error safe_create_leading_directories_no_share(char *path); -/* - * Callback function for raceproof_create_file(). This function is - * expected to do something that makes dirname(path) permanent despite - * the fact that other processes might be cleaning up empty - * directories at the same time. Usually it will create a file named - * path, but alternatively it could create another file in that - * directory, or even chdir() into that directory. The function should - * return 0 if the action was completed successfully. On error, it - * should return a nonzero result and set errno. - * raceproof_create_file() treats two errno values specially: - * - * - ENOENT -- dirname(path) does not exist. In this case, - * raceproof_create_file() tries creating dirname(path) - * (and any parent directories, if necessary) and calls - * the function again. - * - * - EISDIR -- the file already exists and is a directory. In this - * case, raceproof_create_file() removes the directory if - * it is empty (and recursively any empty directories that - * it contains) and calls the function again. - * - * Any other errno causes raceproof_create_file() to fail with the - * callback's return value and errno. - * - * Obviously, this function should be OK with being called again if it - * fails with ENOENT or EISDIR. In other scenarios it will not be - * called again. - */ -typedef int create_file_fn(const char *path, void *cb); - -/* - * Create a file in dirname(path) by calling fn, creating leading - * directories if necessary. Retry a few times in case we are racing - * with another process that is trying to clean up the directory that - * contains path. See the documentation for create_file_fn for more - * details. - * - * Return the value and set the errno that resulted from the most - * recent call of fn. fn is always called at least once, and will be - * called more than once if it returns ENOENT or EISDIR. - */ -int raceproof_create_file(const char *path, create_file_fn fn, void *cb); - int mkdir_in_gitdir(const char *path); char *expand_user_path(const char *path, int real_home); const char *enter_repo(const char *path, int strict); diff --git a/object-file.c b/object-file.c index ecca5a8da00..231a02997ba 100644 --- a/object-file.c +++ b/object-file.c @@ -414,74 +414,6 @@ enum scld_error safe_create_leading_directories_const(const char *path) return result; } -int raceproof_create_file(const char *path, create_file_fn fn, void *cb) -{ - /* - * The number of times we will try to remove empty directories - * in the way of path. This is only 1 because if another - * process is racily creating directories that conflict with - * us, we don't want to fight against them. - */ - int remove_directories_remaining = 1; - - /* - * The number of times that we will try to create the - * directories containing path. We are willing to attempt this - * more than once, because another process could be trying to - * clean up empty directories at the same time as we are - * trying to create them. - */ - int create_directories_remaining = 3; - - /* A scratch copy of path, filled lazily if we need it: */ - struct strbuf path_copy = STRBUF_INIT; - - int ret, save_errno; - - /* Sanity check: */ - assert(*path); - -retry_fn: - ret = fn(path, cb); - save_errno = errno; - if (!ret) - goto out; - - if (errno == EISDIR && remove_directories_remaining-- > 0) { - /* - * A directory is in the way. Maybe it is empty; try - * to remove it: - */ - if (!path_copy.len) - strbuf_addstr(&path_copy, path); - - if (!remove_dir_recursively(&path_copy, REMOVE_DIR_EMPTY_ONLY)) - goto retry_fn; - } else if (errno == ENOENT && create_directories_remaining-- > 0) { - /* - * Maybe the containing directory didn't exist, or - * maybe it was just deleted by a process that is - * racing with us to clean up empty directories. Try - * to create it: - */ - enum scld_error scld_result; - - if (!path_copy.len) - strbuf_addstr(&path_copy, path); - - do { - scld_result = safe_create_leading_directories(path_copy.buf); - if (scld_result == SCLD_OK) - goto retry_fn; - } while (scld_result == SCLD_VANISHED && create_directories_remaining-- > 0); - } - -out: - strbuf_release(&path_copy); - errno = save_errno; - return ret; -} - static void fill_loose_path(struct strbuf *buf, const struct object_id *oid) { int i; diff --git a/refs/files-backend.c b/refs/files-backend.c index 443182da102..9fc596fc75a 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -852,6 +852,115 @@ static struct ref_iterator *files_ref_iterator_begin( return ref_iterator; } +/* + * Callback function for raceproof_create_file(). This function is + * expected to do something that makes dirname(path) permanent despite + * the fact that other processes might be cleaning up empty + * directories at the same time. Usually it will create a file named + * path, but alternatively it could create another file in that + * directory, or even chdir() into that directory. The function should + * return 0 if the action was completed successfully. On error, it + * should return a nonzero result and set errno. + * raceproof_create_file() treats two errno values specially: + * + * - ENOENT -- dirname(path) does not exist. In this case, + * raceproof_create_file() tries creating dirname(path) + * (and any parent directories, if necessary) and calls + * the function again. + * + * - EISDIR -- the file already exists and is a directory. In this + * case, raceproof_create_file() removes the directory if + * it is empty (and recursively any empty directories that + * it contains) and calls the function again. + * + * Any other errno causes raceproof_create_file() to fail with the + * callback's return value and errno. + * + * Obviously, this function should be OK with being called again if it + * fails with ENOENT or EISDIR. In other scenarios it will not be + * called again. + */ +typedef int create_file_fn(const char *path, void *cb); + +/* + * Create a file in dirname(path) by calling fn, creating leading + * directories if necessary. Retry a few times in case we are racing + * with another process that is trying to clean up the directory that + * contains path. See the documentation for create_file_fn for more + * details. + * + * Return the value and set the errno that resulted from the most + * recent call of fn. fn is always called at least once, and will be + * called more than once if it returns ENOENT or EISDIR. + */ +static int raceproof_create_file(const char *path, create_file_fn fn, void *cb) +{ + /* + * The number of times we will try to remove empty directories + * in the way of path. This is only 1 because if another + * process is racily creating directories that conflict with + * us, we don't want to fight against them. + */ + int remove_directories_remaining = 1; + + /* + * The number of times that we will try to create the + * directories containing path. We are willing to attempt this + * more than once, because another process could be trying to + * clean up empty directories at the same time as we are + * trying to create them. + */ + int create_directories_remaining = 3; + + /* A scratch copy of path, filled lazily if we need it: */ + struct strbuf path_copy = STRBUF_INIT; + + int ret, save_errno; + + /* Sanity check: */ + assert(*path); + +retry_fn: + ret = fn(path, cb); + save_errno = errno; + if (!ret) + goto out; + + if (errno == EISDIR && remove_directories_remaining-- > 0) { + /* + * A directory is in the way. Maybe it is empty; try + * to remove it: + */ + if (!path_copy.len) + strbuf_addstr(&path_copy, path); + + if (!remove_dir_recursively(&path_copy, REMOVE_DIR_EMPTY_ONLY)) + goto retry_fn; + } else if (errno == ENOENT && create_directories_remaining-- > 0) { + /* + * Maybe the containing directory didn't exist, or + * maybe it was just deleted by a process that is + * racing with us to clean up empty directories. Try + * to create it: + */ + enum scld_error scld_result; + + if (!path_copy.len) + strbuf_addstr(&path_copy, path); + + do { + scld_result = safe_create_leading_directories(path_copy.buf); + if (scld_result == SCLD_OK) + goto retry_fn; + } while (scld_result == SCLD_VANISHED && create_directories_remaining-- > 0); + } + +out: + strbuf_release(&path_copy); + errno = save_errno; + return ret; +} + static int remove_empty_directories(struct strbuf *path) { /* From patchwork Tue Jul 20 10:33:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= X-Patchwork-Id: 12388009 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D07CCC636C8 for ; Tue, 20 Jul 2021 10:34:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BBA126113B for ; Tue, 20 Jul 2021 10:34:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237050AbhGTJxf (ORCPT ); Tue, 20 Jul 2021 05:53:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45422 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237747AbhGTJw6 (ORCPT ); Tue, 20 Jul 2021 05:52:58 -0400 Received: from mail-wr1-x431.google.com (mail-wr1-x431.google.com [IPv6:2a00:1450:4864:20::431]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BA9A2C061766 for ; Tue, 20 Jul 2021 03:33:36 -0700 (PDT) Received: by mail-wr1-x431.google.com with SMTP id c15so1849606wrs.5 for ; Tue, 20 Jul 2021 03:33:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=8NVtBzykseMSgq5/5UylxP0KhLLIOhfcfT3ZvXlLOZQ=; b=KWTSFXqLsY/CrysoJlCJ7kxD/w/HTcMe6sDHozXQk+x3xEwxVzINMfYQB26Nn4VCTG ygpEQJDXD++H98C/E7tv89VNI2LY3f8bfpgEiZei/7pVS3Z6NMo2I2dwbTbXvNGktwDi UNV1NYOjFMIqOxVeTBZaqKJD4IJ8IVdzMPzkrldxPMLeX7W1TbGxTlIruDemEeTz8lJG H9gZ0s5GHeS6jg1lopgiMRzHjKaYT48g34kBflunNZZ9XFDmwD0krjogBttdkjF3ZHMD i+9NUrP1WzBSRzGURkqPVBkhBax5zA0wKSoupbD0bX0Goi+V2WftXohEp4U9nqSjLiOR jrow== 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=8NVtBzykseMSgq5/5UylxP0KhLLIOhfcfT3ZvXlLOZQ=; b=YchOfgDVsB/iGTDJOWRvLMtNPiUsij2E1v2y2HhlggUaSMrHm8HOnUDSPbIGeJqnTg nA2J0B2LiTcymEO6nyy0iuBQSjcyx6xmuxOMqqr6fOQVmznqIBHqc37EUNPhVh93tqbq s2L8EiXUaWIjV0j1Hns2oSwzjqvuWd0cPiq9VKCibvpDm8bInZ+cV6AxceOzSUOfQg0y ch+OTjDPi09ZeLT7ZOUIW5FlsMY72BVCm9NID1BxzG6+cvVHVxQxsRkBI4Airdb4BCX+ vsYkGqxMarCE+Ld51ZcK67uHb6aZTjWl3AnjsLqwDZoUCS/kTUL6xKD0nGiTMUF41uKW Aeww== X-Gm-Message-State: AOAM533eeKnSCKS5pjAsVjsXzX7sT1ygBQc2gRuEmntQUwz1eyYh+YCM 7LCDgBzb/d1IdWnjThuC6d9+I5IgyaB/Dw== X-Google-Smtp-Source: ABdhPJyOaOp1iY/4NUv4SkCKlCvZUoKdrJCpUIVlNDxBrZDwMxkrcZaJSMJnHetpnZqT6KMzY2kkig== X-Received: by 2002:a5d:591c:: with SMTP id v28mr34657053wrd.373.1626777215087; Tue, 20 Jul 2021 03:33:35 -0700 (PDT) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id l14sm22179852wrs.22.2021.07.20.03.33.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Jul 2021 03:33:34 -0700 (PDT) From: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= To: git@vger.kernel.org Cc: Junio C Hamano , Jeff King , Han-Wen Nienhuys , Michael Haggerty , Jonathan Tan , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBC?= =?utf-8?b?amFybWFzb24=?= Subject: [PATCH v9 2/7] refs: remove EINVAL errno output from specification of read_raw_ref_fn Date: Tue, 20 Jul 2021 12:33:25 +0200 Message-Id: X-Mailer: git-send-email 2.32.0.874.ge7a9d58bfcf In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Han-Wen Nienhuys This commit does not change code; it documents the fact that an alternate ref backend does not need to return EINVAL from read_raw_ref_fn to function properly. This is correct, because refs_read_raw_ref is only called from; * resolve_ref_unsafe(), which does not care for the EINVAL errno result. * refs_verify_refname_available(), which does not inspect errno. * files-backend.c, where errno is overwritten on failure. * packed-backend.c (is_packed_transaction_needed), which calls it for the packed ref backend, which never emits EINVAL. A grep for EINVAL */*c reveals that no code checks errno against EINVAL after reading references. In addition, the refs.h file does not mention errno at all. A grep over resolve_ref_unsafe() turned up the following callers that inspect errno: * sequencer.c::print_commit_summary, which uses it for die_errno * lock_ref_oid_basic(), which only treats EISDIR and ENOTDIR specially. The files ref backend does use EINVAL. The files backend does not call into the generic API (refs_read_raw), but into the files-specific function (files_read_raw_ref), which we are not changing in this commit. As the errno sideband is unintuitive and error-prone, remove EINVAL value, as a step towards getting rid of the errno sideband altogether. Spotted by Ævar Arnfjörð Bjarmason . Signed-off-by: Han-Wen Nienhuys Signed-off-by: Ævar Arnfjörð Bjarmason --- refs/refs-internal.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/refs/refs-internal.h b/refs/refs-internal.h index 3155708345f..dc0d826c3ac 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -622,9 +622,9 @@ typedef int reflog_expire_fn(struct ref_store *ref_store, * * Return 0 on success. If the ref doesn't exist, set errno to ENOENT * and return -1. If the ref exists but is neither a symbolic ref nor - * an object ID, it is broken; set REF_ISBROKEN in type, set errno to - * EINVAL, and return -1. If there is another error reading the ref, - * set errno appropriately and return -1. + * an object ID, it is broken; set REF_ISBROKEN in type, and return -1 + * (errno should not be ENOENT) If there is another error reading the + * ref, set errno appropriately and return -1. * * Backend-specific flags might be set in type as well, regardless of * outcome. From patchwork Tue Jul 20 10:33:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= X-Patchwork-Id: 12388011 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EBBC3C07E95 for ; Tue, 20 Jul 2021 10:35:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CB0A661003 for ; Tue, 20 Jul 2021 10:35:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234146AbhGTJxs (ORCPT ); Tue, 20 Jul 2021 05:53:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45428 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237882AbhGTJw7 (ORCPT ); Tue, 20 Jul 2021 05:52:59 -0400 Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [IPv6:2a00:1450:4864:20::335]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9CF62C061767 for ; Tue, 20 Jul 2021 03:33:37 -0700 (PDT) Received: by mail-wm1-x335.google.com with SMTP id g8-20020a1c9d080000b02901f13dd1672aso1326671wme.0 for ; Tue, 20 Jul 2021 03:33:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=304iIfSiGLscPNtKwb+exyYfNv+ZazXaWiDUM5C6rP4=; b=jqi/deN+TLx0cNDvVA24/iv6TRnCueQ+scSGAqumxOtSfTHtKIQ7lLqbp4YZhXym2S td0NCcH4BOhoKm7fsny/Mq8D3KpGQ9Lk9dKTU6YebyVS02jz09c3ZZQWooiCUysnTdHY RkYZKeBI0y3jLQjkt8xOEWZ3X9EeGNiedHBkIJdtGeUixtFvY5DHVv2fTpIouBSZ6EIf iNNKsjxzalgatDUV01fvG0wrmV21OsRRtLjrdPT59lnxTWnTtZNqMcFovjmtJqEIf1Hd 3uOiWnMFCvMSiHwpLxn5rMnrtn7ewucL3MidIas3IWbSWskjNO89KjH3/y/LIr67NgbF NHyg== 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=304iIfSiGLscPNtKwb+exyYfNv+ZazXaWiDUM5C6rP4=; b=g/D7xMICTRq0rY09QAj4OfcEi/mHEU6quZ35eYJEgNLMcLSHW6MJktmIedXS86/UML NtO8eaUYT0VuCwvWupuUn+XUUZqsYemQhdMKCYmXV3A8+LITam7wp2uvCzoBWc2iiUM1 DHT5Ft/+W9jsJVBq7RQ5Pc3sYd6g0Fux8j0xdezBzhOiF93ogy7YRjgEhilB4qOzGJEw lAKqBVU+4U/Y0jftm/uf3N9Xp5nmf5aZovgZCHOoikucWhpOCN5KzOMDRaytbC4lZJ5E WxpGsXw9pILe6r0TJFVpoOZDI1UVPG+ZyiZXHklaPfd0z3ha8MtvO3t6UBAQQc4e6yGF EeBA== X-Gm-Message-State: AOAM533JNW/4uUToFRw5x2I8EO0SP7EbPMrFWrO1hJsNXWsJRM4pxlJU X08Tk/9VTk/8OXRah8VvRt+CrJCtrqt+iQ== X-Google-Smtp-Source: ABdhPJy+V5KaGLsqajTHLAbRoAo9imp9s3sVLQUz+hzeh3rCIS09BK1yAe9uGk5yBS6t0GkaodklWg== X-Received: by 2002:a7b:cb13:: with SMTP id u19mr30363568wmj.122.1626777216030; Tue, 20 Jul 2021 03:33:36 -0700 (PDT) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id l14sm22179852wrs.22.2021.07.20.03.33.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Jul 2021 03:33:35 -0700 (PDT) From: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= To: git@vger.kernel.org Cc: Junio C Hamano , Jeff King , Han-Wen Nienhuys , Michael Haggerty , Jonathan Tan , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBC?= =?utf-8?b?amFybWFzb24=?= Subject: [PATCH v9 3/7] refs/files-backend: stop setting errno from lock_ref_oid_basic Date: Tue, 20 Jul 2021 12:33:26 +0200 Message-Id: X-Mailer: git-send-email 2.32.0.874.ge7a9d58bfcf In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Han-Wen Nienhuys refs/files-backend.c::lock_ref_oid_basic() tries to signal how it failed to its callers using errno. It is safe to stop setting errno here, because the callers of this file-scope static function are * files_copy_or_rename_ref() * files_create_symref() * files_reflog_expire() None of them looks at errno after seeing a negative return from lock_ref_oid_basic() to make any decision, and no caller of these three functions looks at errno after they signal a failure by returning a negative value. In particular, * files_copy_or_rename_ref() - here, calls are followed by error() (which performs I/O) or write_ref_to_lockfile() (which calls parse_object() which may perform I/O) * files_create_symref() - here, calls are followed by error() or create_symref_locked() (which performs I/O and does not inspect errno) * files_reflog_expire() - here, calls are followed by error() or refs_reflog_exists() (which calls a function in a vtable that is not documented to use and/or preserve errno) Signed-off-by: Han-Wen Nienhuys Signed-off-by: Ævar Arnfjörð Bjarmason --- refs/files-backend.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/refs/files-backend.c b/refs/files-backend.c index 9fc596fc75a..9e00da76121 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -982,7 +982,6 @@ static int create_reflock(const char *path, void *cb) /* * Locks a ref returning the lock on success and NULL on failure. - * On failure errno is set to something meaningful. */ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs, const char *refname, @@ -991,7 +990,6 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs, { struct strbuf ref_file = STRBUF_INIT; struct ref_lock *lock; - int last_errno = 0; files_assert_main_repository(refs, "lock_ref_oid_basic"); assert(err); @@ -1002,11 +1000,10 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs, if (!refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_NO_RECURSE, &lock->old_oid, type)) { - last_errno = errno; if (!refs_verify_refname_available(&refs->base, refname, NULL, NULL, err)) strbuf_addf(err, "unable to resolve reference '%s': %s", - refname, strerror(last_errno)); + refname, strerror(errno)); goto error_return; } @@ -1019,15 +1016,12 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs, */ if (is_null_oid(&lock->old_oid) && refs_verify_refname_available(refs->packed_ref_store, refname, - NULL, NULL, err)) { - last_errno = ENOTDIR; + NULL, NULL, err)) goto error_return; - } lock->ref_name = xstrdup(refname); if (raceproof_create_file(ref_file.buf, create_reflock, &lock->lk)) { - last_errno = errno; unable_to_lock_message(ref_file.buf, errno, err); goto error_return; } @@ -1044,7 +1038,6 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs, out: strbuf_release(&ref_file); - errno = last_errno; return lock; } From patchwork Tue Jul 20 10:33:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= X-Patchwork-Id: 12388015 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EF216C07E9B for ; Tue, 20 Jul 2021 10:35:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D206161107 for ; Tue, 20 Jul 2021 10:35:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237389AbhGTJx5 (ORCPT ); Tue, 20 Jul 2021 05:53:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45434 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237714AbhGTJxA (ORCPT ); Tue, 20 Jul 2021 05:53:00 -0400 Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [IPv6:2a00:1450:4864:20::335]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 90B82C061768 for ; Tue, 20 Jul 2021 03:33:38 -0700 (PDT) Received: by mail-wm1-x335.google.com with SMTP id a23-20020a05600c2257b0290236ec98bebaso1742018wmm.1 for ; Tue, 20 Jul 2021 03:33:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=exCQ0t4cuYVrmo1Jt6usFhqFnku3z4Ti6De+emN/wZk=; b=auFlPMlaLjPsfrCGd3wb/uz56sF11nDmWQihRRQC5bIlvzrDz9azE5gfCkuCYCdItb PPrEM7MLmIhk2bl84ETwQ+Joban8g17zRHKkmoJ3UVJfGZ+DJivvthV7cDxTMyIUTLu/ IBB2V+m9xwWRkbZT2H+vMRiYCfoP2XxnekaZWWaEMvgIiHu2MD82lCg+yKojzuEBdsea 6gaY01x20DJko0JqPsW09ac1SK3EWLNmu4VkfGa4mOXR7tMNhB3wiPr/zNujglNX6wj2 f5h+U1X3w37gF/6P5eOVJSj4gxMDWJi9DwhKgsbB41oG1RyY1nTy2g90shP2PA6nlhbg FG5Q== 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=exCQ0t4cuYVrmo1Jt6usFhqFnku3z4Ti6De+emN/wZk=; b=DWAtKhKRo5SjEmXoGbAds6aJ/Jefgpf6oUZXKxpVsdGYvkpQ9oQyp6DUyP8PyrPc0Z JNLGOqLzc/9IS49lISBlidKGAjvXpOkqUNUghu6CJP4jGg630Vy0lM4YfwvYkjzxILzy 5kTtMu02r++0ssnSS101o4e0OmlQ3YTvsp27HGJZaRtEw89Rbs3zmznxMLtyB9XirnzA yVTWWR6+/jOsu/CHRw6li4gErUbyrjFHh/txLAGdsjJHuWb2t/Ut+WIJqXUng4RmB251 rXMBGUn3UI8rnCwSeV4iZ3H2SHj/3Y6OidNpG3ULrh1v9GCKmJcRIsNK6JLmyfLAFLEG Z4+Q== X-Gm-Message-State: AOAM53139asxHNgXnVKAIglrH4iCp0Cr19sH2buqxCcDZjpfoJpkNXrG GULLlbd2ydLp2TrES7Zt+9tQEdSaYYRRrg== X-Google-Smtp-Source: ABdhPJyYkirWxrQR71v2t1Hmvs5tIWWnnk8XVplqjY9PmEvksljv3h0Tpowp0HS386l4rcUFSflC5g== X-Received: by 2002:a1c:494:: with SMTP id 142mr31127756wme.60.1626777216846; Tue, 20 Jul 2021 03:33:36 -0700 (PDT) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id l14sm22179852wrs.22.2021.07.20.03.33.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Jul 2021 03:33:36 -0700 (PDT) From: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= To: git@vger.kernel.org Cc: Junio C Hamano , Jeff King , Han-Wen Nienhuys , Michael Haggerty , Jonathan Tan , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBC?= =?utf-8?b?amFybWFzb24=?= Subject: [PATCH v9 4/7] refs: make errno output explicit for read_raw_ref_fn Date: Tue, 20 Jul 2021 12:33:27 +0200 Message-Id: X-Mailer: git-send-email 2.32.0.874.ge7a9d58bfcf In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Han-Wen Nienhuys This makes it explicit how alternative ref backends should report errors in read_raw_ref_fn. read_raw_ref_fn needs to supply a credible errno for a number of cases. These are primarily: 1) The files backend calls read_raw_ref from lock_raw_ref, and uses the resulting error codes to create/remove directories as needed. 2) ENOENT should be translated in a zero OID, optionally with REF_ISBROKEN set, returning the last successfully resolved symref. This is necessary so read_raw_ref("HEAD") on an empty repo returns refs/heads/main (or the default branch du-jour), and we know on which branch to create the first commit. Make this information flow explicit by adding a failure_errno to the signature of read_raw_ref. All errnos from the files backend are still propagated unchanged, even though inspection suggests only ENOTDIR, EISDIR and ENOENT are relevant. Signed-off-by: Han-Wen Nienhuys Signed-off-by: Ævar Arnfjörð Bjarmason --- refs.c | 2 +- refs/debug.c | 4 ++-- refs/files-backend.c | 29 +++++++++++++++-------------- refs/packed-backend.c | 8 ++++---- refs/refs-internal.h | 20 ++++++++++++-------- 5 files changed, 34 insertions(+), 29 deletions(-) diff --git a/refs.c b/refs.c index d9635436759..fc6c0ddffae 100644 --- a/refs.c +++ b/refs.c @@ -1682,7 +1682,7 @@ int refs_read_raw_ref(struct ref_store *ref_store, } return ref_store->be->read_raw_ref(ref_store, refname, oid, referent, - type); + type, &errno); } /* This function needs to return a meaningful errno on failure */ diff --git a/refs/debug.c b/refs/debug.c index 18fd9bca595..d0aaea6d918 100644 --- a/refs/debug.c +++ b/refs/debug.c @@ -238,7 +238,7 @@ debug_ref_iterator_begin(struct ref_store *ref_store, const char *prefix, static int debug_read_raw_ref(struct ref_store *ref_store, const char *refname, struct object_id *oid, struct strbuf *referent, - unsigned int *type) + unsigned int *type, int *failure_errno) { struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store; int res = 0; @@ -246,7 +246,7 @@ static int debug_read_raw_ref(struct ref_store *ref_store, const char *refname, oidcpy(oid, null_oid()); errno = 0; res = drefs->refs->be->read_raw_ref(drefs->refs, refname, oid, referent, - type); + type, failure_errno); if (res == 0) { trace_printf_key(&trace_refs, "read_raw_ref: %s: %s (=> %s) type %x: %d\n", diff --git a/refs/files-backend.c b/refs/files-backend.c index 9e00da76121..85b4d791444 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -341,9 +341,9 @@ static struct ref_cache *get_loose_ref_cache(struct files_ref_store *refs) return refs->loose; } -static int files_read_raw_ref(struct ref_store *ref_store, - const char *refname, struct object_id *oid, - struct strbuf *referent, unsigned int *type) +static int files_read_raw_ref(struct ref_store *ref_store, const char *refname, + struct object_id *oid, struct strbuf *referent, + unsigned int *type, int *failure_errno) { struct files_ref_store *refs = files_downcast(ref_store, REF_STORE_READ, "read_raw_ref"); @@ -354,7 +354,6 @@ static int files_read_raw_ref(struct ref_store *ref_store, struct stat st; int fd; int ret = -1; - int save_errno; int remaining_retries = 3; *type = 0; @@ -459,10 +458,9 @@ static int files_read_raw_ref(struct ref_store *ref_store, ret = parse_loose_ref_contents(buf, oid, referent, type); out: - save_errno = errno; + *failure_errno = errno; strbuf_release(&sb_path); strbuf_release(&sb_contents); - errno = save_errno; return ret; } @@ -540,6 +538,7 @@ static int lock_raw_ref(struct files_ref_store *refs, struct strbuf ref_file = STRBUF_INIT; int attempts_remaining = 3; int ret = TRANSACTION_GENERIC_ERROR; + int failure_errno; assert(err); files_assert_main_repository(refs, "lock_raw_ref"); @@ -610,7 +609,9 @@ static int lock_raw_ref(struct files_ref_store *refs, if (hold_lock_file_for_update_timeout( &lock->lk, ref_file.buf, LOCK_NO_DEREF, get_files_ref_lock_timeout_ms()) < 0) { - if (errno == ENOENT && --attempts_remaining > 0) { + int myerr = errno; + errno = 0; + if (myerr == ENOENT && --attempts_remaining > 0) { /* * Maybe somebody just deleted one of the * directories leading to ref_file. Try @@ -618,7 +619,7 @@ static int lock_raw_ref(struct files_ref_store *refs, */ goto retry; } else { - unable_to_lock_message(ref_file.buf, errno, err); + unable_to_lock_message(ref_file.buf, myerr, err); goto error_return; } } @@ -628,9 +629,9 @@ static int lock_raw_ref(struct files_ref_store *refs, * fear that its value will change. */ - if (files_read_raw_ref(&refs->base, refname, - &lock->old_oid, referent, type)) { - if (errno == ENOENT) { + if (files_read_raw_ref(&refs->base, refname, &lock->old_oid, referent, + type, &failure_errno)) { + if (failure_errno == ENOENT) { if (mustexist) { /* Garden variety missing reference. */ strbuf_addf(err, "unable to resolve reference '%s'", @@ -654,7 +655,7 @@ static int lock_raw_ref(struct files_ref_store *refs, * reference named "refs/foo/bar/baz". */ } - } else if (errno == EISDIR) { + } else if (failure_errno == EISDIR) { /* * There is a directory in the way. It might have * contained references that have been deleted. If @@ -692,13 +693,13 @@ static int lock_raw_ref(struct files_ref_store *refs, goto error_return; } } - } else if (errno == EINVAL && (*type & REF_ISBROKEN)) { + } else if (failure_errno == EINVAL && (*type & REF_ISBROKEN)) { strbuf_addf(err, "unable to resolve reference '%s': " "reference broken", refname); goto error_return; } else { strbuf_addf(err, "unable to resolve reference '%s': %s", - refname, strerror(errno)); + refname, strerror(failure_errno)); goto error_return; } diff --git a/refs/packed-backend.c b/refs/packed-backend.c index 24a360b719f..159ac776240 100644 --- a/refs/packed-backend.c +++ b/refs/packed-backend.c @@ -724,9 +724,9 @@ static struct snapshot *get_snapshot(struct packed_ref_store *refs) return refs->snapshot; } -static int packed_read_raw_ref(struct ref_store *ref_store, - const char *refname, struct object_id *oid, - struct strbuf *referent, unsigned int *type) +static int packed_read_raw_ref(struct ref_store *ref_store, const char *refname, + struct object_id *oid, struct strbuf *referent, + unsigned int *type, int *failure_errno) { struct packed_ref_store *refs = packed_downcast(ref_store, REF_STORE_READ, "read_raw_ref"); @@ -739,7 +739,7 @@ static int packed_read_raw_ref(struct ref_store *ref_store, if (!rec) { /* refname is not a packed reference. */ - errno = ENOENT; + *failure_errno = ENOENT; return -1; } diff --git a/refs/refs-internal.h b/refs/refs-internal.h index dc0d826c3ac..33a31d5c236 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -620,11 +620,15 @@ typedef int reflog_expire_fn(struct ref_store *ref_store, * properly-formatted or even safe reference name. NEITHER INPUT NOR * OUTPUT REFERENCE NAMES ARE VALIDATED WITHIN THIS FUNCTION. * - * Return 0 on success. If the ref doesn't exist, set errno to ENOENT - * and return -1. If the ref exists but is neither a symbolic ref nor - * an object ID, it is broken; set REF_ISBROKEN in type, and return -1 - * (errno should not be ENOENT) If there is another error reading the - * ref, set errno appropriately and return -1. + * Return 0 on success, or -1 on failure. If the ref exists but is neither a + * symbolic ref nor an object ID, it is broken. In this case set REF_ISBROKEN in + * type, and return -1 (failure_errno should not be ENOENT) + * + * failure_errno provides errno codes that are interpreted beyond error + * reporting. The following error codes have special meaning: + * * ENOENT: the ref doesn't exist + * * EISDIR: ref name is a directory + * * ENOTDIR: ref prefix is not a directory * * Backend-specific flags might be set in type as well, regardless of * outcome. @@ -638,9 +642,9 @@ typedef int reflog_expire_fn(struct ref_store *ref_store, * - in all other cases, referent will be untouched, and therefore * refname will still be valid and unchanged. */ -typedef int read_raw_ref_fn(struct ref_store *ref_store, - const char *refname, struct object_id *oid, - struct strbuf *referent, unsigned int *type); +typedef int read_raw_ref_fn(struct ref_store *ref_store, const char *refname, + struct object_id *oid, struct strbuf *referent, + unsigned int *type, int *failure_errno); struct ref_storage_be { struct ref_storage_be *next; From patchwork Tue Jul 20 10:33:28 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= X-Patchwork-Id: 12388013 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 07B47C636C8 for ; Tue, 20 Jul 2021 10:35:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DE0C561164 for ; Tue, 20 Jul 2021 10:35:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237588AbhGTJyH (ORCPT ); Tue, 20 Jul 2021 05:54:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45436 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237496AbhGTJxC (ORCPT ); Tue, 20 Jul 2021 05:53:02 -0400 Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [IPv6:2a00:1450:4864:20::32c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7191AC0613DB for ; Tue, 20 Jul 2021 03:33:39 -0700 (PDT) Received: by mail-wm1-x32c.google.com with SMTP id n4so12008466wms.1 for ; Tue, 20 Jul 2021 03:33:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=MPe3T+8UKpLqrbwKgF9DA/IbxEzVKaLF5pi9KCJ0qgs=; b=ttADS1tX0JTKUzUkeawfHxaNdy9zacmuRI5B9e7UQPdLvUBQi9kM6AqizwisHnxvK5 wKQO1A48SvxYorMtN4NoJBDP1KKgh2yf141CTdRiECGfOcHhO6pip4rQIzSCOHRs4SKS 0ze/Jb7x2/MfJeq4+pZ4N467a3fH9w9zKT4w4aPwKKVDZlNIymaqbALWqJZ0jC5cauxS MzmD+xQTA80zfAlQYTNx0hNvpCd9S7+PN/xsSSaRWT/opcCAivvuyi0Np+psWSRNP/vX 4wKwhTqj29jfVq0pQPjTpJjPH1w335MJ5wnnAPSuDTGtGlHX2O8SVnCF/FV9X9FLiwJd u87w== 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=MPe3T+8UKpLqrbwKgF9DA/IbxEzVKaLF5pi9KCJ0qgs=; b=HuW11XLp4QTkGQl0Qs3pqvTjmW7Wr1Zfsr3Jugzybt780560I9Ymn6ppR99OexgtfB FdzOUfqZcOoyeQtRQOxWejiau2Ms4Y9Q1Sk18ztjQd219U8Q+DRNAFMcSN6n0yQysTal Viu92HcjObrC+ZNg/wtjsE3MWOKZnVtncbH9siAD4Idds9DC+C39/SIh4BMLxZMaacv2 yuqX4ezSeC2rn+6WJe0rkNfc0X+Fb1PmV38SCjc0pzAe2EvzNQhj6nZUpgBnEQuM+mWl FCAfNwyNTxhce804+k0Qqdg+3pyyhvg6KMC8x3PJMw3IV9JAyh1sRwbCue825O+S6U91 n1Mw== X-Gm-Message-State: AOAM532RxVbKkDiA+DL7A6j0jkHLD9QGUHzTAFVsdfKrHH1vD1qLnSqn Rzvs9tqogjJuzU3hdq7GCjirdi+Fq5VEUw== X-Google-Smtp-Source: ABdhPJxqLNQptpcRqJNbB1IP2iLSaTrEnlSqYdQT8lSQ/N7Nv6S9h4rdFKFZ+prKUOKiRDCzTTAnuQ== X-Received: by 2002:a05:600c:cc:: with SMTP id u12mr37279419wmm.19.1626777217804; Tue, 20 Jul 2021 03:33:37 -0700 (PDT) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id l14sm22179852wrs.22.2021.07.20.03.33.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Jul 2021 03:33:37 -0700 (PDT) From: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= To: git@vger.kernel.org Cc: Junio C Hamano , Jeff King , Han-Wen Nienhuys , Michael Haggerty , Jonathan Tan , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBC?= =?utf-8?b?amFybWFzb24=?= Subject: [PATCH v9 5/7] refs: add failure_errno to refs_read_raw_ref() signature Date: Tue, 20 Jul 2021 12:33:28 +0200 Message-Id: X-Mailer: git-send-email 2.32.0.874.ge7a9d58bfcf In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Han-Wen Nienhuys This lets us use the explicit errno output parameter in refs_resolve_ref_unsafe. Some of our callers explicitly do not care about the errno, rather than understanding NULL let's have them declare that they don't care by passing in an "ignore_errno". There's only three of them, and using that pattern will make it more obvious that they want to throw away data, let's also add a comment to one of the callers about why we'd like to ignore the errno. Let's not extend that to refs_resolve_ref_unsafe() itself for now, it has a large set of legacy callers, so we're faking up the old "errno" behavior for it. We can convert those callers to refs_resolve_ref_unsafe_with_errno() later. We are leaving out out the refs_read_special_head() in refs_read_raw_ref() for now, as noted in the next commit moving it to "failure_errno" will require some special consideration. We're intentionally mis-indenting the argument list of the new refs_resolve_ref_unsafe_with_errno(), it will be non-static in a subsequent commit, doing it this way makes that diff smaller. Signed-off-by: Han-Wen Nienhuys Signed-off-by: Ævar Arnfjörð Bjarmason --- refs.c | 61 ++++++++++++++++++++++++++++++------------- refs/files-backend.c | 10 ++++--- refs/packed-backend.c | 7 ++--- refs/refs-internal.h | 6 ++--- 4 files changed, 56 insertions(+), 28 deletions(-) diff --git a/refs.c b/refs.c index fc6c0ddffae..728285c9220 100644 --- a/refs.c +++ b/refs.c @@ -1672,30 +1672,33 @@ static int refs_read_special_head(struct ref_store *ref_store, return result; } -int refs_read_raw_ref(struct ref_store *ref_store, - const char *refname, struct object_id *oid, - struct strbuf *referent, unsigned int *type) +int refs_read_raw_ref(struct ref_store *ref_store, const char *refname, + struct object_id *oid, struct strbuf *referent, + unsigned int *type, int *failure_errno) { + assert(failure_errno); if (!strcmp(refname, "FETCH_HEAD") || !strcmp(refname, "MERGE_HEAD")) { return refs_read_special_head(ref_store, refname, oid, referent, type); } return ref_store->be->read_raw_ref(ref_store, refname, oid, referent, - type, &errno); + type, failure_errno); } -/* This function needs to return a meaningful errno on failure */ -const char *refs_resolve_ref_unsafe(struct ref_store *refs, - const char *refname, - int resolve_flags, - struct object_id *oid, int *flags) +static const char *refs_resolve_ref_unsafe_with_errno(struct ref_store *refs, + const char *refname, + int resolve_flags, + struct object_id *oid, + int *flags, int *failure_errno) { static struct strbuf sb_refname = STRBUF_INIT; struct object_id unused_oid; int unused_flags; int symref_count; + assert(failure_errno); + if (!oid) oid = &unused_oid; if (!flags) @@ -1706,7 +1709,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs, if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) { if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) || !refname_is_safe(refname)) { - errno = EINVAL; + *failure_errno = EINVAL; return NULL; } @@ -1724,8 +1727,8 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs, for (symref_count = 0; symref_count < SYMREF_MAXDEPTH; symref_count++) { unsigned int read_flags = 0; - if (refs_read_raw_ref(refs, refname, - oid, &sb_refname, &read_flags)) { + if (refs_read_raw_ref(refs, refname, oid, &sb_refname, + &read_flags, failure_errno)) { *flags |= read_flags; /* In reading mode, refs must eventually resolve */ @@ -1737,9 +1740,9 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs, * may show errors besides ENOENT if there are * similarly-named refs. */ - if (errno != ENOENT && - errno != EISDIR && - errno != ENOTDIR) + if (*failure_errno != ENOENT && + *failure_errno != EISDIR && + *failure_errno != ENOTDIR) return NULL; oidclr(oid); @@ -1766,7 +1769,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs, if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) { if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) || !refname_is_safe(refname)) { - errno = EINVAL; + *failure_errno = EINVAL; return NULL; } @@ -1774,10 +1777,24 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs, } } - errno = ELOOP; + *failure_errno = ELOOP; return NULL; } +const char *refs_resolve_ref_unsafe(struct ref_store *refs, const char *refname, + int resolve_flags, struct object_id *oid, + int *flags) +{ + int failure_errno = 0; + const char *refn; + refn = refs_resolve_ref_unsafe_with_errno(refs, refname, resolve_flags, + oid, flags, &failure_errno); + if (!refn) + /* For unmigrated legacy callers */ + errno = failure_errno; + return refn; +} + /* backend functions */ int refs_init_db(struct strbuf *err) { @@ -2228,6 +2245,13 @@ int refs_verify_refname_available(struct ref_store *refs, strbuf_grow(&dirname, strlen(refname) + 1); for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) { + /* + * Just saying "Is a directory" when we e.g. can't + * lock some multi-level ref isn't very informative, + * the user won't be told *what* is a directory, so + * let's not use strerror() below. + */ + int ignore_errno; /* Expand dirname to the new prefix, not including the trailing slash: */ strbuf_add(&dirname, refname + dirname.len, slash - refname - dirname.len); @@ -2239,7 +2263,8 @@ int refs_verify_refname_available(struct ref_store *refs, if (skip && string_list_has_string(skip, dirname.buf)) continue; - if (!refs_read_raw_ref(refs, dirname.buf, &oid, &referent, &type)) { + if (!refs_read_raw_ref(refs, dirname.buf, &oid, &referent, + &type, &ignore_errno)) { strbuf_addf(err, _("'%s' exists; cannot create '%s'"), dirname.buf, refname); goto cleanup; diff --git a/refs/files-backend.c b/refs/files-backend.c index 85b4d791444..bbd8caec624 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -381,10 +381,11 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname, goto out; if (lstat(path, &st) < 0) { + int ignore_errno; if (errno != ENOENT) goto out; - if (refs_read_raw_ref(refs->packed_ref_store, refname, - oid, referent, type)) { + if (refs_read_raw_ref(refs->packed_ref_store, refname, oid, + referent, type, &ignore_errno)) { errno = ENOENT; goto out; } @@ -418,13 +419,14 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname, /* Is it a directory? */ if (S_ISDIR(st.st_mode)) { + int ignore_errno; /* * Even though there is a directory where the loose * ref is supposed to be, there could still be a * packed ref: */ - if (refs_read_raw_ref(refs->packed_ref_store, refname, - oid, referent, type)) { + if (refs_read_raw_ref(refs->packed_ref_store, refname, oid, + referent, type, &ignore_errno)) { errno = EISDIR; goto out; } diff --git a/refs/packed-backend.c b/refs/packed-backend.c index 159ac776240..923b9ad89de 100644 --- a/refs/packed-backend.c +++ b/refs/packed-backend.c @@ -1347,6 +1347,7 @@ int is_packed_transaction_needed(struct ref_store *ref_store, ret = 0; for (i = 0; i < transaction->nr; i++) { struct ref_update *update = transaction->updates[i]; + int failure_errno; unsigned int type; struct object_id oid; @@ -1357,9 +1358,9 @@ int is_packed_transaction_needed(struct ref_store *ref_store, */ continue; - if (!refs_read_raw_ref(ref_store, update->refname, - &oid, &referent, &type) || - errno != ENOENT) { + if (!refs_read_raw_ref(ref_store, update->refname, &oid, + &referent, &type, &failure_errno) || + failure_errno != ENOENT) { /* * We have to actually delete that reference * -> this transaction is needed. diff --git a/refs/refs-internal.h b/refs/refs-internal.h index 33a31d5c236..7beb38f79cc 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -149,9 +149,9 @@ struct ref_update { const char refname[FLEX_ARRAY]; }; -int refs_read_raw_ref(struct ref_store *ref_store, - const char *refname, struct object_id *oid, - struct strbuf *referent, unsigned int *type); +int refs_read_raw_ref(struct ref_store *ref_store, const char *refname, + struct object_id *oid, struct strbuf *referent, + unsigned int *type, int *failure_errno); /* * Write an error to `err` and return a nonzero value iff the same From patchwork Tue Jul 20 10:33:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= X-Patchwork-Id: 12388017 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 15ABEC07E95 for ; Tue, 20 Jul 2021 10:35:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E87A66113B for ; Tue, 20 Jul 2021 10:35:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237423AbhGTJyS (ORCPT ); Tue, 20 Jul 2021 05:54:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45442 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237897AbhGTJxC (ORCPT ); Tue, 20 Jul 2021 05:53:02 -0400 Received: from mail-wm1-x32a.google.com (mail-wm1-x32a.google.com [IPv6:2a00:1450:4864:20::32a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 47D06C0613DC for ; Tue, 20 Jul 2021 03:33:40 -0700 (PDT) Received: by mail-wm1-x32a.google.com with SMTP id f8-20020a1c1f080000b029022d4c6cfc37so1174027wmf.5 for ; Tue, 20 Jul 2021 03:33:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=iiTTwg5PcMcGhontITZqYXf19SuqGYRzHnFAbQWsOa4=; b=GF6Bq5/IQwrK3rIFfk49bzwIhJaFCTrMdk4TF/WfAJs1o6bAB7EeFALP49BqnVao13 oG8iOQvHv43QNFMCqXiVKBHOMBZnIOM08rmLp8sNMU245EFp044xF+1HPeBAmP6FFBnE vH9H01Atbh9GduW6R4M+KaZq/y84GKsWXY/N3oj7jbq7Mt/+C/P2DfaW+PKRNadPDEIo eoZ7LhhcOvACpnZanFaMeIV1WszndC6bLVCUnLU7GsU1RhmAWubpcJoytFJPxsvOhi1S 4BTWBiWWHL6NaIs3M6oDPk8VR+pjaBpaVk8fgkafMBzWXkjuCqh72GOZCSmutoigTNj6 UUpQ== 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=iiTTwg5PcMcGhontITZqYXf19SuqGYRzHnFAbQWsOa4=; b=muU5kf7pIeKeQOxPPPdxgliqlU5O8JTb3ZMefRNyW2GAcGZqJxPHcZ/Jn+qzLfPSPX dzrsMJDimYODlQaRw/uJD9Yf/lR31knEf3B+Us9M9Z2APuJpBry7KmuvLSjaYLntsaKb ngQEqOvWq/5tY9mCkpYUFTeetROlyoQGn/uCyqMWaxSpGPXbKNKDzhfQrwUaZhcWyP0i HVd+h2xpa5qdrNhf+OhCEDhRNyhK4o7Y2+XXtyN0mTaxRsLm5/NrBkM/lmMrzl6QhUIB IJqx9YtCUxy6v2e6dzJliHPNldBHinnuNHAPRm64N9ZozUEobDfndCr1HWo/xdUVQmYc YKtg== X-Gm-Message-State: AOAM532702m6vv7kqNtD6sCUtnIB/dRQmu224y0XTEF8Ax5+yZyZLYjO SzoCZEmyFJRBgzp9oCUaqMTNyNWs6Xj9xQ== X-Google-Smtp-Source: ABdhPJxwzXAAJ0af6IfAu6iv2jKImBhJd6mjhFjVzZSKLW6A/xDwxsUcnFkb+eX2tc2HDeG+DiJm9g== X-Received: by 2002:a7b:c042:: with SMTP id u2mr30376558wmc.86.1626777218590; Tue, 20 Jul 2021 03:33:38 -0700 (PDT) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id l14sm22179852wrs.22.2021.07.20.03.33.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Jul 2021 03:33:38 -0700 (PDT) From: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= To: git@vger.kernel.org Cc: Junio C Hamano , Jeff King , Han-Wen Nienhuys , Michael Haggerty , Jonathan Tan , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBC?= =?utf-8?b?amFybWFzb24=?= Subject: [PATCH v9 6/7] refs: explicitly return failure_errno from parse_loose_ref_contents Date: Tue, 20 Jul 2021 12:33:29 +0200 Message-Id: X-Mailer: git-send-email 2.32.0.874.ge7a9d58bfcf In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Han-Wen Nienhuys The EINVAL error from parse_loose_ref_contents is used in files-backend to create a custom error message. In untangling this we discovered a tricky edge case. The refs_read_special_head() function was relying on parse_loose_ref_contents() setting EINVAL. By converting it to use "saved_errno" we can migrate away from "errno" in this part of the code entirely, and do away with an existing "save_errno" pattern, its only purpose was to not clobber the "errno" we previously needed at the end of files_read_raw_ref(). Let's assert that we can do that by not having files_read_raw_ref() itself operate on *failure_errno in addition to passing it on. Instead we'll assert that if we return non-zero we actually do set errno, thus assuring ourselves and callers that they can trust the resulting "failure_errno". Signed-off-by: Han-Wen Nienhuys Signed-off-by: Ævar Arnfjörð Bjarmason --- refs.c | 8 +++++--- refs/files-backend.c | 30 +++++++++++++++++++----------- refs/refs-internal.h | 6 ++++-- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/refs.c b/refs.c index 728285c9220..b31dbdd0fa2 100644 --- a/refs.c +++ b/refs.c @@ -1654,7 +1654,8 @@ int for_each_fullref_in_prefixes(const char *namespace, static int refs_read_special_head(struct ref_store *ref_store, const char *refname, struct object_id *oid, - struct strbuf *referent, unsigned int *type) + struct strbuf *referent, unsigned int *type, + int *failure_errno) { struct strbuf full_path = STRBUF_INIT; struct strbuf content = STRBUF_INIT; @@ -1664,7 +1665,8 @@ static int refs_read_special_head(struct ref_store *ref_store, if (strbuf_read_file(&content, full_path.buf, 0) < 0) goto done; - result = parse_loose_ref_contents(content.buf, oid, referent, type); + result = parse_loose_ref_contents(content.buf, oid, referent, type, + failure_errno); done: strbuf_release(&full_path); @@ -1679,7 +1681,7 @@ int refs_read_raw_ref(struct ref_store *ref_store, const char *refname, assert(failure_errno); if (!strcmp(refname, "FETCH_HEAD") || !strcmp(refname, "MERGE_HEAD")) { return refs_read_special_head(ref_store, refname, oid, referent, - type); + type, failure_errno); } return ref_store->be->read_raw_ref(ref_store, refname, oid, referent, diff --git a/refs/files-backend.c b/refs/files-backend.c index bbd8caec624..746831c86cb 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -355,6 +355,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname, int fd; int ret = -1; int remaining_retries = 3; + int myerr = 0; *type = 0; strbuf_reset(&sb_path); @@ -382,11 +383,13 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname, if (lstat(path, &st) < 0) { int ignore_errno; - if (errno != ENOENT) + myerr = errno; + errno = 0; + if (myerr != ENOENT) goto out; if (refs_read_raw_ref(refs->packed_ref_store, refname, oid, referent, type, &ignore_errno)) { - errno = ENOENT; + myerr = ENOENT; goto out; } ret = 0; @@ -397,7 +400,9 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname, if (S_ISLNK(st.st_mode)) { strbuf_reset(&sb_contents); if (strbuf_readlink(&sb_contents, path, st.st_size) < 0) { - if (errno == ENOENT || errno == EINVAL) + myerr = errno; + errno = 0; + if (myerr == ENOENT || myerr == EINVAL) /* inconsistent with lstat; retry */ goto stat_ref; else @@ -427,7 +432,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname, */ if (refs_read_raw_ref(refs->packed_ref_store, refname, oid, referent, type, &ignore_errno)) { - errno = EISDIR; + myerr = EISDIR; goto out; } ret = 0; @@ -440,7 +445,8 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname, */ fd = open(path, O_RDONLY); if (fd < 0) { - if (errno == ENOENT && !S_ISLNK(st.st_mode)) + myerr = errno; + if (myerr == ENOENT && !S_ISLNK(st.st_mode)) /* inconsistent with lstat; retry */ goto stat_ref; else @@ -448,26 +454,28 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname, } strbuf_reset(&sb_contents); if (strbuf_read(&sb_contents, fd, 256) < 0) { - int save_errno = errno; close(fd); - errno = save_errno; goto out; } close(fd); strbuf_rtrim(&sb_contents); buf = sb_contents.buf; - ret = parse_loose_ref_contents(buf, oid, referent, type); + ret = parse_loose_ref_contents(buf, oid, referent, type, &myerr); out: - *failure_errno = errno; + if (ret && !myerr) + BUG("returning non-zero %d, should have set myerr!", ret); + *failure_errno = myerr; + strbuf_release(&sb_path); strbuf_release(&sb_contents); return ret; } int parse_loose_ref_contents(const char *buf, struct object_id *oid, - struct strbuf *referent, unsigned int *type) + struct strbuf *referent, unsigned int *type, + int *failure_errno) { const char *p; if (skip_prefix(buf, "ref:", &buf)) { @@ -486,7 +494,7 @@ int parse_loose_ref_contents(const char *buf, struct object_id *oid, if (parse_oid_hex(buf, oid, &p) || (*p != '\0' && !isspace(*p))) { *type |= REF_ISBROKEN; - errno = EINVAL; + *failure_errno = EINVAL; return -1; } return 0; diff --git a/refs/refs-internal.h b/refs/refs-internal.h index 7beb38f79cc..9aa4af81836 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -692,10 +692,12 @@ struct ref_store { }; /* - * Parse contents of a loose ref file. + * Parse contents of a loose ref file. *failure_errno maybe be set to EINVAL for + * invalid contents. */ int parse_loose_ref_contents(const char *buf, struct object_id *oid, - struct strbuf *referent, unsigned int *type); + struct strbuf *referent, unsigned int *type, + int *failure_errno); /* * Fill in the generic part of refs and add it to our collection of From patchwork Tue Jul 20 10:33:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= X-Patchwork-Id: 12388019 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C8611C07E95 for ; Tue, 20 Jul 2021 10:36:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AF99461107 for ; Tue, 20 Jul 2021 10:36:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237625AbhGTJyV (ORCPT ); Tue, 20 Jul 2021 05:54:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45372 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237352AbhGTJxI (ORCPT ); Tue, 20 Jul 2021 05:53:08 -0400 Received: from mail-wm1-x32b.google.com (mail-wm1-x32b.google.com [IPv6:2a00:1450:4864:20::32b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2050AC0613DD for ; Tue, 20 Jul 2021 03:33:41 -0700 (PDT) Received: by mail-wm1-x32b.google.com with SMTP id g8-20020a1c9d080000b02901f13dd1672aso1326743wme.0 for ; Tue, 20 Jul 2021 03:33:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Cog0ZtNZpMOyK/ahzkmspl6CXOBmDJRhbOcaYmSSGqY=; b=M9rAocSeb99YgvXxXqsMc47zluSImvBVtBGWKBQ/wbR9DI9ui+7g6v5en0KSdguMNT Q99+B/IrnIR52JDIcax1w6c1r9zl1sezB0uCWRFG6RRa3N9GFyqkFlzaCf4JiWAUwiYx Pv1ZfNR06i8lhJEJCJg9dPN0DrvsM9J96zlwgcg/wHtFvhVQsVDVvCOY4y5YhQlXdkeE 9gRrIiyhMxoz3b/rhUGka06UvYOJb7lrhx/Gq022MNdaUq5vvvn4k8LBPI5CzkZfHWYY TN/w6s95aSlju2NLYK5P2efnoDDizTMGPyHDVUHAJ7LoQjX+IwyioLq0brhP2FB1iR9M Ah5g== 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=Cog0ZtNZpMOyK/ahzkmspl6CXOBmDJRhbOcaYmSSGqY=; b=DM1m+mQXPE4PIQQBj/edJB6UzoB+WrehRoyUbKDMtjxJ7+1nY4QLJcKkB15XGSaICV k0UqZAu3q4c4JDqW4gUC8MKeInfuVS2urlUfw1tcuLKodKt0PcP87qSXkZ7AYTxNI1yH bdWH1URu769qx7VV56hZISg8+C5wthyGYvvp8cG70IrJvoykO4IldXrbD9GeS1uk9mJR a/HcPLjtsXHGvPLMr2azyeehR6fcHN7BxfXsv/f+r3VSD7TrXNrhvpeRizAhYBnjtvrT LrMaSOHh0hMu/JSASNFnwZ3915PmsSyg6DrRv4UluZfXiFzr9xPuR1oAI2D25m+n9+jw buDA== X-Gm-Message-State: AOAM532IL8YfeEEc7QB2uMHyL1uesuoPXuKkx5Tr8i09vslBFcKN4aUc PkRTj84ZCekODfWJZ4XHseDGF/cum31dng== X-Google-Smtp-Source: ABdhPJwNVsrN1P3Kg/hS7YzQCrGfk/tTU2JdLxtVy9jFEvaWy1CQoGagxWnHQH6t/HcgLjqxMa22NQ== X-Received: by 2002:a1c:1bd4:: with SMTP id b203mr37259429wmb.171.1626777219531; Tue, 20 Jul 2021 03:33:39 -0700 (PDT) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id l14sm22179852wrs.22.2021.07.20.03.33.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Jul 2021 03:33:38 -0700 (PDT) From: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= To: git@vger.kernel.org Cc: Junio C Hamano , Jeff King , Han-Wen Nienhuys , Michael Haggerty , Jonathan Tan , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBC?= =?utf-8?b?amFybWFzb24=?= Subject: [PATCH v9 7/7] refs: make errno output explicit for refs_resolve_ref_unsafe Date: Tue, 20 Jul 2021 12:33:30 +0200 Message-Id: X-Mailer: git-send-email 2.32.0.874.ge7a9d58bfcf In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Han-Wen Nienhuys This introduces refs_resolve_ref_unsafe_with_errno(), which makes the API contract for the errno output explicit. The implementation still relies on the global errno variable to ensure no side effects of this refactoring. lock_ref_oid_basic() in files-backend.c is the only caller of refs_resolve_ref() that needs error information to make logic decisions, so update that caller Signed-off-by: Han-Wen Nienhuys Signed-off-by: Ævar Arnfjörð Bjarmason --- refs.c | 2 +- refs.h | 11 +++++++++++ refs/files-backend.c | 10 ++++++---- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/refs.c b/refs.c index b31dbdd0fa2..9497b51e0a1 100644 --- a/refs.c +++ b/refs.c @@ -1688,7 +1688,7 @@ int refs_read_raw_ref(struct ref_store *ref_store, const char *refname, type, failure_errno); } -static const char *refs_resolve_ref_unsafe_with_errno(struct ref_store *refs, +const char *refs_resolve_ref_unsafe_with_errno(struct ref_store *refs, const char *refname, int resolve_flags, struct object_id *oid, diff --git a/refs.h b/refs.h index c009707438d..ba09ba0687b 100644 --- a/refs.h +++ b/refs.h @@ -68,6 +68,17 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs, int resolve_flags, struct object_id *oid, int *flags); +/** + * refs_resolve_ref_unsafe_with_errno() is like + * refs_resolve_ref_unsafe(), but provide access to errno code that + * lead to a failure. We guarantee that errno is set to a meaningful + * value on non-zero return. + */ +const char *refs_resolve_ref_unsafe_with_errno(struct ref_store *refs, + const char *refname, + int resolve_flags, + struct object_id *oid, + int *flags, int *failure_errno); const char *resolve_ref_unsafe(const char *refname, int resolve_flags, struct object_id *oid, int *flags); diff --git a/refs/files-backend.c b/refs/files-backend.c index 746831c86cb..68182296c1b 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -1001,6 +1001,7 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs, { struct strbuf ref_file = STRBUF_INIT; struct ref_lock *lock; + int resolve_errno = 0; files_assert_main_repository(refs, "lock_ref_oid_basic"); assert(err); @@ -1008,13 +1009,14 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs, CALLOC_ARRAY(lock, 1); files_ref_path(refs, &ref_file, refname); - if (!refs_resolve_ref_unsafe(&refs->base, refname, - RESOLVE_REF_NO_RECURSE, - &lock->old_oid, type)) { + if (!refs_resolve_ref_unsafe_with_errno(&refs->base, refname, + RESOLVE_REF_NO_RECURSE, + &lock->old_oid, type, + &resolve_errno)) { if (!refs_verify_refname_available(&refs->base, refname, NULL, NULL, err)) strbuf_addf(err, "unable to resolve reference '%s': %s", - refname, strerror(errno)); + refname, strerror(resolve_errno)); goto error_return; }