public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
To: Florian Weimer <fweimer@redhat.com>, libc-alpha@sourceware.org
Subject: Re: [PATCH 7/7] nss: Access nss_files through direct references
Date: Wed, 7 Jul 2021 10:49:40 -0300	[thread overview]
Message-ID: <c064c087-6be4-91b5-042c-f530f2d8d48b@linaro.org> (raw)
In-Reply-To: <a11b3386cbab6622b6a19fda20090c8ab5fd3a7b.1624961355.git.fweimer@redhat.com>



On 29/06/2021 07:11, Florian Weimer via Libc-alpha wrote:
> This partially fixes static-only NSS support (bug 27959): The files
> module no longer needs dlopen.  Support for the dns module remains
> to be added, and also support for disabling dlopen altogher.

s/altogher/altogether

LGTM, only a minor nit below.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org> 

> ---
>  include/nss_files.h              | 10 ++++++++
>  nss/Makefile                     |  3 ++-
>  nss/nss_files/files-XXX.c        |  6 ++++-
>  nss/nss_files/files-alias.c      |  7 +++---
>  nss/nss_files/files-ethers.c     |  2 --
>  nss/nss_files/files-grp.c        |  2 --
>  nss/nss_files/files-hosts.c      |  6 +++--
>  nss/nss_files/files-init.c       |  4 +--
>  nss/nss_files/files-initgroups.c |  3 +--
>  nss/nss_files/files-netgrp.c     |  5 ++--
>  nss/nss_files/files-network.c    |  1 -
>  nss/nss_files/files-proto.c      |  2 --
>  nss/nss_files/files-pwd.c        |  2 --
>  nss/nss_files/files-rpc.c        |  2 --
>  nss/nss_files/files-service.c    |  2 --
>  nss/nss_files/files-sgrp.c       |  2 --
>  nss/nss_files/files-spwd.c       |  2 --
>  nss/nss_files_functions.c        | 43 ++++++++++++++++++++++++++++++++
>  nss/nss_module.c                 | 38 +++++++++++++++++++++++++++-
>  nss/nss_module.h                 |  4 +++
>  20 files changed, 114 insertions(+), 32 deletions(-)
>  create mode 100644 nss/nss_files_functions.c
> 
> diff --git a/include/nss_files.h b/include/nss_files.h
> index dd0081a0f1..6190cac6be 100644
> --- a/include/nss_files.h
> +++ b/include/nss_files.h
> @@ -19,6 +19,7 @@
>  #ifndef _NSS_FILES_H
>  #define _NSS_FILES_H
>  
> +#include <nss.h>
>  #include <stdio.h>
>  #if IS_IN (libc)
>  #include <libc-lock.h>
> @@ -134,6 +135,15 @@ libc_hidden_proto (_nss_files_parse_servent)
>  libc_hidden_proto (_nss_files_parse_sgent)
>  libc_hidden_proto (_nss_files_parse_spent)
>  
> +NSS_DECLARE_MODULE_FUNCTIONS (files)
> +#undef DEFINE_NSS_FUNCTION
> +#define DEFINE_NSS_FUNCTION(x) libc_hidden_proto (_nss_files_##x)
> +#include <nss/function.def>
> +#undef DEFINE_NSS_FUNCTION
> +
> +void _nss_files_init (void (*cb) (size_t, struct traced_file *));
> +libc_hidden_proto (_nss_files_init)
> +
>  /* Generic implementation of fget*ent_r.  Reads lines from FP until
>     EOF or a successful parse into *RESULT using PARSER.  Returns 0 on
>     success, ENOENT on EOF, ERANGE on too-small buffer.  */

Ok.

