🌐 AI搜索 & 代理 主页
blob: 4d50cc5ce18c24a1dc853d3050062b864fe0b943 [file] [log] [blame]
Linus Torvaldsc38138c2005-06-27 03:27:561/*
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"
Nicolas Pitre2a128d62007-10-30 21:06:2111#include "progress.h"
Linus Torvaldsc38138c2005-06-27 03:27:5612#include "csum-file.h"
13
Shawn O. Pearcee782e122008-10-10 15:39:2014static void flush(struct sha1file *f, void * buf, unsigned int count)
Linus Torvaldsc38138c2005-06-27 03:27:5615{
Linus Torvaldsc38138c2005-06-27 03:27:5616 for (;;) {
Junio C Hamano1c15afb2005-12-20 00:18:2817 int ret = xwrite(f->fd, buf, count);
Linus Torvaldsc38138c2005-06-27 03:27:5618 if (ret > 0) {
Nicolas Pitre218558a2007-11-05 03:15:4119 f->total += ret;
20 display_throughput(f->tp, f->total);
Florian Forster1d7f1712006-06-18 15:18:0921 buf = (char *) buf + ret;
Linus Torvaldsc38138c2005-06-27 03:27:5622 count -= ret;
23 if (count)
24 continue;
David Rientjes78b713a2006-08-14 20:32:0125 return;
Linus Torvaldsc38138c2005-06-27 03:27:5626 }
27 if (!ret)
Linus Torvaldse1808842005-06-27 05:01:4628 die("sha1 file '%s' write error. Out of diskspace", f->name);
Thomas Rastd824cbb2009-06-27 15:58:4629 die_errno("sha1 file '%s' write error", f->name);
Linus Torvaldsc38138c2005-06-27 03:27:5630 }
31}
32
Nicolas Pitre838cd342008-10-10 02:08:5133void sha1flush(struct sha1file *f)
Linus Torvaldsc38138c2005-06-27 03:27:5634{
35 unsigned offset = f->offset;
Linus Torvalds4c81b032008-05-30 15:42:1636
Linus Torvaldsc38138c2005-06-27 03:27:5637 if (offset) {
Nicolas Pitre9126f002008-10-01 18:05:2038 git_SHA1_Update(&f->ctx, f->buffer, offset);
Shawn O. Pearcee782e122008-10-10 15:39:2039 flush(f, f->buffer, offset);
Dana L. Howf0215362007-05-13 18:28:1940 f->offset = 0;
Linus Torvaldsc38138c2005-06-27 03:27:5641 }
Nicolas Pitre838cd342008-10-10 02:08:5142}
43
44int sha1close(struct sha1file *f, unsigned char *result, unsigned int flags)
45{
46 int fd;
47
48 sha1flush(f);
Nicolas Pitre9126f002008-10-01 18:05:2049 git_SHA1_Final(f->buffer, &f->ctx);
Nicolas Pitreac0463e2008-08-29 20:08:0050 if (result)
51 hashcpy(result, f->buffer);
Linus Torvalds4c81b032008-05-30 15:42:1652 if (flags & (CSUM_CLOSE | CSUM_FSYNC)) {
Nicolas Pitre7ba502c2007-10-17 01:55:4853 /* write checksum and close fd */
Shawn O. Pearcee782e122008-10-10 15:39:2054 flush(f, f->buffer, 20);
Linus Torvalds4c81b032008-05-30 15:42:1655 if (flags & CSUM_FSYNC)
56 fsync_or_die(f->fd, f->name);
Nicolas Pitre7ba502c2007-10-17 01:55:4857 if (close(f->fd))
Thomas Rastd824cbb2009-06-27 15:58:4658 die_errno("%s: sha1 file error on close", f->name);
Nicolas Pitre7ba502c2007-10-17 01:55:4859 fd = 0;
60 } else
61 fd = f->fd;
Sergey Vlasov7bf058f2005-08-08 18:46:1362 free(f);
Nicolas Pitre7ba502c2007-10-17 01:55:4863 return fd;
Linus Torvaldsc38138c2005-06-27 03:27:5664}
65
66int sha1write(struct sha1file *f, void *buf, unsigned int count)
67{
68 while (count) {
69 unsigned offset = f->offset;
70 unsigned left = sizeof(f->buffer) - offset;
71 unsigned nr = count > left ? left : count;
Nicolas Pitrea8032d12008-09-02 14:22:2072 void *data;
Linus Torvaldsc38138c2005-06-27 03:27:5673
Nicolas Pitrea8032d12008-09-02 14:22:2074 if (f->do_crc)
75 f->crc32 = crc32(f->crc32, buf, nr);
76
77 if (nr == sizeof(f->buffer)) {
78 /* process full buffer directly without copy */
79 data = buf;
80 } else {
81 memcpy(f->buffer + offset, buf, nr);
82 data = f->buffer;
83 }
84
Linus Torvaldsc38138c2005-06-27 03:27:5685 count -= nr;
86 offset += nr;
Florian Forster1d7f1712006-06-18 15:18:0987 buf = (char *) buf + nr;
Linus Torvaldsc38138c2005-06-27 03:27:5688 left -= nr;
89 if (!left) {
Nicolas Pitre9126f002008-10-01 18:05:2090 git_SHA1_Update(&f->ctx, data, offset);
Shawn O. Pearcee782e122008-10-10 15:39:2091 flush(f, data, offset);
Linus Torvaldsc38138c2005-06-27 03:27:5692 offset = 0;
93 }
94 f->offset = offset;
95 }
96 return 0;
97}
98
Linus Torvalds4397f012005-06-28 18:10:0699struct sha1file *sha1fd(int fd, const char *name)
100{
Nicolas Pitre2a128d62007-10-30 21:06:21101 return sha1fd_throughput(fd, name, NULL);
102}
103
104struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp)
105{
Nicolas Pitreec640ed2007-11-05 03:54:50106 struct sha1file *f = xmalloc(sizeof(*f));
Linus Torvalds4397f012005-06-28 18:10:06107 f->fd = fd;
Linus Torvalds4397f012005-06-28 18:10:06108 f->offset = 0;
Nicolas Pitre218558a2007-11-05 03:15:41109 f->total = 0;
Nicolas Pitre2a128d62007-10-30 21:06:21110 f->tp = tp;
Nicolas Pitreec640ed2007-11-05 03:54:50111 f->name = name;
Nicolas Pitre78d1e842007-04-09 05:06:31112 f->do_crc = 0;
Nicolas Pitre9126f002008-10-01 18:05:20113 git_SHA1_Init(&f->ctx);
Linus Torvalds4397f012005-06-28 18:10:06114 return f;
115}
116
Nicolas Pitre78d1e842007-04-09 05:06:31117void crc32_begin(struct sha1file *f)
118{
119 f->crc32 = crc32(0, Z_NULL, 0);
120 f->do_crc = 1;
121}
Linus Torvaldsc38138c2005-06-27 03:27:56122
Nicolas Pitre78d1e842007-04-09 05:06:31123uint32_t crc32_end(struct sha1file *f)
124{
125 f->do_crc = 0;
126 return f->crc32;
127}