sha1_file.c 35.1 KB
Newer Older
1 2 3 4 5 6 7 8
/*
 * GIT - The information manager from hell
 *
 * Copyright (C) Linus Torvalds, 2005
 *
 * This handles basic git sha1 object files - packing, unpacking,
 * creation etc.
 */
9 10
#include <sys/types.h>
#include <dirent.h>
11
#include "cache.h"
12
#include "delta.h"
13
#include "pack.h"
14

15 16 17 18 19 20 21 22
#ifndef O_NOATIME
#if defined(__linux__) && (defined(__i386__) || defined(__PPC__))
#define O_NOATIME 01000000
#else
#define O_NOATIME 0
#endif
#endif

J
Junio C Hamano 已提交
23 24
const unsigned char null_sha1[20] = { 0, };

25 26
static unsigned int sha1_file_open_flag = O_NOATIME;

27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
static unsigned hexval(char c)
{
	if (c >= '0' && c <= '9')
		return c - '0';
	if (c >= 'a' && c <= 'f')
		return c - 'a' + 10;
	if (c >= 'A' && c <= 'F')
		return c - 'A' + 10;
	return ~0;
}

int get_sha1_hex(const char *hex, unsigned char *sha1)
{
	int i;
	for (i = 0; i < 20; i++) {
		unsigned int val = (hexval(hex[0]) << 4) | hexval(hex[1]);
		if (val & ~0xff)
			return -1;
		*sha1++ = val;
		hex += 2;
	}
	return 0;
}

51 52 53
int safe_create_leading_directories(char *path)
{
	char *pos = path;
54 55
	if (*pos == '/')
		pos++;
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70

	while (pos) {
		pos = strchr(pos, '/');
		if (!pos)
			break;
		*pos = 0;
		if (mkdir(path, 0777) < 0)
			if (errno != EEXIST) {
				*pos = '/';
				return -1;
			}
		*pos++ = '/';
	}
	return 0;
}
71