> diff --git a/nss/Makefile b/nss/Makefile
> index 8905a5fd9b..75afb22cb3 100644
> --- a/nss/Makefile
> +++ b/nss/Makefile
> @@ -31,7 +31,8 @@ routines		= nsswitch getnssent getnssent_r digits_dots \
>  			  compat-lookup nss_hash nss_files_fopen \
>  			  nss_readline nss_parse_line_result \
>  			  nss_fgetent_r nss_module nss_action \
> -			  nss_action_parse nss_database nss_files_data
> +			  nss_action_parse nss_database nss_files_data \
> +			  nss_files_functions
>  
>  # These are the databases that go through nss dispatch.
>  # Caution: if you add a database here, you must add its real name

Maybe add one entry per line here?

> diff --git a/nss/nss_files/files-XXX.c b/nss/nss_files/files-XXX.c
> index 91553d7ca5..c158a891bd 100644
> --- a/nss/nss_files/files-XXX.c
> +++ b/nss/nss_files/files-XXX.c
> @@ -91,12 +91,14 @@ CONCAT(_nss_files_set,ENTNAME) (int stayopen)
>  {
>    return __nss_files_data_setent (CONCAT (nss_file_, ENTNAME), DATAFILE);
>  }
> +libc_hidden_def (CONCAT (_nss_files_set,ENTNAME))
>  
>  enum nss_status
>  CONCAT(_nss_files_end,ENTNAME) (void)
>  {
>    return __nss_files_data_endent (CONCAT (nss_file_, ENTNAME));
>  }
> +libc_hidden_def (CONCAT (_nss_files_end,ENTNAME))
>  \f
>  
>  /* Parsing the database file into `struct STRUCTURE' data structures.  */
> @@ -179,6 +181,7 @@ CONCAT(_nss_files_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer,
>    __nss_files_data_put (data);
>    return status;
>  }
> +libc_hidden_def (CONCAT (_nss_files_get,ENTNAME_r))
>  \f
>  /* Macro for defining lookup functions for this file-based database.
>  
> @@ -215,4 +218,5 @@ _nss_files_get##name##_r (proto,					      \
>      }									      \
>  									      \
>    return status;							      \
> -}
> +}									      \
> +libc_hidden_def (_nss_files_get##name##_r)

Ok.

> diff --git a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c
> index 75d91e0b0a..8c6e176ff6 100644
> --- a/nss/nss_files/files-alias.c
> +++ b/nss/nss_files/files-alias.c
> @@ -31,8 +31,6 @@
>  #include "nsswitch.h"
>  #include <nss_files.h>
>  
> -NSS_DECLARE_MODULE_FUNCTIONS (files)
> -
>  \f
>  /* Maintenance of the stream open on the database file.  For getXXent
>     operations the stream needs to be held open across calls, the other
> @@ -63,12 +61,14 @@ _nss_files_setaliasent (void)
>  {
>    return __nss_files_data_setent (nss_file_aliasent, "/etc/aliases");
>  }
> +libc_hidden_def (_nss_files_setaliasent)
>  
>  enum nss_status
>  _nss_files_endaliasent (void)
>  {
>    return __nss_files_data_endent (nss_file_aliasent);
>  }
> +libc_hidden_def (_nss_files_endaliasent)
>  \f
>  /* Parsing the database file into `struct aliasent' data structures.  */
>  static enum nss_status
> @@ -354,7 +354,7 @@ _nss_files_getaliasent_r (struct aliasent *result, char *buffer, size_t buflen,
>    __nss_files_data_put (data);
>    return status;
>  }
> -
> +libc_hidden_def (_nss_files_getaliasent_r)
>  
>  enum nss_status
>  _nss_files_getaliasbyname_r (const char *name, struct aliasent *result,
> @@ -387,3 +387,4 @@ _nss_files_getaliasbyname_r (const char *name, struct aliasent *result,
>  
>    return status;
>  }
> +libc_hidden_def (_nss_files_getaliasbyname_r)

Ok.

> diff --git a/nss/nss_files/files-ethers.c b/nss/nss_files/files-ethers.c
> index 2fe7f81e4b..7c2c2b9833 100644
> --- a/nss/nss_files/files-ethers.c
> +++ b/nss/nss_files/files-ethers.c
> @@ -20,8 +20,6 @@
>  #include <netinet/if_ether.h>
>  #include <nss.h>
>  
> -NSS_DECLARE_MODULE_FUNCTIONS (files)
> -
>  struct etherent_data {};
>  
>  #define ENTNAME		etherent

Ok.

> diff --git a/nss/nss_files/files-grp.c b/nss/nss_files/files-grp.c
> index 49be38e8b1..a716d948e2 100644
> --- a/nss/nss_files/files-grp.c
> +++ b/nss/nss_files/files-grp.c
> @@ -19,8 +19,6 @@
>  #include <grp.h>
>  #include <nss.h>
>  
> -NSS_DECLARE_MODULE_FUNCTIONS (files)
> -
>  #define STRUCTURE	group
>  #define ENTNAME		grent
>  #define DATABASE	"group"

Ok.

> diff --git a/nss/nss_files/files-hosts.c b/nss/nss_files/files-hosts.c
> index 894b85d501..d54d91d038 100644
> --- a/nss/nss_files/files-hosts.c
> +++ b/nss/nss_files/files-hosts.c
> @@ -26,8 +26,6 @@
>  #include <alloc_buffer.h>
>  #include <nss.h>
>  
> -NSS_DECLARE_MODULE_FUNCTIONS (files)
> -
>  /* Get implementation for some internal functions.  */
>  #include "../resolv/res_hconf.h"
>  
> @@ -358,6 +356,7 @@ _nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result,
>  
>    return status;
>  }
> +libc_hidden_def (_nss_files_gethostbyname3_r)
>  
>  enum nss_status
>  _nss_files_gethostbyname_r (const char *name, struct hostent *result,
> @@ -367,6 +366,7 @@ _nss_files_gethostbyname_r (const char *name, struct hostent *result,
>    return _nss_files_gethostbyname3_r (name, AF_INET, result, buffer, buflen,
>  				      errnop, herrnop, NULL, NULL);
>  }
> +libc_hidden_def (_nss_files_gethostbyname_r)
>  
>  enum nss_status
>  _nss_files_gethostbyname2_r (const char *name, int af, struct hostent *result,
> @@ -376,6 +376,7 @@ _nss_files_gethostbyname2_r (const char *name, int af, struct hostent *result,
>    return _nss_files_gethostbyname3_r (name, af, result, buffer, buflen,
>  				      errnop, herrnop, NULL, NULL);
>  }
> +libc_hidden_def (_nss_files_gethostbyname2_r)
>  
>  enum nss_status
>  _nss_files_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
> @@ -491,3 +492,4 @@ _nss_files_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
>  
>    return status;
>  }
> +libc_hidden_def (_nss_files_gethostbyname4_r)

Ok.

> diff --git a/nss/nss_files/files-init.c b/nss/nss_files/files-init.c
> index 36d5ebce1f..18d48168e8 100644
> --- a/nss/nss_files/files-init.c
> +++ b/nss/nss_files/files-init.c
> @@ -21,8 +21,7 @@
>  #include <string.h>
>  #include <nscd/nscd.h>
>  #include <nss.h>
> -
> -NSS_DECLARE_MODULE_FUNCTIONS (files)
> +#include <nss_files.h>
>  
>  static void
>  register_file (void (*cb) (size_t, struct traced_file *),
> @@ -49,5 +48,6 @@ _nss_files_init (void (*cb) (size_t, struct traced_file *))
>    register_file (cb, servdb, "/etc/services", 0);
>    register_file (cb, netgrdb, "/etc/netgroup", 0);
>  }
> +libc_hidden_def (_nss_files_init)
>  
>  #endif

Ok.

> diff --git a/nss/nss_files/files-initgroups.c b/nss/nss_files/files-initgroups.c
> index 6fcea40b55..b44211e50b 100644
> --- a/nss/nss_files/files-initgroups.c
> +++ b/nss/nss_files/files-initgroups.c
> @@ -28,8 +28,6 @@
>  #include <nss.h>
>  #include <nss_files.h>
>  
> -NSS_DECLARE_MODULE_FUNCTIONS (files)
> -
>  enum nss_status
>  _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start,
>  			   long int *size, gid_t **groupsp, long int limit,
> @@ -129,3 +127,4 @@ _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start,
>  
>    return status == NSS_STATUS_SUCCESS && !any ? NSS_STATUS_NOTFOUND : status;
>  }
> +libc_hidden_def (_nss_files_initgroups_dyn)

