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"
1213
static void sha1flush(struct sha1file *f, unsigned int count)
14{
15void *buf = f->buffer;
1617
for (;;) {
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}
3132
int 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}
5152
int 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;
6061
memcpy(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}
7576
struct sha1file *sha1fd(int fd, const char *name)
77{
78struct sha1file *f;
79unsigned len;
8081
f = xmalloc(sizeof(*f));
8283
len = strlen(name);
84if (len >= PATH_MAX)
85die("you wascally wabbit, you");
86f->namelen = len;
87memcpy(f->name, name, len+1);
8889
f->fd = fd;
90f->error = 0;
91f->offset = 0;
92f->do_crc = 0;
93SHA1_Init(&f->ctx);
94return f;
95}
9697
void crc32_begin(struct sha1file *f)
98{
99f->crc32 = crc32(0, Z_NULL, 0);
100f->do_crc = 1;
101}
102103
uint32_t crc32_end(struct sha1file *f)
104{
105f->do_crc = 0;
106return f->crc32;
107}