72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
char * sha1_to_hex(const unsigned char *sha1)
{
	static char buffer[50];
	static const char hex[] = "0123456789abcdef";
	char *buf = buffer;
	int i;

	for (i = 0; i < 20; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	return buffer;
}

87 88 89 90 91 92 93 94 95 96 97 98
static void fill_sha1_path(char *pathbuf, const unsigned char *sha1)
{
	int i;
	for (i = 0; i < 20; i++) {
		static char hex[] = "0123456789abcdef";
		unsigned int val = sha1[i];
		char *pos = pathbuf + i*2 + (i > 0);
		*pos++ = hex[val >> 4];
		*pos = hex[val & 0xf];
	}
}

99 100 101 102
/*
 * NOTE! This returns a statically allocated buffer, so you have to be
 * careful about using it. Do a "strdup()" if you need to save the
 * filename.
103 104 105
 *
 * Also note that this returns the location for creating.  Reading
 * SHA1 file can happen from any alternate directory listed in the
J
Junio C Hamano 已提交
106
 * DB_ENVIRONMENT environment variable if it is not found in
107
 * the primary object database.
108 109 110 111 112 113
 */
char *sha1_file_name(const unsigned char *sha1)
{
	static char *name, *base;

	if (!base) {
J
Junio C Hamano 已提交
114
		const char *sha1_file_directory = get_object_directory();
115
		int len = strlen(sha1_file_directory);
116
		base = xmalloc(len + 60);
117 118 119 120 121 122
		memcpy(base, sha1_file_directory, len);
		memset(base+len, 0, 60);
		base[len] = '/';
		base[len+3] = '/';
		name = base + len + 1;
	}
123
	fill_sha1_path(name, sha1);
124 125 126
	return base;
}

127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
char *sha1_pack_name(const unsigned char *sha1)
{
	static const char hex[] = "0123456789abcdef";
	static char *name, *base, *buf;
	int i;

	if (!base) {
		const char *sha1_file_directory = get_object_directory();
		int len = strlen(sha1_file_directory);
		base = xmalloc(len + 60);
		sprintf(base, "%s/pack/pack-1234567890123456789012345678901234567890.pack", sha1_file_directory);
		name = base + len + 11;
	}

	buf = name;

	for (i = 0; i < 20; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	
	return base;
}

char *sha1_pack_index_name(const unsigned char *sha1)
{
	static const char hex[] = "0123456789abcdef";
	static char *name, *base, *buf;
	int i;

	if (!base) {
		const char *sha1_file_directory = get_object_directory();
		int len = strlen(sha1_file_directory);
		base = xmalloc(len + 60);
		sprintf(base, "%s/pack/pack-1234567890123456789012345678901234567890.idx", sha1_file_directory);
		name = base + len + 11;
	}

	buf = name;

	for (i = 0; i < 20; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	
	return base;
}

177 178
struct alternate_object_database *alt_odb_list;
static struct alternate_object_database **alt_odb_tail;
179

J
Junio C Hamano 已提交
180 181
/*
 * Prepare alternate object database registry.
182 183 184 185 186 187 188 189 190 191 192 193
 *
 * The variable alt_odb_list points at the list of struct
 * alternate_object_database.  The elements on this list come from
 * non-empty elements from colon separated ALTERNATE_DB_ENVIRONMENT
 * environment variable, and $GIT_OBJECT_DIRECTORY/info/alternates,
 * whose contents is exactly in the same format as that environment
 * variable.  Its base points at a statically allocated buffer that
 * contains "/the/directory/corresponding/to/.git/objects/...", while
 * its name points just after the slash at the end of ".git/objects/"
 * in the example above, and has enough space to hold 40-byte hex
 * SHA1, an extra slash for the first level indirection, and the
 * terminating NUL.
J
Junio C Hamano 已提交
194
 */
195 196
static void link_alt_odb_entries(const char *alt, const char *ep, int sep,
				 const char *relative_base)
197 198
{
	const char *cp, *last;
199
	struct alternate_object_database *ent;
200
	int base_len = -1;
201 202

	last = alt;
203 204 205 206 207 208 209 210 211
	while (last < ep) {
		cp = last;
		if (cp < ep && *cp == '#') {
			while (cp < ep && *cp != sep)
				cp++;
			last = cp + 1;
			continue;
		}
		for ( ; cp < ep && *cp != sep; cp++)
212 213 214 215 216 217
			;
		if (last != cp) {
			/* 43 = 40-byte + 2 '/' + terminating NUL */
			int pfxlen = cp - last;
			int entlen = pfxlen + 43;

218 219 220 221 222 223 224
			if (*last != '/' && relative_base) {
				/* Relative alt-odb */
				if (base_len < 0)
					base_len = strlen(relative_base) + 1;
				entlen += base_len;
				pfxlen += base_len;
			}
225 226 227 228
			ent = xmalloc(sizeof(*ent) + entlen);
			*alt_odb_tail = ent;
			alt_odb_tail = &(ent->next);
			ent->next = NULL;
229 230 231 232 233 234 235 236
			if (*last != '/' && relative_base) {
				memcpy(ent->base, relative_base, base_len - 1);
				ent->base[base_len - 1] = '/';
				memcpy(ent->base + base_len,
				       last, cp - last);
			}
			else
				memcpy(ent->base, last, pfxlen);
237 238 239 240
			ent->name = ent->base + pfxlen + 1;
			ent->base[pfxlen] = ent->base[pfxlen + 3] = '/';
			ent->base[entlen-1] = 0;
		}
241
		while (cp < ep && *cp == sep)
242 243
			cp++;
		last = cp;
244
	}
245 246 247 248 249
}

void prepare_alt_odb(void)
{
	char path[PATH_MAX];
250
	char *map;
251 252
	int fd;
	struct stat st;
J
Jason Riedy 已提交
253 254
	char *alt;

255
	alt = getenv(ALTERNATE_DB_ENVIRONMENT);
J
Jason Riedy 已提交
256
	if (!alt) alt = "";
257

258 259 260
	if (alt_odb_tail)
		return;
	alt_odb_tail = &alt_odb_list;
261
	link_alt_odb_entries(alt, alt + strlen(alt), ':', NULL);
262

263
	sprintf(path, "%s/info/alternates", get_object_directory());
264 265 266 267 268
	fd = open(path, O_RDONLY);
	if (fd < 0)
		return;
	if (fstat(fd, &st) || (st.st_size == 0)) {
		close(fd);
269
		return;
270
	}
271 272 273 274 275
	map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
	close(fd);
	if (map == MAP_FAILED)
		return;

276 277
	link_alt_odb_entries(map, map + st.st_size, '\n',
			     get_object_directory());
278
	munmap(map, st.st_size);
279 280 281 282 283
}

static char *find_sha1_file(const unsigned char *sha1, struct stat *st)
{
	char *name = sha1_file_name(sha1);
284
	struct alternate_object_database *alt;
285 286 287

	if (!stat(name, st))
		return name;
288
	prepare_alt_odb();
289 290
	for (alt = alt_odb_list; alt; alt = alt->next) {
		name = alt->name;
291
		fill_sha1_path(name, sha1);
292 293
		if (!stat(alt->base, st))
			return alt->base;
294 295 296 297
	}
	return NULL;
}

298 299 300
#define PACK_MAX_SZ (1<<26)
static int pack_used_ctr;
static unsigned long pack_mapped;
301
struct packed_git *packed_git;
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324

static int check_packed_git_idx(const char *path, unsigned long *idx_size_,
				void **idx_map_)
{
	void *idx_map;
	unsigned int *index;
	unsigned long idx_size;
	int nr, i;
	int fd = open(path, O_RDONLY);
	struct stat st;
	if (fd < 0)
		return -1;
	if (fstat(fd, &st)) {
		close(fd);
		return -1;
	}
	idx_size = st.st_size;
	idx_map = mmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0);
	close(fd);
	if (idx_map == MAP_FAILED)
		return -1;

	index = idx_map;
325 326
	*idx_map_ = idx_map;
	*idx_size_ = idx_size;
327 328

	/* check index map */
329
	if (idx_size < 4*256 + 20 + 20)
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
		return error("index file too small");
	nr = 0;
	for (i = 0; i < 256; i++) {
		unsigned int n = ntohl(index[i]);
		if (n < nr)
			return error("non-monotonic index");
		nr = n;
	}

	/*
	 * Total size:
	 *  - 256 index entries 4 bytes each
	 *  - 24-byte entries * nr (20-byte sha1 + 4-byte offset)
	 *  - 20-byte SHA1 of the packfile
	 *  - 20-byte SHA1 file checksum
	 */
	if (idx_size != 4*256 + nr * 24 + 20 + 20)
		return error("wrong index file size");

	return 0;
}

352
static int unuse_one_packed_git(void)
353
{
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
	struct packed_git *p, *lru = NULL;

	for (p = packed_git; p; p = p->next) {
		if (p->pack_use_cnt || !p->pack_base)
			continue;
		if (!lru || p->pack_last_used < lru->pack_last_used)
			lru = p;
	}
	if (!lru)
		return 0;
	munmap(lru->pack_base, lru->pack_size);
	lru->pack_base = NULL;
	return 1;
}

void unuse_packed_git(struct packed_git *p)
{
	p->pack_use_cnt--;
372 373
}

374
int use_packed_git(struct packed_git *p)
375
{
376 377 378 379 380 381 382 383
	if (!p->pack_size) {
		struct stat st;
		// We created the struct before we had the pack
		stat(p->pack_name, &st);
		if (!S_ISREG(st.st_mode))
			die("packfile %s not a regular file", p->pack_name);
		p->pack_size = st.st_size;
	}
384 385 386 387 388 389
	if (!p->pack_base) {
		int fd;
		struct stat st;
		void *map;

		pack_mapped += p->pack_size;
390 391
		while (PACK_MAX_SZ < pack_mapped && unuse_one_packed_git())
			; /* nothing */
392 393
		fd = open(p->pack_name, O_RDONLY);
		if (fd < 0)
394
			die("packfile %s cannot be opened", p->pack_name);
395 396
		if (fstat(fd, &st)) {
			close(fd);
397
			die("packfile %s cannot be opened", p->pack_name);
398 399
		}
		if (st.st_size != p->pack_size)
400
			die("packfile %s size mismatch.", p->pack_name);
401 402 403
		map = mmap(NULL, p->pack_size, PROT_READ, MAP_PRIVATE, fd, 0);
		close(fd);
		if (map == MAP_FAILED)
404
			die("packfile %s cannot be mapped.", p->pack_name);
405
		p->pack_base = map;
406 407 408 409 410

		/* Check if the pack file matches with the index file.
		 * this is cheap.
		 */
		if (memcmp((char*)(p->index_base) + p->index_size - 40,
411 412
			   p->pack_base + p->pack_size - 20, 20)) {
			      
413
			die("packfile %s does not match index.", p->pack_name);
414
		}
415 416
	}
	p->pack_last_used = pack_used_ctr++;
417
	p->pack_use_cnt++;
418 419 420
	return 0;
}

421
struct packed_git *add_packed_git(char *path, int path_len, int local)
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
{
	struct stat st;
	struct packed_git *p;
	unsigned long idx_size;
	void *idx_map;

	if (check_packed_git_idx(path, &idx_size, &idx_map))
		return NULL;

	/* do we have a corresponding .pack file? */
	strcpy(path + path_len - 4, ".pack");
	if (stat(path, &st) || !S_ISREG(st.st_mode)) {
		munmap(idx_map, idx_size);
		return NULL;
	}
	/* ok, it looks sane as far as we can check without
	 * actually mapping the pack file.
	 */
	p = xmalloc(sizeof(*p) + path_len + 2);
	strcpy(p->pack_name, path);
	p->index_size = idx_size;
	p->pack_size = st.st_size;
	p->index_base = idx_map;
	p->next = NULL;
446
	p->pack_base = NULL;
447
	p->pack_last_used = 0;
448
	p->pack_use_cnt = 0;
449
	p->pack_local = local;
450 451 452
	return p;
}

453
struct packed_git *parse_pack_index(unsigned char *sha1)
454 455 456 457 458
{
	char *path = sha1_pack_index_name(sha1);
	return parse_pack_index_file(sha1, path);
}

459
struct packed_git *parse_pack_index_file(const unsigned char *sha1, char *idx_path)
460 461 462 463
{
	struct packed_git *p;
	unsigned long idx_size;
	void *idx_map;
464
	char *path;
465

466
	if (check_packed_git_idx(idx_path, &idx_size, &idx_map))
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
		return NULL;

	path = sha1_pack_name(sha1);

	p = xmalloc(sizeof(*p) + strlen(path) + 2);
	strcpy(p->pack_name, path);
	p->index_size = idx_size;
	p->pack_size = 0;
	p->index_base = idx_map;
	p->next = NULL;
	p->pack_base = NULL;
	p->pack_last_used = 0;
	p->pack_use_cnt = 0;
	memcpy(p->sha1, sha1, 20);
	return p;
}

void install_packed_git(struct packed_git *pack)
{
	pack->next = packed_git;
	packed_git = pack;
}

490
static void prepare_packed_git_one(char *objdir, int local)
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
{
	char path[PATH_MAX];
	int len;
	DIR *dir;
	struct dirent *de;

	sprintf(path, "%s/pack", objdir);
	len = strlen(path);
	dir = opendir(path);
	if (!dir)
		return;
	path[len++] = '/';
	while ((de = readdir(dir)) != NULL) {
		int namelen = strlen(de->d_name);
		struct packed_git *p;

		if (strcmp(de->d_name + namelen - 4, ".idx"))
			continue;

		/* we have .idx.  Is it a file we can map? */
		strcpy(path + len, de->d_name);
512
		p = add_packed_git(path, len + namelen, local);
513 514 515 516 517
		if (!p)
			continue;
		p->next = packed_git;
		packed_git = p;
	}
518
	closedir(dir);
519 520
}

521
void prepare_packed_git(void)
522 523
{
	static int run_once = 0;
524
	struct alternate_object_database *alt;
525

526
	if (run_once)
527
		return;
528
	prepare_packed_git_one(get_object_directory(), 1);
529
	prepare_alt_odb();
530 531
	for (alt = alt_odb_list; alt; alt = alt->next) {
		alt->name[0] = 0;
532
		prepare_packed_git_one(alt->base, 0);
533
	}
534
	run_once = 1;
535 536
}

537
int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long size, const char *type)
538
{
539
	char header[100];
540 541 542 543
	unsigned char real_sha1[20];
	SHA_CTX c;

	SHA1_Init(&c);
544
	SHA1_Update(&c, header, 1+sprintf(header, "%s %lu", type, size));
545 546 547 548 549
	SHA1_Update(&c, map, size);
	SHA1_Final(real_sha1, &c);
	return memcmp(sha1, real_sha1, 20) ? -1 : 0;
}

550
static void *map_sha1_file_internal(const unsigned char *sha1,
D
Daniel Barkalow 已提交
551
				    unsigned long *size)
552 553 554
{
	struct stat st;
	void *map;
555
	int fd;
556 557 558 559 560
	char *filename = find_sha1_file(sha1, &st);

	if (!filename) {
		return NULL;
	}
561

562
	fd = open(filename, O_RDONLY | sha1_file_open_flag);
563
	if (fd < 0) {
564 565 566 567 568 569 570 571 572 573 574
		/* See if it works without O_NOATIME */
		switch (sha1_file_open_flag) {
		default:
			fd = open(filename, O_RDONLY);
			if (fd >= 0)
				break;
		/* Fallthrough */
		case 0:
			return NULL;
		}

575 576 577
		/* If it failed once, it will probably fail again.
		 * Stop using O_NOATIME
		 */
578
		sha1_file_open_flag = 0;
579 580 581
	}
	map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
	close(fd);
P
Pavel Roskin 已提交
582
	if (map == MAP_FAILED)
583 584 585 586 587
		return NULL;
	*size = st.st_size;
	return map;
}

588 589 590 591 592 593 594 595 596 597 598 599 600
int unpack_sha1_header(z_stream *stream, void *map, unsigned long mapsize, void *buffer, unsigned long size)
{
	/* Get the data stream */
	memset(stream, 0, sizeof(*stream));
	stream->next_in = map;
	stream->avail_in = mapsize;
	stream->next_out = buffer;
	stream->avail_out = size;

	inflateInit(stream);
	return inflate(stream, 0);
}

L
Linus Torvalds 已提交
601
static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size)
602 603
{
	int bytes = strlen(buffer) + 1;
604
	unsigned char *buf = xmalloc(1+size);
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668

	memcpy(buf, buffer + bytes, stream->total_out - bytes);
	bytes = stream->total_out - bytes;
	if (bytes < size) {
		stream->next_out = buf + bytes;
		stream->avail_out = size - bytes;
		while (inflate(stream, Z_FINISH) == Z_OK)
			/* nothing */;
	}
	buf[size] = 0;
	inflateEnd(stream);
	return buf;
}