Ok.

> diff --git a/nss/nss_files/files-netgrp.c b/nss/nss_files/files-netgrp.c
> index be9c72accf..75bfbd9e44 100644
> --- a/nss/nss_files/files-netgrp.c
> +++ b/nss/nss_files/files-netgrp.c
> @@ -28,8 +28,6 @@
>  #include "netgroup.h"
>  #include <nss_files.h>
>  
> -NSS_DECLARE_MODULE_FUNCTIONS (files)
> -
>  #define DATAFILE	"/etc/netgroup"
>  
>  libc_hidden_proto (_nss_files_endnetgrent)
> @@ -152,7 +150,7 @@ _nss_files_setnetgrent (const char *group, struct __netgrent *result)
>  
>    return status;
>  }
> -
> +libc_hidden_def (_nss_files_setnetgrent)
>  
>  enum nss_status
>  _nss_files_endnetgrent (struct __netgrent *result)
> @@ -293,3 +291,4 @@ _nss_files_getnetgrent_r (struct __netgrent *result, char *buffer,
>  
>    return status;
>  }
> +libc_hidden_def (_nss_files_getnetgrent_r)

Ok.

> diff --git a/nss/nss_files/files-network.c b/nss/nss_files/files-network.c
> index 75c9f8a57e..217ed78609 100644
> --- a/nss/nss_files/files-network.c
> +++ b/nss/nss_files/files-network.c
> @@ -21,7 +21,6 @@
>  #include <netdb.h>
>  #include <stdint.h>
>  #include <nss.h>
> -#include <nss_files.h>
>  
>  #define ENTNAME		netent
>  #define DATABASE	"networks"

