return 0;
}
+static inline int offset_1st_component(const char *path)
+{
+ if (has_dos_drive_prefix(path))
+ return 2 + (path[2] == '/');
+ return *path == '/';
+}
+
int safe_create_leading_directories(char *path)
{
- char *pos = path;
+ char *pos = path + offset_1st_component(path);
struct stat st;
- if (is_absolute_path(path))
- pos++;
-
while (pos) {
pos = strchr(pos, '/');
if (!pos)
if (!alt) alt = "";
alt_odb_tail = &alt_odb_list;
- link_alt_odb_entries(alt, alt + strlen(alt), ':', NULL, 0);
+ link_alt_odb_entries(alt, alt + strlen(alt), PATH_SEP, NULL, 0);
read_info_alternates(get_object_directory(), 0);
}
version = ntohl(hdr->idx_version);
if (version < 2 || version > 2) {
munmap(idx_map, idx_size);
- return error("index file %s is version %d"
+ return error("index file %s is version %"PRIu32
" and is not supported by this binary"
" (try upgrading GIT to a newer version)",
path, version);
if (hdr.hdr_signature != htonl(PACK_SIGNATURE))
return error("file %s is not a GIT packfile", p->pack_name);
if (!pack_version_ok(hdr.hdr_version))
- return error("packfile %s is version %u and not supported"
- " (try upgrading GIT to a newer version)",
+ return error("packfile %s is version %"PRIu32" and not"
+ " supported (try upgrading GIT to a newer version)",
p->pack_name, ntohl(hdr.hdr_version));
/* Verify the pack matches its index. */
if (p->num_objects != ntohl(hdr.hdr_entries))
- return error("packfile %s claims to have %u objects"
- " while index indicates %u objects",
+ return error("packfile %s claims to have %"PRIu32" objects"
+ " while index indicates %"PRIu32" objects",
p->pack_name, ntohl(hdr.hdr_entries),
p->num_objects);
if (lseek(p->pack_fd, p->pack_size - sizeof(sha1), SEEK_SET) == -1)
p->num_bad_objects++;
}
+static int has_packed_and_bad(const unsigned char *sha1)
+{
+ struct packed_git *p;
+ unsigned i;
+
+ for (p = packed_git; p; p = p->next)
+ for (i = 0; i < p->num_bad_objects; i++)
+ if (!hashcmp(sha1, p->bad_object_sha1 + 20 * i))
+ return 1;
+ return 0;
+}
+
int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long size, const char *type)
{
unsigned char real_sha1[20];
(uintmax_t)curpos, p->pack_name);
return NULL;
}
+ unuse_pack(w_curs);
base = cache_or_unpack_entry(p, base_offset, &base_size, type, 0);
if (!base) {
/*
sha1_to_hex(base_sha1), (uintmax_t)base_offset,
p->pack_name);
mark_bad_packed_object(p, base_sha1);
- base = read_sha1_file(base_sha1, type, &base_size);
+ base = read_object(base_sha1, type, &base_size);
if (!base)
return NULL;
}
}
}
-static off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n)
+off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n)
{
const unsigned char *index = p->index_data;
index += 4 * 256;
}
if (debug_lookup)
- printf("%02x%02x%02x... lo %u hi %u nr %u\n",
+ printf("%02x%02x%02x... lo %u hi %u nr %"PRIu32"\n",
sha1[0], sha1[1], sha1[2], lo, hi, p->num_objects);
if (use_lookup < 0)
error("failed to read object %s at offset %"PRIuMAX" from %s",
sha1_to_hex(sha1), (uintmax_t)e.offset, e.p->pack_name);
mark_bad_packed_object(e.p, sha1);
- data = read_sha1_file(sha1, type, size);
+ data = read_object(sha1, type, size);
}
return data;
}
return 0;
}
-void *read_sha1_file(const unsigned char *sha1, enum object_type *type,
- unsigned long *size)
+void *read_object(const unsigned char *sha1, enum object_type *type,
+ unsigned long *size)
{
unsigned long mapsize;
void *map, *buf;
return read_packed_sha1(sha1, type, size);
}
+void *read_sha1_file(const unsigned char *sha1, enum object_type *type,
+ unsigned long *size)
+{
+ void *data = read_object(sha1, type, size);
+ /* legacy behavior is to die on corrupted objects */
+ if (!data && (has_loose_object(sha1) || has_packed_and_bad(sha1)))
+ die("object %s is corrupted", sha1_to_hex(sha1));
+ return data;
+}
+
void *read_object_with_reference(const unsigned char *sha1,
const char *required_type_name,
unsigned long *size,
/* Finalize a file on disk, and close it. */
static void close_sha1_file(int fd)
{
- /* For safe-mode, we could fsync_or_die(fd, "sha1 file") here */
+ if (fsync_object_files)
+ fsync_or_die(fd, "sha1 file");
fchmod(fd, 0444);
if (close(fd) != 0)
die("unable to write sha1 file");
return has_loose_object(sha1);
}
-int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object)
+static int index_mem(unsigned char *sha1, void *buf, size_t size,
+ int write_object, enum object_type type, const char *path)
{
- struct strbuf buf;
- int ret;
-
- strbuf_init(&buf, 0);
- if (strbuf_read(&buf, fd, 4096) < 0) {
- strbuf_release(&buf);
- return -1;
- }
-
- if (!type)
- type = blob_type;
- if (write_object)
- ret = write_sha1_file(buf.buf, buf.len, type, sha1);
- else
- ret = hash_sha1_file(buf.buf, buf.len, type, sha1);
- strbuf_release(&buf);
-
- return ret;
-}
-
-int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
- enum object_type type, const char *path)
-{
- size_t size = xsize_t(st->st_size);
- void *buf = NULL;
int ret, re_allocated = 0;
- if (size)
- buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
- close(fd);
-
if (!type)
type = OBJ_BLOB;
/*
* Convert blobs to git internal format
*/
- if ((type == OBJ_BLOB) && S_ISREG(st->st_mode)) {
+ if ((type == OBJ_BLOB) && path) {
struct strbuf nbuf;
strbuf_init(&nbuf, 0);
if (convert_to_git(path, buf, size, &nbuf,
write_object ? safe_crlf : 0)) {
- munmap(buf, size);
buf = strbuf_detach(&nbuf, &size);
re_allocated = 1;
}
ret = write_sha1_file(buf, size, typename(type), sha1);
else
ret = hash_sha1_file(buf, size, typename(type), sha1);
- if (re_allocated) {
+ if (re_allocated)
free(buf);
- return ret;
- }
- if (size)
+ return ret;
+}
+
+int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
+ enum object_type type, const char *path)
+{
+ int ret;
+ size_t size = xsize_t(st->st_size);
+
+ if (!S_ISREG(st->st_mode)) {
+ struct strbuf sbuf;
+ strbuf_init(&sbuf, 0);
+ if (strbuf_read(&sbuf, fd, 4096) >= 0)
+ ret = index_mem(sha1, sbuf.buf, sbuf.len, write_object,
+ type, path);
+ else
+ ret = -1;
+ strbuf_release(&sbuf);
+ } else if (size) {
+ void *buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+ ret = index_mem(sha1, buf, size, write_object, type, path);
munmap(buf, size);
+ } else
+ ret = index_mem(sha1, NULL, size, write_object, type, path);
+ close(fd);
return ret;
}