/*
 * We used to just use "sscanf()", but that's actually way
 * too permissive for what we want to check. So do an anal
 * object header parse by hand.
 */
int parse_sha1_header(char *hdr, char *type, unsigned long *sizep)
{
	int i;
	unsigned long size;

	/*
	 * The type can be at most ten bytes (including the 
	 * terminating '\0' that we add), and is followed by
	 * a space. 
	 */
	i = 10;
	for (;;) {
		char c = *hdr++;
		if (c == ' ')
			break;
		if (!--i)
			return -1;
		*type++ = c;
	}
	*type = 0;

	/*
	 * The length must follow immediately, and be in canonical
	 * decimal format (ie "010" is not valid).
	 */
	size = *hdr++ - '0';
	if (size > 9)
		return -1;
	if (size) {
		for (;;) {
			unsigned long c = *hdr - '0';
			if (c > 9)
				break;
			hdr++;
			size = size * 10 + c;
		}
	}
	*sizep = size;

	/*
	 * The length must be followed by a zero byte
	 */
	return *hdr ? -1 : 0;
}

669 670
void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size)
{
671
	int ret;
672
	z_stream stream;
673
	char hdr[8192];
674

675 676
	ret = unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr));
	if (ret < Z_OK || parse_sha1_header(hdr, type, size) < 0)
