void sched_tx_payload(shkey_t *dest_key, void *data, size_t data_len, void *payload, size_t payload_len) { tx_t *tx = (tx_t *)data; tx_t sig_tx; tx_net_t net; shsig_t sig; shsig_t new_sig; shbuf_t *buff; shpeer_t *self_peer; if (!data) return; if (data_len < sizeof(tx_t)) return; prep_net_tx(tx, &net, dest_key, data_len + payload_len); buff = shbuf_init(); shbuf_cat(buff, &net, sizeof(tx_net_t)); shbuf_cat(buff, data, data_len); if (payload && payload_len) shbuf_cat(buff, payload, payload_len); tx_wrap(NULL, shbuf_data(buff) + sizeof(tx_net_t)); broadcast_raw(shbuf_data(buff), shbuf_size(buff)); shbuf_free(&buff); fprintf(stderr, "DEBUG: SEND: sched_tx_payload: [OP %d] hash(%s) peer(%s) stamp(%llu) nonce(%d) method(%d) OP(%d)\n", (int)tx->tx_op, tx->hash, shkey_print(&tx->tx_peer), (unsigned long long)tx->tx_stamp, (int)tx->nonce, TXHASH_SCRYPT, (int)tx->tx_op); }
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); }
int shfs_ref_get(shfs_ino_t *file, shfs_t **ref_fs_p, shfs_ino_t **ref_p) { shfs_ino_t *ref; shfs_ino_t *parent; shpeer_t *peer; shfs_t *fs; shkey_t *hier; shbuf_t *buff; char path[SHFS_PATH_MAX]; int hier_cnt; int err; int i; *ref_p = NULL; *ref_fs_p = NULL; if (!file || !file->tree) return (SHERR_INVAL); buff = shbuf_init(); err = _shfs_ref_raw_read(file, buff); if (err) return (err); peer = (shpeer_t *)shbuf_data(buff); hier = (shkey_t *)(shbuf_data(buff) + sizeof(shpeer_t)); fs = shfs_init(peer); if (!fs) return (SHERR_IO); memset(path, 0, sizeof(path)); strcpy(path, "/"); ref = fs->fsbase_ino; for (i = SHFS_MAX_REFERENCE_HIERARCHY - 1; i >= 0; i--) { if (shkey_cmp(&hier[i], ashkey_blank())) continue; if (shkey_cmp(&hier[i], shfs_token(file->tree->fsbase_ino))) continue; ref = shfs_inode_load(ref, &hier[i]); if (!ref) { shfs_free(&fs); return (SHERR_NOENT); } if (shfs_type(ref) == SHINODE_DIRECTORY) strncat(path, "/", SHFS_PATH_MAX - strlen(path) - 1); strncat(path, shfs_filename(ref), SHFS_PATH_MAX - strlen(path) - 1); } shbuf_free(&buff); *ref_p = ref; *ref_fs_p = fs; return (0); }
int shfs_rev_diff(shfs_ino_t *file, shkey_t *rev_key, shbuf_t *buff) { shbuf_t *work_buff; shbuf_t *head_buff; shfs_ino_t *new_rev; shfs_ino_t *delta; shfs_ino_t *rev; shfs_t *fs; int err; if (!file || shfs_type(file) != SHINODE_FILE) return (SHERR_INVAL); if (!buff) return (SHERR_INVAL); if (!rev_key) { /* obtain current committed revision. */ rev = shfs_rev_base(file); } else { rev = shfs_rev_get(file, rev_key); } if (!rev) return (SHERR_NOENT); /* obtain work-data for BASE branch revision. */ head_buff = shbuf_init(); err = shfs_rev_ref_read(file, "tag", "BASE", head_buff); if (err) { shbuf_free(&head_buff); return (err); } work_buff = shbuf_init(); err = shfs_read(file, work_buff); if (err) { shbuf_free(&head_buff); shbuf_free(&work_buff); return (err); } 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 to report */ err = 0; } else { /* print textual difference to <buff> */ err = shdiff(buff, shbuf_data(work_buff), shbuf_data(head_buff)); } shbuf_free(&work_buff); shbuf_free(&head_buff); return (err); }
void shmap_load(shmap_t *ht, shbuf_t *buff) { shmap_value_t *hdr; unsigned char *map_data; unsigned char *data; shsize_t b_len; shsize_t b_of; b_of = 0; b_len = shbuf_size(buff); map_data = shbuf_data(buff); while (b_of < b_len) { hdr = (shmap_value_t *)(map_data + b_of); b_of += sizeof(shmap_value_t); if (b_of > b_len) break; if (hdr->magic != SHMEM32_MAGIC) { sherr(SHERR_IO, "shmap_load: error reading map record."); continue; } data = NULL; if (hdr->sz) { data = (map_data + b_of); b_of += hdr->sz; } if (!data) { continue; } shmap_set_ent(ht, &hdr->name, hdr->pf | SHMAP_ALLOC, data, hdr->sz); } }
int shpam_shadow_pass_remove(shfs_ino_t *file, uint64_t rem_uid) { shbuf_t *rbuff; shbuf_t *buff; shseed_t *seeds; int total; int idx; int err; rbuff = shbuf_init(); shfs_read(file, rbuff); buff = shbuf_init(); seeds = (shseed_t *)shbuf_data(rbuff); total = shbuf_size(rbuff) / sizeof(shseed_t); for (idx = 0; idx < total; idx++) { if (seeds[idx].seed_uid == rem_uid) continue; shbuf_cat(buff, &seeds[idx], sizeof(shseed_t)); } shbuf_free(&rbuff); err = shfs_write(file, buff); shbuf_free(&buff); if (err) return (err); return (0); }
int shpam_shadow_pass_append(shfs_ino_t *file, shseed_t *seed) { shbuf_t *buff; shseed_t *seeds; int total; int idx; int err; buff = shbuf_init(); shfs_read(file, buff); seeds = (shseed_t *)shbuf_data(buff); total = shbuf_size(buff) / sizeof(shseed_t); for (idx = 0; idx < total; idx++) { if (seeds[idx].seed_uid == seed->seed_uid) { memcpy(&seeds[idx], seed, sizeof(shseed_t)); break; } } if (idx == total) { shbuf_cat(buff, seed, sizeof(shseed_t)); } err = shfs_write(file, buff); shbuf_free(&buff); if (err) return (err); return (0); }
const shseed_t *shpam_shadow_pass(shfs_ino_t *file, uint64_t uid) { static shseed_t ret_seed; shbuf_t *buff; shseed_t *seeds; int total; int idx; int err; memset(&ret_seed, 0, sizeof(ret_seed)); buff = shbuf_init(); err = shfs_read(file, buff); if (err) { shbuf_free(&buff); return (NULL); } seeds = (shseed_t *)shbuf_data(buff); total = shbuf_size(buff) / sizeof(shseed_t); for (idx = 0; idx < total; idx++) { if (seeds[idx].seed_uid == uid) { memcpy(&ret_seed, &seeds[idx], sizeof(shseed_t)); break; } } shbuf_free(&buff); if (idx != total) { return (&ret_seed); } return (NULL); }
int install_sexe_userdata(sexe_t *S, char *tag) { SHFL *fl; shjson_t *udata; shfs_t *fs; shbuf_t *buff; shkey_t *k; char path[PATH_MAX+1]; int is_new; k = shkey_str(tag); sprintf(path, "/sys/data/sexe/%s", shkey_hex(k)); memcpy(&S->pname, k, sizeof(S->pname)); shkey_free(&k); buff = shbuf_init(); fs = shfs_init(NULL); fl = shfs_file_find(fs, path); is_new = shfs_read(fl, buff); udata = shjson_init(shbuf_size(buff) ? (char *)shbuf_data(buff) : NULL); shbuf_free(&buff); if (is_new) shjson_num_add(udata, "birth", shtimef(shtime())); sexe_table_set(S, udata); lua_setglobal(S, "userdata"); shjson_free(&udata); shfs_free(&fs); return (0); }
static int _test_shproc_req(int fd, shbuf_t *buff) { int val; if (!fd) { if (shbuf_size(buff) != sizeof(val)) { return (-1); } val = *((int *)shbuf_data(buff)); } else { if (shbuf_size(buff) != 0) { return (-1); } lseek(fd, 0L, SEEK_SET); read(fd, &val, sizeof(int)); close(fd); } _test_shproc_value[val] = -1; shbuf_clear(buff); shbuf_cat(buff, &val, sizeof(int)); return (0); }
int shfs_rev_delta(shfs_ino_t *file, shbuf_t *diff_buff) { shstat st; shbuf_t *work_buff; shbuf_t *head_buff; shbuf_t *ref_buff; shfs_t *fs; shkey_t *key; int err; if (shfs_type(file) != SHINODE_FILE) return (SHERR_INVAL); err = shfs_fstat(file, &st); if (err) return (err); work_buff = shbuf_init(); err = shfs_read(file, work_buff); if (err) { shbuf_free(&work_buff); return (err); } /* obtain BASE branch snapshot */ 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; } err = shdelta(work_buff, head_buff, diff_buff); done: shbuf_free(&work_buff); shbuf_free(&head_buff); shbuf_free(&work_buff); return (err); }
static int _test_shproc_resp(int err_code, shbuf_t *buff) { if (err_code == 0) { int val = *((int *)shbuf_data(buff)); _test_shproc_value[val] = val+1; } return (0); }
int sexe_exec_popen(shbuf_t *buff, shjson_t *arg, sexe_t **mod_p) { lua_State *L = luaL_newstate(); sexe_mod_t *mod; int narg = 1; int status; int err; if (!mod_p) return (SHERR_INVAL); *mod_p = NULL; if (shbuf_size(buff) < sizeof(sexe_mod_t)) return (SHERR_INVAL); mod = (sexe_mod_t *)shbuf_data(buff); if (0 != memcmp(mod->sig, SEXE_SIGNATURE, sizeof(mod->sig))) return (SHERR_ILSEQ); /* open standard libraries */ luaL_checkversion(L); lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ luaL_openlibs(L); /* open libraries */ lua_gc(L, LUA_GCRESTART, 0); //if (!args[has_E] && handle_luainit(L) != LUA_OK) err = _api_handle_luainit(L); if (err) { lua_close(L); return (err); } install_sexe_userdata(L, mod->name); /* sexe api lib */ install_sexe_functions(L); /* sexe api lib */ if (!arg) arg = shjson_init(NULL); lua_pushstring(L, "arg"); sexe_exec_pset(L, "arg", arg); status = sexe_loadmem(L, mod->name, buff); lua_insert(L, -(narg+1)); if (status != LUA_OK) { lua_pop(L, narg); status = _api_report(L, status); lua_close(L); return (status); } *mod_p = L; return (LUA_OK); }
void shlog_write(shbuf_t *buff, int level, int err_code, char *log_str) { static char log_path[PATH_MAX+1]; char line[640]; char *beg_line; size_t mem_size; if (!buff) return; if (!*log_path) { char *label; shpeer_t peer; memcpy(&peer, ashpeer(), sizeof(peer)); label = (!*peer.label ? PACKAGE_NAME : peer.label); sprintf(log_path, "%s%s.log", shlog_path(label), label); } if (*log_path && !_shlog_file) { _shlog_file = fopen(log_path, "ab"); } beg_line = shbuf_data(buff) + shbuf_size(buff); sprintf(line, "%s", shstrtime(shtime(), "[%x %T] ")); shbuf_catstr(buff, line); if (level == SHLOG_ERROR) { shbuf_catstr(buff, "error"); } else if (level == SHLOG_WARNING) { shbuf_catstr(buff, "warning"); } else { shbuf_catstr(buff, "info"); } if (err_code) { memset(line, 0, sizeof(line)); snprintf(line, sizeof(line) - 1, ": %s [code %d]", strerror(-(err_code)), (err_code)); shbuf_catstr(buff, line); } if (log_str) { shbuf_catstr(buff, ": "); shbuf_catstr(buff, log_str); } mem_size = shlog_mem_size(); if (mem_size > 100000) { sprintf(line, " (mem:%dm)", (mem_size / 1000)); shbuf_catstr(buff, line); } shbuf_catstr(buff, "\n"); }
int shlog(int level, int err_code, char *log_str) { static time_t last_day; static time_t last_flush; static shbuf_t *buff; time_t day; time_t now; int err; if (level < _log_level) return (0); now = time(NULL); day = now / 86400; if (day != last_day) { // shlog_zcompr(); /* compress .YY.WW bin log file, removing prev zip */ shlog_free(); } last_day = day; if (!buff) buff = shbuf_init(); { shbuf_lock(buff); shbuf_clear(buff); shlog_write(buff, level, err_code, log_str); if (shbuf_data(buff) && _shlog_file) { fprintf(_shlog_file, "%s", shbuf_data(buff)); if (last_flush < (now - MAX_FLUSH_SPAN)) { fflush(_shlog_file); last_flush = now; } } shbuf_unlock(buff); } return (0); }
int share_file_cat(char *path, int pflags) { shstat st; shfs_t *tree; shfs_ino_t *file; shbuf_t *buff; char fpath[PATH_MAX+1]; unsigned char *data; size_t data_len; size_t of; int w_len; int err; tree = shfs_uri_init(path, 0, &file); if (!tree) return (SHERR_NOENT); err = shfs_fstat(file, &st); if (err) { shfs_free(&tree); return (err); } buff = shbuf_init(); err = shfs_read(file, buff); if (err) { shbuf_free(&buff); shfs_free(&tree); return (err); } of = 0; while (of < shbuf_size(buff)) { data_len = MIN((shbuf_size(buff) - of), 65536); data = shbuf_data(buff) + of; w_len = fwrite(data, sizeof(char), data_len, sharetool_fout); if (w_len < 0) { shbuf_free(&buff); shfs_free(&tree); return (-errno); } of += w_len; } shbuf_free(&buff); shfs_free(&tree); return (0); }
static int shproc_write(shproc_t *proc, shproc_req_t *req) { int w_len; int err; int of; req->data_len = shbuf_size(proc->proc_buff); req->crc = shcrc(shbuf_data(proc->proc_buff), shbuf_size(proc->proc_buff)); err = write(proc->proc_fd, req, sizeof(shproc_req_t)); if (err == -1) return (errno2sherr()); if (err == 0) return (SHERR_AGAIN); of = 0; while (of < shbuf_size(proc->proc_buff)) { /* * On i386 the buffer is 4096 and 65k otherwise. * Parent is granted 100ms to 'poll' when size exceeds buffer limit. */ err = shproc_write_wait(proc, 100); if (err) return (err); w_len = write(proc->proc_fd, shbuf_data(proc->proc_buff) + of, shbuf_size(proc->proc_buff) - of); if (w_len == -1) return (errno2sherr()); if (w_len == 0) return (SHERR_AGAIN); of += w_len; } return (0); }
int shfs_mem_write(char *path, shbuf_t *buff) { FILE *fl; char hier[NAME_MAX + 1]; char dir[NAME_MAX + 1]; char *n_tok; char *tok; ssize_t b_of; ssize_t b_len; ssize_t len; int err; if (*path != '/') { /* recursive dir generation for relative paths. */ memset(hier, 0, sizeof(hier)); strncpy(hier, path, sizeof(hier) - 1); tok = strtok(hier, "/"); while (tok) { n_tok = strtok(NULL, "/"); if (!n_tok) break; strcat(dir, tok); strcat(dir, "/"); mkdir(dir, 0777); tok = n_tok; } } fl = fopen(path, "wb"); if (!fl) return (-1); b_of = 0; while (b_of < shbuf_size(buff)) { len = MIN(65536, (shbuf_size(buff) - b_of)); b_len = fwrite(shbuf_data(buff) + b_of, sizeof(char), len, fl); if (b_len < 0) return (errno2sherr()); b_of += b_len; } err = fclose(fl); if (err) return (err); return (0); }
int confirm_tx_key(txop_t *op, tx_t *tx) { shkey_t *c_key = &tx->tx_key; shkey_t *key; shbuf_t *buff; tx_t *k_tx; size_t len; int confirm; if (!op || !tx) return (SHERR_INVAL); if (op->op_size == 0) return (0); /* allocate working copy */ len = MAX(sizeof(tx_t), op->op_keylen ? op->op_keylen : op->op_size); buff = shbuf_init(); shbuf_cat(buff, (char *)tx, len); /* blank out tx key */ k_tx = (tx_t *)shbuf_data(buff); memset(&k_tx->tx_key, '\000', sizeof(k_tx->tx_key)); /* verify generated tx key matches. */ key = shkey_bin(shbuf_data(buff), shbuf_size(buff)); confirm = shkey_cmp(c_key, key); shkey_free(&key); shbuf_free(&buff); if (!confirm) { return (SHERR_INVAL); } return (0); }
static int _xd3_read_primary_input(_xd3_file *file, uint8_t *buf, size_t size, size_t *nread) { size_t max_len; if (!file->buff) return (SHERR_IO); max_len = MIN(size, shbuf_size(file->buff)); if (max_len) { memcpy(buf, shbuf_data(file->buff), max_len); shbuf_trim(file->buff, max_len); } if (nread) *nread = max_len; file->nread += max_len; return (0); }
int shfs_file_read(shfs_ino_t *file, unsigned char *data, size_t data_len) { shbuf_t *buff; ssize_t r_len; int err; buff = shbuf_init(); err = shfs_read(file, buff); if (err) { shbuf_free(&buff); return (err); } r_len = MIN(shbuf_size(buff), data_len); if (shbuf_size(buff) != 0) memcpy(data, shbuf_data(buff), r_len); shbuf_free(&buff); return ((int)r_len); }
int shpam_pshadow_load(shfs_ino_t *file, uint64_t uid, shseed_t *ret_seed) { shbuf_t *buff; shseed_t *seeds; int total; int idx; int err; if (ret_seed) memset(ret_seed, 0, sizeof(shseed_t)); buff = shbuf_init(); err = shfs_read(file, buff); if (err) { shbuf_free(&buff); return (err); } seeds = (shseed_t *)shbuf_data(buff); total = shbuf_size(buff) / sizeof(shseed_t); if (!total) { shbuf_free(&buff); return (SHERR_NOENT); /* done */ } for (idx = 0; idx < total; idx++) { if (seeds[idx].seed_uid == uid) break; } if (idx == total) { shbuf_free(&buff); return (SHERR_NOENT); } if (ret_seed) memcpy(ret_seed, &seeds[idx], sizeof(shseed_t)); shbuf_free(&buff); return (0); }
int shpam_pshadow_store(shfs_ino_t *file, shseed_t *seed) { shbuf_t *buff; shseed_t *seeds; int total; int idx; int err; #if 0 /* ensure record exists. */ err = shpam_pshadow_load(file, seed->seed_uid, NULL); if (err) return (err); #endif buff = shbuf_init(); shfs_read(file, buff); seeds = (shseed_t *)shbuf_data(buff); total = shbuf_size(buff) / sizeof(shseed_t); for (idx = 0; idx < total; idx++) { if (seeds[idx].seed_uid == seed->seed_uid) { memcpy(&seeds[idx], seed, sizeof(shseed_t)); break; } } if (idx == total) { shbuf_cat(buff, seed, sizeof(shseed_t)); } err = shfs_write(file, buff); shbuf_free(&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 sharelog_list(shpeer_t *peer, time_t stime, time_t etime) { shbuf_t *buff; fd_set read_fd; shjson_t *json; char tbuf[256]; char *data; time_t now; char *str; int err; int fd; fd = shconnect_host("127.0.0.1", PROCESS_PORT, SHNET_ASYNC); if (fd < 0) return (fd); json = shjson_init(NULL); shjson_num_add(json, "id", 1); shjson_str_add(json, "method", "log.list"); shjson_str_add(json, "key", (char *)shkey_print(shpeer_kpub(peer))); shjson_null_add(json, "params"); str = shjson_print(json); shjson_free(&json); err = shnet_write(fd, str, strlen(str)); free(str); if (err < 0) { shclose(fd); return (err); } err = shnet_write(fd, "\n", 1); if (err < 0) { shclose(fd); return (err); } while (1) { FD_ZERO(&read_fd); FD_SET(fd, &read_fd); err = shnet_verify(&read_fd, NULL, NULL); if (err < 0) { continue; } buff = shnet_read_buf(fd); if (!buff) break; data = shbuf_data(buff); if (!strchr(data, '\n')) continue; json = shjson_init(data); if (json) { char *text = shjson_astr(json, "result", NULL); if (text) { printf("%s", text); } shjson_free(&json); } break; } shclose(fd); return (0); }
ssize_t shnet_read(int fd, const void *buf, size_t count) { unsigned int usk = (unsigned int)fd; struct timeval to; size_t max_r_len; ssize_t r_len; size_t len; fd_set read_set; fd_set exc_set; char tbuf[8]; int err; if (_sk_table[usk].fd == 0) return (SHERR_BADF); if (count == 0) { buf = NULL; count = 65536; } count = MIN(MAX_READ_BUFFER_SIZE, count); if (!_sk_table[usk].recv_buff) _sk_table[usk].recv_buff = shbuf_init(); if (!(_sk_table[usk].flags & SHNET_ASYNC)) { FD_ZERO(&read_set); FD_SET(fd, &read_set); FD_ZERO(&exc_set); FD_SET(fd, &exc_set); /* block for data */ err = select(fd+1, &read_set, NULL, &exc_set, NULL); if (err == -1) return (errno2sherr()); } /* data available for read. */ memset(_read_buff, 0, sizeof(_read_buff)); r_len = read(fd, _read_buff, count); if (r_len == 0) { #if 0 if (shbuf_size(_sk_table[usk].recv_buff) == 0) #endif return (SHERR_CONNRESET); } else if (r_len < 1) { return (errno2sherr()); } else { /* append to internal buffer */ shbuf_cat(_sk_table[usk].recv_buff, _read_buff, r_len); } if (buf) { /* extract head */ r_len = MIN(count, shbuf_size(_sk_table[usk].recv_buff)); if (r_len != 0) { memcpy((char *)buf, (char *)shbuf_data(_sk_table[usk].recv_buff), r_len); shbuf_trim(_sk_table[usk].recv_buff, r_len); } } return (r_len); }
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 sharelog_tail(shpeer_t *peer) { shbuf_t *buff; fd_set read_fd; shjson_t *json; char tbuf[256]; time_t stime, etime; time_t now; char *str; int err; int fd; fd = shconnect_host("127.0.0.1", PROCESS_PORT, SHNET_ASYNC); if (fd < 0) return (fd); json = shjson_init(NULL); shjson_num_add(json, "id", 1); shjson_str_add(json, "method", "log.subscribe"); shjson_str_add(json, "key", (char *)shkey_print(shpeer_kpub(peer))); shjson_null_add(json, "params"); str = shjson_print(json); shjson_free(&json); err = shnet_write(fd, str, strlen(str)); free(str); if (err < 0) { shclose(fd); return (err); } err = shnet_write(fd, "\n", 1); if (err < 0) { shclose(fd); return (err); } while (proc_mode == RUN_TAIL) { FD_ZERO(&read_fd); FD_SET(fd, &read_fd); err = shnet_verify(&read_fd, NULL, NULL); if (err < 0) { continue; } buff = shnet_read_buf(fd); if (!buff || shbuf_size(buff) == 0) continue; json = shjson_init(shbuf_data(buff)); if (json) { char *text = shjson_astr(json, "result", NULL); if (text) { now = time(NULL); strftime(tbuf, sizeof(tbuf) - 1, "%D %T", localtime(&now)); printf("[%s] %s", tbuf, text); } } shbuf_clear(buff); } shclose(fd); return (0); }