Re: [PATCH v5 1/5] setup: add gentle version of read_gitfile

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, Apr 25, 2015 at 11:49 PM, Erik Elfström <erik.elfstrom@xxxxxxxxx> wrote:
> read_gitfile will die on most error cases. This makes it unsuitable
> for speculative calls. Extract the core logic and provide a gentle
> version that returns NULL on failure.
>
> The first usecase of the new gentle version will be to probe for
> submodules during git clean.
>
> Helped-by: Junio C Hamano <gitster@xxxxxxxxx>
> Helped-by: Jeff King <peff@xxxxxxxx>
> Signed-off-by: Erik Elfström <erik.elfstrom@xxxxxxxxx>
> ---
>  cache.h | 11 ++++++++-
>  setup.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++--------------
>  2 files changed, 75 insertions(+), 18 deletions(-)
>
> diff --git a/cache.h b/cache.h
> index 3d3244b..868e4d3 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -431,7 +431,16 @@ extern int set_git_dir(const char *path);
>  extern const char *get_git_namespace(void);
>  extern const char *strip_namespace(const char *namespaced_ref);
>  extern const char *get_git_work_tree(void);
> -extern const char *read_gitfile(const char *path);
> +
> +#define READ_GITFILE_ERR_STAT_FAILED 1
> +#define READ_GITFILE_ERR_NOT_A_FILE 2
> +#define READ_GITFILE_ERR_OPEN_FAILED 3
> +#define READ_GITFILE_ERR_READ_FAILED 4
> +#define READ_GITFILE_ERR_INVALID_FORMAT 5
> +#define READ_GITFILE_ERR_NO_PATH 6
> +#define READ_GITFILE_ERR_NOT_A_REPO 7
> +extern const char *read_gitfile_gently(const char *path, int *return_error_code);
> +#define read_gitfile(path) read_gitfile_gently((path), NULL)
>  extern const char *resolve_gitdir(const char *suspect);
>  extern void set_git_work_tree(const char *tree);
>
> diff --git a/setup.c b/setup.c
> index 979b13f..c4538ca 100644
> --- a/setup.c
> +++ b/setup.c
> @@ -335,35 +335,53 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
>  /*
>   * Try to read the location of the git directory from the .git file,
>   * return path to git directory if found.
> + *
> + * On failure, if return_error_code is not NULL, return_error_code
> + * will be set to an error code and NULL will be returned. If
> + * return_error_code is NULL the function will die instead (for most
> + * cases).
>   */
> -const char *read_gitfile(const char *path)
> +const char *read_gitfile_gently(const char *path, int *return_error_code)
>  {
> -       char *buf;
> -       char *dir;
> +       int error_code = 0;
> +       char *buf = NULL;
> +       char *dir = NULL;
>         const char *slash;
>         struct stat st;
>         int fd;
>         ssize_t len;
>
> -       if (stat(path, &st))
> -               return NULL;
> -       if (!S_ISREG(st.st_mode))
> -               return NULL;
> +       if (stat(path, &st)) {
> +               error_code = READ_GITFILE_ERR_STAT_FAILED;
> +               goto cleanup_return;
> +       }
> +       if (!S_ISREG(st.st_mode)) {
> +               error_code = READ_GITFILE_ERR_NOT_A_FILE;
> +               goto cleanup_return;
> +       }
>         fd = open(path, O_RDONLY);
> -       if (fd < 0)
> -               die_errno("Error opening '%s'", path);
> +       if (fd < 0) {
> +               error_code = READ_GITFILE_ERR_OPEN_FAILED;
> +               goto cleanup_return;
> +       }
>         buf = xmalloc(st.st_size + 1);
>         len = read_in_full(fd, buf, st.st_size);
>         close(fd);
> -       if (len != st.st_size)
> -               die("Error reading %s", path);
> +       if (len != st.st_size) {
> +               error_code = READ_GITFILE_ERR_READ_FAILED;
> +               goto cleanup_return;

Sorry for the late review.

So when you jump from here to the cleanup, there is no close(fd) involved?
I think there are code paths now, which leak fd.

> +       }
>         buf[len] = '\0';
> -       if (!starts_with(buf, "gitdir: "))
> -               die("Invalid gitfile format: %s", path);
> +       if (!starts_with(buf, "gitdir: ")) {
> +               error_code = READ_GITFILE_ERR_INVALID_FORMAT;
> +               goto cleanup_return;
> +       }
>         while (buf[len - 1] == '\n' || buf[len - 1] == '\r')
>                 len--;
> -       if (len < 9)
> -               die("No path in gitfile: %s", path);
> +       if (len < 9) {
> +               error_code = READ_GITFILE_ERR_NO_PATH;
> +               goto cleanup_return;
> +       }
>         buf[len] = '\0';
>         dir = buf + 8;
>
> @@ -378,11 +396,41 @@ const char *read_gitfile(const char *path)
>                 buf = dir;
>         }
>
> -       if (!is_git_directory(dir))
> -               die("Not a git repository: %s", dir);
> +       if (!is_git_directory(dir)) {
> +               error_code = READ_GITFILE_ERR_NOT_A_REPO;
> +               goto cleanup_return;
> +       }
>         path = real_path(dir);
>
> +cleanup_return:
>         free(buf);
> +
> +       if (return_error_code)
> +               *return_error_code = error_code;
> +
> +       if (error_code) {
> +               if (return_error_code)
> +                       return NULL;
> +
> +               switch (error_code) {
> +               case READ_GITFILE_ERR_STAT_FAILED:
> +               case READ_GITFILE_ERR_NOT_A_FILE:
> +                       return NULL;
> +               case READ_GITFILE_ERR_OPEN_FAILED:
> +                       die_errno("Error opening '%s'", path);
> +               case READ_GITFILE_ERR_READ_FAILED:
> +                       die("Error reading %s", path);
> +               case READ_GITFILE_ERR_INVALID_FORMAT:
> +                       die("Invalid gitfile format: %s", path);
> +               case READ_GITFILE_ERR_NO_PATH:
> +                       die("No path in gitfile: %s", path);
> +               case READ_GITFILE_ERR_NOT_A_REPO:
> +                       die("Not a git repository: %s", dir);
> +               default:
> +                       assert(0);
> +               }
> +       }
> +
>         return path;
>  }
>
> --
> 2.4.0.rc3.8.gbb31afb
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]