677 678
		return NULL;

679
	return unpack_sha1_rest(&stream, hdr, *size);
680 681
}

J
Junio C Hamano 已提交
682 683 684 685
/* forward declaration for a mutually recursive function */
static int packed_object_info(struct pack_entry *entry,
			      char *type, unsigned long *sizep);

686 687 688 689
static int packed_delta_info(unsigned char *base_sha1,
			     unsigned long delta_size,
			     unsigned long left,
			     char *type,
J
Junio C Hamano 已提交
690 691
			     unsigned long *sizep,
			     struct packed_git *p)
692
{
J
Junio C Hamano 已提交
693 694
	struct pack_entry base_ent;

695 696 697
	if (left < 20)
		die("truncated pack file");

J
Junio C Hamano 已提交
698 699 700 701 702
	/* The base entry _must_ be in the same pack */
	if (!find_pack_entry_one(base_sha1, &base_ent, p))
		die("failed to find delta-pack base object %s",
		    sha1_to_hex(base_sha1));

703 704 705 706 707
	/* We choose to only get the type of the base object and
	 * ignore potentially corrupt pack file that expects the delta
	 * based on a base with a wrong size.  This saves tons of
	 * inflate() calls.
	 */
708

J
Junio C Hamano 已提交
709
	if (packed_object_info(&base_ent, type, NULL))
710
		die("cannot get info for delta-pack base");
711

712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737
	if (sizep) {
		const unsigned char *data;
		unsigned char delta_head[64];
		unsigned long result_size;
		z_stream stream;
		int st;

		memset(&stream, 0, sizeof(stream));

		data = stream.next_in = base_sha1 + 20;
		stream.avail_in = left - 20;
		stream.next_out = delta_head;
		stream.avail_out = sizeof(delta_head);

		inflateInit(&stream);
		st = inflate(&stream, Z_FINISH);
		inflateEnd(&stream);
		if ((st != Z_STREAM_END) &&
		    stream.total_out != sizeof(delta_head))
			die("delta data unpack-initial failed");

		/* Examine the initial part of the delta to figure out
		 * the result size.
		 */
		data = delta_head;
		get_delta_hdr_size(&data); /* ignore base size */
738

739 740 741 742
		/* Read the result size */
		result_size = get_delta_hdr_size(&data);
		*sizep = result_size;
	}
743 744 745
	return 0;
}

746 747 748
static unsigned long unpack_object_header(struct packed_git *p, unsigned long offset,
	enum object_type *type, unsigned long *sizep)
{
749
	unsigned shift;
750 751 752 753 754 755 756 757 758 759 760
	unsigned char *pack, c;
	unsigned long size;

	if (offset >= p->pack_size)
		die("object offset outside of pack file");

	pack =  p->pack_base + offset;
	c = *pack++;
	offset++;
	*type = (c >> 4) & 7;
	size = c & 15;
761
	shift = 4;
762 763 764 765 766
	while (c & 0x80) {
		if (offset >= p->pack_size)
			die("object offset outside of pack file");
		c = *pack++;
		offset++;
767 768
		size += (c & 0x7f) << shift;
		shift += 7;
769 770 771 772 773
	}
	*sizep = size;
	return offset;
}

774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819
void packed_object_info_detail(struct pack_entry *e,
			       char *type,
			       unsigned long *size,
			       unsigned long *store_size,
			       int *delta_chain_length,
			       unsigned char *base_sha1)
{
	struct packed_git *p = e->p;
	unsigned long offset, left;
	unsigned char *pack;
	enum object_type kind;

	offset = unpack_object_header(p, e->offset, &kind, size);
	pack = p->pack_base + offset;
	left = p->pack_size - offset;
	if (kind != OBJ_DELTA)
		*delta_chain_length = 0;
	else {
		int chain_length = 0;
		memcpy(base_sha1, pack, 20);
		do {
			struct pack_entry base_ent;
			unsigned long junk;

			find_pack_entry_one(pack, &base_ent, p);
			offset = unpack_object_header(p, base_ent.offset,
						      &kind, &junk);
			pack = p->pack_base + offset;
			chain_length++;
		} while (kind == OBJ_DELTA);
		*delta_chain_length = chain_length;
	}
	switch (kind) {
	case OBJ_COMMIT:
		strcpy(type, "commit");
		break;
	case OBJ_TREE:
		strcpy(type, "tree");
		break;
	case OBJ_BLOB:
		strcpy(type, "blob");
		break;
	case OBJ_TAG:
		strcpy(type, "tag");
		break;
	default:
820 821
		die("corrupted pack file %s containing object of kind %d",
		    p->pack_name, kind);
822 823 824 825
	}
	*store_size = 0; /* notyet */
}

