csum-file interface updates: return resulting SHA1
authorLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 27 Jun 2005 05:01:46 +0000 (22:01 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 27 Jun 2005 05:01:46 +0000 (22:01 -0700)
Also, make the writing of the SHA1 as a end-header be conditional: not
every user will necessarily want to write the SHA1 to the file itself,
even though current users do (but we migh end up using the same helper
functions for the object files themselves, that don't do this).

This also makes the packed index file contain the SHA1 of the packed
data file at the end (just before its own SHA1).  That way you can
validate the pairing of the two if you want to.

csum-file.c
csum-file.h
pack-objects.c
unpack-objects.c

index 98cb59ddda86386a4255f3c3d8ee951a415d7d70..9f9553ae035e762d12dc7d885432abd920af6e5b 100644 (file)
@@ -24,14 +24,14 @@ static int sha1flush(struct sha1file *f, unsigned int count)
                        return 0;
                }
                if (!ret)
-                       die("sha1 file write error. Out of diskspace");
+                       die("sha1 file '%s' write error. Out of diskspace", f->name);
                if (errno == EAGAIN || errno == EINTR)
                        continue;
-               die("sha1 file write error (%s)", strerror(errno));
+               die("sha1 file '%s' write error (%s)", f->name, strerror(errno));
        }
 }
 
-int sha1close(struct sha1file *f)
+int sha1close(struct sha1file *f, unsigned char *result, int update)
 {
        unsigned offset = f->offset;
        if (offset) {
@@ -39,7 +39,12 @@ int sha1close(struct sha1file *f)
                sha1flush(f, offset);
        }
        SHA1_Final(f->buffer, &f->ctx);
-       sha1flush(f, 20);
+       if (result)
+               memcpy(result, f->buffer, 20);
+       if (update)
+               sha1flush(f, 20);
+       if (close(f->fd))
+               die("%s: sha1 file error on close (%s)", f->name, strerror(errno));
        return 0;
 }
 
@@ -66,22 +71,23 @@ int sha1write(struct sha1file *f, void *buf, unsigned int count)
 
 struct sha1file *sha1create(const char *fmt, ...)
 {
-       static char filename[PATH_MAX];
        struct sha1file *f;
        unsigned len;
        va_list arg;
        int fd;
 
+       f = xmalloc(sizeof(*f));
+
        va_start(arg, fmt);
-       len = vsnprintf(filename, PATH_MAX, fmt, arg);
+       len = vsnprintf(f->name, sizeof(f->name), fmt, arg);
        va_end(arg);
-
        if (len >= PATH_MAX)
                die("you wascally wabbit, you");
-       fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
+       f->namelen = len;
+
+       fd = open(f->name, O_CREAT | O_EXCL | O_WRONLY, 0644);
        if (fd < 0)
-               die("unable to open %s (%s)", filename, strerror(errno));
-       f = xmalloc(sizeof(*f));
+               die("unable to open %s (%s)", f->name, strerror(errno));
        f->fd = fd;
        f->error = 0;
        f->offset = 0;
index 1086f04caa228f044cdce0b5f0f63edfbc3bed79..2b6c8dcad25c29ddd13742e9904c54b97286bc0a 100644 (file)
@@ -4,13 +4,14 @@
 /* A SHA1-protected file */
 struct sha1file {
        int fd, error;
-       unsigned long offset;
+       unsigned int offset, namelen;
        SHA_CTX ctx;
+       char name[PATH_MAX];
        unsigned char buffer[8192];
 };
 
 extern struct sha1file *sha1create(const char *fmt, ...);
-extern int sha1close(struct sha1file *);
+extern int sha1close(struct sha1file *, unsigned char *, int);
 extern int sha1write(struct sha1file *, void *, unsigned int);
 extern int sha1write_compressed(struct sha1file *, void *, unsigned int);
 
index f0c84c9a746a3dcf1e3427d33310d2cdaf0bf69a..3fe3b05d51e7960d978a9efb765cfcd8d8a43009 100644 (file)
@@ -29,6 +29,7 @@ static struct object_entry **sorted_by_sha, **sorted_by_type;
 static struct object_entry *objects = NULL;
 static int nr_objects = 0, nr_alloc = 0;
 static const char *base_name;
+static unsigned char pack_file_sha1[20];
 
 static void *delta_against(void *buf, unsigned long size, struct object_entry *entry)
 {
@@ -95,7 +96,7 @@ static void write_pack_file(void)
                entry->offset = offset;
                offset += write_object(f, entry);
        }
-       sha1close(f);
+       sha1close(f, pack_file_sha1, 1);
        mb = offset >> 20;
        offset &= 0xfffff;
 }
@@ -111,7 +112,7 @@ static void write_index_file(void)
        /*
         * Write the first-level table (the list is sorted,
         * but we use a 256-entry lookup to be able to avoid
-        * having to do eight extra binary search iterations)
+        * having to do eight extra binary search iterations).
         */
        for (i = 0; i < 256; i++) {
                struct object_entry **next = list;
@@ -136,7 +137,8 @@ static void write_index_file(void)
                sha1write(f, &offset, 4);
                sha1write(f, entry->sha1, 20);
        }
-       sha1close(f);
+       sha1write(f, pack_file_sha1, 20);
+       sha1close(f, NULL, 1);
 }
 
 static void add_object_entry(unsigned char *sha1, unsigned int hash)
index 91a71c55c6bb720c7fbe3d1d2bd393d5d22f764f..a792b92ece0770e5c2305b26d70eb26ee51d26c7 100644 (file)
@@ -74,9 +74,10 @@ static int check_index(void)
         * 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 (index_size != 4*256 + nr * 24 + 20)
+       if (index_size != 4*256 + nr * 24 + 20 + 20)
                return error("wrong index file size");
 
        nr_entries = nr;