git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] Reorganize common code

From
Daniel Barkalow <barkalow@iabervon.org>
Date
Apr 13, 2005, 22:00 UTC
Message-ID
<Pine.LNX.4.21.0504131755550.30848-100000@iabervon.org>
In-Reply-To
<Pine.LNX.4.21.0504131752410.30848-100000@iabervon.org>

This splits read-cache.c into util.c, cache.c, and objects.c, based on what the code is used for; similarly, cache.h becomes util.h, cache.h, and objects.h. For simplicity, cache.h includes the other two to give the previous overall behavior.

Signed-Off-By: Daniel Barkalow <barkalow@iabervon.org>
Index: Makefile
===================================================================
--- 783978eb212c1402ba2612bb32626e93af78b72d/Makefile  (mode:100644 sha1:2b626ec05b2e29016d26b5cb7b4f82ec5c4e79d6)
+++ e8194c62bfc68725972a6847fa2c6d529ca64137/Makefile  (mode:100644 sha1:0b263fa693cb2addb2516a8f7af2ea05b95d3c8c)
@@ -20,7 +20,7 @@
 	gitmerge.sh gitpull.sh gitrm.sh gittag.sh gittrack.sh gitexport.sh \
 	gitapply.sh
 
-COMMON=	read-cache.o
+COMMON=	cache.o objects.o util.o
 
 GEN_SCRIPT= gitversion.sh
 
@@ -36,7 +36,7 @@
 $(PROG):%: %.o $(COMMON)
 	$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
 
-read-cache.o: cache.h
+cache.o: cache.h
 show-diff.o: cache.h
 
 gitversion.sh: $(VERSION)
