void send_file_by_fd(int sfd, int fd){ data_t buf; //发送文件给客户端 while(bzero(&buf, sizeof(buf)), (buf.len = read(fd, buf.data, sizeof(buf.data) - 1)) > 0){ send_complete(sfd, &buf); } }
/** * Sends a pending aggregate message for a given group and message */ void send_pending(int listidx, int pendidx) { switch (group_list[listidx].pending[pendidx].msg) { case REGISTER: send_register(listidx, pendidx); break; case INFO_ACK: send_info_ack(listidx, pendidx, FILEINFO); break; case STATUS: send_status(listidx, pendidx); break; case COMPLETE: send_complete(listidx, pendidx); break; default: log(group_list[listidx].group_id, 0, "Tried to send pending on " "invalid type %s", func_name(group_list[listidx].pending[pendidx].msg)); return; } if (group_list[listidx].pending[pendidx].count <= 0) { // Finish the cleanup we started in load_pending free(group_list[listidx].pending[pendidx].naklist); memset(&group_list[listidx].pending[pendidx], 0, sizeof(struct pr_pending_info_t)); } }
/** * Sends a pending aggregate message for a given group and message */ void send_pending(struct pr_group_list_t *group, int pendidx) { switch (group->pending[pendidx].msg) { case REGISTER: send_register(group, pendidx); break; case FILEINFO_ACK: send_fileinfo_ack(group, pendidx); break; case STATUS: send_status(group, pendidx); break; case COMPLETE: send_complete(group, pendidx); break; default: glog1(group, "Tried to send pending on invalid type %s", func_name(group->pending[pendidx].msg)); return; } if ((group->pending[pendidx].count <= 0) || (group->pending[pendidx].msg == STATUS)) { // Finish the cleanup we started in load_pending // Always do this for a STATUS, since we don't have a pending list free(group->pending[pendidx].naklist); memset(&group->pending[pendidx], 0, sizeof(struct pr_pending_info_t)); } }
/** * Send a COMPLETE with the given status in response to a FILEINFO, * set the phase to MIDGROUP, and reset the timeout */ void early_complete(struct group_list_t *group, int status, int freespace) { group->phase = PHASE_MIDGROUP; group->fileinfo.comp_status = status; send_complete(group, freespace); print_result_status(group); set_timeout(group, 0); }
static void force_completion(guint key_id) { if (completion_framework) { GeanyDocument* doc = document_get_current(); if (doc != NULL) { send_complete(doc->editor, 0); } } }
void send_file_by_name(int sfd, char * file_name){ struct stat file_stat; int status = stat(file_name, &file_stat); int fd = open(file_name, O_RDONLY); long file_len, offset; data_t buf; if(-1 == status || -1 == fd){ send_status(sfd, -1); return; } send_status(sfd, 0); //接收文件续传位置 recv(sfd, &offset, sizeof(long), 0); //重定位到续传位置 lseek(fd, offset, SEEK_SET); //发送文件大小 file_len = file_stat.st_size; send(sfd, &file_len, sizeof(long), 0); //发送文件内容 if(file_len > FILE_MMAP_SIZE){//大文件采用内存映射 int i; long j = 0; long send_len = file_len - offset; //char * mpt = (char *)mmap(0, send_len, PROT_READ, MAP_SHARED, fd, offset); char * mpt = (char *)mmap(0, send_len, PROT_READ, MAP_SHARED, fd, 0); while(j < send_len){ bzero(&buf, sizeof(buf)); for(i = 0; i < sizeof(buf.data) && j < send_len; i++, j++){ buf.data[i] = mpt[j]; } buf.len = i; send_complete(sfd, &buf); } munmap(mpt, send_len); }else{//小文件直接发送 while(bzero(&buf, sizeof(buf)), (buf.len = read(fd, buf.data, sizeof(buf.data) - 1)) > 0){ send_complete(sfd, &buf); } } close(fd); printf("send flie %s, %ld Bytes\n", file_name, file_len); fflush(stdout); }
static gboolean on_editor_notify(GObject* obj, GeanyEditor* editor, SCNotification* nt, gpointer* user_data) { if (!is_completion_file_now()) { return FALSE; } switch (nt->nmhdr.code) { case SCN_UPDATEUI: // TODO relocation suggestion window when typings occur scroll (e.g. editting long line) if (nt->updated & SC_UPDATE_SELECTION) { suggestWindow->close(); } break; case SCN_MODIFIED: // report before insert position, after delete position if (edit_tracker.valid) { if (nt->modificationType & SC_MOD_INSERTTEXT) { if (nt->position == edit_tracker.start_pos + edit_tracker.text.length()) { std::string text(nt->text, nt->length); // nt->text is not null term edit_tracker.text += text; suggestWindow->filter_add(text.c_str()); } else { edit_tracker.valid = false; suggestWindow->close(); } } if (nt->modificationType & SC_MOD_DELETETEXT) { // it was caused by backspace? if (nt->length == 1 && edit_tracker.text.length() > 0 && nt->position + 1 == edit_tracker.start_pos + edit_tracker.text.length()) { edit_tracker.text.erase(edit_tracker.text.size() - 1); suggestWindow->filter_backspace(); } else { edit_tracker.valid = false; suggestWindow->close(); } } } break; case SCN_CHARADDED: if (check_trigger_char(editor)) { send_complete(editor, FALSE); } break; default: break; } return FALSE; }
/** * Read in the contents of a FILEINFO message * Returns 1 on success, 0 on error or ignore */ int read_fileinfo(struct group_list_t *group, const unsigned char *message, int meslen, struct timeval rxtime) { const struct fileinfo_h *fileinfo; const uint32_t *addrlist; int listlen, maxsecsize; const char *name, *flink, *p; fileinfo = (const struct fileinfo_h *)message; addrlist = (const uint32_t *)(message + (fileinfo->hlen * 4)); name = (const char *)message + sizeof(struct fileinfo_h); flink = name + (fileinfo->namelen * 4); listlen = (meslen - (fileinfo->hlen * 4)) / 4; if ((meslen < (fileinfo->hlen * 4)) || ((fileinfo->hlen * 4) < sizeof(struct fileinfo_h)) || ((fileinfo->namelen * 4) > MAXPATHNAME) || ((fileinfo->linklen * 4) > MAXPATHNAME) || ((fileinfo->hlen * 4) != sizeof(struct fileinfo_h) + (fileinfo->namelen * 4) + (fileinfo->linklen * 4))) { glog1(group, "Rejecting FILEINFO from server: invalid message size"); send_abort(group, "Rejecting FILEINFO: invalid message size"); return 0; } if (!uid_in_list(addrlist, listlen)) { set_timeout(group, 0); return 0; } if (group->phase == PHASE_RECEIVING) { // We already got the FILEINFO, so no need to reprocess. // Just resend the INFO_ACK and reset the timeout send_fileinfo_ack(group, group->fileinfo.restart); set_timeout(group, 0); return 0; } if ((group->phase == PHASE_MIDGROUP) && (group->file_id == ntohs(fileinfo->file_id))) { // We already got the FILEINFO, and it's for a completed file. // So resend the COMPLETE and reset the timeout send_complete(group, (fileinfo->ftype == FTYPE_FREESPACE)); set_timeout(group, 0); return 0; } // Load fileinfo params into list memset(&group->fileinfo, 0, sizeof(struct file_t)); group->fileinfo.ftype = fileinfo->ftype; group->file_id = ntohs(fileinfo->file_id); strncpy(group->fileinfo.name, name, fileinfo->namelen * 4); strncpy(group->fileinfo.linkname, flink, fileinfo->linklen * 4); group->fileinfo.size = (f_offset_t)ntohs(fileinfo->hifsize) << 32; group->fileinfo.size |= ntohl(fileinfo->lofsize); if (group->fileinfo.size) { maxsecsize = (group->blocksize * 8 > MAXSECTION ? MAXSECTION : group->blocksize * 8); group->fileinfo.blocks = (int32_t)((group->fileinfo.size / group->blocksize) + (group->fileinfo.size % group->blocksize ? 1 : 0)); group->fileinfo.sections = (group->fileinfo.blocks / maxsecsize) + (group->fileinfo.blocks % maxsecsize ? 1 : 0); group->fileinfo.secsize_small = group->fileinfo.blocks / group->fileinfo.sections; group->fileinfo.secsize_big = group->fileinfo.secsize_small + (group->fileinfo.blocks % group->fileinfo.sections ? 1 : 0); group->fileinfo.big_sections = group->fileinfo.blocks - (group->fileinfo.secsize_small * group->fileinfo.sections); } else { group->fileinfo.blocks = 0; group->fileinfo.sections = 0; group->fileinfo.secsize_small = 0; group->fileinfo.secsize_big = 0; group->fileinfo.big_sections = 0; } group->fileinfo.tstamp = ntohl(fileinfo->ftstamp); group->last_server_ts.tv_sec = ntohl(fileinfo->tstamp_sec); group->last_server_ts.tv_usec = ntohl(fileinfo->tstamp_usec); group->last_server_rx_ts = rxtime; group->fileinfo.fd = -1; // Run some checks on the filename if (strlen(group->fileinfo.name) == 0) { glog1(group, "Rejecting FILEINFO from server: blank file name"); early_complete(group, COMP_STAT_REJECTED, 0); return 0; } p = strstr(group->fileinfo.name, ".."); if ((p != NULL) && ((p[2] == '\x0') || (p[2] == '/') || (p[2] == '\\')) && ((p == group->fileinfo.name) || (p[-1] == '/') || (p[-1] == '\\'))) { glog1(group, "Rejecting FILEINFO from server: filename contains .."); early_complete(group, COMP_STAT_REJECTED, 0); return 0; } if (fileinfo->ftype == FTYPE_LINK) { if (strlen(group->fileinfo.linkname) == 0) { glog1(group, "Rejecting FILEINFO from server: blank link name"); early_complete(group, COMP_STAT_REJECTED, 0); return 0; } } return 1; }
static int send_diffs (krb5_context context, slave *s, int log_fd, const char *database, u_int32_t current_version) { krb5_storage *sp; u_int32_t ver; time_t timestamp; enum kadm_ops op; u_int32_t len; off_t right, left; krb5_data data; int ret = 0; if (s->version == current_version) return 0; if (s->flags & SLAVE_F_DEAD) return 0; sp = kadm5_log_goto_end (log_fd); right = krb5_storage_seek(sp, 0, SEEK_CUR); for (;;) { if (kadm5_log_previous (sp, &ver, ×tamp, &op, &len)) abort (); left = krb5_storage_seek(sp, -16, SEEK_CUR); if (ver == s->version) return 0; if (ver == s->version + 1) break; if (left == 0) return send_complete (context, s, database, current_version); } ret = krb5_data_alloc (&data, right - left + 4); if (ret) { krb5_warn (context, ret, "send_diffs: krb5_data_alloc"); slave_dead(s); return 1; } krb5_storage_read (sp, (char *)data.data + 4, data.length - 4); krb5_storage_free(sp); sp = krb5_storage_from_data (&data); if (sp == NULL) { krb5_warnx (context, "send_diffs: krb5_storage_from_data"); slave_dead(s); return 1; } krb5_store_int32 (sp, FOR_YOU); krb5_storage_free(sp); ret = krb5_write_priv_message(context, s->ac, &s->fd, &data); krb5_data_free(&data); if (ret) { krb5_warn (context, ret, "send_diffs: krb5_write_priv_message"); slave_dead(s); return 1; } slave_seen(s); return 0; }
static int send_diffs (kadm5_server_context *server_context, slave *s, int log_fd, const char *database, uint32_t current_version, uint32_t current_tstamp) { krb5_context context = server_context->context; krb5_storage *sp; uint32_t ver, initial_version, initial_version2; uint32_t initial_tstamp, initial_tstamp2; enum kadm_ops op; uint32_t len; off_t right, left; krb5_ssize_t bytes; krb5_data data; int ret = 0; if (s->flags & SLAVE_F_DEAD) { krb5_warnx(context, "not sending diffs to dead slave %s", s->name); return 0; } if (s->version == current_version) { char buf[4]; sp = krb5_storage_from_mem(buf, 4); if (sp == NULL) krb5_errx(context, IPROPD_RESTART, "krb5_storage_from_mem"); ret = krb5_store_uint32(sp, YOU_HAVE_LAST_VERSION); krb5_storage_free(sp); data.data = buf; data.length = 4; if (ret == 0) { ret = krb5_write_priv_message(context, s->ac, &s->fd, &data); if (ret) { krb5_warn(context, ret, "send_diffs: failed to send to slave"); slave_dead(context, s); } krb5_warnx(context, "slave %s in sync already at version %ld", s->name, (long)s->version); } return ret; } if (verbose) krb5_warnx(context, "sending diffs to live-seeming slave %s", s->name); /* * XXX The code that makes the diffs should be made a separate function, * then error handling (send_are_you_there() or slave_dead()) can be done * here. */ if (flock(log_fd, LOCK_SH) == -1) { krb5_warn(context, errno, "could not obtain shared lock on log file"); send_are_you_there(context, s); return errno; } ret = kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_FIRST, &initial_version, &initial_tstamp); sp = kadm5_log_goto_end(server_context, log_fd); flock(log_fd, LOCK_UN); if (ret) { if (sp != NULL) krb5_storage_free(sp); krb5_warn(context, ret, "send_diffs: failed to read log"); send_are_you_there(context, s); return ret; } if (sp == NULL) { send_are_you_there(context, s); krb5_warn(context, errno ? errno : EINVAL, "send_diffs: failed to read log"); return errno ? errno : EINVAL; } /* * We're not holding any locks here, so we can't prevent truncations. * * We protect against this by re-checking that the initial version and * timestamp are the same before and after this loop. */ right = krb5_storage_seek(sp, 0, SEEK_CUR); if (right == (off_t)-1) { krb5_storage_free(sp); send_are_you_there(context, s); return errno; } for (;;) { ret = kadm5_log_previous (context, sp, &ver, NULL, &op, &len); if (ret) krb5_err(context, IPROPD_RESTART, ret, "send_diffs: failed to find previous entry"); left = krb5_storage_seek(sp, -16, SEEK_CUR); if (left == (off_t)-1) { krb5_storage_free(sp); send_are_you_there(context, s); return errno; } if (ver == s->version + 1) break; /* * We don't expect to reach the slave's version, except when it is * starting empty with the uber record. */ if (ver == s->version && !(ver == 0 && op == kadm_nop)) { /* * This shouldn't happen, but recall we're not holding a lock on * the log. */ krb5_storage_free(sp); krb5_warnx(context, "iprop log truncated while sending diffs to " "slave?? ver = %lu", (unsigned long)ver); send_are_you_there(context, s); return 0; } /* If we've reached the uber record, send the complete database */ if (left == 0 || (ver == 0 && op == kadm_nop)) { krb5_storage_free(sp); krb5_warnx(context, "slave %s (version %lu) out of sync with master " "(first version in log %lu), sending complete database", s->name, (unsigned long)s->version, (unsigned long)ver); return send_complete (context, s, database, current_version, ver, initial_tstamp); } } assert(ver == s->version + 1); krb5_warnx(context, "syncing slave %s from version %lu to version %lu", s->name, (unsigned long)s->version, (unsigned long)current_version); ret = krb5_data_alloc (&data, right - left + 4); if (ret) { krb5_storage_free(sp); krb5_warn (context, ret, "send_diffs: krb5_data_alloc"); send_are_you_there(context, s); return 1; } bytes = krb5_storage_read(sp, (char *)data.data + 4, data.length - 4); krb5_storage_free(sp); if (bytes != data.length - 4) { krb5_warnx(context, "iprop log truncated while sending diffs to " "slave?? ver = %lu", (unsigned long)ver); send_are_you_there(context, s); return 1; } /* * Check that we have the same log initial version and timestamp now as * when we dropped the shared lock on the log file! Else we could be * sending garbage to the slave. */ if (flock(log_fd, LOCK_SH) == -1) { krb5_warn(context, errno, "could not obtain shared lock on log file"); send_are_you_there(context, s); return 1; } ret = kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_FIRST, &initial_version2, &initial_tstamp2); flock(log_fd, LOCK_UN); if (ret) { krb5_warn(context, ret, "send_diffs: failed to read log while producing diffs"); send_are_you_there(context, s); return 1; } if (initial_version != initial_version2 || initial_tstamp != initial_tstamp2) { krb5_warn(context, ret, "send_diffs: log truncated while producing diffs"); send_are_you_there(context, s); return 1; } sp = krb5_storage_from_data (&data); if (sp == NULL) { krb5_warnx (context, "send_diffs: krb5_storage_from_data"); send_are_you_there(context, s); return 1; } krb5_store_uint32 (sp, FOR_YOU); krb5_storage_free(sp); ret = krb5_write_priv_message(context, s->ac, &s->fd, &data); krb5_data_free(&data); if (ret) { krb5_warn (context, ret, "send_diffs: krb5_write_priv_message"); slave_dead(context, s); return 1; } slave_seen(s); s->version = current_version; krb5_warnx(context, "slave %s is now up to date (%u)", s->name, s->version); return 0; }
/** * Gets the current timeout value to use for the main loop * * First check to see if any active groups have an expired timeout, and * handle that timeout. Once all expired timeouts have been handled, find * the active group with the earliest timeout and return the time until that * timeout. If there are no active groups, return NULL. */ struct timeval *getrecenttimeout(void) { static struct timeval tv = {0,0}; struct timeval current_timestamp, min_timestamp; int i, found_timeout, done, sent_naks; struct group_list_t *group; unsigned int section, nak_count; unsigned char *naks; gettimeofday(¤t_timestamp, NULL); done = 0; while (!done) { found_timeout = 0; done = 1; for (i = 0; i < MAXLIST; i++) { group = &group_list[i]; if (group->group_id != 0) { if (cmptimestamp(current_timestamp, group->timeout_time) >= 0) { switch (group->phase) { case PHASE_REGISTERED: send_register(group); break; case PHASE_RECEIVING: case PHASE_MIDGROUP: glog1(group, "Transfer timed out"); send_abort(group, "Transfer timed out"); break; case PHASE_COMPLETE: send_complete(group, 0); break; } done = 0; } else if ((!found_timeout) || (cmptimestamp(group->timeout_time, min_timestamp) < 0)) { glog5(group, "found min timeout time: %d:%06d", group->timeout_time.tv_sec, group->timeout_time.tv_usec); min_timestamp = group->timeout_time; found_timeout = 1; } // Check for a NAK timeout for sending a STATUS or COMPLETE if ((group->fileinfo.nak_time.tv_sec != 0) && cmptimestamp(current_timestamp, group->fileinfo.nak_time) >= 0) { group->fileinfo.nak_time.tv_sec = 0; group->fileinfo.nak_time.tv_usec = 0; // Send NAKs sent_naks = 0; retry_naks: for (section = group->fileinfo.nak_section_first; section < group->fileinfo.nak_section_last; section++) { naks = NULL; nak_count = get_naks(group, section, &naks); glog3(group, "read %d NAKs for section %d", nak_count, section); if (nak_count > 0) { send_status(group, section, naks, nak_count); sent_naks = 1; } free(naks); naks = NULL; } if (file_done(group, 1)) { glog2(group, "File transfer complete"); send_complete(group, 0); file_cleanup(group, 0); } else if (group->fileinfo.got_done && !sent_naks) { // We didn't send any NAKs since the last time // but the server is asking for some, // so check all prior sections group->fileinfo.nak_section_last = group->fileinfo.nak_section_first; group->fileinfo.nak_section_first = 0; group->fileinfo.got_done = 0; goto retry_naks; } } else if ((group->fileinfo.nak_time.tv_sec != 0) && ((!found_timeout) || (cmptimestamp(group->fileinfo.nak_time, min_timestamp) < 0))) { glog5(group, "found min nak time: %d:%06d", group->fileinfo.nak_time.tv_sec, group->fileinfo.nak_time.tv_usec); min_timestamp = group->fileinfo.nak_time; found_timeout = 1; } // Check congestion control feedback timer if (!group->isclr) { if ((group->cc_time.tv_sec != 0) && (cmptimestamp(current_timestamp, group->cc_time) >= 0)) { send_cc_ack(group); } else if ((group->cc_time.tv_sec != 0) && ((!found_timeout) || (cmptimestamp(group->cc_time, min_timestamp) < 0))) { glog5(group, "found min CC time: %d:%06d", group->cc_time.tv_sec, group->cc_time.tv_usec); min_timestamp = group->cc_time; found_timeout = 1; } } } } // Check timeout for proxy key request if (has_proxy && (proxy_pubkey.key == 0)) { if (cmptimestamp(current_timestamp, next_keyreq_time) >= 0) { send_key_req(); done = 0; } else if ((!found_timeout) || (cmptimestamp(next_keyreq_time, min_timestamp) < 0)) { min_timestamp = next_keyreq_time; found_timeout = 1; } } // Check timeout for sending heartbeat if (hbhost_count) { if (cmptimestamp(current_timestamp, next_hb_time) >= 0) { send_hb_request(listener, hb_hosts, hbhost_count, &next_hb_time, hb_interval, uid); done = 0; } else if ((!found_timeout) || (cmptimestamp(next_hb_time, min_timestamp) < 0)) { min_timestamp = next_hb_time; found_timeout = 1; } } } if (found_timeout) { tv = diff_timeval(min_timestamp, current_timestamp); return &tv; } else { return NULL; } }
/** * Gets the current timeout value to use for the main loop * * First check to see if any active groups have an expired timeout, and * handle that timeout. Once all expired timeouts have been handled, find * the active group with the earliest timeout and return the time until that * timeout. If there are no active groups, return NULL. */ struct timeval *getrecenttimeout() { static struct timeval tv = {0,0}; struct timeval current_timestamp, min_timestamp; int i, found_timeout, done; int32_t usecs; gettimeofday(¤t_timestamp, NULL); done = 0; while (!done) { found_timeout = 0; done = 1; for (i = 0; i < MAXLIST; i++) { if (group_list[i].group_id != 0) { if (cmptimestamp(current_timestamp, group_list[i].timeout_time) >= 0) { switch (group_list[i].phase) { case PHASE_REGISTERED: send_register(i); break; case PHASE_RECEIVING: case PHASE_MIDGROUP: log1(group_list[i].group_id, group_list[i].file_id, "Transfer timed out"); send_abort(i, "Transfer timed out"); break; case PHASE_COMPLETE: send_complete(i); break; } done = 0; } else if (!found_timeout) { min_timestamp = group_list[i].timeout_time; found_timeout = 1; } else if (cmptimestamp(group_list[i].timeout_time, min_timestamp) < 0) { min_timestamp = group_list[i].timeout_time; } } } // Check timeout for proxy key request if (has_proxy && (proxy_key == (RSA_key_t)NULL)) { if (cmptimestamp(current_timestamp, next_keyreq_time) >= 0) { send_key_req(); done = 0; } else if ((!found_timeout) || (cmptimestamp(next_keyreq_time, min_timestamp) < 0)) { min_timestamp = next_keyreq_time; found_timeout = 1; } } // Check timeout for sending heartbeat if (hbhost_count) { if (cmptimestamp(current_timestamp, next_hb_time) >= 0) { send_hb_request(listener, hb_hosts, hbhost_count, &next_hb_time, hb_interval); done = 0; } else if ((!found_timeout) || (cmptimestamp(next_hb_time, min_timestamp) < 0)) { min_timestamp = next_hb_time; found_timeout = 1; } } } if (found_timeout) { usecs = (int32_t)diff_usec(min_timestamp, current_timestamp); tv.tv_sec = usecs / 1000000; tv.tv_usec = usecs % 1000000; return &tv; } else { return NULL; } }
static int send_diffs (krb5_context context, slave *s, int log_fd, const char *database, uint32_t current_version) { krb5_storage *sp; uint32_t ver; time_t timestamp; enum kadm_ops op; uint32_t len; off_t right, left; krb5_data data; int ret = 0; if (s->version == current_version) { krb5_warnx(context, "slave %s in sync already at version %ld", s->name, (long)s->version); return 0; } if (s->flags & SLAVE_F_DEAD) return 0; /* if slave is a fresh client, starting over */ if (s->version == 0) { krb5_warnx(context, "sending complete log to fresh slave %s", s->name); return send_complete (context, s, database, current_version); } sp = kadm5_log_goto_end (log_fd); right = krb5_storage_seek(sp, 0, SEEK_CUR); for (;;) { ret = kadm5_log_previous (context, sp, &ver, ×tamp, &op, &len); if (ret) krb5_err(context, 1, ret, "send_diffs: failed to find previous entry"); left = krb5_storage_seek(sp, -16, SEEK_CUR); if (ver == s->version) return 0; if (ver == s->version + 1) break; if (left == 0) { krb5_storage_free(sp); krb5_warnx(context, "slave %s (version %lu) out of sync with master " "(first version in log %lu), sending complete database", s->name, (unsigned long)s->version, (unsigned long)ver); return send_complete (context, s, database, current_version); } } krb5_warnx(context, "syncing slave %s from version %lu to version %lu", s->name, (unsigned long)s->version, (unsigned long)current_version); ret = krb5_data_alloc (&data, right - left + 4); if (ret) { krb5_storage_free(sp); krb5_warn (context, ret, "send_diffs: krb5_data_alloc"); slave_dead(context, s); return 1; } krb5_storage_read (sp, (char *)data.data + 4, data.length - 4); krb5_storage_free(sp); sp = krb5_storage_from_data (&data); if (sp == NULL) { krb5_warnx (context, "send_diffs: krb5_storage_from_data"); slave_dead(context, s); return 1; } krb5_store_int32 (sp, FOR_YOU); krb5_storage_free(sp); ret = krb5_write_priv_message(context, s->ac, &s->fd, &data); krb5_data_free(&data); if (ret) { krb5_warn (context, ret, "send_diffs: krb5_write_priv_message"); slave_dead(context, s); return 1; } slave_seen(s); s->version = current_version; return 0; }