From patchwork Fri Jul 16 14:22: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: 12382279 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 557D3C07E95 for ; Fri, 16 Jul 2021 14:22:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 38A0D613F2 for ; Fri, 16 Jul 2021 14:22:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233055AbhGPOZj (ORCPT ); Fri, 16 Jul 2021 10:25:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40862 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232990AbhGPOZe (ORCPT ); Fri, 16 Jul 2021 10:25:34 -0400 Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7934AC061760 for ; Fri, 16 Jul 2021 07:22:37 -0700 (PDT) Received: by mail-wr1-x42a.google.com with SMTP id d12so12262415wre.13 for ; Fri, 16 Jul 2021 07:22: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=wqbySUk+au2MN4TlNHME//yBXenwBCjbMsFq0YaE7O8=; b=Qjn8VEkO/nquX6DN9AimTthUdElmZoFI73mTrvPHn4RYmg2V7QuvUxgXkzCWNzpH4B +9CzpX4QnP+QafLC+5EcPGw6qj7yfhY8ZhzFyH5Ui6LtfmGzs4MJVZ0uJ+rektWytGqF mHDibI9AHP2Qwz2dvb9rS60YV49E4725kegxOyyT52cHgyIDPPeU6reLfcAd57w1xYFe riuySEc6qIFA8GHM2I5f6KTcWlFYd2cr5xgHQMXAY/P7i4qdYNBmeMHz0pM627sC4jIr k4DJvUDKyil/b/9vhJ1YxM3I7jGx+WOgmO25SMco8Ezkk73HosNUtJLo5XZyAGp5U/2M VhPw== 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=wqbySUk+au2MN4TlNHME//yBXenwBCjbMsFq0YaE7O8=; b=nEueyR9uxU3gcicfhZCc3v7h4rEfvia/PeaEZlOPReUf81A+4Eyo8nYkxTH16ACpaS fydfIW+xhDdDmVFmbnfmlKDwno9Fff4r4y0F2j5AUaGXq5Af8Ka/9qrwBNimNL8p0vEo FdwgOZ9okmQNWBzplxm5MMiVTzQkZ8TvBArHaO83gKLeaEQ2+D7c98lomhlcqDIxz5av mB7Cv18ePkU1VS2D4fqjZQ3FIjTN5qo9cSWoiIUdcdXbvfoBXaCihgclyDS5xOgr5C4H lZKBCbWS5pEsTcvkzIDz/whawNd/D+J2aVXhmJ+tXO5hVNZjV2qtGfJiGXCgoxc0Vf4J wvTA== X-Gm-Message-State: AOAM5312KjX1d64yIVBkQax9PdqgLY85GNaWWHUx9By2EiP0E/geFrih KWBdZKdldcH906WYthouB8olCetPfHJDjw== X-Google-Smtp-Source: ABdhPJyJX0V2e6QM58d3zQulw0wmPwsJHIsCNWjjcpLgKcRv6ab4PmX7OnFYnN0AUX7fIurGc/rsPg== X-Received: by 2002:a5d:6189:: with SMTP id j9mr12963121wru.196.1626445355712; Fri, 16 Jul 2021 07:22:35 -0700 (PDT) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id z7sm7463236wmp.34.2021.07.16.07.22.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Jul 2021 07:22: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 v8 1/7] refs file backend: move raceproof_create_file() here Date: Fri, 16 Jul 2021 16:22:26 +0200 Message-Id: X-Mailer: git-send-email 2.32.0.874.gfa1990a4f10 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 f233b440b22..ae766e18b4e 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 bd99bc570de..36af99af844 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 Fri Jul 16 14:22: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: 12382283 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=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED,DKIM_INVALID,DKIM_SIGNED,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 64F97C12002 for ; Fri, 16 Jul 2021 14:22:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4EEFE613F5 for ; Fri, 16 Jul 2021 14:22:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239885AbhGPOZr (ORCPT ); Fri, 16 Jul 2021 10:25:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40866 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233032AbhGPOZg (ORCPT ); Fri, 16 Jul 2021 10:25:36 -0400 Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com [IPv6:2a00:1450:4864:20::32d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BE700C061762 for ; Fri, 16 Jul 2021 07:22:38 -0700 (PDT) Received: by mail-wm1-x32d.google.com with SMTP id q18-20020a1ce9120000b02901f259f3a250so5969845wmc.2 for ; Fri, 16 Jul 2021 07:22: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=Dd5qrkZH5laEigirq6zvsEzR3g3ZRQCaRTLgN8MtPdM=; b=i8TsUQRz3VUISRD9dSp7KxXBqLHohXOHHPZEMnK7oegsyQRHoqRVYbTuXt17yhLfTJ TdPH8ZGRW1AG6315p5O1hXrDF7AA25/w2CzyJvZok7vhKhLSbylLB+LU6MmlTiDReBpe RNOXB5fQIY+kUO00MpBmUJ+ghu88f/H4BowckcLRvRGSZOKHyk+PMMvjjYw796eTC4uS bhLktZg69Q/65WmW5xnFhGxiCPLKCbZ+rbzPxsiePfB4eDW6q5mnGdvLKTgT5ZJOcy2q NU5QGmgjUjRGgiJ5ncxfxcgcYrRpnV0MDLb1edP9RhlFfVY0lahM1AWc3xZoGWfrAugw vIhQ== 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=Dd5qrkZH5laEigirq6zvsEzR3g3ZRQCaRTLgN8MtPdM=; b=ZRNNjW1JvBGnyGUbanyujLdkNvbOM5VfdbpXmmL2ii7ejYZDLCk360gRlf+xNIVkUI ErgQ6VtVv7eBRNfkA1ADym9Qo5J86tdyk0sFfgslzVwQNFJ/tFg6HA4Upz/MgxoPEkvF saWd7nIppw8TQ50KUYtcNQgDJ/TkqGhKFEK+MrzKFQ5Dg4+TCnmSJaSzjvjD4LW8zDYp Y30AEpXo1ERS7IyI/8b+LCQYzEHHJNfwBdXrhuq0Cdeuboxx6E/CtT68kPJuGanuqRtu 734gSsA39cKbr0oClGt77Wko5vnfxfUnMPuaqOMoXq/6dwYvCPeQAmzucBkI5wm1BOeP vCYQ== X-Gm-Message-State: AOAM532DcLRAGr/ZLHqkCJyANpgt545Wgm+hXSG2FkBDMxMAMJCZjZQh peUwtQbvYkGm2wZJRsiQMIURcrOZ8Acgdg== X-Google-Smtp-Source: ABdhPJwwLzK2MZoBQdnGqRuMjvA2bDBc7zWuQMKGI+UWhhD2/cfpIsdA4pvfywe8+xHA2Kgassv53Q== X-Received: by 2002:a1c:7c08:: with SMTP id x8mr11087058wmc.2.1626445356809; Fri, 16 Jul 2021 07:22:36 -0700 (PDT) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id z7sm7463236wmp.34.2021.07.16.07.22.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Jul 2021 07:22: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 v8 2/7] refs: remove EINVAL errno output from specification of read_raw_ref_fn Date: Fri, 16 Jul 2021 16:22:27 +0200 Message-Id: X-Mailer: git-send-email 2.32.0.874.gfa1990a4f10 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 467f4b3c936..f4445e32904 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -619,9 +619,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 Fri Jul 16 14:22: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: 12382281 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=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED,DKIM_INVALID,DKIM_SIGNED,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 47496C636CA for ; Fri, 16 Jul 2021 14:22:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 29466613F5 for ; Fri, 16 Jul 2021 14:22:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240100AbhGPOZp (ORCPT ); Fri, 16 Jul 2021 10:25:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40868 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233009AbhGPOZg (ORCPT ); Fri, 16 Jul 2021 10:25:36 -0400 Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6BC78C061764 for ; Fri, 16 Jul 2021 07:22:39 -0700 (PDT) Received: by mail-wr1-x434.google.com with SMTP id i94so12309280wri.4 for ; Fri, 16 Jul 2021 07:22: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=qGw4pF+/zu6oie8tEYy8CzZCe1JD3M57QqLH7HxpbdI=; b=tOk//XR0gfRV3Dlcu1pb/gb89OMLM9BGzUie6HcdSpDxtuKBk8IEY7CJCk1qxlKths XaKh33DMnSx5q3/p739/Ix8Wg5B0rnQio5BA+6rFXlETTKrXEsE2z/Rwctxuggu6dt1c wFe8K8FY3tgqKFi7qZBhosM6Sogxmm7cR2NIJc0pI3ZbeIAHO3+zPPTu0eqQRl49fUC4 LJ0kzoNVyQ6M23RS9CtjMfWkXfED/K3wJUwe8+KqPylVMRJ0FTl0ZUPMbBHwND11KttV m/SjEjVp62tOXgzaZ/LxE9Q3CiFDakLSYSH/hFPinDsAs85GGhpCDl4Bk4mQERW2g2Ms 4fFQ== 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=qGw4pF+/zu6oie8tEYy8CzZCe1JD3M57QqLH7HxpbdI=; b=YIVeeaT+XP+iabRSmibqtrRlp1m2FGY32vTNIUh1Gdbna9G3k1ta2UEIIlFC7b//Wh tVYtwWyokgP75X/yoYEfmRwsy52LaR06PkONzWPJ97tMBqQFGZfYZM7FRvfciQxiW6MJ BrHNCc7sWLsgspTgi5aIJx61P4xcJu/y0q5nb8ztwcgpOZBuFgNb4AnCigpSzUC05Yv1 tqWmiKKQh7dIAkrlCN3GhrHWJXQCNUvcwEJMwCNr059WJEZMOJuR+KMgxn+NNKdXvuIA I4LtGpXhsGsSzZA1x5icFVWv/PoSdt3jxFZv+uHVDoDIshnX8evZnwjle5gegmcGtBYw o0mQ== X-Gm-Message-State: AOAM530XYBGwA+o+nET019tr7SoKHlAbUU/hDOM5VU29HwXOlMK4Zu+O xIz7dLbljRGj6+YUVMrrJfghumE9W+rD5A== X-Google-Smtp-Source: ABdhPJyOzxVfAh/gI13eNIqx+QeeIqSOOBD84CDeTR8RZRUpIl8T0KnMIu0IP6Sk+ulLEEXa/I/93Q== X-Received: by 2002:a5d:4bc4:: with SMTP id l4mr12594166wrt.67.1626445357674; Fri, 16 Jul 2021 07:22:37 -0700 (PDT) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id z7sm7463236wmp.34.2021.07.16.07.22.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Jul 2021 07:22: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 v8 3/7] refs/files-backend: stop setting errno from lock_ref_oid_basic Date: Fri, 16 Jul 2021 16:22:28 +0200 Message-Id: X-Mailer: git-send-email 2.32.0.874.gfa1990a4f10 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) In the case of the "errno != ENOTDIR" case that originates in 5b2d8d6f218 (lock_ref_sha1_basic(): improve diagnostics for ref D/F conflicts, 2015-05-11), there the "last_errno" was saved away to return it from lock_ref_oid_basic(), now that we're no longer doing that we can skip that entirely and use "errno" directly. A follow-up change will extract the specific errno we want earlier in this function. Signed-off-by: Han-Wen Nienhuys Signed-off-by: Ævar Arnfjörð Bjarmason --- refs/files-backend.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/refs/files-backend.c b/refs/files-backend.c index 36af99af844..a6a9f2b99fa 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); @@ -1001,14 +999,15 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs, files_ref_path(refs, &ref_file, refname); if (!refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_NO_RECURSE, - &lock->old_oid, type)) { - last_errno = errno; - if (last_errno != ENOTDIR || - !refs_verify_refname_available(&refs->base, refname, - NULL, NULL, err)) - strbuf_addf(err, "unable to resolve reference '%s': %s", - refname, strerror(last_errno)); - + &lock->old_oid, type) && + (errno != ENOTDIR || + /* in case of D/F conflict, try to generate a better error + * message. If that fails, fall back to strerror(ENOTDIR). + */ + !refs_verify_refname_available(&refs->base, refname, NULL, + NULL, err))) { + strbuf_addf(err, "unable to resolve reference '%s': %s", + refname, strerror(errno)); goto error_return; } @@ -1020,15 +1019,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; } @@ -1045,7 +1041,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 Fri Jul 16 14:22: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: 12382291 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=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED,DKIM_INVALID,DKIM_SIGNED,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 6A586C07E95 for ; Fri, 16 Jul 2021 14:22:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 52A32613F2 for ; Fri, 16 Jul 2021 14:22:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240327AbhGPOZu (ORCPT ); Fri, 16 Jul 2021 10:25:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40882 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233075AbhGPOZi (ORCPT ); Fri, 16 Jul 2021 10:25:38 -0400 Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 94BA3C061765 for ; Fri, 16 Jul 2021 07:22:40 -0700 (PDT) Received: by mail-wr1-x42e.google.com with SMTP id f17so12320306wrt.6 for ; Fri, 16 Jul 2021 07:22: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=2uJ6/dYkRWLACADaEH+daNQZ1U0/fFs2Yk2beee1oK8=; b=txnz0fennK2sD0ooco5ccCuZWpFIpcLZkP145lpjrVPCsHdFSqXunRGcha4pLjm+TQ yZXSGAjjdj4/nih0VuySK8CENb+KnkSNg+HW8KFZdgfFZbCfUZZu4+XjNYjz+geLDW7g Hordzsf/BwrnaQigy2gf/OcX1hxV3qnPbdchlUyyH1pSZygw/WGmhT3P6xvKxmC+jdOg x7ndJWIz19Wi2/QviIBojramuKBO+x9unIDJlNgPPHMTvmnQnKQMJW7ZCvA0zshkp0Va ceaPy+Reybaza2Ms2pTsx71SxakfbVscPI0XiGGbv6HTu/nvH7eQO4vdY9KTjWIR8uCm m1Lw== 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=2uJ6/dYkRWLACADaEH+daNQZ1U0/fFs2Yk2beee1oK8=; b=j6/mlHPKGIvDmehhSQhXrJ2E5x63BoAkEpNJCcFbkOmXPhKpCK33Zx7Ss3sNJx0XoV 41i9RojfTY9KNI4CZpBuO/IoFSA//QU9uBpqN/jyZ7Ptj0qO399vw4vcEGAh/D7/+o7g Je600kWNbRAeV54cNZQoj0b7We0do1XYH2Dbas+XXRsQqjNjvaRW1hvf0aFvkuuOWHQz ceQ6XuZgPrCI8Zx7KG9z/lOJwKJBLsy96O+m6qywsTdVyyyMs6C1tq7cw0KhStjjkjcn b7cmhRB79BckavAMVS+Sl4cKx/dCvoV787HYyewUPjk7W9i/vRMMIrLzMUJAfE+a3wL+ 6oPg== X-Gm-Message-State: AOAM533YoCIgZbWVChTpBURAYLMgtbLOKy9VlOddyZ9/Si58XmwcolHa HF2In4FC43pXDDyqCjwqT3eZPvqGyyARLw== X-Google-Smtp-Source: ABdhPJz+j3xoZ+jU9e4aM9eYDSxUG1TcUAgS61hLr3BGAOC1ofICg4QL+SoFj3Oa1GUM6QGKB9PF0w== X-Received: by 2002:a05:6000:18a9:: with SMTP id b9mr12817771wri.418.1626445358784; Fri, 16 Jul 2021 07:22:38 -0700 (PDT) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id z7sm7463236wmp.34.2021.07.16.07.22.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Jul 2021 07:22: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 v8 4/7] refs: make errno output explicit for read_raw_ref_fn Date: Fri, 16 Jul 2021 16:22:29 +0200 Message-Id: X-Mailer: git-send-email 2.32.0.874.gfa1990a4f10 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 5e2330bf78e..136e2e4c78a 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 a6a9f2b99fa..70970f6f770 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 53d1ec27b60..1cb7f8e8f70 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 f4445e32904..79dfb3af484 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -617,11 +617,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. @@ -635,9 +639,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 Fri Jul 16 14:22: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: 12382285 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 861AAC636CD for ; Fri, 16 Jul 2021 14:22:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 72F27613F2 for ; Fri, 16 Jul 2021 14:22:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240366AbhGPOZw (ORCPT ); Fri, 16 Jul 2021 10:25:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40884 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233094AbhGPOZi (ORCPT ); Fri, 16 Jul 2021 10:25:38 -0400 Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7DFA0C06175F for ; Fri, 16 Jul 2021 07:22:41 -0700 (PDT) Received: by mail-wr1-x42d.google.com with SMTP id v5so12340576wrt.3 for ; Fri, 16 Jul 2021 07:22: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=IFNYfMMsu6uaXzykxi5NAUTZugtCJzZEgDy9xX1ajjo=; b=KXQNvLmTkyuwo79PAqN71ISy52wisJ9nKiFCUOTLhiR8N4cTDyxoBB2wvaAdR8Ark2 nUm3pGaUYVENcIMBJBcJ3lrQSwePI1BiVObSt9CNRkDUcQ6gCSQpZyWaOGx4OJGDd83P TbY30pUHXG8m6Mj86a1zChY+yewm04mnlekKoBCDuZHc1rUWYRkBZwGOa2+3fdwghM6A Wko4+C2fEeT+W/ltS46+FFwoyo7ksbb/RJjCA/mAk3DJr2HxtGwBIltyAOmQ67BvlI8X d2FcPQ+7YnGxMy20tcAQT4nHZ+PxpSVDvQlRlUu15NQ27bFMeIhyRCi3iCdnGAKGlAw8 fYzA== 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=IFNYfMMsu6uaXzykxi5NAUTZugtCJzZEgDy9xX1ajjo=; b=SYkSHvavcwgx56tXCq5dqSoA1aP23AUcNqDd8+QPMrJXHdosWIuVuPHpdl9RZ83VBj ulGCogq3UJVRAACweP7YZy0NCNNSsJWqULLoCPoIHj7gi9dxUctaC1+9D0JhihPzEAaA xKzYTi1rMHDPHfBE6ztoY12DnPvKtsgAQZRmMReTLYDHCO+mNHWbaHGcuWYyOeyTHRz4 7ICKuQHxcJT1TvKrvwcsgRY/3nvBaHmJUBQDU5pJD0e8x7vpipP4cwjYMlEypGF+1ges n5tumuftWIyXh9urR+sVxeNqJXw9E961tbqYDESHTH1L5z2yIPn685YpzqfV4wT+vnEo 1PeQ== X-Gm-Message-State: AOAM531IO46jsOXfzgxZx3j+a56LJi31s68JQ5z8KfhoQnye1o/uoVDj QJRDkcmuKiBFGQ8BUxnHzssF4OE0QSqH9Q== X-Google-Smtp-Source: ABdhPJwcICdNqe8seILRL0wHXDp0cu96aMDVkTg+LkmI9ZgbGmmIo6bpxN9q9GpWmRX89o2ICZacgA== X-Received: by 2002:a5d:6841:: with SMTP id o1mr12745789wrw.370.1626445359791; Fri, 16 Jul 2021 07:22:39 -0700 (PDT) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id z7sm7463236wmp.34.2021.07.16.07.22.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Jul 2021 07:22:39 -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 v8 5/7] refs: add failure_errno to refs_read_raw_ref() signature Date: Fri, 16 Jul 2021 16:22:30 +0200 Message-Id: X-Mailer: git-send-email 2.32.0.874.gfa1990a4f10 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 136e2e4c78a..b451f917d39 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 70970f6f770..25bb225d92a 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 1cb7f8e8f70..a4bf3d22d77 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 79dfb3af484..54f57c6a2df 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 Fri Jul 16 14:22:31 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: 12382289 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=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED,DKIM_INVALID,DKIM_SIGNED,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 5EB67C636CE for ; Fri, 16 Jul 2021 14:23:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 485F8613F2 for ; Fri, 16 Jul 2021 14:23:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240389AbhGPOZx (ORCPT ); Fri, 16 Jul 2021 10:25:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40884 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233115AbhGPOZk (ORCPT ); Fri, 16 Jul 2021 10:25:40 -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 46FF0C061760 for ; Fri, 16 Jul 2021 07:22:42 -0700 (PDT) Received: by mail-wm1-x329.google.com with SMTP id w13so5956875wmc.3 for ; Fri, 16 Jul 2021 07:22:42 -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=be1m4K9hcVqyYA72w4nj+evRTQY5Fovx/babRobDhS8=; b=l0CQoB+OlojnIP+LmQeBKve7WUQt2JjSy3rJIuqo+xjPv6NACPSNgQy7axaOBRDoF6 jsfI0G6PwCwb9se+Z3zZWCB6hpjW2jFIvDfCSWV51HDKTqWSE5z5d5sdcZJK08/71JpF FV/m8v+MvzAjTKdPI8tAd/8RGjzBXSJRvZJpp509qYzLrlNaNDW9JCMWgjj/20hwd1p7 Dx7A5ZPX7b5DFpZ9zqMeSXgrgejfruLWatV7wii4In8pJ5UC/YhAP2vwNz4/tC9QDWBG rSAHXgsy/UoiWDbdFRSBd7NmdgrrPGBy859+29Wd35ms6Vx7SZbh5kaaCOJXVo3/Vjgp UyoA== 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=be1m4K9hcVqyYA72w4nj+evRTQY5Fovx/babRobDhS8=; b=nxr45PsY75gleogLzsceltQfz7KvBBRAE4gq6ryf9i+R3Ep3WEoj10ScGcrruEleOQ v3iXHYiuVagXUBzEwanyVSQb7IAkbp7FCz8QWQFUTWuEwWvldptFtgjYLZOCGnbguBb3 FEB7zetlhiSoYeKLQUB9C+yU7Iht1o6Fkfce37Nnd83ZjmfmVLSt0MBNiybRkac0NLK/ 1mvJswQUqYDtt6FTV5XvSl5ofzRnK2SFdPVsc+5tg/S1yHZZulWexgKOGgk5gKssxMNw CyfRBz8PFuBnkWY7enISMtPl/Ouojmj3OhhycSUcqsINvRrNdp2+Tajz59XuYTRuG8FP Z+jQ== X-Gm-Message-State: AOAM533BQcgVZCUBAIL79EUHgPXERXvmE57QQN2/bdxlt8kRlBmSSazy exHsUi7AQnCWnkC4Besn4HbxDG+goRePog== X-Google-Smtp-Source: ABdhPJxWwkYzp8NpBQEvk5eTL9/W8GGUuQUVUMqP7KU29CX12aUgnMhP8YpSwof0WTh/SrrOkSAP1w== X-Received: by 2002:a05:600c:3201:: with SMTP id r1mr10868072wmp.41.1626445360735; Fri, 16 Jul 2021 07:22:40 -0700 (PDT) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id z7sm7463236wmp.34.2021.07.16.07.22.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Jul 2021 07:22:40 -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 v8 6/7] refs: explicitly return failure_errno from parse_loose_ref_contents Date: Fri, 16 Jul 2021 16:22:31 +0200 Message-Id: X-Mailer: git-send-email 2.32.0.874.gfa1990a4f10 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 b451f917d39..ceaaccc1680 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 25bb225d92a..45d7c346dea 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 54f57c6a2df..bf581e70cf6 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -689,10 +689,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 Fri Jul 16 14:22:32 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: 12382287 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=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED,DKIM_INVALID,DKIM_SIGNED,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 E4154C636CB for ; Fri, 16 Jul 2021 14:23:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C8CF9613F7 for ; Fri, 16 Jul 2021 14:23:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240413AbhGPOZ5 (ORCPT ); Fri, 16 Jul 2021 10:25:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40894 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233122AbhGPOZk (ORCPT ); Fri, 16 Jul 2021 10:25:40 -0400 Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5D3CDC061762 for ; Fri, 16 Jul 2021 07:22:43 -0700 (PDT) Received: by mail-wr1-x436.google.com with SMTP id k4so12285994wrc.8 for ; Fri, 16 Jul 2021 07:22:43 -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=9+mmuclnhrs765KxbdUjbayDT+Vmr9AVPFH4hv+TLbk=; b=Up8DOqhImzomR8/5ObWpqgf+0xOUNX982V9buhK87WiUq/eQ9bRPhtRK6kCvvN9zqi QdCxORMnPAF45yz4mcRMwbMcgjm67CEAeLoQkK5iu6KboGqCmzhD725oYDS1Zop2KdeF /I+90FZxnZF66tJuEUcnXT4M8PPmJ1HqSQWyhEqx41mKEv2N7Y5HTiSi6cSbjzr0WIPz KCAsD6TDYE8sTXOk608sqZOPQHRmcOIlSlL8BRe4lrckDS6lLxoBnoCxIdv1hBmliLBH W1s8Ja2rbOgIM/NT/Yvxs4aDnoXLGwpFj896BWIwlCa/HAAzUHjm4n764uIhAokzveHi aZrA== 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=9+mmuclnhrs765KxbdUjbayDT+Vmr9AVPFH4hv+TLbk=; b=WtVJn5UflydJJBvPnPu7FaCdqHVnPTKSYxudeLVuL/P+B3kSaLvWOa4pZ9+VNX4mpS KQVdMMjgBcN8LbGEyv6/uQWuINZANAw+310iCsq+EL+8br4/8IwLy2PmKzsAebaxQoVQ GyBOLPwdvpKJlA/xyDzSCrEtxssgL6GXkKvvalTzBwiMZyYKQr3IIySThhM+EWzXkMzS ktbHlOCvoh+mbcW7geGbkaOoB+n+sqJI6PIRmr2tq6t2Q2sgW3H4jLm/A0ldclZtAiqw PGyU8x4ZSoUJ6fNoL+Xjc8L+gIt8Caxqwfxt5tupcVa/eSoxy6KZeCqkqD48bJyaZObC yqEQ== X-Gm-Message-State: AOAM531FPBaivgmTTOBiDHRMcfcRTOorvxJ2fHOq9WnyPXjNNNXudw9D SpBWJn1oNsNDTvn1N9L2DRQE1AzPlAxejQ== X-Google-Smtp-Source: ABdhPJz5lqRFyEPHi7jSqDhPiqDWxljrG7ru7UBLaLKpbrRcFjdd2PQr+QYfSo30zaJkJGXrSuRm7g== X-Received: by 2002:adf:ffcf:: with SMTP id x15mr12943237wrs.76.1626445361709; Fri, 16 Jul 2021 07:22:41 -0700 (PDT) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id z7sm7463236wmp.34.2021.07.16.07.22.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Jul 2021 07:22:41 -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 v8 7/7] refs: make errno output explicit for refs_resolve_ref_unsafe Date: Fri, 16 Jul 2021 16:22:32 +0200 Message-Id: X-Mailer: git-send-email 2.32.0.874.gfa1990a4f10 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 | 12 +++++++----- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/refs.c b/refs.c index ceaaccc1680..9e2592ee28a 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 45d7c346dea..be5f386f64d 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,17 +1009,18 @@ 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) && - (errno != ENOTDIR || + if (!refs_resolve_ref_unsafe_with_errno(&refs->base, refname, + RESOLVE_REF_NO_RECURSE, + &lock->old_oid, type, + &resolve_errno) && + (resolve_errno != ENOTDIR || /* in case of D/F conflict, try to generate a better error * message. If that fails, fall back to strerror(ENOTDIR). */ !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; }