int shfs_rev_init(shfs_ino_t *file) { shfs_attr_t attr; shfs_ino_t *repo; shfs_ino_t *head; shfs_ino_t *rev; shfs_ino_t *tag; int err; if (shfs_type(file) != SHINODE_FILE) return (SHERR_OPNOTSUPP); attr = shfs_attr(file); if (attr & SHATTR_VER) { /* inode is already initialized for repository. */ return (0); } /* commit current data content */ err = shfs_rev_commit(file, &rev); if (err) return (err); /* set initial description */ shfs_rev_desc_set(rev, "initial revision"); /* create master branch */ err = shfs_rev_branch(file, "master", rev); 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); }
static int _shfs_lock_verify_hier(shfs_ino_t *inode) { shfs_t *parent; int err; if (shfs_type(inode) == SHINODE_FILE_LOCK) return (SHERR_OPNOTSUPP); if ((shfs_attr(inode) & SHATTR_FLOCK)) { return (SHERR_ACCESS); } /* reference fs from parent for fresh inodes */ parent = shfs_inode_parent(inode); if (parent) { err = _shfs_lock_verify_hier(parent); if (err) return (err); } 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_read_of(shfs_ino_t *file, shbuf_t *buff, off_t of, size_t size) { shfs_ino_t *aux; int format; int err; if (file == NULL) return (SHERR_INVAL); if (shfs_format(file) == SHINODE_NULL) return (SHERR_NOENT); /* no data content */ if (!buff) return (0); err = 0; format = shfs_format(file); switch (format) { case SHINODE_REFERENCE: err = shfs_ref_read(file, buff); if (!err) { /* cheat */ if (of) shbuf_trim(buff, of); if (size) shbuf_truncate(buff, size); } break; case SHINODE_EXTERNAL: err = shfs_ext_read(file, buff); if (!err) { /* cheat */ if (of) shbuf_trim(buff, of); if (size) shbuf_truncate(buff, size); } break; case SHINODE_COMPRESS: err = shfs_zlib_read(file, buff); if (!err) { /* cheat */ if (of) shbuf_trim(buff, of); if (size) shbuf_truncate(buff, size); } break; case SHINODE_DATABASE: err = shfs_db_read_of(file, buff, of, size); break; case SHINODE_BINARY: err = shfs_bin_read_of(file, buff, of, size); break; case SHINODE_DIRECTORY: if (!(shfs_attr(file) & SHATTR_ARCH)) return (SHERR_ISDIR); err = shfs_arch_read(file, buff); if (!err) { /* cheat */ if (of) shbuf_trim(buff, of); if (size) shbuf_truncate(buff, size); } break; } 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); }
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); }