X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=sha1_file.c;h=b4ff233bad3c15692610f93549b25cd0cf042392;hb=ae448e3854d8b6e7e37aa88fa3917f5dd97f3210;hp=223001033c30eed20d7c5ee59719bffd25036ded;hpb=5c87a8c5602eb09810679dd3e0bcfc7ae1fed111;p=git.git diff --git a/sha1_file.c b/sha1_file.c index 22300103..b4ff233b 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -50,29 +50,6 @@ int get_sha1_hex(const char *hex, unsigned char *sha1) return 0; } -int adjust_shared_perm(const char *path) -{ - struct stat st; - int mode; - - if (!shared_repository) - return 0; - if (lstat(path, &st) < 0) - return -1; - mode = st.st_mode; - if (mode & S_IRUSR) - mode |= S_IRGRP; - if (mode & S_IWUSR) - mode |= S_IWGRP; - if (mode & S_IXUSR) - mode |= S_IXGRP; - if (S_ISDIR(mode)) - mode |= S_ISGID; - if (chmod(path, mode) < 0) - return -2; - return 0; -} - int safe_create_leading_directories(char *path) { char *pos = path; @@ -617,6 +594,12 @@ static void prepare_packed_git_one(char *objdir, int local) /* we have .idx. Is it a file we can map? */ strcpy(path + len, de->d_name); + for (p = packed_git; p; p = p->next) { + if (!memcmp(path, p->pack_name, len + namelen - 4)) + break; + } + if (p) + continue; p = add_packed_git(path, len + namelen, local); if (!p) continue; @@ -626,12 +609,12 @@ static void prepare_packed_git_one(char *objdir, int local) closedir(dir); } +static int prepare_packed_git_run_once = 0; void prepare_packed_git(void) { - static int run_once = 0; struct alternate_object_database *alt; - if (run_once) + if (prepare_packed_git_run_once) return; prepare_packed_git_one(get_object_directory(), 1); prepare_alt_odb(); @@ -640,7 +623,13 @@ void prepare_packed_git(void) prepare_packed_git_one(alt->base, 0); alt->name[-1] = '/'; } - run_once = 1; + prepare_packed_git_run_once = 1; +} + +static void reprepare_packed_git(void) +{ + prepare_packed_git_run_once = 0; + prepare_packed_git(); } int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long size, const char *type) @@ -1212,9 +1201,12 @@ int sha1_object_info(const unsigned char *sha1, char *type, unsigned long *sizep if (!map) { struct pack_entry e; - if (!find_pack_entry(sha1, &e)) - return error("unable to find %s", sha1_to_hex(sha1)); - return packed_object_info(&e, type, sizep); + if (find_pack_entry(sha1, &e)) + return packed_object_info(&e, type, sizep); + reprepare_packed_git(); + if (find_pack_entry(sha1, &e)) + return packed_object_info(&e, type, sizep); + return error("unable to find %s", sha1_to_hex(sha1)); } if (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0) status = error("unable to unpack %s header", @@ -1256,6 +1248,9 @@ void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size munmap(map, mapsize); return buf; } + reprepare_packed_git(); + if (find_pack_entry(sha1, &e)) + return read_packed_sha1(sha1, type, size); return NULL; } @@ -1399,6 +1394,25 @@ int move_temp_to_file(const char *tmpfile, char *filename) return 0; } +static int write_buffer(int fd, const void *buf, size_t len) +{ + while (len) { + ssize_t size; + + size = write(fd, buf, len); + if (!size) + return error("file write: disk full"); + if (size < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + return error("file write error (%s)", strerror(errno)); + } + len -= size; + buf += size; + } + return 0; +} + int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *returnsha1) { int size; @@ -1465,8 +1479,8 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha deflateEnd(&stream); size = stream.total_out; - if (write(fd, compressed, size) != size) - die("unable to write file"); + if (write_buffer(fd, compressed, size) < 0) + die("unable to write sha1 file"); fchmod(fd, 0444); close(fd); free(compressed); @@ -1474,73 +1488,70 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha return move_temp_to_file(tmpfile, filename); } -int write_sha1_to_fd(int fd, const unsigned char *sha1) +/* + * We need to unpack and recompress the object for writing + * it out to a different file. + */ +static void *repack_object(const unsigned char *sha1, unsigned long *objsize) { - ssize_t size; - unsigned long objsize; - int posn = 0; - void *map = map_sha1_file_internal(sha1, &objsize); - void *buf = map; - void *temp_obj = NULL; + size_t size; z_stream stream; + unsigned char *unpacked; + unsigned long len; + char type[20]; + char hdr[50]; + int hdrlen; + void *buf; - if (!buf) { - unsigned char *unpacked; - unsigned long len; - char type[20]; - char hdr[50]; - int hdrlen; - // need to unpack and recompress it by itself - unpacked = read_packed_sha1(sha1, type, &len); + // need to unpack and recompress it by itself + unpacked = read_packed_sha1(sha1, type, &len); - hdrlen = sprintf(hdr, "%s %lu", type, len) + 1; + hdrlen = sprintf(hdr, "%s %lu", type, len) + 1; - /* Set it up */ - memset(&stream, 0, sizeof(stream)); - deflateInit(&stream, Z_BEST_COMPRESSION); - size = deflateBound(&stream, len + hdrlen); - temp_obj = buf = xmalloc(size); - - /* Compress it */ - stream.next_out = buf; - stream.avail_out = size; - - /* First header.. */ - stream.next_in = (void *)hdr; - stream.avail_in = hdrlen; - while (deflate(&stream, 0) == Z_OK) - /* nothing */; + /* Set it up */ + memset(&stream, 0, sizeof(stream)); + deflateInit(&stream, Z_BEST_COMPRESSION); + size = deflateBound(&stream, len + hdrlen); + buf = xmalloc(size); - /* Then the data itself.. */ - stream.next_in = unpacked; - stream.avail_in = len; - while (deflate(&stream, Z_FINISH) == Z_OK) - /* nothing */; - deflateEnd(&stream); - free(unpacked); - - objsize = stream.total_out; - } + /* Compress it */ + stream.next_out = buf; + stream.avail_out = size; - do { - size = write(fd, buf + posn, objsize - posn); - if (size <= 0) { - if (!size) { - fprintf(stderr, "write closed\n"); - } else { - perror("write "); - } - return -1; - } - posn += size; - } while (posn < objsize); + /* First header.. */ + stream.next_in = (void *)hdr; + stream.avail_in = hdrlen; + while (deflate(&stream, 0) == Z_OK) + /* nothing */; + + /* Then the data itself.. */ + stream.next_in = unpacked; + stream.avail_in = len; + while (deflate(&stream, Z_FINISH) == Z_OK) + /* nothing */; + deflateEnd(&stream); + free(unpacked); - if (map) - munmap(map, objsize); - if (temp_obj) - free(temp_obj); + *objsize = stream.total_out; + return buf; +} - return 0; +int write_sha1_to_fd(int fd, const unsigned char *sha1) +{ + int retval; + unsigned long objsize; + void *buf = map_sha1_file_internal(sha1, &objsize); + + if (buf) { + retval = write_buffer(fd, buf, objsize); + munmap(buf, objsize); + return retval; + } + + buf = repack_object(sha1, &objsize); + retval = write_buffer(fd, buf, objsize); + free(buf); + return retval; } int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer, @@ -1579,7 +1590,8 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer, SHA1_Update(&c, discard, sizeof(discard) - stream.avail_out); } while (stream.avail_in && ret == Z_OK); - write(local, buffer, *bufposn - stream.avail_in); + if (write_buffer(local, buffer, *bufposn - stream.avail_in) < 0) + die("unable to write sha1 file"); memmove(buffer, buffer + *bufposn - stream.avail_in, stream.avail_in); *bufposn = stream.avail_in; @@ -1645,16 +1657,24 @@ int has_sha1_file(const unsigned char *sha1) return find_sha1_file(sha1, &st) ? 1 : 0; } -int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object) +/* + * reads from fd as long as possible into a supplied buffer of size bytes. + * If neccessary the buffer's size is increased using realloc() + * + * returns 0 if anything went fine and -1 otherwise + * + * NOTE: both buf and size may change, but even when -1 is returned + * you still have to free() it yourself. + */ +int read_pipe(int fd, char** return_buf, unsigned long* return_size) { - unsigned long size = 4096; - char *buf = malloc(size); - int iret, ret; + char* buf = *return_buf; + unsigned long size = *return_size; + int iret; unsigned long off = 0; - unsigned char hdr[50]; - int hdrlen; + do { - iret = read(fd, buf + off, size - off); + iret = xread(fd, buf + off, size - off); if (iret > 0) { off += iret; if (off == size) { @@ -1663,16 +1683,34 @@ int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object) } } } while (iret > 0); - if (iret < 0) { + + *return_buf = buf; + *return_size = off; + + if (iret < 0) + return -1; + return 0; +} + +int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object) +{ + unsigned long size = 4096; + char *buf = malloc(size); + int ret; + unsigned char hdr[50]; + int hdrlen; + + if (read_pipe(fd, &buf, &size)) { free(buf); return -1; } + if (!type) type = blob_type; if (write_object) - ret = write_sha1_file(buf, off, type, sha1); + ret = write_sha1_file(buf, size, type, sha1); else { - write_sha1_file_prepare(buf, off, type, sha1, hdr, &hdrlen); + write_sha1_file_prepare(buf, size, type, sha1, hdr, &hdrlen); ret = 0; } free(buf);