get_ref_dir(): return early if directory cannot be read

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael Haggerty committed Apr 25, 2012 at 00:45 UTC d5fdae67379778502ca8b3b3186ce4692d912e30
1 file changed +44 -41
refs.c
+44 -41
@@ -754,6 +754,9 @@ static void get_ref_dir(struct ref_cache *refs, const char *base,
754 {
755 DIR *d;
756 const char *path;
757 + struct dirent *de;
758 + int baselen;
759 + char *refname;
760
761 if (*refs->name)
762 path = git_path_submodule(refs->name, "%s", base);
@@ -761,55 +764,55 @@ static void get_ref_dir(struct ref_cache *refs, const char *base,
764 path = git_path("%s", base);
765
766 d = opendir(path);
764 - if (d) {
765 - struct dirent *de;
766 - int baselen = strlen(base);
767 - char *refname = xmalloc(baselen + 257);
767 + if (!d)
768 + return;
769
769 - memcpy(refname, base, baselen);
770 - if (baselen && base[baselen-1] != '/')
771 - refname[baselen++] = '/';
770 + baselen = strlen(base);
771 + refname = xmalloc(baselen + 257);
772
773 - while ((de = readdir(d)) != NULL) {
774 - unsigned char sha1[20];
775 - struct stat st;
776 - int flag;
777 - int namelen;
778 - const char *refdir;
773 + memcpy(refname, base, baselen);
774 + if (baselen && base[baselen-1] != '/')
775 + refname[baselen++] = '/';
776
780 - if (de->d_name[0] == '.')
781 - continue;
782 - namelen = strlen(de->d_name);
783 - if (namelen > 255)
784 - continue;
785 - if (has_extension(de->d_name, ".lock"))
786 - continue;
787 - memcpy(refname + baselen, de->d_name, namelen+1);
788 - refdir = *refs->name
789 - ? git_path_submodule(refs->name, "%s", refname)
790 - : git_path("%s", refname);
791 - if (stat(refdir, &st) < 0)
792 - continue;
793 - if (S_ISDIR(st.st_mode)) {
794 - get_ref_dir(refs, refname, dir);
795 - continue;
796 - }
797 - if (*refs->name) {
798 - hashclr(sha1);
799 - flag = 0;
800 - if (resolve_gitlink_ref(refs->name, refname, sha1) < 0) {
801 - hashclr(sha1);
802 - flag |= REF_ISBROKEN;
803 - }
804 - } else if (read_ref_full(refname, sha1, 1, &flag)) {
777 + while ((de = readdir(d)) != NULL) {
778 + unsigned char sha1[20];
779 + struct stat st;
780 + int flag;
781 + int namelen;
782 + const char *refdir;
783 +
784 + if (de->d_name[0] == '.')
785 + continue;
786 + namelen = strlen(de->d_name);
787 + if (namelen > 255)
788 + continue;
789 + if (has_extension(de->d_name, ".lock"))
790 + continue;
791 + memcpy(refname + baselen, de->d_name, namelen+1);
792 + refdir = *refs->name
793 + ? git_path_submodule(refs->name, "%s", refname)
794 + : git_path("%s", refname);
795 + if (stat(refdir, &st) < 0)
796 + continue;
797 + if (S_ISDIR(st.st_mode)) {
798 + get_ref_dir(refs, refname, dir);
799 + continue;
800 + }
801 + if (*refs->name) {
802 + hashclr(sha1);
803 + flag = 0;
804 + if (resolve_gitlink_ref(refs->name, refname, sha1) < 0) {
805 hashclr(sha1);
806 flag |= REF_ISBROKEN;
807 }
808 - add_ref(dir, create_ref_entry(refname, sha1, flag, 1));
808 + } else if (read_ref_full(refname, sha1, 1, &flag)) {
809 + hashclr(sha1);
810 + flag |= REF_ISBROKEN;
811 }
810 - free(refname);
811 - closedir(d);
812 + add_ref(dir, create_ref_entry(refname, sha1, flag, 1));
813 }
814 + free(refname);
815 + closedir(d);
816 }
817
818 static struct ref_dir *get_loose_refs(struct ref_cache *refs)