static int write_cache(int newfd, struct cache_entry **cache, int entries) { SHA_CTX c; struct cache_header hdr; int i; hdr.signature = CACHE_SIGNATURE; hdr.version = 1; hdr.entries = entries; SHA1_Init(&c); SHA1_Update(&c, &hdr, offsetof(struct cache_header, sha1)); for (i = 0; i < entries; i++) { struct cache_entry *ce = cache[i]; int size = ce_size(ce); SHA1_Update(&c, ce, size); } SHA1_Final(hdr.sha1, &c); if (write(newfd, &hdr, sizeof(hdr)) != sizeof(hdr)) return -1; for (i = 0; i < entries; i++) { struct cache_entry *ce = cache[i]; int size = ce_size(ce); if (write(newfd, ce, size) != size) return -1; } return 0; }
static struct cache_entry *dup_entry(const struct cache_entry *ce) { unsigned int size = ce_size(ce); struct cache_entry *new = xmalloc(size); memcpy(new, ce, size); return new; }
int read_cache(void) { int fd, i; struct stat st; unsigned long size, offset; void *map; struct cache_header *hdr; errno = EBUSY; if (active_cache) return error("more than one cachefile"); errno = ENOENT; sha1_file_directory = getenv(DB_ENVIRONMENT); if (!sha1_file_directory) sha1_file_directory = DEFAULT_DB_ENVIRONMENT; if (access(sha1_file_directory, X_OK) < 0) return error("no access to SHA1 file directory"); fd = open(get_index_file(), O_RDONLY); if (fd < 0) return (errno == ENOENT) ? 0 : error("open failed"); size = 0; // avoid gcc warning map = (void *)-1; if (!fstat(fd, &st)) { size = st.st_size; errno = EINVAL; if (size >= sizeof(struct cache_header) + 20) map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); } close(fd); if (-1 == (int)(long)map) return error("mmap failed"); hdr = map; if (verify_hdr(hdr, size) < 0) goto unmap; active_nr = ntohl(hdr->hdr_entries); active_alloc = alloc_nr(active_nr); active_cache = calloc(active_alloc, sizeof(struct cache_entry *)); offset = sizeof(*hdr); for (i = 0; i < active_nr; i++) { struct cache_entry *ce = map + offset; offset = offset + ce_size(ce); active_cache[i] = ce; } return active_nr; unmap: munmap(map, size); errno = EINVAL; return error("verify header failed"); }
int write_cache(int newfd, struct cache_entry **cache, int entries) { SHA_CTX c; struct cache_header hdr; int i; hdr.hdr_signature = htonl(CACHE_SIGNATURE); hdr.hdr_version = htonl(2); hdr.hdr_entries = htonl(entries); SHA1_Init(&c); if (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0) return -1; for (i = 0; i < entries; i++) { struct cache_entry *ce = cache[i]; if (ce_write(&c, newfd, ce, ce_size(ce)) < 0) return -1; } return ce_flush(&c, newfd); }