Ok.

> diff --git a/nss/nss_files/files-proto.c b/nss/nss_files/files-proto.c
> index 98d082c642..13072692c1 100644
> --- a/nss/nss_files/files-proto.c
> +++ b/nss/nss_files/files-proto.c
> @@ -19,8 +19,6 @@
>  #include <netdb.h>
>  #include <nss.h>
>  
> -NSS_DECLARE_MODULE_FUNCTIONS (files)
> -
>  #define ENTNAME		protoent
>  #define DATABASE	"protocols"
>  

Ok.

> diff --git a/nss/nss_files/files-pwd.c b/nss/nss_files/files-pwd.c
> index b04165ddde..5c74c6da9b 100644
> --- a/nss/nss_files/files-pwd.c
> +++ b/nss/nss_files/files-pwd.c
> @@ -19,8 +19,6 @@
>  #include <pwd.h>
>  #include <nss.h>
>  
> -NSS_DECLARE_MODULE_FUNCTIONS (files)
> -
>  #define STRUCTURE	passwd
>  #define ENTNAME		pwent
>  #define DATABASE	"passwd"

Ok.

> diff --git a/nss/nss_files/files-rpc.c b/nss/nss_files/files-rpc.c
> index eeb2725d2c..3dea8f18f2 100644
> --- a/nss/nss_files/files-rpc.c
> +++ b/nss/nss_files/files-rpc.c
> @@ -19,8 +19,6 @@
>  #include <rpc/netdb.h>
>  #include <nss.h>
>  
> -NSS_DECLARE_MODULE_FUNCTIONS (files)
> -
>  #define ENTNAME		rpcent
>  #define DATABASE	"rpc"
>  

Ok.

