1/*2* csum-file.c3*4* Copyright (C) 2005 Linus Torvalds5*6* Simple file write infrastructure for writing SHA1-summed7* files. Useful when you write a file that you want to be8* able to verify hasn't been messed with afterwards.9*/10#include "cache.h"11#include "csum-file.h"1213static void sha1flush(struct sha1file *f, unsigned int count)14{15void *buf = f->buffer;1617for (;;) {18int ret = xwrite(f->fd, buf, count);19if (ret > 0) {20buf = (char *) buf + ret;21count -= ret;22if (count)23continue;24return;25}26if (!ret)27die("sha1 file '%s' write error. Out of diskspace", f->name);28die("sha1 file '%s' write error (%s)", f->name, strerror(errno));29}30}3132int sha1close(struct sha1file *f, unsigned char *result, int final)33{34unsigned offset = f->offset;35if (offset) {36SHA1_Update(&f->ctx, f->buffer, offset);37sha1flush(f, offset);38f->offset = 0;39}40if (!final)41return 0; /* only want to flush (no checksum write, no close) */42SHA1_Final(f->buffer, &f->ctx);43if (result)44hashcpy(result, f->buffer);45sha1flush(f, 20);46if (close(f->fd))47die("%s: sha1 file error on close (%s)", f->name, strerror(errno));48free(f);49return 0;50}5152int sha1write(struct sha1file *f, void *buf, unsigned int count)53{54if (f->do_crc)55f->crc32 = crc32(f->crc32, buf, count);56while (count) {57unsigned offset = f->offset;58unsigned left = sizeof(f->buffer) - offset;59unsigned nr = count > left ? left : count;6061memcpy(f->buffer + offset, buf, nr);62count -= nr;63offset += nr;64buf = (char *) buf + nr;65left -= nr;66if (!left) {67SHA1_Update(&f->ctx, f->buffer, offset);68sha1flush(f, offset);69offset = 0;70}71f->offset = offset;72}73return 0;74}7576struct sha1file *sha1fd(int fd, const char *name)77{78struct sha1file *f;79unsigned len;8081f = xmalloc(sizeof(*f));8283len = strlen(name);84if (len >= PATH_MAX)85die("you wascally wabbit, you");86f->namelen = len;87memcpy(f->name, name, len+1);8889f->fd = fd;90f->error = 0;91f->offset = 0;92f->do_crc = 0;93SHA1_Init(&f->ctx);94return f;95}9697void crc32_begin(struct sha1file *f)98{99f->crc32 = crc32(0, Z_NULL, 0);100f->do_crc = 1;101}102103uint32_t crc32_end(struct sha1file *f)104{105f->do_crc = 0;106return f->crc32;107}