826 827 828 829 830 831
static int packed_object_info(struct pack_entry *entry,
			      char *type, unsigned long *sizep)
{
	struct packed_git *p = entry->p;
	unsigned long offset, size, left;
	unsigned char *pack;
832
	enum object_type kind;
833
	int retval;
834 835 836 837

	if (use_packed_git(p))
		die("cannot map packed file");

838
	offset = unpack_object_header(p, entry->offset, &kind, &size);
839
	pack = p->pack_base + offset;
840 841 842 843
	left = p->pack_size - offset;

	switch (kind) {
	case OBJ_DELTA:
J
Junio C Hamano 已提交
844
		retval = packed_delta_info(pack, size, left, type, sizep, p);
845 846
		unuse_packed_git(p);
		return retval;
847
	case OBJ_COMMIT:
848 849
		strcpy(type, "commit");
		break;
850
	case OBJ_TREE:
851 852
		strcpy(type, "tree");
		break;
853
	case OBJ_BLOB:
854 855
		strcpy(type, "blob");
		break;
856
	case OBJ_TAG:
857 858
		strcpy(type, "tag");
		break;
859
	default:
860 861
		die("corrupted pack file %s containing object of kind %d",
		    p->pack_name, kind);
862
	}
863 864
	if (sizep)
		*sizep = size;
865
	unuse_packed_git(p);
866 867 868 869 870 871 872 873 874 875
	return 0;
}

/* forward declaration for a mutually recursive function */
static void *unpack_entry(struct pack_entry *, char *, unsigned long *);

static void *unpack_delta_entry(unsigned char *base_sha1,
				unsigned long delta_size,
				unsigned long left,
				char *type,
J
Junio C Hamano 已提交
876 877
				unsigned long *sizep,
				struct packed_git *p)
878
{
J
Junio C Hamano 已提交
879
	struct pack_entry base_ent;
880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903
	void *data, *delta_data, *result, *base;
	unsigned long data_size, result_size, base_size;
	z_stream stream;
	int st;

	if (left < 20)
		die("truncated pack file");
	data = base_sha1 + 20;
	data_size = left - 20;
	delta_data = xmalloc(delta_size);

	memset(&stream, 0, sizeof(stream));

	stream.next_in = data;
	stream.avail_in = data_size;
	stream.next_out = delta_data;
	stream.avail_out = delta_size;

	inflateInit(&stream);
	st = inflate(&stream, Z_FINISH);
	inflateEnd(&stream);
	if ((st != Z_STREAM_END) || stream.total_out != delta_size)
		die("delta data unpack failed");

J
Junio C Hamano 已提交
904 905 906 907 908
	/* The base entry _must_ be in the same pack */
	if (!find_pack_entry_one(base_sha1, &base_ent, p))
		die("failed to find delta-pack base object %s",
		    sha1_to_hex(base_sha1));
	base = unpack_entry_gently(&base_ent, type, &base_size);
909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928
	if (!base)
		die("failed to read delta-pack base object %s",
		    sha1_to_hex(base_sha1));
	result = patch_delta(base, base_size,
			     delta_data, delta_size,
			     &result_size);
	if (!result)
		die("failed to apply delta");
	free(delta_data);
	free(base);
	*sizep = result_size;
	return result;
}

static void *unpack_non_delta_entry(unsigned char *data,
				    unsigned long size,
				    unsigned long left)
{
	int st;
	z_stream stream;
929
	unsigned char *buffer;
930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953

	buffer = xmalloc(size + 1);
	buffer[size] = 0;
	memset(&stream, 0, sizeof(stream));
	stream.next_in = data;
	stream.avail_in = left;
	stream.next_out = buffer;
	stream.avail_out = size;

	inflateInit(&stream);
	st = inflate(&stream, Z_FINISH);
	inflateEnd(&stream);
	if ((st != Z_STREAM_END) || stream.total_out != size) {
		free(buffer);
		return NULL;
	}

	return buffer;
}

static void *unpack_entry(struct pack_entry *entry,
			  char *type, unsigned long *sizep)
{
	struct packed_git *p = entry->p;
954
	void *retval;
955 956 957

	if (use_packed_git(p))
		die("cannot map packed file");
J
Junio C Hamano 已提交
958 959 960
	retval = unpack_entry_gently(entry, type, sizep);
	unuse_packed_git(p);
	if (!retval)
961
		die("corrupted pack file %s", p->pack_name);
J
Junio C Hamano 已提交
962 963 964 965 966 967 968 969 970 971 972 973
	return retval;
}

/* The caller is responsible for use_packed_git()/unuse_packed_git() pair */
void *unpack_entry_gently(struct pack_entry *entry,
			  char *type, unsigned long *sizep)
{
	struct packed_git *p = entry->p;
	unsigned long offset, size, left;
	unsigned char *pack;
	enum object_type kind;
	void *retval;
974

975
	offset = unpack_object_header(p, entry->offset, &kind, &size);
976
	pack = p->pack_base + offset;
977 978 979
	left = p->pack_size - offset;
	switch (kind) {
	case OBJ_DELTA:
J
Junio C Hamano 已提交
980
		retval = unpack_delta_entry(pack, size, left, type, sizep, p);
981
		return retval;
982
	case OBJ_COMMIT:
983 984
		strcpy(type, "commit");
		break;
985
	case OBJ_TREE:
986 987
		strcpy(type, "tree");
		break;
988
	case OBJ_BLOB:
989 990
		strcpy(type, "blob");
		break;
991
	case OBJ_TAG:
992 993
		strcpy(type, "tag");
		break;
994
	default:
J
Junio C Hamano 已提交
995
		return NULL;
996 997
	}
	*sizep = size;
998 999
	retval = unpack_non_delta_entry(pack, size, left);
	return retval;
1000 1001
}