> diff --git a/nss/nss_files/files-service.c b/nss/nss_files/files-service.c
> index f4f0985377..a8d83e094e 100644
> --- a/nss/nss_files/files-service.c
> +++ b/nss/nss_files/files-service.c
> @@ -20,8 +20,6 @@
>  #include <netdb.h>
>  #include <nss.h>
>  
> -NSS_DECLARE_MODULE_FUNCTIONS (files)
> -
>  #define ENTNAME		servent
>  #define DATABASE	"services"
>  

Ok.

> diff --git a/nss/nss_files/files-sgrp.c b/nss/nss_files/files-sgrp.c
> index 6b1c9eac02..213a408e7b 100644
> --- a/nss/nss_files/files-sgrp.c
> +++ b/nss/nss_files/files-sgrp.c
> @@ -19,8 +19,6 @@
>  #include <gshadow.h>
>  #include <nss.h>
>  
> -NSS_DECLARE_MODULE_FUNCTIONS (files)
> -
>  #define STRUCTURE	sgrp
>  #define ENTNAME		sgent
>  #define DATABASE	"gshadow"
> diff --git a/nss/nss_files/files-spwd.c b/nss/nss_files/files-spwd.c
> index 976deaf918..d031257a20 100644
> --- a/nss/nss_files/files-spwd.c
> +++ b/nss/nss_files/files-spwd.c
> @@ -19,8 +19,6 @@
>  #include <shadow.h>
>  #include <nss.h>
>  
> -NSS_DECLARE_MODULE_FUNCTIONS (files)
> -
>  #define STRUCTURE	spwd
>  #define ENTNAME		spent
>  #define DATABASE	"shadow"

Ok.

> diff --git a/nss/nss_files_functions.c b/nss/nss_files_functions.c
> new file mode 100644
> index 0000000000..85720b4311
> --- /dev/null
> +++ b/nss/nss_files_functions.c
> @@ -0,0 +1,43 @@
> +/* Direct access for nss_files functions for NSS module loading.
> +   Copyright (C) 2021 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <nss_module.h>
> +#include <nss_files.h>
> +
> +void
> +__nss_files_functions (nss_module_functions_untyped pointers)
> +{
> +  void **fptr = pointers;
> +
> +  /* Functions which are not implemented.  */
> +#define _nss_files_getcanonname_r NULL
> +#define _nss_files_gethostbyaddr2_r NULL
> +#define _nss_files_getpublickey NULL
> +#define _nss_files_getsecretkey NULL
> +#define _nss_files_netname2user NULL
> +
> +#undef DEFINE_NSS_FUNCTION
> +#define DEFINE_NSS_FUNCTION(x) *fptr++ = _nss_files_##x;
> +#include "function.def"
> +
> +#ifdef PTR_MANGLE
> +  void **end = fptr;
> +  for (fptr = pointers; fptr != end; ++fptr)
> +    PTR_MANGLE (*fptr);
> +#endif
> +}

Ok.

> diff --git a/nss/nss_module.c b/nss/nss_module.c
> index 60c070c851..7b42c585a4 100644
> --- a/nss/nss_module.c
> +++ b/nss/nss_module.c
> @@ -30,6 +30,7 @@
>  #include <stdio.h>
>  #include <stdlib.h>
>  #include <string.h>
> +#include <nss_files.h>
>  
>  /* Suffix after .so of NSS service modules.  This is a bit of magic,
>     but we assume LIBNSS_FILES_SO looks like "libnss_files.so.2" and we
> @@ -110,10 +111,45 @@ static const function_name nss_function_name_array[] =
>  #include "function.def"
>    };
>  
> +static bool
> +module_load_nss_files (struct nss_module *module)
> +{
> +  if (is_nscd)
> +    {
> +      void (*cb) (size_t, struct traced_file *) = nscd_init_cb;
> +#  ifdef PTR_DEMANGLE
> +      PTR_DEMANGLE (cb);
> +#  endif
> +      _nss_files_init (cb);
> +    }
> +
> +  /* Initialize the function pointers, following the double-checked
> +     locking idiom.  */
> +  __libc_lock_lock (nss_module_list_lock);
> +  switch ((enum nss_module_state) atomic_load_acquire (&module->state))
> +    {
> +    case nss_module_uninitialized:
> +    case nss_module_failed:
> +      __nss_files_functions (module->functions.untyped);
> +      module->handle = NULL;
> +      /* Synchronizes with unlocked __nss_module_load atomic_load_acquire.  */
> +      atomic_store_release (&module->state, nss_module_loaded);
> +      break;
> +    case nss_module_loaded:
> +      /* Nothing to clean up.  */
> +      break;
> +    }
> +  __libc_lock_unlock (nss_module_list_lock);
> +  return true;
> +}
> +

