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{
34int fd;
35unsigned offset = f->offset;
36if (offset) {
37SHA1_Update(&f->ctx, f->buffer, offset);
38sha1flush(f, offset);
39f->offset = 0;
40}
41if (final) {
42/* write checksum and close fd */
43SHA1_Final(f->buffer, &f->ctx);
44if (result)
45hashcpy(result, f->buffer);
46sha1flush(f, 20);
47if (close(f->fd))
48die("%s: sha1 file error on close (%s)",
49f->name, strerror(errno));
50fd = 0;
51} else
52fd = f->fd;
53free(f);
54return fd;
55}
5657
int sha1write(struct sha1file *f, void *buf, unsigned int count)
58{
59if (f->do_crc)
60f->crc32 = crc32(f->crc32, buf, count);
61while (count) {
62unsigned offset = f->offset;
63unsigned left = sizeof(f->buffer) - offset;
64unsigned nr = count > left ? left : count;
6566
memcpy(f->buffer + offset, buf, nr);
67count -= nr;
68offset += nr;
69buf = (char *) buf + nr;
70left -= nr;
71if (!left) {
72SHA1_Update(&f->ctx, f->buffer, offset);
73sha1flush(f, offset);
74offset = 0;
75}
76f->offset = offset;
77}
78return 0;
79}
8081
struct sha1file *sha1fd(int fd, const char *name)
82{
83struct sha1file *f;
84unsigned len;
8586
f = xmalloc(sizeof(*f));
8788
len = strlen(name);
89if (len >= PATH_MAX)
90die("you wascally wabbit, you");
91f->namelen = len;
92memcpy(f->name, name, len+1);
9394
f->fd = fd;
95f->error = 0;
96f->offset = 0;
97f->do_crc = 0;
98SHA1_Init(&f->ctx);
99return f;
100}
101102
void crc32_begin(struct sha1file *f)
103{
104f->crc32 = crc32(0, Z_NULL, 0);
105f->do_crc = 1;
106}
107108
uint32_t crc32_end(struct sha1file *f)
109{
110f->do_crc = 0;
111return f->crc32;
112}