1002 1003
int num_packed_objects(const struct packed_git *p)
{
1004
	/* See check_packed_git_idx() */
1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017
	return (p->index_size - 20 - 20 - 4*256) / 24;
}

int nth_packed_object_sha1(const struct packed_git *p, int n,
			   unsigned char* sha1)
{
	void *index = p->index_base + 256;
	if (n < 0 || num_packed_objects(p) <= n)
		return -1;
	memcpy(sha1, (index + 24 * n + 4), 20);
	return 0;
}

J
Junio C Hamano 已提交
1018 1019
int find_pack_entry_one(const unsigned char *sha1,
			struct pack_entry *e, struct packed_git *p)
1020
{
1021
	unsigned int *level1_ofs = p->index_base;
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048
	int hi = ntohl(level1_ofs[*sha1]);
	int lo = ((*sha1 == 0x0) ? 0 : ntohl(level1_ofs[*sha1 - 1]));
	void *index = p->index_base + 256;

	do {
		int mi = (lo + hi) / 2;
		int cmp = memcmp(index + 24 * mi + 4, sha1, 20);
		if (!cmp) {
			e->offset = ntohl(*((int*)(index + 24 * mi)));
			memcpy(e->sha1, sha1, 20);
			e->p = p;
			return 1;
		}
		if (cmp > 0)
			hi = mi;
		else
			lo = mi+1;
	} while (lo < hi);
	return 0;
}

static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
{
	struct packed_git *p;
	prepare_packed_git();

	for (p = packed_git; p; p = p->next) {
J
Junio C Hamano 已提交
1049
		if (find_pack_entry_one(sha1, e, p))
1050 1051 1052 1053 1054
			return 1;
	}
	return 0;
}

1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
struct packed_git *find_sha1_pack(const unsigned char *sha1, 
				  struct packed_git *packs)
{
	struct packed_git *p;
	struct pack_entry e;

	for (p = packs; p; p = p->next) {
		if (find_pack_entry_one(sha1, &e, p))
			return p;
	}
	return NULL;
	
}

1069
int sha1_object_info(const unsigned char *sha1, char *type, unsigned long *sizep)
1070
{
1071
	int status;
1072 1073 1074
	unsigned long mapsize, size;
	void *map;
	z_stream stream;
1075
	char hdr[128];
1076

D
Daniel Barkalow 已提交
1077
	map = map_sha1_file_internal(sha1, &mapsize);
1078 1079 1080 1081 1082
	if (!map) {
		struct pack_entry e;

		if (!find_pack_entry(sha1, &e))
			return error("unable to find %s", sha1_to_hex(sha1));
1083
		return packed_object_info(&e, type, sizep);
1084
	}
1085 1086 1087 1088 1089
	if (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0)
		status = error("unable to unpack %s header",
			       sha1_to_hex(sha1));
	if (parse_sha1_header(hdr, type, &size) < 0)
		status = error("unable to parse %s header", sha1_to_hex(sha1));
1090
	else {
1091
		status = 0;
1092 1093
		if (sizep)
			*sizep = size;
1094 1095 1096 1097 1098 1099
	}
	inflateEnd(&stream);
	munmap(map, mapsize);
	return status;
}

1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
static void *read_packed_sha1(const unsigned char *sha1, char *type, unsigned long *size)
{
	struct pack_entry e;

	if (!find_pack_entry(sha1, &e)) {
		error("cannot read sha1_file for %s", sha1_to_hex(sha1));
		return NULL;
	}
	return unpack_entry(&e, type, size);
}

1111 1112 1113 1114
void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)
{
	unsigned long mapsize;
	void *map, *buf;
1115
	struct pack_entry e;
1116

1117 1118
	if (find_pack_entry(sha1, &e))
		return read_packed_sha1(sha1, type, size);
D
Daniel Barkalow 已提交
1119
	map = map_sha1_file_internal(sha1, &mapsize);
1120 1121 1122 1123 1124
	if (map) {
		buf = unpack_sha1_file(map, mapsize, type, size);
		munmap(map, mapsize);
		return buf;
	}
1125
	return NULL;
1126 1127
}

1128
void *read_object_with_reference(const unsigned char *sha1,
1129
				 const char *required_type,
1130 1131
				 unsigned long *size,
				 unsigned char *actual_sha1_return)
1132 1133 1134 1135
{
	char type[20];
	void *buffer;
	unsigned long isize;
1136
	unsigned char actual_sha1[20];
1137

1138 1139 1140 1141
	memcpy(actual_sha1, sha1, 20);
	while (1) {
		int ref_length = -1;
		const char *ref_type = NULL;
1142

1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
		buffer = read_sha1_file(actual_sha1, type, &isize);
		if (!buffer)
			return NULL;
		if (!strcmp(type, required_type)) {
			*size = isize;
			if (actual_sha1_return)
				memcpy(actual_sha1_return, actual_sha1, 20);
			return buffer;
		}
		/* Handle references */
		else if (!strcmp(type, "commit"))
			ref_type = "tree ";
		else if (!strcmp(type, "tag"))
			ref_type = "object ";
		else {
			free(buffer);
			return NULL;
		}
		ref_length = strlen(ref_type);
1162

1163 1164 1165 1166 1167
		if (memcmp(buffer, ref_type, ref_length) ||
		    get_sha1_hex(buffer + ref_length, actual_sha1)) {
			free(buffer);
			return NULL;
		}
1168
		free(buffer);
1169 1170
		/* Now we have the ID of the referred-to object in
		 * actual_sha1.  Check again. */
1171 1172 1173
	}
}

1174 1175 1176 1177 1178 1179
char *write_sha1_file_prepare(void *buf,
			      unsigned long len,
			      const char *type,
			      unsigned char *sha1,
			      unsigned char *hdr,
			      int *hdrlen)
1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194
{
	SHA_CTX c;

	/* Generate the header */
	*hdrlen = sprintf((char *)hdr, "%s %lu", type, len)+1;

	/* Sha1.. */
	SHA1_Init(&c);
	SHA1_Update(&c, hdr, *hdrlen);
	SHA1_Update(&c, buf, len);
	SHA1_Final(sha1, &c);

	return sha1_file_name(sha1);
}