Ok (it is mainly the code already presented on module_load()).

>  /* Internal implementation of __nss_module_load.  */
>  static bool
>  module_load (struct nss_module *module)
>  {
> +  if (strcmp (module->name, "files") == 0)
> +    return module_load_nss_files (module);
> +
>    void *handle;
>    {
>      char *shlib_name;
> @@ -360,7 +396,7 @@ __nss_module_freeres (void)
>    struct nss_module *current = nss_module_list;
>    while (current != NULL)
>      {
> -      if (current->state == nss_module_loaded)
> +      if (current->state == nss_module_loaded && current->handle != NULL)
>          __libc_dlclose (current->handle);
>  
>        struct nss_module *next = current->next;

Ok.

> diff --git a/nss/nss_module.h b/nss/nss_module.h
> index 05c4791d11..c1a1d90b60 100644
> --- a/nss/nss_module.h
> +++ b/nss/nss_module.h
> @@ -38,6 +38,10 @@ struct nss_module_functions
>  typedef void *nss_module_functions_untyped[sizeof (struct nss_module_functions)
>                                             / sizeof (void *)];
>  
> +/* Locate the nss_files functions, as if by dlopen/dlsym.  */
> +void __nss_files_functions (nss_module_functions_untyped pointers)
> +  attribute_hidden;
> +
>  /* Initialization state of a NSS module.  */
>  enum nss_module_state
>  {
> 

Ok.

  reply	other threads:[~2021-07-07 13:49 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-29 10:11 [PATCH v2 0/7] nss_files move Florian Weimer
2021-06-29 10:11 ` [PATCH 1/7] inet: Add hidden prototype for __inet_network Florian Weimer
2021-07-07 13:33   ` Adhemerval Zanella
2021-06-29 10:11 ` [PATCH 2/7] libio: Add hidden prototype for ungetc Florian Weimer
2021-07-07 13:33   ` Adhemerval Zanella
2021-06-29 10:11 ` [PATCH v2 3/7] libio: Replace internal _IO_getdelim symbol with __getdelim Florian Weimer
2021-07-07 13:33   ` Adhemerval Zanella
2021-06-29 10:11 ` [PATCH 4/7] nss_files: Allocate nscd file registration data on the heap Florian Weimer
2021-07-07 13:35   ` Adhemerval Zanella
2021-06-29 10:11 ` [PATCH 5/7] nss_files: Add generic code for set*ent, end*ent and file open Florian Weimer
2021-07-07 13:42   ` Adhemerval Zanella
2021-06-29 10:11 ` [PATCH 6/7] nss_files: Move into libc Florian Weimer
2021-07-07 13:45   ` Adhemerval Zanella
2021-06-29 10:11 ` [PATCH 7/7] nss: Access nss_files through direct references Florian Weimer
2021-07-07 13:49   ` Adhemerval Zanella [this message]
2021-07-08 10:28 ` [PATCH v2 0/7] nss_files move Andreas Schwab
2021-07-08 10:33   ` Florian Weimer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c064c087-6be4-91b5-042c-f530f2d8d48b@linaro.org \
    --to=adhemerval.zanella@linaro.org \
    --cc=fweimer@redhat.com \
    --cc=libc-alpha@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).