worktree: use xsize_t to access file size
[gitweb.git] / packfile.c
index 84d16bf7e05fce0f7e30d20fbdaf5e854d9da5fe..263efb7151a4c4b1ef2dbc96d53b0636ff8ce287 100644 (file)
@@ -444,6 +444,7 @@ static int open_packed_git_1(struct packed_git *p)
        unsigned char sha1[20];
        unsigned char *idx_sha1;
        long fd_flag;
+       ssize_t read_result;
 
        if (!p->index_data && open_pack_index(p))
                return error("packfile %s index unavailable", p->pack_name);
@@ -485,7 +486,10 @@ static int open_packed_git_1(struct packed_git *p)
                return error("cannot set FD_CLOEXEC");
 
        /* Verify we recognize this pack file format. */
-       if (read_in_full(p->pack_fd, &hdr, sizeof(hdr)) != sizeof(hdr))
+       read_result = read_in_full(p->pack_fd, &hdr, sizeof(hdr));
+       if (read_result < 0)
+               return error_errno("error reading from %s", p->pack_name);
+       if (read_result != sizeof(hdr))
                return error("file %s is far too short to be a packfile", p->pack_name);
        if (hdr.hdr_signature != htonl(PACK_SIGNATURE))
                return error("file %s is not a GIT packfile", p->pack_name);
@@ -502,7 +506,10 @@ static int open_packed_git_1(struct packed_git *p)
                             p->num_objects);
        if (lseek(p->pack_fd, p->pack_size - sizeof(sha1), SEEK_SET) == -1)
                return error("end of packfile %s is unavailable", p->pack_name);
-       if (read_in_full(p->pack_fd, sha1, sizeof(sha1)) != sizeof(sha1))
+       read_result = read_in_full(p->pack_fd, sha1, sizeof(sha1));
+       if (read_result < 0)
+               return error_errno("error reading from %s", p->pack_name);
+       if (read_result != sizeof(sha1))
                return error("packfile %s signature is unavailable", p->pack_name);
        idx_sha1 = ((unsigned char *)p->index_data) + p->index_size - 40;
        if (hashcmp(sha1, idx_sha1))
@@ -1854,3 +1861,43 @@ int has_pack_index(const unsigned char *sha1)
                return 0;
        return 1;
 }
+
+static int for_each_object_in_pack(struct packed_git *p, each_packed_object_fn cb, void *data)
+{
+       uint32_t i;
+       int r = 0;
+
+       for (i = 0; i < p->num_objects; i++) {
+               struct object_id oid;
+
+               if (!nth_packed_object_oid(&oid, p, i))
+                       return error("unable to get sha1 of object %u in %s",
+                                    i, p->pack_name);
+
+               r = cb(&oid, p, i, data);
+               if (r)
+                       break;
+       }
+       return r;
+}
+
+int for_each_packed_object(each_packed_object_fn cb, void *data, unsigned flags)
+{
+       struct packed_git *p;
+       int r = 0;
+       int pack_errors = 0;
+
+       prepare_packed_git();
+       for (p = packed_git; p; p = p->next) {
+               if ((flags & FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
+                       continue;
+               if (open_pack_index(p)) {
+                       pack_errors = 1;
+                       continue;
+               }
+               r = for_each_object_in_pack(p, cb, data);
+               if (r)
+                       break;
+       }
+       return r ? r : pack_errors;
+}