Index: cache.c
===================================================================
--- /dev/null  (tree:783978eb212c1402ba2612bb32626e93af78b72d)
+++ e8194c62bfc68725972a6847fa2c6d529ca64137/cache.c  (mode:100644 sha1:fe61eae561e8ebaab9d9fe6d8f146ed7353b6a1c)
@@ -0,0 +1,224 @@
+/*
+ * GIT - The information manager from hell
+ *
+ * Copyright (C) Linus Torvalds, 2005
+ */
+#include <stdarg.h>
+#include "cache.h"
+
+const char *sha1_file_directory = NULL;
+struct cache_entry **active_cache = NULL;
+unsigned int active_nr = 0, active_alloc = 0;
+
+int cache_match_stat(struct cache_entry *ce, struct stat *st)
+{
+	unsigned int changed = 0;
+
+	/* nsec seems unreliable - not all filesystems support it, so
+	 * as long as it is in the inode cache you get right nsec
+	 * but after it gets flushed, you get zero nsec. */
+	if (ce->mtime.sec  != (unsigned int)st->st_mtim.tv_sec
+#ifdef NSEC
+	    || ce->mtime.nsec != (unsigned int)st->st_mtim.tv_nsec
+#endif
+	    )
+		changed |= MTIME_CHANGED;
+	if (ce->ctime.sec  != (unsigned int)st->st_ctim.tv_sec
+#ifdef NSEC
+	    || ce->ctime.nsec != (unsigned int)st->st_ctim.tv_nsec
+#endif
+	    )
+		changed |= CTIME_CHANGED;
+	if (ce->st_uid != (unsigned int)st->st_uid ||
+	    ce->st_gid != (unsigned int)st->st_gid)
+		changed |= OWNER_CHANGED;
+	if (ce->st_mode != (unsigned int)st->st_mode)
+		changed |= MODE_CHANGED;
+	if (ce->st_dev != (unsigned int)st->st_dev ||
+	    ce->st_ino != (unsigned int)st->st_ino)
+		changed |= INODE_CHANGED;
+	if (ce->st_size != (unsigned int)st->st_size)
+		changed |= DATA_CHANGED;
+	return changed;
+}
+
+int cache_name_compare(const char *name1, int len1, const char *name2, int len2)
+{
+	int len = len1 < len2 ? len1 : len2;
+	int cmp;
+
+	cmp = memcmp(name1, name2, len);
+	if (cmp)
+		return cmp;
+	if (len1 < len2)
+		return -1;
+	if (len1 > len2)
+		return 1;
+	return 0;
+}
+
+int cache_name_pos(const char *name, int namelen)
+{
+	int first, last;
+
+	first = 0;
+	last = active_nr;
+	while (last > first) {
+		int next = (last + first) >> 1;
+		struct cache_entry *ce = active_cache[next];
+		int cmp = cache_name_compare(name, namelen, ce->name, ce->namelen);
+		if (!cmp)
+			return next;
+		if (cmp < 0) {
+			last = next;
+			continue;
+		}
+		first = next+1;
+	}
+	return -first-1;
+}
+
+int remove_file_from_cache(char *path)
+{
+	int pos = cache_name_pos(path, strlen(path));
+	if (pos >= 0) {
+		active_nr--;
+		if (pos < active_nr)
+			memmove(active_cache + pos, active_cache + pos + 1, (active_nr - pos) * sizeof(struct cache_entry *));
+	}
+	return 0;
+}
+
+int add_cache_entry(struct cache_entry *ce, int ok_to_add)
+{
+	int pos;
+
+	pos = cache_name_pos(ce->name, ce->namelen);
+
+	/* existing match? Just replace it */
+	if (pos >= 0) {
+		active_cache[pos] = ce;
+		return 0;
+	}
+	pos = -pos-1;
+
+	if (!ok_to_add)
+		return -1;
+
+	/* Make sure the array is big enough .. */
+	if (active_nr == active_alloc) {
+		active_alloc = alloc_nr(active_alloc);
+		active_cache = realloc(active_cache, active_alloc * sizeof(struct cache_entry *));
+	}
+
+	/* Add it in.. */
+	active_nr++;
+	if (active_nr > pos)
+		memmove(active_cache + pos + 1, active_cache + pos, (active_nr - pos - 1) * sizeof(ce));
+	active_cache[pos] = ce;
+	return 0;
+}
+
+static int verify_hdr(struct cache_header *hdr, unsigned long size)
+{
+	SHA_CTX c;
+	unsigned char sha1[20];
+
+	if (hdr->signature != CACHE_SIGNATURE)
+		return error("bad signature");
+	if (hdr->version != 1)
+		return error("bad version");
+	SHA1_Init(&c);
+	SHA1_Update(&c, hdr, offsetof(struct cache_header, sha1));
+	SHA1_Update(&c, hdr+1, size - sizeof(*hdr));
+	SHA1_Final(sha1, &c);
+	if (memcmp(sha1, hdr->sha1, 20))
+		return error("bad header sha1");
+	return 0;
+}
+
+int read_cache(void)
+{
+	int fd, i;
+	struct stat st;
+	unsigned long size, offset;
+	void *map;
+	struct cache_header *hdr;
+
+	errno = EBUSY;
+	if (active_cache)
+		return error("more than one cachefile");
+	errno = ENOENT;
+	sha1_file_directory = getenv(DB_ENVIRONMENT);
+	if (!sha1_file_directory)
+		sha1_file_directory = DEFAULT_DB_ENVIRONMENT;
+	if (access(sha1_file_directory, X_OK) < 0)
+		return error("no access to SHA1 file directory");
+	fd = open(".git/index", O_RDONLY);
+	if (fd < 0)
+		return (errno == ENOENT) ? 0 : error("open failed");
+
+	size = 0; // avoid gcc warning
+	map = (void *)-1;
+	if (!fstat(fd, &st)) {
+		size = st.st_size;
+		errno = EINVAL;
+		if (size >= sizeof(struct cache_header))
+			map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+	}
+	close(fd);
+	if (-1 == (int)(long)map)
+		return error("mmap failed");
+
+	hdr = map;
+	if (verify_hdr(hdr, size) < 0)
+		goto unmap;
+
+	active_nr = hdr->entries;
+	active_alloc = alloc_nr(active_nr);
+	active_cache = calloc(active_alloc, sizeof(struct cache_entry *));
+
+	offset = sizeof(*hdr);
+	for (i = 0; i < hdr->entries; i++) {
+		struct cache_entry *ce = map + offset;
+		offset = offset + ce_size(ce);
+		active_cache[i] = ce;
+	}
+	return active_nr;
+
+unmap:
+	munmap(map, size);
+	errno = EINVAL;
+	return error("verify header failed");
+}
+
+int write_cache(int newfd, struct cache_entry **cache, int entries)
+{
+	SHA_CTX c;
+	struct cache_header hdr;
+	int i;
+
+	hdr.signature = CACHE_SIGNATURE;
+	hdr.version = 1;
+	hdr.entries = entries;
+
+	SHA1_Init(&c);
+	SHA1_Update(&c, &hdr, offsetof(struct cache_header, sha1));
+	for (i = 0; i < entries; i++) {
+		struct cache_entry *ce = cache[i];
+		int size = ce_size(ce);
+		SHA1_Update(&c, ce, size);
+	}
+	SHA1_Final(hdr.sha1, &c);
+
+	if (write(newfd, &hdr, sizeof(hdr)) != sizeof(hdr))
+		return -1;
+
+	for (i = 0; i < entries; i++) {
+		struct cache_entry *ce = cache[i];
+		int size = ce_size(ce);
+		if (write(newfd, ce, size) != size)
+			return -1;
+	}
+	return 0;
+}
Index: cache.h
===================================================================
--- 783978eb212c1402ba2612bb32626e93af78b72d/cache.h  (mode:100644 sha1:d3e9a21b7d9a2ac32abacf5cc40ee1a4d83f9fe8)
+++ e8194c62bfc68725972a6847fa2c6d529ca64137/cache.h  (mode:100644 sha1:e3302b454e5d55d4d7bd46bbfe870cb34733ce46)
@@ -14,6 +14,9 @@
 #include <openssl/sha.h>
 #include <zlib.h>
 
