/* A file entry went away or appeared */ static int show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base) { unsigned mode; const char *path; const unsigned char *sha1 = extract(desc, &path, &mode); if (opt->recursive && S_ISDIR(mode)) { char type[20]; char *newbase = malloc_base(base, path, strlen(path)); struct tree_desc inner; void *tree; tree = read_sha1_file(sha1, type, &inner.size); if (!tree || strcmp(type, "tree")) die("corrupt tree sha %s", sha1_to_hex(sha1)); inner.buf = tree; show_tree(opt, prefix, &inner, newbase); free(tree); free(newbase); return 0; } opt->add_remove(opt, prefix[0], mode, sha1, base, path); return 0; }
/* A file entry went away or appeared */ static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base, int baselen) { unsigned mode; const char *path; const unsigned char *sha1 = tree_entry_extract(desc, &path, &mode); int pathlen = tree_entry_len(path, sha1); if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode)) { enum object_type type; char *newbase = malloc_base(base, baselen, path, pathlen); struct tree_desc inner; void *tree; unsigned long size; tree = read_sha1_file(sha1, &type, &size); if (!tree || type != OBJ_TREE) die("corrupt tree sha %s", sha1_to_hex(sha1)); init_tree_desc(&inner, tree, size); show_tree(opt, prefix, &inner, newbase, baselen + 1 + pathlen); free(tree); free(newbase); } else { char *fullname = malloc_fullname(base, baselen, path, pathlen); opt->add_remove(opt, prefix[0], mode, sha1, fullname); free(fullname); } }
static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const char *base, int baselen, struct diff_options *opt) { unsigned mode1, mode2; const char *path1, *path2; const unsigned char *sha1, *sha2; int cmp, pathlen1, pathlen2; char *fullname; sha1 = tree_entry_extract(t1, &path1, &mode1); sha2 = tree_entry_extract(t2, &path2, &mode2); pathlen1 = tree_entry_len(path1, sha1); pathlen2 = tree_entry_len(path2, sha2); cmp = base_name_compare(path1, pathlen1, mode1, path2, pathlen2, mode2); if (cmp < 0) { show_entry(opt, "-", t1, base, baselen); return -1; } if (cmp > 0) { show_entry(opt, "+", t2, base, baselen); return 1; } if (!DIFF_OPT_TST(opt, FIND_COPIES_HARDER) && !hashcmp(sha1, sha2) && mode1 == mode2) return 0; /* * If the filemode has changed to/from a directory from/to a regular * file, we need to consider it a remove and an add. */ if (S_ISDIR(mode1) != S_ISDIR(mode2)) { show_entry(opt, "-", t1, base, baselen); show_entry(opt, "+", t2, base, baselen); return 0; } if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode1)) { int retval; char *newbase = malloc_base(base, baselen, path1, pathlen1); if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) { newbase[baselen + pathlen1] = 0; opt->change(opt, mode1, mode2, sha1, sha2, newbase); newbase[baselen + pathlen1] = '/'; } retval = diff_tree_sha1(sha1, sha2, newbase, opt); free(newbase); return retval; } fullname = malloc_fullname(base, baselen, path1, pathlen1); opt->change(opt, mode1, mode2, sha1, sha2, fullname); free(fullname); return 0; }
void *realloc(void *ptr, size_t size) { void *newptr = malloc(size); if (newptr && ptr && ptr >= malloc_base() && ptr <= sbrk(0)) { Chunk c = (Chunk) ptr - 1; if (c->data == ptr) { size_t length = c->size > size ? size : c->size; char *dst = newptr, *src = ptr; for (size_t i = 0; i < length; *dst = *src, ++src, ++dst, ++i); free(ptr); } } return newptr; }
static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt) { unsigned mode1, mode2; const char *path1, *path2; const unsigned char *sha1, *sha2; int cmp, pathlen1, pathlen2; sha1 = extract(t1, &path1, &mode1); sha2 = extract(t2, &path2, &mode2); pathlen1 = strlen(path1); pathlen2 = strlen(path2); cmp = base_name_compare(path1, pathlen1, mode1, path2, pathlen2, mode2); if (cmp < 0) { show_entry(opt, "-", t1, base); return -1; } if (cmp > 0) { show_entry(opt, "+", t2, base); return 1; } if (!opt->find_copies_harder && !memcmp(sha1, sha2, 20) && mode1 == mode2) return 0; /* * If the filemode has changed to/from a directory from/to a regular * file, we need to consider it a remove and an add. */ if (S_ISDIR(mode1) != S_ISDIR(mode2)) { show_entry(opt, "-", t1, base); show_entry(opt, "+", t2, base); return 0; } if (opt->recursive && S_ISDIR(mode1)) { int retval; char *newbase = malloc_base(base, path1, pathlen1); if (opt->tree_in_recursive) opt->change(opt, mode1, mode2, sha1, sha2, base, path1); retval = diff_tree_sha1(sha1, sha2, newbase, opt); free(newbase); return retval; } opt->change(opt, mode1, mode2, sha1, sha2, base, path1); return 0; }
void *malloc(size_t size) { void *ret; if (!ptr_list) ptr_list = (t_chunk *)malloc_base(sizeof(t_chunk)); ret = mmap(singleton(), size, PROT_WRITE | PROT_READ , MAP_ANON | MAP_PRIVATE, -1, 0); if (ret == MAP_FAILED) { write(2, "mmap fail.\n", 12); ret = NULL; } return (ret); }
void free(void *ptr) { if (!ptr || ptr < malloc_base() || ptr > sbrk(0)) return; Chunk c = (Chunk) ptr - 1; if (c->data != ptr) return; c->free = 1; if (c->next && c->next->free) { malloc_merge_next(c); } if (c->prev->free) { malloc_merge_next(c = c->prev); } if (!c->next) { c->prev->next = NULL; sbrk(- c->size - sizeof(struct chunk)); } }
Chunk malloc_chunk_find(size_t s, Chunk *heap) { Chunk c = malloc_base(); for (; c && (!c->free || c->size < s); *heap = c, c = c->next); return c; }