/** * Format: * <> := * num_keys | [key | name_len | name | rev_nr | [<load_frs>][...]][...] */ struct node *load_vfr_tree(FILE *infile) { struct node *root; struct vfile_record *vfr; uint16_t key; uint16_t num_keys; uint16_t name_len; uint8_t rev_nr; register int i, j; root = NULL; memset(&num_keys, 0, sizeof(uint16_t)); fread(&num_keys, sizeof(uint16_t), 1, infile); for (i = 0; i < num_keys; i++) { memset(&key, 0, sizeof(uint16_t)); fread(&key, sizeof(uint16_t), 1, infile); memset(&name_len, 0, sizeof(uint16_t)); fread(&name_len, sizeof(uint16_t), 1, infile); memset(&path_buf, 0, PATH_MAX); fread(&path_buf, name_len * sizeof(unsigned char), 1, infile); memset(&rev_nr, 0, sizeof(uint8_t)); fread(&rev_nr, sizeof(uint8_t), 1, infile); vfr = make_vfr((const char *) path_buf); root = insert(root, key, (void *) vfr); for (j = 0; j < rev_nr; j++) { vfr->history[j] = malloc(sizeof(struct file_record)); memset(vfr->history[j], 0, sizeof(struct file_record)); fread(vfr->history[j], sizeof(struct file_record), 1, infile); PHOENIXFS_DBG("load_vfr_tree:: %s [%d]", vfr->name, j); } vfr->HEAD = rev_nr - 1; } return root; }
void fstree_insert_update_file(const char *path, const char *follow) { struct dir_record *dr; struct vfile_record *vfr; struct file_record *fr, *new_fr; uint16_t key = ~0; char *filename; size_t length; filename = split_basename(path, dirname); if (!(dr = find_dr(dirname))) goto DR; else { length = (size_t) strlen((char *) filename); key = compute_crc32(key, (const unsigned char *) filename, length); if (!(vfr = find(dr->vroot, key, 0))) { PHOENIXFS_DBG("fstree_insert_update_file:: missing vfr: %s", filename); goto VFR; } else { if (vfr->HEAD >= 0) fr = vfr->history[vfr->HEAD]; else fr = NULL; goto FR; } } DR: dr = make_dr(dirname); insert_dr(dr); VFR: vfr = make_vfr(filename); insert_vfr(dr, vfr); FR: if (!(new_fr = make_fr(path, follow))) { PHOENIXFS_DBG("fstree_insert_update_file:: Can't make fr %s", path); return; } /* If content is present in the old fr, don't make a new fr */ if (fr && !memcmp(fr->sha1, new_fr->sha1, 20)) { PHOENIXFS_DBG("fstree_insert_update_file:: unmodified: %s", path); free(new_fr); return; } insert_fr(vfr, new_fr); }
static int phoenixfs_rename(const char *path, const char *newpath) { char xnewpath[PATH_MAX]; struct dir_record *dr; struct vfile_record *vfr, *new_vfr; char *filename, *newfilename; uint16_t key = ~0; size_t length; uint8_t start_rev, rev_nr; PHOENIXFS_DBG("rename:: %s to %s", path, newpath); build_xpath(xpath, path, 0); build_xpath(xnewpath, newpath, 0); if (rename(xpath, xnewpath) < 0) return -errno; /* Update fstree */ filename = split_basename(path, xpath); if (!(dr = find_dr(xpath))) { PHOENIXFS_DBG("rename:: Missing dr for %s", xpath); return 0; } /* Find the old vfr to copy out data from and remove */ length = (size_t) strlen((char *) filename); key = compute_crc32(key, (const unsigned char *) filename, length); if (!(vfr = find(dr->vroot, key, 0))) { PHOENIXFS_DBG("rename:: Missing vfr for %s", path); return 0; } /* Make a new vfr and copy out history from old vfr */ newfilename = split_basename(path, NULL); new_vfr = make_vfr(newfilename); /* Compute start_rev and rev_nr */ if (vfr->HEAD < 0) { start_rev = 0; rev_nr = 0; } else if (vfr->history[(vfr->HEAD + 1) % REV_TRUNCATE]) { /* History is full, and is probably wrapping around */ start_rev = (vfr->HEAD + 1) % REV_TRUNCATE; rev_nr = 20; } else { /* History is not completely filled */ start_rev = 0; rev_nr = vfr->HEAD + 1; } PHOENIXFS_DBG("rename:: copying %d revisions", rev_nr); while (start_rev < rev_nr) { new_vfr->history[start_rev] = vfr->history[start_rev]; start_rev = (start_rev + 1) % REV_TRUNCATE; } new_vfr->HEAD = rev_nr - 1; insert_vfr(dr, new_vfr); /* Remove old vfr */ dr->vroot = remove_entry(dr->vroot, key); return 0; }