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 int sha1flush(struct sha1file *f, unsigned int count)14{15void *buf = f->buffer;1617for (;;) {18int ret = write(f->fd, buf, count);19if (ret > 0) {20buf += ret;21count -= ret;22if (count)23continue;24return 0;25}26if (!ret)27die("sha1 file '%s' write error. Out of diskspace", f->name);28if (errno == EAGAIN || errno == EINTR)29continue;30die("sha1 file '%s' write error (%s)", f->name, strerror(errno));31}32}3334int sha1close(struct sha1file *f, unsigned char *result, int update)35{36unsigned offset = f->offset;37if (offset) {38SHA1_Update(&f->ctx, f->buffer, offset);39sha1flush(f, offset);40}41SHA1_Final(f->buffer, &f->ctx);42if (result)43memcpy(result, f->buffer, 20);44if (update)45sha1flush(f, 20);46if (close(f->fd))47die("%s: sha1 file error on close (%s)", f->name, strerror(errno));48return 0;49}5051int sha1write(struct sha1file *f, void *buf, unsigned int count)52{53while (count) {54unsigned offset = f->offset;55unsigned left = sizeof(f->buffer) - offset;56unsigned nr = count > left ? left : count;5758memcpy(f->buffer + offset, buf, nr);59count -= nr;60offset += nr;61buf += nr;62left -= nr;63if (!left) {64SHA1_Update(&f->ctx, f->buffer, offset);65sha1flush(f, offset);66offset = 0;67}68f->offset = offset;69}70return 0;71}7273struct sha1file *sha1create(const char *fmt, ...)74{75struct sha1file *f;76unsigned len;77va_list arg;78int fd;7980f = xmalloc(sizeof(*f));8182va_start(arg, fmt);83len = vsnprintf(f->name, sizeof(f->name), fmt, arg);84va_end(arg);85if (len >= PATH_MAX)86die("you wascally wabbit, you");87f->namelen = len;8889fd = open(f->name, O_CREAT | O_EXCL | O_WRONLY, 0644);90if (fd < 0)91die("unable to open %s (%s)", f->name, strerror(errno));92f->fd = fd;93f->error = 0;94f->offset = 0;95SHA1_Init(&f->ctx);96return f;97}9899struct sha1file *sha1fd(int fd, const char *name)100{101struct sha1file *f;102unsigned len;103104f = xmalloc(sizeof(*f));105106len = strlen(name);107if (len >= PATH_MAX)108die("you wascally wabbit, you");109f->namelen = len;110memcpy(f->name, name, len+1);111112f->fd = fd;113f->error = 0;114f->offset = 0;115SHA1_Init(&f->ctx);116return f;117}118119int sha1write_compressed(struct sha1file *f, void *in, unsigned int size)120{121z_stream stream;122unsigned long maxsize;123void *out;124125memset(&stream, 0, sizeof(stream));126deflateInit(&stream, Z_DEFAULT_COMPRESSION);127maxsize = deflateBound(&stream, size);128out = xmalloc(maxsize);129130/* Compress it */131stream.next_in = in;132stream.avail_in = size;133134stream.next_out = out;135stream.avail_out = maxsize;136137while (deflate(&stream, Z_FINISH) == Z_OK)138/* nothing */;139deflateEnd(&stream);140141size = stream.total_out;142sha1write(f, out, size);143free(out);144return size;145}146147