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); }
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_write(shfs_ino_t *file, shbuf_t *buff) { shfs_ino_t *aux; int format; int err; if (!file) return (SHERR_INVAL); err = 0; format = shfs_format(file); if (!buff) return (SHERR_INVAL); /* presume user wants to erase content. */ if (shfs_attr(file) & SHATTR_DB) format = SHINODE_DATABASE; switch (format) { case SHINODE_REFERENCE: err = shfs_ref_write(file, buff); break; case SHINODE_EXTERNAL: err = shfs_ext_write(file, buff); break; case SHINODE_COMPRESS: err = shfs_zlib_write(file, buff); break; case SHINODE_DATABASE: err = shfs_db_write(file, buff); break; case SHINODE_DIRECTORY: err = shfs_attr_set(file, SHATTR_ARCH); if (err) break; err = shfs_arch_write(file, buff); break; default: err = shfs_bin_write(file, buff); break; } if (!err) err = shfs_inode_write_entity(file); if (!err && (file->blk.hdr.attr & SHATTR_SYNC)) shfs_file_notify(file); return (err); }
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); }
/** * @param file The inode refeferencing another inode. * @param ref_file The inode being referenced. */ int shfs_ref_set(shfs_ino_t *file, shfs_ino_t *ref_file) { shfs_ino_t *parent; shbuf_t *buff; int err; int i; if (!file || !file->tree) return (SHERR_INVAL); if (shfs_type(file) != shfs_type(ref_file)) { if (shfs_type(ref_file) != SHINODE_DIRECTORY) return (SHERR_ISDIR); return (SHERR_NOTDIR); } buff = shbuf_init(); shbuf_cat(buff, &file->tree->peer, sizeof(shpeer_t)); parent = ref_file; for (i = 0; i < SHFS_MAX_REFERENCE_HIERARCHY; i++) { if (parent) { shbuf_cat(buff, &parent->blk.hdr.name, sizeof(shkey_t)); parent = shfs_inode_parent(parent); } } err = _shfs_ref_raw_write(file, buff); shbuf_free(&buff); if (err) return (err); err = shfs_inode_write_entity(file); if (err) return (err); 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_attr_set(shfs_ino_t *file, int attr) { shfs_attr_t cur_flag; shmime_t *mime; int err_code; if (!file || !attr) return (SHERR_INVAL); cur_flag = shfs_attr(file); if (cur_flag & attr) return (0); /* already set */ err_code = SHERR_OPNOTSUPP; switch (attr) { case SHATTR_ARCH: if (shfs_type(file) == SHINODE_DIRECTORY) { err_code = 0; } break; case SHATTR_COMP: if (shfs_type(file) == SHINODE_DIRECTORY) { /* files inherit */ err_code = 0; break; } err_code = shfs_format_set(file, SHINODE_COMPRESS); break; case SHATTR_SYNC: err_code = 0; //err_code = shfs_file_notify(file); break; case SHATTR_TEMP: err_code = 0; break; case SHATTR_VER: err_code = shfs_rev_init(file); break; case SHATTR_READ: case SHATTR_WRITE: case SHATTR_EXE: err_code = 0; break; case SHATTR_DB: if (shfs_type(file) != SHINODE_FILE || shfs_format(file) != SHINODE_NULL) { /* not a file or already contains content */ err_code = SHERR_INVAL; break; } err_code = 0; #if 0 err_code = shfs_format_set(file, SHINODE_DATABASE); #endif #if 0 if (shfs_size(file) == 0) { /* new database. */ err_code = 0; } mime = shmime_file(file); if (!mime || 0 == strcmp(mime->mime_name, SHMIME_APP_SQLITE)) { err_code = SHERR_INVAL; break; } /* DEBUG: move to copy file area */ #endif break; } if (!err_code) { file->blk.hdr.attr |= attr; err_code = shfs_inode_write_entity(file); } if (!err_code && ((file->blk.hdr.attr & SHATTR_SYNC) || (cur_flag & cur_flag))) { /* notify share daemon of altered attribute state for synchronized inode. */ shfs_file_notify(file); } return (err_code); }
int shfs_attr_unset(shfs_ino_t *file, int attr) { shfs_attr_t cur_attr; shfs_attr_t new_attr; int err_code; int format; if (!file || !attr) return (SHERR_INVAL); cur_attr = shfs_attr(file); if (!(cur_attr & attr)) return (0); /* already unset */ new_attr = cur_attr; new_attr &= ~attr; err_code = SHERR_OPNOTSUPP; switch (attr) { case SHATTR_COMP: err_code = 0; format = SHINODE_DEFAULT_ATTR_FORMAT(new_attr); if (format != shfs_format(file)) err_code = shfs_format_set(file, format); break; case SHATTR_SYNC: err_code = 0; break; case SHATTR_TEMP: err_code = 0; break; case SHATTR_VER: err_code = shfs_rev_clear(file); break; case SHATTR_LINK: /* unimplemented. */ err_code = SHERR_OPNOTSUPP; /* this is now a local copy */ file->blk.hdr.attr &= ~SHATTR_SYNC; break; case SHATTR_READ: case SHATTR_WRITE: case SHATTR_EXE: err_code = 0; break; case SHATTR_DB: /* DEBUG: TODO: write file pertaining to original aux contents. */ err_code = 0; break; } if (!err_code) { file->blk.hdr.attr = new_attr; err_code = shfs_inode_write_entity(file); } if (!err_code && (file->blk.hdr.attr & SHATTR_SYNC)) shfs_file_notify(file); return (err_code); }
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); }