+#include "util.h"
+#include "objects.h"
+
 /*
  * Basic data structures for the directory cache
  *
@@ -59,13 +62,9 @@
 	char name[0];
 };
 
-const char *sha1_file_directory;
 struct cache_entry **active_cache;
 unsigned int active_nr, active_alloc;
 
-#define DB_ENVIRONMENT "SHA1_FILE_DIRECTORY"
-#define DEFAULT_DB_ENVIRONMENT ".git/objects"
-
 #define cache_entry_size(len) ((offsetof(struct cache_entry,name) + (len) + 8) & ~7)
 #define ce_size(ce) cache_entry_size((ce)->namelen)
 
@@ -74,7 +73,10 @@
 /* Initialize and use the cache information */
 extern int read_cache(void);
 extern int write_cache(int newfd, struct cache_entry **cache, int entries);
+
+/* Returns the location of the given name in the cache. */
 extern int cache_name_pos(const char *name, int namelen);
+
 extern int add_cache_entry(struct cache_entry *ce, int ok_to_add);
 extern int remove_file_from_cache(char *path);
 extern int cache_match_stat(struct cache_entry *ce, struct stat *st);
@@ -86,28 +88,7 @@
 #define INODE_CHANGED   0x0010
 #define DATA_CHANGED    0x0020
 
-/* Return a statically allocated filename matching the sha1 signature */
-extern char *sha1_file_name(const unsigned char *sha1);
-
-/* Write a memory buffer out to the sha file */
-extern int write_sha1_buffer(const unsigned char *sha1, void *buf, unsigned int size);
-
-/* Read and unpack a sha1 file into memory, write memory to a sha1 file */
-extern void * map_sha1_file(const unsigned char *sha1, unsigned long *size);
-extern void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size);
-extern void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size);
-extern int write_sha1_file(char *buf, unsigned len, unsigned char *return_sha1);
-extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size);
-
-/* Convert to/from hex/sha1 representation */
-extern int get_sha1_hex(const char *hex, unsigned char *sha1);
-extern char *sha1_to_hex(const unsigned char *sha1);	/* static buffer result! */
-
-/* General helper functions */
-extern void usage(const char *err);
-extern void die(const char *err, ...);
-extern int error(const char *err, ...);
-
-extern int cache_name_compare(const char *name1, int len1, const char *name2, int len2);
+extern int cache_name_compare(const char *name1, int len1, 
+			      const char *name2, int len2);
 
 #endif /* CACHE_H */