1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233
/*
 * Link the tempfile to the final place, possibly creating the
 * last directory level as you do so.
 *
 * Returns the errno on failure, 0 on success.
 */
static int link_temp_to_file(const char *tmpfile, char *filename)
{
	int ret;

	if (!link(tmpfile, filename))
		return 0;

	/*
	 * Try to mkdir the last path component if that failed
	 * with an ENOENT.
	 *
	 * Re-try the "link()" regardless of whether the mkdir
	 * succeeds, since a race might mean that somebody
	 * else succeeded.
	 */
	ret = errno;
	if (ret == ENOENT) {
		char *dir = strrchr(filename, '/');
		if (dir) {
			*dir = 0;
			mkdir(filename, 0777);
			*dir = '/';
			if (!link(tmpfile, filename))
				return 0;
			ret = errno;
		}
	}
	return ret;
}

/*
 * Move the just written object into its final resting place
 */
1234
int move_temp_to_file(const char *tmpfile, char *filename)
1235 1236
{
	int ret = link_temp_to_file(tmpfile, filename);
1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250

	/*
	 * Coda hack - coda doesn't like cross-directory links,
	 * so we fall back to a rename, which will mean that it
	 * won't be able to check collisions, but that's not a
	 * big deal.
	 *
	 * The same holds for FAT formatted media.
	 *
	 * When this succeeds, we just return 0. We have nothing
	 * left to unlink.
	 */
	if (ret && ret != EEXIST) {
		if (!rename(tmpfile, filename))
1251
			return 0;
1252
		ret = errno;
1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265
	}
	unlink(tmpfile);
	if (ret) {
		if (ret != EEXIST) {
			fprintf(stderr, "unable to write sha1 filename %s: %s", filename, strerror(ret));
			return -1;
		}
		/* FIXME!!! Collision check here ? */
	}

	return 0;
}

1266
int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *returnsha1)
1267 1268
{
	int size;
1269
	unsigned char *compressed;
1270 1271
	z_stream stream;
	unsigned char sha1[20];
1272
	char *filename;
1273
	static char tmpfile[PATH_MAX];
1274
	unsigned char hdr[50];
1275
	int fd, hdrlen;
1276

1277 1278 1279 1280
	/* Normally if we have it in the pack then we do not bother writing
	 * it out into .git/objects/??/?{38} file.
	 */
	filename = write_sha1_file_prepare(buf, len, type, sha1, hdr, &hdrlen);
1281 1282
	if (returnsha1)
		memcpy(returnsha1, sha1, 20);
1283 1284
	if (has_sha1_file(sha1))
		return 0;
1285 1286
	fd = open(filename, O_RDONLY);
	if (fd >= 0) {
1287
		/*
1288 1289
		 * FIXME!!! We might do collision checking here, but we'd
		 * need to uncompress the old file and check it. Later.
1290
		 */
1291
		close(fd);
1292 1293 1294
		return 0;
	}

1295 1296 1297 1298 1299 1300
	if (errno != ENOENT) {
		fprintf(stderr, "sha1 file %s: %s", filename, strerror(errno));
		return -1;
	}

	snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX", get_object_directory());
1301

1302 1303 1304 1305 1306 1307
	fd = mkstemp(tmpfile);
	if (fd < 0) {
		fprintf(stderr, "unable to create temporary sha1 filename %s: %s", tmpfile, strerror(errno));
		return -1;
	}

1308 1309 1310
	/* Set it up */
	memset(&stream, 0, sizeof(stream));
	deflateInit(&stream, Z_BEST_COMPRESSION);
1311
	size = deflateBound(&stream, len+hdrlen);
1312
	compressed = xmalloc(size);
1313 1314 1315 1316

	/* Compress it */
	stream.next_out = compressed;
	stream.avail_out = size;
1317 1318 1319 1320 1321

	/* First header.. */
	stream.next_in = hdr;
	stream.avail_in = hdrlen;
	while (deflate(&stream, 0) == Z_OK)
1322
		/* nothing */;
1323 1324 1325 1326

	/* Then the data itself.. */
	stream.next_in = buf;
	stream.avail_in = len;
1327 1328 1329 1330 1331
	while (deflate(&stream, Z_FINISH) == Z_OK)
		/* nothing */;
	deflateEnd(&stream);
	size = stream.total_out;

1332 1333
	if (write(fd, compressed, size) != size)
		die("unable to write file");
1334
	fchmod(fd, 0444);
1335
	close(fd);
1336
	free(compressed);
1337

1338
	return move_temp_to_file(tmpfile, filename);
1339
}
1340

D
Daniel Barkalow 已提交
1341 1342 1343 1344 1345
int write_sha1_to_fd(int fd, const unsigned char *sha1)
{
	ssize_t size;
	unsigned long objsize;
	int posn = 0;
1346 1347 1348
	void *map = map_sha1_file_internal(sha1, &objsize);
	void *buf = map;
	void *temp_obj = NULL;
D
Daniel Barkalow 已提交
1349
	z_stream stream;
1350

D
Daniel Barkalow 已提交
1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365
	if (!buf) {
		unsigned char *unpacked;
		unsigned long len;
		char type[20];
		char hdr[50];
		int hdrlen;
		// need to unpack and recompress it by itself
		unpacked = read_packed_sha1(sha1, type, &len);

		hdrlen = sprintf(hdr, "%s %lu", type, len) + 1;

		/* Set it up */
		memset(&stream, 0, sizeof(stream));
		deflateInit(&stream, Z_BEST_COMPRESSION);
		size = deflateBound(&stream, len + hdrlen);
1366
		temp_obj = buf = xmalloc(size);
D
Daniel Barkalow 已提交
1367 1368 1369 1370 1371 1372

		/* Compress it */
		stream.next_out = buf;
		stream.avail_out = size;
		
		/* First header.. */
1373
		stream.next_in = (void *)hdr;
D
Daniel Barkalow 已提交
1374 1375 1376 1377 1378 1379 1380 1381 1382 1383
		stream.avail_in = hdrlen;
		while (deflate(&stream, 0) == Z_OK)
			/* nothing */;

		/* Then the data itself.. */
		stream.next_in = unpacked;
		stream.avail_in = len;
		while (deflate(&stream, Z_FINISH) == Z_OK)
			/* nothing */;
		deflateEnd(&stream);
1384
		free(unpacked);
D
Daniel Barkalow 已提交
1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400
		
		objsize = stream.total_out;
	}

	do {
		size = write(fd, buf + posn, objsize - posn);
		if (size <= 0) {
			if (!size) {
				fprintf(stderr, "write closed");
			} else {
				perror("write ");
			}
			return -1;
		}
		posn += size;
	} while (posn < objsize);
1401 1402 1403 1404 1405 1406

	if (map)
		munmap(map, objsize);
	if (temp_obj)
		free(temp_obj);

D
Daniel Barkalow 已提交
1407 1408 1409
	return 0;
}

