csum-file.con commit Teach prune-packed to use the standard progress meter (b5d72f0)
   1/*
   2 * csum-file.c
   3 *
   4 * Copyright (C) 2005 Linus Torvalds
   5 *
   6 * Simple file write infrastructure for writing SHA1-summed
   7 * files. Useful when you write a file that you want to be
   8 * able to verify hasn't been messed with afterwards.
   9 */
  10#include "cache.h"
  11#include "csum-file.h"
  12
  13static void sha1flush(struct sha1file *f, unsigned int count)
  14{
  15        void *buf = f->buffer;
  16
  17        for (;;) {
  18                int ret = xwrite(f->fd, buf, count);
  19                if (ret > 0) {
  20                        buf = (char *) buf + ret;
  21                        count -= ret;
  22                        if (count)
  23                                continue;
  24                        return;
  25                }
  26                if (!ret)
  27                        die("sha1 file '%s' write error. Out of diskspace", f->name);
  28                die("sha1 file '%s' write error (%s)", f->name, strerror(errno));
  29        }
  30}
  31
  32int sha1close(struct sha1file *f, unsigned char *result, int final)
  33{
  34        int fd;
  35        unsigned offset = f->offset;
  36        if (offset) {
  37                SHA1_Update(&f->ctx, f->buffer, offset);
  38                sha1flush(f, offset);
  39                f->offset = 0;
  40        }
  41        if (final) {
  42                /* write checksum and close fd */
  43                SHA1_Final(f->buffer, &f->ctx);
  44                if (result)
  45                        hashcpy(result, f->buffer);
  46                sha1flush(f, 20);
  47                if (close(f->fd))
  48                        die("%s: sha1 file error on close (%s)",
  49                            f->name, strerror(errno));
  50                fd = 0;
  51        } else
  52                fd = f->fd;
  53        free(f);
  54        return fd;
  55}
  56
  57int sha1write(struct sha1file *f, void *buf, unsigned int count)
  58{
  59        if (f->do_crc)
  60                f->crc32 = crc32(f->crc32, buf, count);
  61        while (count) {
  62                unsigned offset = f->offset;
  63                unsigned left = sizeof(f->buffer) - offset;
  64                unsigned nr = count > left ? left : count;
  65
  66                memcpy(f->buffer + offset, buf, nr);
  67                count -= nr;
  68                offset += nr;
  69                buf = (char *) buf + nr;
  70                left -= nr;
  71                if (!left) {
  72                        SHA1_Update(&f->ctx, f->buffer, offset);
  73                        sha1flush(f, offset);
  74                        offset = 0;
  75                }
  76                f->offset = offset;
  77        }
  78        return 0;
  79}
  80
  81struct sha1file *sha1fd(int fd, const char *name)
  82{
  83        struct sha1file *f;
  84        unsigned len;
  85
  86        f = xmalloc(sizeof(*f));
  87
  88        len = strlen(name);
  89        if (len >= PATH_MAX)
  90                die("you wascally wabbit, you");
  91        f->namelen = len;
  92        memcpy(f->name, name, len+1);
  93
  94        f->fd = fd;
  95        f->error = 0;
  96        f->offset = 0;
  97        f->do_crc = 0;
  98        SHA1_Init(&f->ctx);
  99        return f;
 100}
 101
 102void crc32_begin(struct sha1file *f)
 103{
 104        f->crc32 = crc32(0, Z_NULL, 0);
 105        f->do_crc = 1;
 106}
 107
 108uint32_t crc32_end(struct sha1file *f)
 109{
 110        f->do_crc = 0;
 111        return f->crc32;
 112}