Index: objects.c
===================================================================
--- /dev/null  (tree:783978eb212c1402ba2612bb32626e93af78b72d)
+++ e8194c62bfc68725972a6847fa2c6d529ca64137/objects.c  (mode:100644 sha1:ee0aed670a76e0af9e4150c93915dad53a198ba5)
@@ -0,0 +1,240 @@
+/*
+ * GIT - The information manager from hell
+ *
+ * Copyright (C) Linus Torvalds, 2005
+ */
+#include <stdarg.h>
+#include "cache.h"
+#include "objects.h"
+#include <openssl/sha.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <zlib.h>
+
+
+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;
+}
+
+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;
+}
+
+/*
+ * 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.
+ */
+char *sha1_file_name(const unsigned char *sha1)
+{
+	int i;
+	static char *name, *base;
+
+	if (!base) {
+		char *sha1_file_directory = getenv(DB_ENVIRONMENT) ? : DEFAULT_DB_ENVIRONMENT;
+		int len = strlen(sha1_file_directory);
+		base = malloc(len + 60);
+		memcpy(base, sha1_file_directory, len);
+		memset(base+len, 0, 60);
+		base[len] = '/';
+		base[len+3] = '/';
+		name = base + len + 1;
+	}
+	for (i = 0; i < 20; i++) {
+		static char hex[] = "0123456789abcdef";
+		unsigned int val = sha1[i];
+		char *pos = name + i*2 + (i > 0);
+		*pos++ = hex[val >> 4];
+		*pos = hex[val & 0xf];
+	}
+	return base;
+}
+
+int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long size)
+{
+	unsigned char real_sha1[20];
+	SHA_CTX c;
+
+	SHA1_Init(&c);
+	SHA1_Update(&c, map, size);
+	SHA1_Final(real_sha1, &c);
+	return memcmp(sha1, real_sha1, 20) ? -1 : 0;
+}
+
+void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
+{
+	char *filename = sha1_file_name(sha1);
+	int fd = open(filename, O_RDONLY);
+	struct stat st;
+	void *map;
+
+	if (fd < 0) {
+		perror(filename);
+		return NULL;
+	}
+	if (fstat(fd, &st) < 0) {
+		close(fd);
+		return NULL;
+	}
+	map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+	close(fd);
+	if (-1 == (int)(long)map)
+		return NULL;
+	*size = st.st_size;
+	return map;
+}
+
+void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size)
+{
+	int ret, bytes;
+	z_stream stream;
+	char buffer[8192];
+	char *buf;
+
+	/* Get the data stream */
+	memset(&stream, 0, sizeof(stream));
+	stream.next_in = map;
+	stream.avail_in = mapsize;
+	stream.next_out = buffer;
+	stream.avail_out = sizeof(buffer);
+
+	inflateInit(&stream);
+	ret = inflate(&stream, 0);
+	if (sscanf(buffer, "%10s %lu", type, size) != 2)
+		return NULL;
+
+	bytes = strlen(buffer) + 1;
+	buf = malloc(*size);
+	if (!buf)
+		return NULL;
+
+	memcpy(buf, buffer + bytes, stream.total_out - bytes);
+	bytes = stream.total_out - bytes;
+	if (bytes < *size && ret == Z_OK) {
+		stream.next_out = buf + bytes;
+		stream.avail_out = *size - bytes;
+		while (inflate(&stream, Z_FINISH) == Z_OK)
+			/* nothing */;
+	}
+	inflateEnd(&stream);
+	return buf;
+}
+
+void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)
+{
+	unsigned long mapsize;
+	void *map, *buf;
+
+	map = map_sha1_file(sha1, &mapsize);
+	if (map) {
+		buf = unpack_sha1_file(map, mapsize, type, size);
+		munmap(map, mapsize);
+		return buf;
+	}
+	return NULL;
+}
+
+int write_sha1_file(char *buf, unsigned len, unsigned char *returnsha1)
+{
+	int size;
+	char *compressed;
+	z_stream stream;
+	unsigned char sha1[20];
+	SHA_CTX c;
+
+	/* Set it up */
+	memset(&stream, 0, sizeof(stream));
+	deflateInit(&stream, Z_BEST_COMPRESSION);
+	size = deflateBound(&stream, len);
+	compressed = malloc(size);
+
+	/* Compress it */
+	stream.next_in = buf;
+	stream.avail_in = len;
+	stream.next_out = compressed;
+	stream.avail_out = size;
+	while (deflate(&stream, Z_FINISH) == Z_OK)
+		/* nothing */;
+	deflateEnd(&stream);
+	size = stream.total_out;
+
+	/* Sha1.. */
+	SHA1_Init(&c);
+	SHA1_Update(&c, compressed, size);
+	SHA1_Final(sha1, &c);
+
+	if (write_sha1_buffer(sha1, compressed, size) < 0)
+		return -1;
+	if (returnsha1)
+		memcpy(returnsha1, sha1, 20);
+	return 0;
+}
+
+int write_sha1_buffer(const unsigned char *sha1, void *buf, unsigned int size)
+{
+	char *filename = sha1_file_name(sha1);
+	int fd;
+
+	fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
+	if (fd < 0) {
+		void *map;
+
+		if (errno != EEXIST)
+			return -1;
+		/* #define NO_COLLISION_CHECK to possibly speed things up,
+		 * but the speedup should be really negligible. */
+#ifndef NO_COLLISION_CHECK
+		fd = open(filename, O_RDONLY);
+		if (fd < 0)
+			return -1;
+		map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+		if (map == MAP_FAILED)
+			return -1;
+		if (memcmp(buf, map, size))
+			return error("SHA1 collision detected!"
+					" This is bad, bad, BAD!\a\n");
+#endif
+		return 0;
+	}
+	write(fd, buf, size);
+	close(fd);
+	return 0;
+}
Index: objects.h
===================================================================
--- /dev/null  (tree:783978eb212c1402ba2612bb32626e93af78b72d)
+++ e8194c62bfc68725972a6847fa2c6d529ca64137/objects.h  (mode:100644 sha1:b6469e3e2ef191b36a23da23cbb8bf70ad54da0e)
@@ -0,0 +1,43 @@
+#ifndef OBJECTS_H
+#define OBJECTS_H
+
+/* Operations on the object database. */
+const char *sha1_file_directory;
+
+#define DB_ENVIRONMENT "SHA1_FILE_DIRECTORY"
+#define DEFAULT_DB_ENVIRONMENT ".git/objects"
+
+/* Takes a key and returns the contents, and sets *type to its type
+ * and size to its size.  
+ */
+extern void * read_sha1_file(const unsigned char *sha1, char *type,
+			     unsigned long *size);
+
+/* Writes the given data and length to a file, and returns the key. */
+extern int write_sha1_file(char *buf, unsigned len, 
+			   unsigned char *return_sha1);
+
+/* mmap the given file, and put its size in *size. */
+extern void * map_sha1_file(const unsigned char *sha1, unsigned long *size);
+
+/* Given a map, its size, and its expected type, return its contents and set
+ * *size to the size of the contents. 
+ */
+extern void * unpack_sha1_file(void *map, unsigned long mapsize, char *type,
+			       unsigned long *size);
+
+/* Return a statically allocated filename matching the sha1 signature */
+extern char *sha1_file_name(const unsigned char *sha1);
+
+/* Write a memory buffer out to the sha file */
+extern int write_sha1_buffer(const unsigned char *sha1, void *buf, 
+			     unsigned int size);
+/* compares the given buffer against its expected sha1 hash. */
+extern int check_sha1_signature(const unsigned char *sha1, void *buf, 
+				unsigned long size);
+
+/* Convert to/from hex/sha1 representation */
+extern int get_sha1_hex(const char *hex, unsigned char *sha1);
+extern char * sha1_to_hex(const unsigned char *sha1); /* static buffer ret! */
+
+#endif /* OBJECTS_H */
Index: read-cache.c
===================================================================
--- 783978eb212c1402ba2612bb32626e93af78b72d/read-cache.c  (mode:100644 sha1:7cdd0f82992789e64f6ea272e43ee4af8cdf7f2a)
+++ /dev/null  (tree:e8194c62bfc68725972a6847fa2c6d529ca64137)
@@ -1,478 +0,0 @@
-/*
- * GIT - The information manager from hell
- *
- * Copyright (C) Linus Torvalds, 2005
- */
-#include <stdarg.h>
-#include "cache.h"
-
-const char *sha1_file_directory = NULL;
-struct cache_entry **active_cache = NULL;
-unsigned int active_nr = 0, active_alloc = 0;
-
-void usage(const char *err)
-{
-	fprintf(stderr, "usage: %s\n", err);
-	exit(1);
-}
-
-static void report(const char *prefix, const char *err, va_list params)
-{
-	fputs(prefix, stderr);
-	vfprintf(stderr, err, params);
-	fputs("\n", stderr);
-}
-
-void die(const char *err, ...)
-{
-	va_list params;
-
-	va_start(params, err);
-	report("fatal: ", err, params);
-	va_end(params);
-	exit(1);
-}
-
-int error(const char *err, ...)
-{
-	va_list params;
-
-	va_start(params, err);
-	report("error: ", err, params);
-	va_end(params);
-	return -1;
-}
-
-
-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;
-}
-
-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;
-}
-
-/*
- * 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.
- */
-char *sha1_file_name(const unsigned char *sha1)
-{
-	int i;
-	static char *name, *base;
-
-	if (!base) {
-		char *sha1_file_directory = getenv(DB_ENVIRONMENT) ? : DEFAULT_DB_ENVIRONMENT;
-		int len = strlen(sha1_file_directory);
-		base = malloc(len + 60);
-		memcpy(base, sha1_file_directory, len);
-		memset(base+len, 0, 60);
-		base[len] = '/';
-		base[len+3] = '/';
-		name = base + len + 1;
-	}
-	for (i = 0; i < 20; i++) {
-		static char hex[] = "0123456789abcdef";
-		unsigned int val = sha1[i];
-		char *pos = name + i*2 + (i > 0);
-		*pos++ = hex[val >> 4];
-		*pos = hex[val & 0xf];
-	}
-	return base;
-}
-
-int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long size)
-{
-	unsigned char real_sha1[20];
-	SHA_CTX c;
-
-	SHA1_Init(&c);
-	SHA1_Update(&c, map, size);
-	SHA1_Final(real_sha1, &c);
-	return memcmp(sha1, real_sha1, 20) ? -1 : 0;
-}
-
-void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
-{
-	char *filename = sha1_file_name(sha1);
-	int fd = open(filename, O_RDONLY);
-	struct stat st;
-	void *map;
-
-	if (fd < 0) {
-		perror(filename);
-		return NULL;
-	}
-	if (fstat(fd, &st) < 0) {
-		close(fd);
-		return NULL;
-	}
-	map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
-	close(fd);
-	if (-1 == (int)(long)map)
-		return NULL;
-	*size = st.st_size;
-	return map;
-}
-
-void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size)
-{
-	int ret, bytes;
-	z_stream stream;
-	char buffer[8192];
-	char *buf;
-
-	/* Get the data stream */
-	memset(&stream, 0, sizeof(stream));
-	stream.next_in = map;
-	stream.avail_in = mapsize;
-	stream.next_out = buffer;
-	stream.avail_out = sizeof(buffer);
-
-	inflateInit(&stream);
-	ret = inflate(&stream, 0);
-	if (sscanf(buffer, "%10s %lu", type, size) != 2)
-		return NULL;
-
-	bytes = strlen(buffer) + 1;
-	buf = malloc(*size);
-	if (!buf)
-		return NULL;
-
-	memcpy(buf, buffer + bytes, stream.total_out - bytes);
-	bytes = stream.total_out - bytes;
-	if (bytes < *size && ret == Z_OK) {
-		stream.next_out = buf + bytes;
-		stream.avail_out = *size - bytes;
-		while (inflate(&stream, Z_FINISH) == Z_OK)
-			/* nothing */;
-	}
-	inflateEnd(&stream);
-	return buf;
-}
-
-void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)
-{
-	unsigned long mapsize;
-	void *map, *buf;
-
-	map = map_sha1_file(sha1, &mapsize);
-	if (map) {
-		buf = unpack_sha1_file(map, mapsize, type, size);
-		munmap(map, mapsize);
-		return buf;
-	}
-	return NULL;
-}
-
-int write_sha1_file(char *buf, unsigned len, unsigned char *returnsha1)
-{
-	int size;
-	char *compressed;
-	z_stream stream;
-	unsigned char sha1[20];
-	SHA_CTX c;
-
-	/* Set it up */
-	memset(&stream, 0, sizeof(stream));
-	deflateInit(&stream, Z_BEST_COMPRESSION);
-	size = deflateBound(&stream, len);
-	compressed = malloc(size);
-
-	/* Compress it */
-	stream.next_in = buf;
-	stream.avail_in = len;
-	stream.next_out = compressed;
-	stream.avail_out = size;
-	while (deflate(&stream, Z_FINISH) == Z_OK)
-		/* nothing */;
-	deflateEnd(&stream);
-	size = stream.total_out;
-
-	/* Sha1.. */
-	SHA1_Init(&c);
-	SHA1_Update(&c, compressed, size);
-	SHA1_Final(sha1, &c);
-
-	if (write_sha1_buffer(sha1, compressed, size) < 0)
-		return -1;
-	if (returnsha1)
-		memcpy(returnsha1, sha1, 20);
-	return 0;
-}
-
-int write_sha1_buffer(const unsigned char *sha1, void *buf, unsigned int size)
-{
-	char *filename = sha1_file_name(sha1);
-	int fd;
-
-	fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
-	if (fd < 0) {
-		void *map;
-
-		if (errno != EEXIST)
-			return -1;
-		/* #define NO_COLLISION_CHECK to possibly speed things up,
-		 * but the speedup should be really negligible. */
-#ifndef NO_COLLISION_CHECK
-		fd = open(filename, O_RDONLY);
-		if (fd < 0)
-			return -1;
-		map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
-		if (map == MAP_FAILED)
-			return -1;
-		if (memcmp(buf, map, size))
-			return error("SHA1 collision detected!"
-					" This is bad, bad, BAD!\a\n");
-#endif
-		return 0;
-	}
-	write(fd, buf, size);
-	close(fd);
-	return 0;
-}
-
-int cache_match_stat(struct cache_entry *ce, struct stat *st)
-{
-	unsigned int changed = 0;
-
-	/* nsec seems unreliable - not all filesystems support it, so
-	 * as long as it is in the inode cache you get right nsec
-	 * but after it gets flushed, you get zero nsec. */
-	if (ce->mtime.sec  != (unsigned int)st->st_mtim.tv_sec
-#ifdef NSEC
-	    || ce->mtime.nsec != (unsigned int)st->st_mtim.tv_nsec
-#endif
-	    )
-		changed |= MTIME_CHANGED;
-	if (ce->ctime.sec  != (unsigned int)st->st_ctim.tv_sec
-#ifdef NSEC
-	    || ce->ctime.nsec != (unsigned int)st->st_ctim.tv_nsec
-#endif
-	    )
-		changed |= CTIME_CHANGED;
-	if (ce->st_uid != (unsigned int)st->st_uid ||
-	    ce->st_gid != (unsigned int)st->st_gid)
-		changed |= OWNER_CHANGED;
-	if (ce->st_mode != (unsigned int)st->st_mode)
-		changed |= MODE_CHANGED;
-	if (ce->st_dev != (unsigned int)st->st_dev ||
-	    ce->st_ino != (unsigned int)st->st_ino)
-		changed |= INODE_CHANGED;
-	if (ce->st_size != (unsigned int)st->st_size)
-		changed |= DATA_CHANGED;
-	return changed;
-}
-
-int cache_name_compare(const char *name1, int len1, const char *name2, int len2)
-{
-	int len = len1 < len2 ? len1 : len2;
-	int cmp;
-
-	cmp = memcmp(name1, name2, len);
-	if (cmp)
-		return cmp;
-	if (len1 < len2)
-		return -1;
-	if (len1 > len2)
-		return 1;
-	return 0;
-}
-
-int cache_name_pos(const char *name, int namelen)
-{
-	int first, last;
-
-	first = 0;
-	last = active_nr;
-	while (last > first) {
-		int next = (last + first) >> 1;
-		struct cache_entry *ce = active_cache[next];
-		int cmp = cache_name_compare(name, namelen, ce->name, ce->namelen);
-		if (!cmp)
-			return next;
-		if (cmp < 0) {
-			last = next;
-			continue;
-		}
-		first = next+1;
-	}
-	return -first-1;
-}
-
-int remove_file_from_cache(char *path)
-{
-	int pos = cache_name_pos(path, strlen(path));
-	if (pos >= 0) {
-		active_nr--;
-		if (pos < active_nr)
-			memmove(active_cache + pos, active_cache + pos + 1, (active_nr - pos) * sizeof(struct cache_entry *));
-	}
-	return 0;
-}
-
-int add_cache_entry(struct cache_entry *ce, int ok_to_add)
-{
-	int pos;
-
-	pos = cache_name_pos(ce->name, ce->namelen);
-
-	/* existing match? Just replace it */
-	if (pos >= 0) {
-		active_cache[pos] = ce;
-		return 0;
-	}
-	pos = -pos-1;
-
-	if (!ok_to_add)
-		return -1;
-
-	/* Make sure the array is big enough .. */
-	if (active_nr == active_alloc) {
-		active_alloc = alloc_nr(active_alloc);
-		active_cache = realloc(active_cache, active_alloc * sizeof(struct cache_entry *));
-	}
-
-	/* Add it in.. */
-	active_nr++;
-	if (active_nr > pos)
-		memmove(active_cache + pos + 1, active_cache + pos, (active_nr - pos - 1) * sizeof(ce));
-	active_cache[pos] = ce;
-	return 0;
-}
-
-static int verify_hdr(struct cache_header *hdr, unsigned long size)
-{
-	SHA_CTX c;
-	unsigned char sha1[20];
-
-	if (hdr->signature != CACHE_SIGNATURE)
-		return error("bad signature");
-	if (hdr->version != 1)
-		return error("bad version");
-	SHA1_Init(&c);
-	SHA1_Update(&c, hdr, offsetof(struct cache_header, sha1));
-	SHA1_Update(&c, hdr+1, size - sizeof(*hdr));
-	SHA1_Final(sha1, &c);
-	if (memcmp(sha1, hdr->sha1, 20))
-		return error("bad header sha1");
-	return 0;
-}
-
-int read_cache(void)
-{
-	int fd, i;
-	struct stat st;
-	unsigned long size, offset;
-	void *map;
-	struct cache_header *hdr;
-
-	errno = EBUSY;
-	if (active_cache)
-		return error("more than one cachefile");
-	errno = ENOENT;
-	sha1_file_directory = getenv(DB_ENVIRONMENT);
-	if (!sha1_file_directory)
-		sha1_file_directory = DEFAULT_DB_ENVIRONMENT;
-	if (access(sha1_file_directory, X_OK) < 0)
-		return error("no access to SHA1 file directory");
-	fd = open(".git/index", O_RDONLY);
-	if (fd < 0)
-		return (errno == ENOENT) ? 0 : error("open failed");
-
-	size = 0; // avoid gcc warning
-	map = (void *)-1;
-	if (!fstat(fd, &st)) {
-		size = st.st_size;
-		errno = EINVAL;
-		if (size >= sizeof(struct cache_header))
-			map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
-	}
-	close(fd);
-	if (-1 == (int)(long)map)
-		return error("mmap failed");
-
-	hdr = map;
-	if (verify_hdr(hdr, size) < 0)
-		goto unmap;
-
-	active_nr = hdr->entries;
-	active_alloc = alloc_nr(active_nr);
-	active_cache = calloc(active_alloc, sizeof(struct cache_entry *));
-
-	offset = sizeof(*hdr);
-	for (i = 0; i < hdr->entries; i++) {
-		struct cache_entry *ce = map + offset;
-		offset = offset + ce_size(ce);
-		active_cache[i] = ce;
-	}
-	return active_nr;
-
-unmap:
-	munmap(map, size);
-	errno = EINVAL;
-	return error("verify header failed");
-}
-
-int write_cache(int newfd, struct cache_entry **cache, int entries)
-{
-	SHA_CTX c;
-	struct cache_header hdr;
-	int i;
-
-	hdr.signature = CACHE_SIGNATURE;
-	hdr.version = 1;
-	hdr.entries = entries;
-
-	SHA1_Init(&c);
-	SHA1_Update(&c, &hdr, offsetof(struct cache_header, sha1));
-	for (i = 0; i < entries; i++) {
-		struct cache_entry *ce = cache[i];
-		int size = ce_size(ce);
-		SHA1_Update(&c, ce, size);
-	}
-	SHA1_Final(hdr.sha1, &c);
-
-	if (write(newfd, &hdr, sizeof(hdr)) != sizeof(hdr))
-		return -1;
-
-	for (i = 0; i < entries; i++) {
-		struct cache_entry *ce = cache[i];
-		int size = ce_size(ce);
-		if (write(newfd, ce, size) != size)
-			return -1;
-	}
-	return 0;
-}
Index: util.h
===================================================================
--- /dev/null  (tree:783978eb212c1402ba2612bb32626e93af78b72d)
+++ e8194c62bfc68725972a6847fa2c6d529ca64137/util.h  (mode:100644 sha1:d81ccd0b3363ff2a883e8d9e543af043728fd32a)
@@ -0,0 +1,9 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+/* General helper functions */
+extern void usage(const char *err);
+extern void die(const char *err, ...);
+extern int error(const char *err, ...);
+
+#endif
Previous: Daniel BarkalowNext: Daniel Barkalow
Message 3 of 5 in “Various cleanups”
  1. Daniel BarkalowApr 13, 2005
  2. Clean up MakefileDaniel Barkalow, Apr 13, 2005
  3. Reorganize common codeDaniel Barkalow, Apr 13, 2005
  4. Daniel BarkalowApr 14, 2005
  5. Petr BaudisApr 14, 2005

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.