1410 1411
int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer,
		       size_t bufsize, size_t *bufposn)
1412
{
1413
	char tmpfile[PATH_MAX];
1414 1415 1416
	int local;
	z_stream stream;
	unsigned char real_sha1[20];
1417
	unsigned char discard[4096];
1418 1419 1420
	int ret;
	SHA_CTX c;

1421
	snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX", get_object_directory());
1422

1423
	local = mkstemp(tmpfile);
1424
	if (local < 0)
1425
		return error("Couldn't open %s for %s\n", tmpfile, sha1_to_hex(sha1));
1426 1427 1428 1429 1430 1431 1432 1433 1434

	memset(&stream, 0, sizeof(stream));

	inflateInit(&stream);

	SHA1_Init(&c);

	do {
		ssize_t size;
1435 1436
		if (*bufposn) {
			stream.avail_in = *bufposn;
P
Pavel Roskin 已提交
1437
			stream.next_in = (unsigned char *) buffer;
1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452
			do {
				stream.next_out = discard;
				stream.avail_out = sizeof(discard);
				ret = inflate(&stream, Z_SYNC_FLUSH);
				SHA1_Update(&c, discard, sizeof(discard) -
					    stream.avail_out);
			} while (stream.avail_in && ret == Z_OK);
			write(local, buffer, *bufposn - stream.avail_in);
			memmove(buffer, buffer + *bufposn - stream.avail_in,
				stream.avail_in);
			*bufposn = stream.avail_in;
			if (ret != Z_OK)
				break;
		}
		size = read(fd, buffer + *bufposn, bufsize - *bufposn);
1453 1454
		if (size <= 0) {
			close(local);
1455
			unlink(tmpfile);
1456 1457 1458 1459 1460
			if (!size)
				return error("Connection closed?");
			perror("Reading from connection");
			return -1;
		}
1461 1462
		*bufposn += size;
	} while (1);
1463 1464 1465 1466 1467
	inflateEnd(&stream);

	close(local);
	SHA1_Final(real_sha1, &c);
	if (ret != Z_STREAM_END) {
1468
		unlink(tmpfile);
1469 1470 1471
		return error("File %s corrupted", sha1_to_hex(sha1));
	}
	if (memcmp(sha1, real_sha1, 20)) {
1472
		unlink(tmpfile);
1473 1474
		return error("File %s has bad hash\n", sha1_to_hex(sha1));
	}
1475 1476

	return move_temp_to_file(tmpfile, sha1_file_name(sha1));
1477 1478
}

1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494
int has_pack_index(const unsigned char *sha1)
{
	struct stat st;
	if (stat(sha1_pack_index_name(sha1), &st))
		return 0;
	return 1;
}

int has_pack_file(const unsigned char *sha1)
{
	struct stat st;
	if (stat(sha1_pack_name(sha1), &st))
		return 0;
	return 1;
}

1495 1496 1497 1498 1499 1500
int has_sha1_pack(const unsigned char *sha1)
{
	struct pack_entry e;
	return find_pack_entry(sha1, &e);
}

1501 1502 1503
int has_sha1_file(const unsigned char *sha1)
{
	struct stat st;
1504 1505
	struct pack_entry e;

1506
	if (find_pack_entry(sha1, &e))
1507
		return 1;
1508
	return find_sha1_file(sha1, &st) ? 1 : 0;
1509
}
J
Junio C Hamano 已提交
1510

1511
int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, const char *type)
J
Junio C Hamano 已提交
1512 1513
{
	unsigned long size = st->st_size;
1514 1515
	void *buf;
	int ret;
1516 1517
	unsigned char hdr[50];
	int hdrlen;
J
Junio C Hamano 已提交
1518

1519
	buf = "";
J
Junio C Hamano 已提交
1520
	if (size)
1521
		buf = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
J
Junio C Hamano 已提交
1522
	close(fd);
P
Pavel Roskin 已提交
1523
	if (buf == MAP_FAILED)
J
Junio C Hamano 已提交
1524 1525
		return -1;

1526 1527 1528 1529 1530 1531 1532 1533
	if (!type)
		type = "blob";
	if (write_object)
		ret = write_sha1_file(buf, size, type, sha1);
	else {
		write_sha1_file_prepare(buf, size, type, sha1, hdr, &hdrlen);
		ret = 0;
	}
1534 1535 1536
	if (size)
		munmap(buf, size);
	return ret;
J
Junio C Hamano 已提交
1537
}
1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576

int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object)
{
	int fd;
	char *target;

	switch (st->st_mode & S_IFMT) {
	case S_IFREG:
		fd = open(path, O_RDONLY);
		if (fd < 0)
			return error("open(\"%s\"): %s", path,
				     strerror(errno));
		if (index_fd(sha1, fd, st, write_object, NULL) < 0)
			return error("%s: failed to insert into database",
				     path);
		break;
	case S_IFLNK:
		target = xmalloc(st->st_size+1);
		if (readlink(path, target, st->st_size+1) != st->st_size) {
			char *errstr = strerror(errno);
			free(target);
			return error("readlink(\"%s\"): %s", path,
			             errstr);
		}
		if (!write_object) {
			unsigned char hdr[50];
			int hdrlen;
			write_sha1_file_prepare(target, st->st_size, "blob",
						sha1, hdr, &hdrlen);
		} else if (write_sha1_file(target, st->st_size, "blob", sha1))
			return error("%s: failed to insert into database",
				     path);
		free(target);
		break;
	default:
		return error("%s: unsupported file type", path);
	}
	return 0;
}