shfs_ino_t *shfs_rev_get(shfs_ino_t *repo, shkey_t *rev_key) { shfs_ino_t *rev; if (shfs_type(repo) == SHINODE_FILE) repo = shfs_inode(repo, NULL, SHINODE_REPOSITORY); if (shfs_type(repo) != SHINODE_REPOSITORY) return (NULL); if (shkey_cmp(rev_key, ashkey_blank())) return (NULL); return (shfs_inode(repo, (char *)shkey_hex(rev_key), SHINODE_REVISION)); }
int shfs_rev_ref_write(shfs_ino_t *file, char *group, char *name, shbuf_t *buff) { shfs_ino_t *ref; shfs_ino_t *aux; char buf[SHFS_PATH_MAX]; int err; memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf) - 1, "%s/%s", group, name); ref = shfs_inode(file, buf, SHINODE_OBJECT); err = shfs_bin_write(ref, buff); if (err) return (err); #if 0 err = shfs_aux_write(aux, buff); if (err) return (err); #endif err = shfs_inode_write_entity(ref); if (err) { sherr(err, "shfs_rev_ref_write [shfs_inode_write_entity]"); return (err); } #if 0 /* copy aux stats to file inode. */ file->blk.hdr.mtime = ref->blk.hdr.mtime; file->blk.hdr.size = ref->blk.hdr.size; file->blk.hdr.crc = ref->blk.hdr.crc; file->blk.hdr.format = SHINODE_OBJECT; #endif return (0); }
shfs_ino_t *shfs_rev_ref_resolve(shfs_ino_t *file, char *group, char *name) { shfs_ino_t *branch; shfs_ino_t *repo; shfs_ino_t *ref; shkey_t *key; char buf[SHFS_PATH_MAX]; int obj_type; int err; if (!file) return (NULL); memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf)-1, "%s/%s", group, name); err = shfs_obj_get(file, buf, &key); if (err) return (NULL); repo = shfs_inode(file, NULL, SHINODE_REPOSITORY); branch = shfs_rev_get(repo, key); shkey_free(&key); return (branch); }
int _shfs_ref_raw_write(shfs_ino_t *file, shbuf_t *buff) { shfs_ino_t *inode; int err; if (!file) return (SHERR_INVAL); inode = shfs_inode(file, NULL, SHINODE_REFERENCE); if (!inode) return (SHERR_IO); if (shbuf_size(buff) > SHFS_BLOCK_DATA_SIZE) { return (SHERR_TOOMANYREFS); } memset((char *)inode->blk.raw, 0, SHFS_BLOCK_DATA_SIZE); memcpy((char *)inode->blk.raw, shbuf_data(buff), shbuf_size(buff)); inode->blk.hdr.size = shbuf_size(buff); inode->blk.hdr.crc = shcrc(shbuf_data(buff), shbuf_size(buff)); err = shfs_inode_write_entity(inode); if (err) return (err); /* copy aux stats to file inode. */ file->blk.hdr.mtime = inode->blk.hdr.mtime; file->blk.hdr.size = inode->blk.hdr.size; file->blk.hdr.crc = inode->blk.hdr.crc; file->blk.hdr.format = SHINODE_REFERENCE; file->blk.hdr.attr |= SHATTR_LINK; return (0); }
/** * Store supplementary credential data in a file. */ int shfs_cred_store(shfs_ino_t *file, shkey_t *key, unsigned char *data, size_t data_len) { shfs_ino_t *cred; shbuf_t *buff; char key_buf[MAX_SHARE_HASH_LENGTH]; int err; memset(key_buf, 0, sizeof(key_buf)); sprintf(key_buf, "%s", shkey_hex(key)); cred = shfs_inode(file, key_buf, SHINODE_ACCESS); if (!cred) return (SHERR_IO); cred->blk.hdr.format = SHINODE_ACCESS; buff = shbuf_map(data, data_len); err = shfs_aux_write(cred, buff); free(buff); if (err) return (err); file->blk.hdr.attr |= SHATTR_CRED; file->blk.hdr.crc = shcrc(data, data_len); file->blk.hdr.size = data_len; err = shfs_inode_write_entity(file); if (err) return (err); return (0); }
int shfs_rev_cat(shfs_ino_t *file, shkey_t *rev_key, shbuf_t *buff, shfs_ino_t **rev_p) { shfs_ino_t *repo; shfs_ino_t *rev; int err; /* obtain repository for inode. */ repo = shfs_inode(file, NULL, SHINODE_REPOSITORY); if (!repo) return (SHERR_IO); if (!rev_key) { /* obtain current revision */ rev = shfs_rev_base(file); } else { rev = shfs_rev_get(repo, rev_key); } if (!rev) return (SHERR_NOENT); err = shfs_rev_read(rev, buff); if (err) return (err); if (rev_p) *rev_p = rev; return (0); }
int shfs_rev_clear(shfs_ino_t *file) { shfs_ino_t *repo; /* obtain repository for inode. */ repo = shfs_inode(file, NULL, SHINODE_REPOSITORY); /* clear contents of repository. */ return (shfs_inode_clear(repo)); }
shfs_ino_t *shfs_file_find(shfs_t *tree, char *path) { shfs_ino_t *dir; shfs_ino_t *file; char fpath[PATH_MAX+1]; char curpath[PATH_MAX+1]; char *filename; char *dirname; char *ptr; file = NULL; if (!path || !*path) return (NULL); if (strlen(path) >= SHFS_PATH_MAX) return (NULL);//SHERR_NAMETOOLONG); memset(fpath, 0, sizeof(fpath)); if (*path == '/') { strncpy(fpath, path + 1, PATH_MAX); } else { strncpy(fpath, path, PATH_MAX); } if (!*fpath || fpath[strlen(fpath)-1] == '/') { dir = shfs_dir_find(tree, fpath); return (dir); } dirname = NULL; filename = NULL; ptr = strrchr(fpath, '/'); if (!ptr) { dirname = ""; filename = fpath; } else { *ptr++ = '\000'; dirname = fpath; filename = ptr; } dir = shfs_dir_find(tree, dirname); if (!dir) return (NULL); file = shfs_inode(dir, filename, SHINODE_FILE); return (file); }
int shfs_rev_ref_read(shfs_ino_t *file, char *group, char *name, shbuf_t *buff) { shfs_ino_t *ref; shfs_ino_t *aux; char buf[SHFS_PATH_MAX]; int err; memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf) - 1, "%s/%s", group, name); ref = shfs_inode(file, buf, SHINODE_OBJECT); err = shfs_bin_read(ref, buff); if (err) return (err); #if 0 aux = shfs_inode(ref, NULL, SHINODE_BINARY); err = shfs_aux_read(aux, buff); if (err) return (err); #endif return (0); }
int shfs_rev_delta_write(shfs_ino_t *rev, shbuf_t *buff) { shfs_ino_t *aux; int err; aux = shfs_inode(rev, NULL, SHINODE_DELTA); if (!aux) return (SHERR_IO); err = shfs_aux_write(aux, buff); if (err) return (err); return (0); }
shkey_t *shfs_index_key(shfs_idx_t *idx, uint64_t crc, shfs_dirent_t *ent_p) { shkey_t *key; int h_num = (crc % 256); if (!idx->hash[h_num]) { key = shkey_bin(&crc, sizeof(uint64_t)); idx->hash_ino[h_num] = shfs_inode(idx->file, shkey_hex(key), SHINODE_INDEX); shkey_free(&key); return (NULL); } for (i = 0; i < idx->hash_max[h_num]; i++) { if ((idx->key[h_num] + i) == crc) { return (idx->hash[h_num] + i); } } return (NULL); }
int shfs_cred_remove(shfs_ino_t *file, shkey_t *key) { shfs_ino_t *cred; char key_buf[MAX_SHARE_HASH_LENGTH]; int err; memset(key_buf, 0, sizeof(key_buf)); sprintf(key_buf, "%s", shkey_hex(key)); cred = shfs_inode(file, key_buf, SHINODE_ACCESS); if (!cred) return (SHERR_IO); if (shfs_format(cred) != SHINODE_ACCESS) return (0); /* done */ err = shfs_inode_clear(cred); if (err) return (err); return (0); }
int shfs_ext_set(shfs_ino_t *file, const char *path) { struct stat st; shfs_ino_t *ext; char fs_path[SHFS_PATH_MAX]; int err; if (file == NULL || !path || !*path) return (SHERR_INVAL); err = stat(path, &st); if (err) { return (errno2sherr()); } ext = shfs_inode(file, NULL, SHINODE_EXTERNAL); if (!ext) return (SHERR_IO); memset(fs_path, 0, sizeof(fs_path)); strncpy(fs_path, path, sizeof(fs_path) - 1); /* save local hard-drive path as inode data. */ memset(ext->blk.raw, 0, SHFS_PATH_MAX); strcpy((char *)ext->blk.raw, fs_path); ext->blk.hdr.size = SHFS_PATH_MAX; ext->blk.hdr.crc = shcrc(fs_path, SHFS_PATH_MAX); err = shfs_inode_write_entity(ext); if (err) return (err); /* copy ext stats to file inode. */ file->blk.hdr.mtime = ext->blk.hdr.mtime; file->blk.hdr.size = ext->blk.hdr.size; file->blk.hdr.crc = ext->blk.hdr.crc; file->blk.hdr.format = SHINODE_EXTERNAL; file->blk.hdr.attr |= SHATTR_LINK_EXT; return (0); }
int _shfs_ref_raw_read(shfs_ino_t *file, shbuf_t *buff) { shfs_ino_t *inode; int err; if (!file) return (SHERR_INVAL); if (shfs_format(file) != SHINODE_REFERENCE) return (SHERR_INVAL); inode = shfs_inode(file, NULL, SHINODE_REFERENCE); if (!inode) return (SHERR_IO); if (inode->blk.hdr.size < (sizeof(shpeer_t) + sizeof(shkey_t)) || inode->blk.hdr.size > SHFS_BLOCK_DATA_SIZE) return (SHERR_IO); shbuf_cat(buff, (char *)inode->blk.raw, inode->blk.hdr.size); return (0); }
int shfs_truncate(shfs_ino_t *file, shsize_t len) { shfs_ino_t *bin; shfs_ino_t *aux; int err; if (!file) return (0); if (!IS_INODE_CONTAINER(shfs_type(file))) return (SHERR_INVAL); /* see shfs_inode_truncate() */ switch (shfs_format(file)) { case SHINODE_NULL: return (SHERR_NOENT); /* no data content */ case SHINODE_BINARY: bin = shfs_inode(file, NULL, SHINODE_BINARY); err = shfs_inode_truncate(bin, len); if (err) return (err); /* update file inode attributes */ file->blk.hdr.mtime = bin->blk.hdr.mtime; file->blk.hdr.size = bin->blk.hdr.size; file->blk.hdr.crc = bin->blk.hdr.crc; err = shfs_inode_write_entity(file); if (err) return (err); break; default: return (SHERR_OPNOTSUPP); } return (0); }
int shfs_rev_checkout(shfs_ino_t *file, shkey_t *key, shfs_ino_t **rev_p) { shfs_ino_t *repo; shfs_ino_t *rev; int err; if (!file || shfs_type(file) != SHINODE_FILE) return (SHERR_INVAL); repo = shfs_inode(file, NULL, SHINODE_REPOSITORY); rev = shfs_rev_get(repo, key); if (!rev) return (SHERR_NOENT); err = shfs_rev_base_set(file, rev); if (err) return (err); if (rev_p) *rev_p = rev; return (0); }
int shfs_ext_write(shfs_ino_t *file, shbuf_t *buff) { shfs_ino_t *ext; char *path; int err; if (file == NULL) return (SHERR_INVAL); if (shfs_format(file) != SHINODE_EXTERNAL) return (SHERR_INVAL); ext = shfs_inode(file, NULL, SHINODE_EXTERNAL); if (!ext) return (SHERR_IO); path = (char *)ext->blk.raw; err = shfs_mem_write(path, buff); if (err) return (err); return (0); }
/** * Load supplementary credential data from a file. */ int shfs_cred_load(shfs_ino_t *file, shkey_t *key, unsigned char *data, size_t max_len) { shfs_ino_t *cred; shbuf_t *buff; char key_buf[MAX_SHARE_HASH_LENGTH]; int err; if (!(file->blk.hdr.attr & SHATTR_CRED)) return (SHERR_NOENT); memset(key_buf, 0, sizeof(key_buf)); sprintf(key_buf, "%s", shkey_hex(key)); cred = shfs_inode(file, key_buf, SHINODE_ACCESS); if (!cred) return (SHERR_IO); if (cred->blk.hdr.format != SHINODE_ACCESS) return (SHERR_NOENT); buff = shbuf_init(); err = shfs_aux_read(cred, buff); if (err) { shbuf_free(&buff); return (err); } if (shbuf_size(buff) == 0) { shbuf_free(&buff); return (SHERR_IO); } /* copy buffer */ memcpy(data, shbuf_data(buff), MIN(shbuf_size(buff), max_len)); shbuf_free(&buff); return (0); }
int shfs_file_remove(shfs_ino_t *file) { shfs_ino_t *child; shbuf_t *buff; shfs_dirent_t *ents; size_t ent_max; int fmt; int err; int i; if (IS_INODE_CONTAINER(shfs_type(file))) { ents = NULL; ent_max = shfs_list(file, NULL, &ents); if (ent_max < 0) { return (ent_max); } if (ents) { for (i = 0; i < ent_max; i++) { if (IS_INODE_CONTAINER(ents[i].d_type)) { child = shfs_inode(file, ents[i].d_name, ents[i].d_type); err = shfs_file_remove(child); if (err) return (err); } else { child = shfs_inode(file, NULL, ents[i].d_type); shfs_inode_clear(child); } } free(ents); } else { /* version repository */ if (shfs_attr(file) & SHATTR_VER) { child = shfs_inode(file, NULL, SHINODE_REPOSITORY); err = shfs_file_remove(child); if (err) return (err); } /* specific format */ fmt = shfs_format(file); if (fmt == SHINODE_NULL && shfs_type(file) == SHINODE_BINARY) { fmt = SHINODE_AUX; } if (fmt != SHINODE_NULL) { child = shfs_inode(file, NULL, fmt); if (!IS_INODE_CONTAINER(shfs_type(child))) { err = shfs_inode_clear(child); } else { err = shfs_file_remove(child); } if (err) return (err); } } } if (shfs_type(file) != SHINODE_DIRECTORY) { #if 0 /* DEBUG: perform inode_clear on 'fpos' index */ /* clear previous format */ err = shfs_format_set(file, SHINODE_NULL); if (err) return (err); #endif /* reset stats on file inode. */ file->blk.hdr.mtime = 0; file->blk.hdr.size = 0; // file->blk.hdr.type = SHINODE_NULL; file->blk.hdr.format = SHINODE_NULL; file->blk.hdr.attr = SHINODE_NULL; file->blk.hdr.crc = 0; err = shfs_inode_write_entity(file); if (err) { return (err); } } return (0); }
int shfs_rev_commit(shfs_ino_t *file, shfs_ino_t **rev_p) { shstat st; shbuf_t *diff_buff; shbuf_t *work_buff; shbuf_t *head_buff; shfs_ino_t *base; shfs_ino_t *repo; /* SHINODE_REPOSITORY */ shfs_ino_t *new_rev; /* SHINODE_REVISION */ shfs_ino_t *delta; /* SHINODE_DELTA */ shkey_t *rev_key; shfs_t *fs; int err; if (rev_p) *rev_p = NULL; head_buff = work_buff = diff_buff = NULL; err = shfs_fstat(file, &st); if (err) return (err); work_buff = shbuf_init(); err = shfs_read(file, work_buff); if (err) goto done; base = shfs_rev_base(file); if (base) { /* obtain delta of current file data content against BASE revision's data content. */ head_buff = shbuf_init(); err = shfs_rev_ref_read(file, "tag", "BASE", head_buff); if (err) goto done; if (shbuf_size(work_buff) == shbuf_size(head_buff) && 0 == memcmp(shbuf_data(work_buff), shbuf_data(head_buff), shbuf_size(work_buff))) { /* no difference */ err = SHERR_AGAIN; goto done; } diff_buff = shbuf_init(); err = shdelta(work_buff, head_buff, diff_buff); shbuf_free(&head_buff); if (err) return (err); rev_key = shfs_token(base); } else { /* initial revision */ rev_key = ashkey_uniq(); } repo = shfs_inode(file, NULL, SHINODE_REPOSITORY); if (!repo) { err = SHERR_IO; goto done; } /* create a new revision using previous revision's inode name */ new_rev = shfs_inode(repo, (char *)shkey_hex(rev_key), SHINODE_REVISION); if (!new_rev) { err = SHERR_IO; goto done; } /* define revision's meta information. */ shfs_meta_set(new_rev, SHMETA_USER_NAME, (char *)get_libshare_account_name()); /* save delta to new revision */ err = shfs_rev_delta_write(new_rev, diff_buff); shbuf_free(&diff_buff); if (err) goto done; /* save new revision as BASE branch head */ err = shfs_rev_base_set(file, new_rev); if (err) goto done; /* save work-data to BASE tag. */ err = shfs_rev_ref_write(file, "tag", "BASE", work_buff); shbuf_free(&work_buff); if (err) goto done; if (base) { /* tag previous revision's key token onto revision inode. */ shfs_rev_tag(new_rev, "PREV", base); } if (rev_p) *rev_p = new_rev; done: shbuf_free(&work_buff); shbuf_free(&diff_buff); shbuf_free(&head_buff); return (err); }
int shfs_file_copy(shfs_ino_t *src_file, shfs_ino_t *dest_file) { shfs_t *ref_fs; shfs_ino_t *ref; shstat st; shbuf_t *buff; int err; if (!src_file || !dest_file) return (SHERR_INVAL); /* ensure there is something to copy */ err = shfs_fstat(src_file, &st); if (err) { fprintf(stderr, "DEBUG: shfs_file_copy: %d = shfs_fstat(src_file)\n", err); return (err); } if (shfs_type(dest_file) == SHINODE_DIRECTORY) { #if 0 /* extract tar archive */ if (shfs_format(dest_file) == SHINODE_BINARY && 0 == strcmp(shfs_meta_get(dest_file, "content.mime"), "application/x-tar")) { buff = shbuf_init(); err = shfs_read(src_file, buff); if (err) { shbuf_free(&buff); return (err); } err = shfs_unarch(buff, dest_file); shbuf_free(&buff); return (0); } #endif if (!(shfs_attr(src_file) & SHATTR_ARCH)) { if (IS_INODE_CONTAINER(shfs_type(src_file))) { dest_file = shfs_inode(dest_file, shfs_filename(src_file), shfs_type(src_file)); } else { dest_file = shfs_inode(dest_file, NULL, shfs_type(src_file)); } } } ref = NULL; ref_fs = NULL; if (shfs_format(dest_file) == SHINODE_REFERENCE) { /* apply operation to end-point inode. */ err = shfs_ref_get(dest_file, &ref_fs, &ref); if (err) { fprintf(stderr, "DEBUG: shfs_file_copy: %d = shfs_ref_get(dest_file)\n", err); return (err); } dest_file = ref; } if (shfs_format(dest_file) != SHINODE_EXTERNAL) { /* direct copy data content without conversion when applicable. */ switch (shfs_format(src_file)) { #if 0 case SHINODE_COMPRESS: err = shfs_zlib_copy(src_file, dest_file); if (err) return (err); return (0); #endif } } /* default case */ buff = shbuf_init(); err = shfs_read(src_file, buff); if (err) { fprintf(stderr, "DEBUG: shfs_file_copy: %d = shfs_read()\n", err); goto done; } err = shfs_write(dest_file, buff); shbuf_free(&buff); if (err) { fprintf(stderr, "DEBUG: shfs_file_copy: %d = shfs_write()\n", err); goto done; } /* success */ err = 0; done: shbuf_free(&buff); if (ref_fs) shfs_free(&ref_fs); return (err); }