/*- * Copyright (c) 2000-2005 MAEKAWA Masahide * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "compat_stdbool.h" #include "compat_stdint.h" #include "compat_inttypes.h" #include "compat_limits.h" #include "compat_unistd.h" #include "basedef.h" #include "attribute.h" #include "collection.h" #include "cvsync.h" #include "cvsync_attr.h" #include "distfile.h" #include "filetypes.h" #include "hash.h" #include "logmsg.h" #include "mux.h" #include "rcslib.h" #include "version.h" #include "filecmp.h" #include "updater.h" bool filecmp_rcs_fetch(struct filecmp_args *); bool filecmp_rcs_add(struct filecmp_args *); bool filecmp_rcs_add_dir(struct filecmp_args *); bool filecmp_rcs_add_file(struct filecmp_args *); bool filecmp_rcs_add_symlink(struct filecmp_args *); bool filecmp_rcs_remove(struct filecmp_args *); bool filecmp_rcs_attic(struct filecmp_args *); bool filecmp_rcs_setattr(struct filecmp_args *); bool filecmp_rcs_update(struct filecmp_args *); bool filecmp_rcs_update_rcs(struct filecmp_args *, struct cvsync_file *); bool filecmp_rcs_update_symlink(struct filecmp_args *); bool filecmp_rcs_admin(struct filecmp_args *, struct rcslib_file *); bool filecmp_rcs_admin_access(struct filecmp_args *, struct rcslib_file *, size_t); bool filecmp_rcs_admin_symbols(struct filecmp_args *, struct rcslib_file *, size_t); bool filecmp_rcs_admin_locks(struct filecmp_args *, struct rcslib_file *, size_t); bool filecmp_rcs_delta(struct filecmp_args *, struct rcslib_file *, uint32_t *); bool filecmp_rcs_delta_add(struct filecmp_args *, struct rcslib_revision *); bool filecmp_rcs_delta_remove(struct filecmp_args *, struct rcsnum *); bool filecmp_rcs_delta_update(struct filecmp_args *, struct rcslib_revision *, uint8_t *); bool filecmp_rcs_desc(struct filecmp_args *, struct rcslib_file *); bool filecmp_rcs_deltatext(struct filecmp_args *, struct rcslib_file *, uint32_t); bool filecmp_rcs_deltatext_add(struct filecmp_args *, struct rcslib_revision *); bool filecmp_rcs_deltatext_remove(struct filecmp_args *, struct rcsnum *); bool filecmp_rcs_deltatext_update(struct filecmp_args *, struct rcslib_revision *, uint8_t *); bool filecmp_rcs_ignore_rcs(struct filecmp_args *); bool filecmp_rcs_ignore_rcs_delta(struct filecmp_args *, uint32_t *); bool filecmp_rcs_ignore_rcs_deltatext(struct filecmp_args *, uint32_t); bool filecmp_rcs_ignore_rcs_list(struct filecmp_args *, uint8_t); bool filecmp_rcs_ignore_rcs_string(struct filecmp_args *, uint8_t); static const uint8_t _cmde[3] = { 0x00, 0x01, UPDATER_UPDATE_END }; bool filecmp_rcs(struct filecmp_args *fca) { struct cvsync_attr *cap = &fca->fca_attr; for (;;) { if (!filecmp_rcs_fetch(fca)) { logmsg_err("%s FileCmp(RCS): Fetch Error", fca->fca_hostinfo); return (false); } if (cap->ca_tag == FILECMP_END) break; switch (cap->ca_tag) { case FILECMP_ADD: if (!filecmp_rcs_add(fca)) { logmsg_err("%s FileCmp(RCS): %s: ADD Error", fca->fca_hostinfo, fca->fca_path); return (false); } break; case FILECMP_REMOVE: if (!filecmp_rcs_remove(fca)) { logmsg_err("%s FileCmp(RCS): %s: REMOVE Error", fca->fca_hostinfo, fca->fca_path); return (false); } break; case FILECMP_RCS_ATTIC: if (!filecmp_rcs_attic(fca)) { logmsg_err("%s FileCmp(RCS): %s: ATTIC Error", fca->fca_hostinfo, fca->fca_path); return (false); } break; case FILECMP_SETATTR: if (!filecmp_rcs_setattr(fca)) { logmsg_err("%s FileCmp(RCS): %s: SETATTR Error", fca->fca_hostinfo, fca->fca_path); return (false); } break; case FILECMP_UPDATE: if (!filecmp_rcs_update(fca)) { logmsg_err("%s FileCmp(RCS): %s: UPDATE Error", fca->fca_hostinfo, fca->fca_path); return (false); } break; default: logmsg_err("%s FileCmp(RCS): %02x: Unknown Command", cap->ca_tag); return (false); } } return (true); } bool filecmp_rcs_fetch(struct filecmp_args *fca) { struct cvsync_attr *cap = &fca->fca_attr; uint8_t *cmd = fca->fca_cmd; size_t pathlen, len; if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); len = GetWord(cmd); if ((len == 0) || (len > fca->fca_cmdmax - 2)) return (false); if ((cap->ca_tag = cmd[2]) == FILECMP_END) return (len == 1); if (len < 2) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); cap->ca_type = cmd[0]; cap->ca_namelen = GetWord(&cmd[1]); if (cap->ca_namelen > sizeof(cap->ca_name)) return (false); switch (cap->ca_tag) { case FILECMP_ADD: case FILECMP_REMOVE: if (cap->ca_namelen != len - 4) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cap->ca_name, cap->ca_namelen)) { return (false); } break; case FILECMP_RCS_ATTIC: if ((cap->ca_type != FILETYPE_RCS) && (cap->ca_type != FILETYPE_RCS_ATTIC)) { return (false); } if (cap->ca_namelen != len - RCS_ATTRLEN_RCS - 4) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cap->ca_name, cap->ca_namelen)) { return (false); } if (!IS_FILE_RCS(cap->ca_name, cap->ca_namelen)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, RCS_ATTRLEN_RCS)) { return (false); } if (!attr_rcs_decode_rcs(cmd, RCS_ATTRLEN_RCS, cap)) return (false); break; case FILECMP_UPDATE: if (cap->ca_type == FILETYPE_DIR) return (false); if (cap->ca_type == FILETYPE_SYMLINK) { if (len != cap->ca_namelen + 4) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cap->ca_name, cap->ca_namelen)) { return (false); } break; } /* FALLTHROUGH */ case FILECMP_SETATTR: switch (cap->ca_type) { case FILETYPE_DIR: if (cap->ca_namelen != len - RCS_ATTRLEN_DIR - 4) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cap->ca_name, cap->ca_namelen)) { return (false); } if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, RCS_ATTRLEN_DIR)) { return (false); } if (!attr_rcs_decode_dir(cmd, RCS_ATTRLEN_DIR, cap)) return (false); break; case FILETYPE_FILE: if (cap->ca_namelen != len - RCS_ATTRLEN_FILE - 4) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cap->ca_name, cap->ca_namelen)) { return (false); } if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, RCS_ATTRLEN_FILE)) { return (false); } if (!attr_rcs_decode_file(cmd, RCS_ATTRLEN_FILE, cap)) return (false); break; case FILETYPE_RCS: case FILETYPE_RCS_ATTIC: if (cap->ca_namelen != len - RCS_ATTRLEN_RCS - 4) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cap->ca_name, cap->ca_namelen)) { return (false); } if (!IS_FILE_RCS(cap->ca_name, cap->ca_namelen)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, RCS_ATTRLEN_RCS)) { return (false); } if (!attr_rcs_decode_rcs(cmd, RCS_ATTRLEN_RCS, cap)) return (false); break; default: return (false); } break; default: return (false); } if (!cvsync_rcs_pathname((char *)cap->ca_name, cap->ca_namelen)) return (false); if ((pathlen = fca->fca_pathlen + cap->ca_namelen) >= fca->fca_pathmax) return (false); (void)memcpy(fca->fca_rpath, cap->ca_name, cap->ca_namelen); fca->fca_rpath[cap->ca_namelen] = '\0'; if (cap->ca_type == FILETYPE_RCS_ATTIC) { if (!cvsync_rcs_insert_attic(fca->fca_path, pathlen, fca->fca_pathmax)) { return (false); } } return (true); } bool filecmp_rcs_add(struct filecmp_args *fca) { switch (fca->fca_attr.ca_type) { case FILETYPE_DIR: return (filecmp_rcs_add_dir(fca)); case FILETYPE_FILE: case FILETYPE_RCS: case FILETYPE_RCS_ATTIC: return (filecmp_rcs_add_file(fca)); case FILETYPE_SYMLINK: return (filecmp_rcs_add_symlink(fca)); default: break; } return (false); } bool filecmp_rcs_add_dir(struct filecmp_args *fca) { struct cvsync_attr *cap = &fca->fca_attr; struct stat st; uint16_t mode; uint8_t *cmd = fca->fca_cmd; size_t len; if (stat(fca->fca_path, &st) == -1) { if (errno != ENOENT) return (false); return (true); } if (!S_ISDIR(st.st_mode)) return (false); if ((len = cap->ca_namelen + 6) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_ADD; cmd[3] = FILETYPE_DIR; SetWord(&cmd[4], cap->ca_namelen); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 6)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, cap->ca_name, cap->ca_namelen)) { return (false); } mode = RCS_MODE(st.st_mode, fca->fca_umask); if ((len = attr_rcs_encode_dir(&cmd[2], fca->fca_cmdmax - 2, mode)) == 0) { return (false); } SetWord(cmd, len); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, len + 2)) return (false); return (true); } bool filecmp_rcs_add_file(struct filecmp_args *fca) { const struct hash_args *hashops = fca->fca_hash_ops; struct cvsync_attr *cap = &fca->fca_attr; struct cvsync_file *cfp; struct stat st; uint16_t mode; uint8_t *cmd = fca->fca_cmd; off_t size = 0; size_t len; if ((len = cap->ca_namelen + 6) > fca->fca_cmdmax) return (false); if ((cfp = cvsync_fopen(fca->fca_path)) == NULL) { if (stat(fca->fca_path, &st) == -1) { if (errno == ENOENT) return (true); } return (false); } mode = RCS_MODE(cfp->cf_mode, fca->fca_umask); SetWord(cmd, len - 2); cmd[2] = UPDATER_ADD; cmd[3] = cap->ca_type; SetWord(&cmd[4], cap->ca_namelen); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 6)) { cvsync_fclose(cfp); return (false); } if (!mux_send(fca->fca_mux, MUX_UPDATER, cap->ca_name, cap->ca_namelen)) { cvsync_fclose(cfp); return (false); } if ((len = attr_rcs_encode_file(&cmd[2], fca->fca_cmdmax - 2, cfp->cf_mtime, cfp->cf_size, mode)) == 0) { cvsync_fclose(cfp); return (false); } SetWord(cmd, len); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, len + 2)) { cvsync_fclose(cfp); return (false); } if (!(*hashops->init)(&fca->fca_hash_ctx)) { cvsync_fclose(cfp); return (false); } while (size < cfp->cf_size) { if ((cfp->cf_size - size) < CVSYNC_BSIZE) len = (size_t)(cfp->cf_size - size); else len = CVSYNC_BSIZE; if (!cvsync_mmap(cfp, size, len)) { (*hashops->destroy)(fca->fca_hash_ctx); cvsync_fclose(cfp); return (false); } if (!mux_send(fca->fca_mux, MUX_UPDATER, cfp->cf_addr, len)) { (*hashops->destroy)(fca->fca_hash_ctx); cvsync_fclose(cfp); return (false); } (*hashops->update)(fca->fca_hash_ctx, cfp->cf_addr, len); if (!cvsync_munmap(cfp)) { (*hashops->destroy)(fca->fca_hash_ctx); cvsync_fclose(cfp); return (false); } size += (off_t)len; } (*hashops->final)(fca->fca_hash_ctx, cmd); if (!cvsync_fclose(cfp)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, hashops->length)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, _cmde, sizeof(_cmde))) return (false); return (true); } bool filecmp_rcs_add_symlink(struct filecmp_args *fca) { struct cvsync_attr *cap = &fca->fca_attr; uint8_t *cmd = fca->fca_cmd; size_t len; int wn; if ((len = cap->ca_namelen + 6) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_ADD; cmd[3] = FILETYPE_SYMLINK; SetWord(&cmd[4], cap->ca_namelen); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 6)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, cap->ca_name, cap->ca_namelen)) { return (false); } if ((wn = readlink(fca->fca_path, (char *)&cmd[2], fca->fca_cmdmax - 2)) == -1) { if (errno == ENOENT) return (true); return (false); } SetWord(cmd, wn); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, wn + 2)) return (false); return (true); } bool filecmp_rcs_remove(struct filecmp_args *fca) { struct cvsync_attr *cap = &fca->fca_attr; uint8_t *cmd = fca->fca_cmd; size_t len; if ((len = cap->ca_namelen + 6) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_REMOVE; cmd[3] = cap->ca_type; SetWord(&cmd[4], cap->ca_namelen); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 6)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, cap->ca_name, cap->ca_namelen)) { return (false); } return (true); } bool filecmp_rcs_attic(struct filecmp_args *fca) { const struct hash_args *hashops = fca->fca_hash_ops; struct cvsync_attr *cap = &fca->fca_attr; struct cvsync_file *cfp; struct stat st; uint16_t mode; uint8_t *cmd = fca->fca_cmd, tag; size_t base, len; if ((cfp = cvsync_fopen(fca->fca_path)) == NULL) { switch (cap->ca_type) { case FILETYPE_RCS: len = fca->fca_pathlen + cap->ca_namelen; cap->ca_type = FILETYPE_RCS_ATTIC; if (!cvsync_rcs_insert_attic(fca->fca_path, len, fca->fca_pathmax)) { return (false); } break; case FILETYPE_RCS_ATTIC: len = fca->fca_pathlen + cap->ca_namelen + 6; cap->ca_type = FILETYPE_RCS; if (!cvsync_rcs_remove_attic(fca->fca_path, len)) return (false); break; default: return (false); } if (stat(fca->fca_path, &st) == -1) return (false); return (filecmp_rcs_update(fca)); } if (!cvsync_mmap(cfp, 0, cfp->cf_size)) { cvsync_fclose(cfp); return (false); } if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) { cvsync_fclose(cfp); return (false); } if (GetWord(cmd) != 1) { cvsync_fclose(cfp); return (false); } tag = cmd[2]; switch (tag) { case FILECMP_UPDATE_GENERIC: if (!(*hashops->init)(&fca->fca_hash_ctx)) { cvsync_fclose(cfp); return (false); } (*hashops->update)(fca->fca_hash_ctx, cfp->cf_addr, (size_t)cfp->cf_size); (*hashops->final)(fca->fca_hash_ctx, fca->fca_hash); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, hashops->length)) { cvsync_fclose(cfp); return (false); } if (memcmp(fca->fca_hash, cmd, hashops->length) == 0) { if (!cvsync_fclose(cfp)) return (false); if (!filecmp_rcs_setattr(fca)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); if (GetWord(cmd) != 1) return (false); if (cmd[2] != FILECMP_UPDATE_END) return (false); return (true); } break; case FILECMP_UPDATE_RCS: { struct rcslib_file *rcs; if ((rcs = rcslib_init(cfp->cf_addr, cfp->cf_size)) == NULL) { if (!filecmp_rcs_ignore_rcs(fca)) { cvsync_fclose(cfp); return (false); } goto done; } rcslib_destroy(rcs); break; } case FILECMP_UPDATE_RDIFF: if (filecmp_access(fca, cap) == DISTFILE_NORDIFF) { if (filecmp_rdiff_ischanged(fca, cfp)) { if (!filecmp_rcs_setattr(fca)) { cvsync_fclose(cfp); return (false); } goto done; } tag = FILECMP_UPDATE_GENERIC; if (!(*hashops->init)(&fca->fca_hash_ctx)) { cvsync_fclose(cfp); return (false); } (*hashops->update)(fca->fca_hash_ctx, cfp->cf_addr, (size_t)cfp->cf_size); (*hashops->final)(fca->fca_hash_ctx, fca->fca_hash); } break; default: cvsync_fclose(cfp); return (false); } mode = RCS_MODE(cfp->cf_mode, fca->fca_umask); if ((base = cap->ca_namelen + 6) > fca->fca_cmdmax) { cvsync_fclose(cfp); return (false); } if ((len = attr_rcs_encode_rcs(&cmd[6], fca->fca_cmdmax - base, cfp->cf_mtime, mode)) == 0) { cvsync_fclose(cfp); return (false); } SetWord(cmd, len + base - 2); cmd[2] = UPDATER_RCS_ATTIC; cmd[3] = cap->ca_type; SetWord(&cmd[4], cap->ca_namelen); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 6)) { cvsync_fclose(cfp); return (false); } if (!mux_send(fca->fca_mux, MUX_UPDATER, cap->ca_name, cap->ca_namelen)) { cvsync_fclose(cfp); return (false); } if (!mux_send(fca->fca_mux, MUX_UPDATER, &cmd[6], len)) { cvsync_fclose(cfp); return (false); } switch (tag) { case FILECMP_UPDATE_GENERIC: if (!filecmp_generic_update(fca, cfp)) { cvsync_fclose(cfp); return (false); } break; case FILECMP_UPDATE_RCS: if (!filecmp_rcs_update_rcs(fca, cfp)) { cvsync_fclose(cfp); return (false); } break; case FILECMP_UPDATE_RDIFF: if (!filecmp_rdiff_update(fca, cfp)) { cvsync_fclose(cfp); return (false); } break; default: cvsync_fclose(cfp); return (false); } done: if (!cvsync_fclose(cfp)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); if (GetWord(cmd) != 1) return (false); if (cmd[2] != FILECMP_UPDATE_END) return (false); return (true); } bool filecmp_rcs_setattr(struct filecmp_args *fca) { struct cvsync_attr *cap = &fca->fca_attr; struct stat st; uint16_t mode; uint8_t *cmd = fca->fca_cmd; size_t base, len; if (stat(fca->fca_path, &st) == -1) { if ((errno != ENOENT) && (errno != ENOTDIR)) return (false); st.st_mode = 0; } mode = RCS_MODE(st.st_mode, fca->fca_umask); if ((base = cap->ca_namelen + 6) > fca->fca_cmdmax) return (false); len = fca->fca_cmdmax - base; switch (cap->ca_type) { case FILETYPE_DIR: if (cap->ca_mode == mode) return (true); if ((len = attr_rcs_encode_dir(&cmd[6], len, mode)) == 0) return (false); break; case FILETYPE_FILE: if ((cap->ca_mtime == (int64_t)st.st_mtime) && (cap->ca_size == (uint64_t)st.st_size) && (cap->ca_mode == mode)) { return (true); } if ((len = attr_rcs_encode_file(&cmd[6], len, st.st_mtime, st.st_size, mode)) == 0) { return (false); } break; case FILETYPE_RCS: case FILETYPE_RCS_ATTIC: if ((cap->ca_mtime == (int64_t)st.st_mtime) && (cap->ca_mode == mode)) { return (true); } if ((len = attr_rcs_encode_rcs(&cmd[6], len, st.st_mtime, mode)) == 0) { return (false); } break; default: return (false); } SetWord(cmd, len + base - 2); cmd[2] = UPDATER_SETATTR; cmd[3] = cap->ca_type; SetWord(&cmd[4], cap->ca_namelen); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 6)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, cap->ca_name, cap->ca_namelen)) { return (false); } if (!mux_send(fca->fca_mux, MUX_UPDATER, &cmd[6], len)) return (false); return (true); } bool filecmp_rcs_update(struct filecmp_args *fca) { const struct hash_args *hashops = fca->fca_hash_ops; struct cvsync_attr *cap = &fca->fca_attr; struct cvsync_file *cfp; struct stat st; uint16_t mode; uint8_t *cmd = fca->fca_cmd, tag; size_t base, len; if (cap->ca_type == FILETYPE_SYMLINK) return (filecmp_rcs_update_symlink(fca)); if ((cfp = cvsync_fopen(fca->fca_path)) == NULL) { switch (cap->ca_type) { case FILETYPE_FILE: /* Nothing to do. */ break; case FILETYPE_RCS: len = fca->fca_pathlen + cap->ca_namelen; cap->ca_type = FILETYPE_RCS_ATTIC; if (!cvsync_rcs_insert_attic(fca->fca_path, len, fca->fca_pathmax)) { return (false); } if (stat(fca->fca_path, &st) == 0) return (filecmp_rcs_attic(fca)); cap->ca_type = FILETYPE_RCS; if (!cvsync_rcs_remove_attic(fca->fca_path, len + 6)) return (false); break; case FILETYPE_RCS_ATTIC: len = fca->fca_pathlen + cap->ca_namelen + 6; cap->ca_type = FILETYPE_RCS; if (!cvsync_rcs_remove_attic(fca->fca_path, len)) return (false); if (stat(fca->fca_path, &st) == 0) return (filecmp_rcs_attic(fca)); cap->ca_type = FILETYPE_RCS_ATTIC; if (!cvsync_rcs_insert_attic(fca->fca_path, len - 6, fca->fca_pathmax)) { return (false); } break; default: return (false); } if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); if (GetWord(cmd) != 1) return (false); tag = cmd[2]; switch (tag) { case FILECMP_UPDATE_GENERIC: if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, hashops->length)) { return (false); } break; case FILECMP_UPDATE_RCS: if (!filecmp_rcs_ignore_rcs(fca)) return (false); break; case FILECMP_UPDATE_RDIFF: if (!filecmp_rdiff_ignore(fca)) return (false); break; default: return (false); } if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); if (GetWord(cmd) != 1) return (false); if (cmd[2] != FILECMP_UPDATE_END) return (false); return (filecmp_rcs_remove(fca)); } if (!cvsync_mmap(cfp, 0, cfp->cf_size)) { cvsync_fclose(cfp); return (false); } if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) { cvsync_fclose(cfp); return (false); } if (GetWord(cmd) != 1) { cvsync_fclose(cfp); return (false); } tag = cmd[2]; switch (tag) { case FILECMP_UPDATE_GENERIC: if (!(*hashops->init)(&fca->fca_hash_ctx)) { cvsync_fclose(cfp); return (false); } (*hashops->update)(fca->fca_hash_ctx, cfp->cf_addr, (size_t)cfp->cf_size); (*hashops->final)(fca->fca_hash_ctx, fca->fca_hash); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, hashops->length)) { cvsync_fclose(cfp); return (false); } if (memcmp(fca->fca_hash, cmd, hashops->length) == 0) { if (!cvsync_fclose(cfp)) return (false); if (!filecmp_rcs_setattr(fca)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); if (GetWord(cmd) != 1) return (false); if (cmd[2] != FILECMP_UPDATE_END) return (false); return (true); } break; case FILECMP_UPDATE_RCS: { struct rcslib_file *rcs; if ((rcs = rcslib_init(cfp->cf_addr, cfp->cf_size)) == NULL) { if (!filecmp_rcs_ignore_rcs(fca)) { cvsync_fclose(cfp); return (false); } goto done; } rcslib_destroy(rcs); break; } case FILECMP_UPDATE_RDIFF: if (filecmp_access(fca, cap) == DISTFILE_NORDIFF) { if (filecmp_rdiff_ischanged(fca, cfp)) { if (!filecmp_rcs_setattr(fca)) { cvsync_fclose(cfp); return (false); } goto done; } tag = FILECMP_UPDATE_GENERIC; if (!(*hashops->init)(&fca->fca_hash_ctx)) { cvsync_fclose(cfp); return (false); } (*hashops->update)(fca->fca_hash_ctx, cfp->cf_addr, (size_t)cfp->cf_size); (*hashops->final)(fca->fca_hash_ctx, fca->fca_hash); } break; default: cvsync_fclose(cfp); return (false); } mode = RCS_MODE(cfp->cf_mode, fca->fca_umask); if ((base = cap->ca_namelen + 6) > fca->fca_cmdmax) { cvsync_fclose(cfp); return (false); } len = fca->fca_cmdmax - base; switch (cap->ca_type) { case FILETYPE_FILE: if ((len = attr_rcs_encode_file(&cmd[6], len, cfp->cf_mtime, cfp->cf_size, mode)) == 0) { cvsync_fclose(cfp); return (false); } break; case FILETYPE_RCS: case FILETYPE_RCS_ATTIC: if ((len = attr_rcs_encode_rcs(&cmd[6], len, cfp->cf_mtime, mode)) == 0) { cvsync_fclose(cfp); return (false); } break; default: cvsync_fclose(cfp); return (false); } SetWord(cmd, len + base - 2); cmd[2] = UPDATER_UPDATE; cmd[3] = cap->ca_type; SetWord(&cmd[4], cap->ca_namelen); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 6)) { cvsync_fclose(cfp); return (false); } if (!mux_send(fca->fca_mux, MUX_UPDATER, cap->ca_name, cap->ca_namelen)) { cvsync_fclose(cfp); return (false); } if (!mux_send(fca->fca_mux, MUX_UPDATER, &cmd[6], len)) { cvsync_fclose(cfp); return (false); } switch (tag) { case FILECMP_UPDATE_GENERIC: if (!filecmp_generic_update(fca, cfp)) { cvsync_fclose(cfp); return (false); } break; case FILECMP_UPDATE_RCS: if (!filecmp_rcs_update_rcs(fca, cfp)) { cvsync_fclose(cfp); return (false); } break; case FILECMP_UPDATE_RDIFF: if (!filecmp_rdiff_update(fca, cfp)) { cvsync_fclose(cfp); return (false); } break; default: cvsync_fclose(cfp); return (false); } done: if (!cvsync_fclose(cfp)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); if (GetWord(cmd) != 1) return (false); if (cmd[2] != FILECMP_UPDATE_END) return (false); return (true); } bool filecmp_rcs_update_rcs(struct filecmp_args *fca, struct cvsync_file *cfp) { static const uint8_t _cmds[3] = { 0x00, 0x01, UPDATER_UPDATE_RCS }; struct rcslib_file *rcs; uint32_t ndeltas; if ((rcs = rcslib_init(cfp->cf_addr, cfp->cf_size)) == NULL) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, _cmds, sizeof(_cmds))) { rcslib_destroy(rcs); return (false); } if (!filecmp_rcs_admin(fca, rcs)) { rcslib_destroy(rcs); return (false); } if (!filecmp_rcs_delta(fca, rcs, &ndeltas)) { rcslib_destroy(rcs); return (false); } if (!filecmp_rcs_desc(fca, rcs)) { rcslib_destroy(rcs); return (false); } if (!filecmp_rcs_deltatext(fca, rcs, ndeltas)) { rcslib_destroy(rcs); return (false); } rcslib_destroy(rcs); if (!mux_send(fca->fca_mux, MUX_UPDATER, _cmde, sizeof(_cmde))) return (false); return (true); } bool filecmp_rcs_update_symlink(struct filecmp_args *fca) { struct cvsync_attr *cap = &fca->fca_attr; uint8_t *cmd = fca->fca_cmd; size_t base; int wn; if ((base = cap->ca_namelen + 6) >= fca->fca_cmdmax) return (false); cmd[2] = UPDATER_UPDATE; cmd[3] = FILETYPE_SYMLINK; SetWord(&cmd[4], cap->ca_namelen); if ((wn = readlink(fca->fca_path, (char *)&cmd[6], fca->fca_cmdmax - base)) == -1) { return (false); } SetWord(cmd, wn + base - 2); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 6)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, cap->ca_name, cap->ca_namelen)) { return (false); } if (!mux_send(fca->fca_mux, MUX_UPDATER, &cmd[6], wn)) return (false); return (true); } bool filecmp_rcs_admin(struct filecmp_args *fca, struct rcslib_file *rcs) { struct rcsnum *num; struct rcsstr *str; uint8_t *cmd = fca->fca_cmd; size_t len, n; /* head */ num = &rcs->head; if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 2)) return (false); len = GetWord(cmd); if ((len < 2) || (len > fca->fca_cmdmax - 2)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, len)) return (false); if (cmd[0] != FILECMP_UPDATE_RCS_HEAD) return (false); if (len != (size_t)cmd[1] + 2) return (false); len = cmd[1]; if ((len != num->n_len) || (memcmp(&cmd[2], num->n_str, len) != 0)) { if ((len = num->n_len + 4) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_HEAD; cmd[3] = num->n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 4)) return (false); if (num->n_len > 0) { if (!mux_send(fca->fca_mux, MUX_UPDATER, num->n_str, num->n_len)) { return (false); } } } /* branch */ num = &rcs->branch; if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 2)) return (false); len = GetWord(cmd); if ((len < 2) || (len > fca->fca_cmdmax - 2)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, len)) return (false); if (cmd[0] != FILECMP_UPDATE_RCS_BRANCH) return (false); if (len != (size_t)cmd[1] + 2) return (false); len = cmd[1]; if ((len != num->n_len) || (memcmp(&cmd[2], num->n_str, len) != 0)) { if ((len = num->n_len + 4) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_BRANCH; cmd[3] = num->n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 4)) return (false); if (num->n_len > 0) { if (!mux_send(fca->fca_mux, MUX_UPDATER, num->n_str, num->n_len)) { return (false); } } } /* access */ if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 4)) return (false); if (GetWord(cmd) != 2) return (false); if (cmd[2] != FILECMP_UPDATE_RCS_ACCESS) return (false); if (!filecmp_rcs_admin_access(fca, rcs, cmd[3])) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); if (GetWord(cmd) != 1) return (false); if (cmd[2] != FILECMP_UPDATE_END) return (false); /* symbols */ if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 2)) return (false); if (fca->fca_proto < CVSYNC_PROTO(0, 24)) { if (GetWord(cmd) != 2) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 2)) return (false); n = cmd[1]; } else { if (GetWord(cmd) != 5) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 5)) return (false); n = GetDWord(&cmd[1]); } if (cmd[0] != FILECMP_UPDATE_RCS_SYMBOLS) return (false); if (!filecmp_rcs_admin_symbols(fca, rcs, n)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); if (GetWord(cmd) != 1) return (false); if (cmd[2] != FILECMP_UPDATE_END) return (false); /* locks */ if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 5)) return (false); if (GetWord(cmd) != 3) return (false); if (cmd[2] != FILECMP_UPDATE_RCS_LOCKS) return (false); n = cmd[4]; if ((cmd[3] != 0) != (rcs->locks.rl_strict != 0)) { SetWord(cmd, 2); cmd[2] = UPDATER_UPDATE_RCS_LOCKS_STRICT; if (rcs->locks.rl_strict != 0) cmd[3] = UPDATER_UPDATE_ADD; else cmd[3] = UPDATER_UPDATE_REMOVE; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 4)) return (false); } if (!filecmp_rcs_admin_locks(fca, rcs, n)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); if (GetWord(cmd) != 1) return (false); if (cmd[2] != FILECMP_UPDATE_END) return (false); /* comment */ str = &rcs->comment; if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 2)) return (false); len = GetWord(cmd); if ((len < 2) || (len > fca->fca_cmdmax - 2)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, len)) return (false); if (cmd[0] != FILECMP_UPDATE_RCS_COMMENT) return (false); if (len != (size_t)cmd[1] + 2) return (false); if ((cmd[1] != str->s_len) || (memcmp(&cmd[2], str->s_str, cmd[1]) != 0)) { if ((len = str->s_len + 4) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_COMMENT; cmd[3] = str->s_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 4)) return (false); if (str->s_len > 0) { if (!mux_send(fca->fca_mux, MUX_UPDATER, str->s_str, str->s_len)) { return (false); } } } /* expand */ str = &rcs->expand; if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 2)) return (false); len = GetWord(cmd); if ((len < 2) || (len > fca->fca_cmdmax - 2)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, len)) return (false); if (cmd[0] != FILECMP_UPDATE_RCS_EXPAND) return (false); if (len != (size_t)cmd[1] + 2) return (false); if ((cmd[1] != str->s_len) || (memcmp(&cmd[2], str->s_str, cmd[1]) != 0)) { if ((len = str->s_len + 4) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_EXPAND; cmd[3] = str->s_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 4)) return (false); if (str->s_len > 0) { if (!mux_send(fca->fca_mux, MUX_UPDATER, str->s_str, str->s_len)) { return (false); } } } if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); if (GetWord(cmd) != 1) return (false); if (cmd[2] != FILECMP_UPDATE_END) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, _cmde, sizeof(_cmde))) return (false); return (true); } bool filecmp_rcs_admin_access(struct filecmp_args *fca, struct rcslib_file *rcs, size_t n) { struct rcsid *i1, *i2, t_id; uint8_t *cmd = fca->fca_cmd; size_t len, c = 0, i = 0; int rv; bool fetched = false; i2 = &t_id; while (i < n) { if (!fetched) { size_t ilen; if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 1)) return (false); ilen = cmd[0]; if ((ilen == 0) || (ilen > fca->fca_cmdmax - 1)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, fca->fca_rvcmd, ilen)) { return (false); } i2->i_id = (char *)fca->fca_rvcmd; i2->i_len = ilen; fetched = true; } if (c == rcs->access.ra_count) { if ((len = i2->i_len + 5) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_ACCESS; cmd[3] = UPDATER_UPDATE_REMOVE; cmd[4] = i2->i_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 5)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, i2->i_id, i2->i_len)) { return (false); } fetched = false; i++; continue; } i1 = &rcs->access.ra_id[c]; rv = rcslib_cmp_id(i1, i2); if (rv == 0) { fetched = false; c++; i++; } else if (rv > 0) { if ((len = i2->i_len + 5) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_ACCESS; cmd[3] = UPDATER_UPDATE_REMOVE; cmd[4] = i2->i_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 5)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, i2->i_id, i2->i_len)) { return (false); } fetched = false; i++; } else { /* rv < 0 */ if ((len = i1->i_len + 5) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_ACCESS; cmd[3] = UPDATER_UPDATE_ADD; cmd[4] = i1->i_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 5)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, i1->i_id, i1->i_len)) { return (false); } c++; } } while (c < rcs->access.ra_count) { i1 = &rcs->access.ra_id[c]; if ((len = i1->i_len + 5) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_ACCESS; cmd[3] = UPDATER_UPDATE_ADD; cmd[4] = i1->i_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 5)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, i1->i_id, i1->i_len)) return (false); c++; } return (true); } bool filecmp_rcs_admin_symbols(struct filecmp_args *fca, struct rcslib_file *rcs, size_t n) { struct rcslib_symbol *sym1, *sym2, t_sym; struct rcsnum *n1, *n2; struct rcssym *s1, *s2; uint8_t *cmd = fca->fca_cmd; size_t len, c = 0, i = 0; int rv; bool fetched = false; sym2 = &t_sym; n2 = &sym2->num; s2 = &sym2->sym; while (i < n) { if (!fetched) { size_t nlen, slen; if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 2)) return (false); if ((slen = (size_t)cmd[0]) == 0) return (false); if ((nlen = (size_t)cmd[1]) == 0) return (false); if ((len = nlen + slen) > fca->fca_cmdmax - 2) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, fca->fca_rvcmd, len)) { return (false); } s2->s_sym = (char *)fca->fca_rvcmd; s2->s_len = slen; if (!rcslib_str2num(&fca->fca_rvcmd[slen], nlen, n2)) return (false); fetched = true; } if (c == rcs->symbols.rs_count) { len = s2->s_len + n2->n_len + 6; if (len > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_SYMBOLS; cmd[3] = UPDATER_UPDATE_REMOVE; cmd[4] = s2->s_len; cmd[5] = n2->n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 6)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, s2->s_sym, s2->s_len)) { return (false); } if (!mux_send(fca->fca_mux, MUX_UPDATER, n2->n_str, n2->n_len)) { return (false); } fetched = false; i++; continue; } sym1 = &rcs->symbols.rs_symbols[c]; rv = rcslib_cmp_symbol(sym1, sym2); if (rv == 0) { fetched = false; c++; i++; } else if (rv > 0) { len = s2->s_len + n2->n_len + 6; if (len > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_SYMBOLS; cmd[3] = UPDATER_UPDATE_REMOVE; cmd[4] = s2->s_len; cmd[5] = n2->n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 6)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, s2->s_sym, s2->s_len)) { return (false); } if (!mux_send(fca->fca_mux, MUX_UPDATER, n2->n_str, n2->n_len)) { return (false); } fetched = false; i++; } else { /* rv < 0 */ n1 = &sym1->num; s1 = &sym1->sym; len = s1->s_len + n1->n_len + 6; if (len > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_SYMBOLS; cmd[3] = UPDATER_UPDATE_ADD; cmd[4] = s1->s_len; cmd[5] = n1->n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 6)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, s1->s_sym, s1->s_len)) { return (false); } if (!mux_send(fca->fca_mux, MUX_UPDATER, n1->n_str, n1->n_len)) { return (false); } c++; } } while (c < rcs->symbols.rs_count) { sym1 = &rcs->symbols.rs_symbols[c]; n1 = &sym1->num; s1 = &sym1->sym; if ((len = s1->s_len + n1->n_len + 6) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_SYMBOLS; cmd[3] = UPDATER_UPDATE_ADD; cmd[4] = s1->s_len; cmd[5] = n1->n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 6)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, s1->s_sym, s1->s_len)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, n1->n_str, n1->n_len)) return (false); c++; } return (true); } bool filecmp_rcs_admin_locks(struct filecmp_args *fca, struct rcslib_file *rcs, size_t n) { struct rcslib_lock *lock1, *lock2, t_lock; struct rcsid *i1, *i2; struct rcsnum *n1, *n2; uint8_t *cmd = fca->fca_cmd; size_t len, c = 0, i = 0; int rv; bool fetched = false; lock2 = &t_lock; i2 = &lock2->id; n2 = &lock2->num; while (i < n) { if (!fetched) { if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 2)) return (false); if ((cmd[0] == 0) || (cmd[1] == 0)) return (false); if ((len = cmd[0] + cmd[1]) > fca->fca_cmdmax - 2) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, fca->fca_rvcmd, len)) { return (false); } i2->i_id = (char *)fca->fca_rvcmd; i2->i_len = cmd[0]; if (!rcslib_str2num(&fca->fca_rvcmd[cmd[0]], cmd[1], n2)) { return (false); } fetched = true; } if (c == rcs->locks.rl_count) { len = i2->i_len + n2->n_len + 6; if (len > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_LOCKS; cmd[3] = UPDATER_UPDATE_REMOVE; cmd[4] = i2->i_len; cmd[5] = n2->n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 6)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, i2->i_id, i2->i_len)) { return (false); } if (!mux_send(fca->fca_mux, MUX_UPDATER, n2->n_str, n2->n_len)) { return (false); } fetched = false; i++; continue; } lock1 = &rcs->locks.rl_locks[c]; rv = rcslib_cmp_lock(lock1, lock2); if (rv == 0) { fetched = false; c++; i++; } else if (rv > 0) { len = i2->i_len + n2->n_len + 6; if (len > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_LOCKS; cmd[3] = UPDATER_UPDATE_REMOVE; cmd[4] = i2->i_len; cmd[5] = n2->n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 6)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, i2->i_id, i2->i_len)) { return (false); } if (!mux_send(fca->fca_mux, MUX_UPDATER, n2->n_str, n2->n_len)) { return (false); } fetched = false; i++; } else { /* rv < 0 */ i1 = &lock1->id; n1 = &lock1->num; len = i1->i_len + n1->n_len + 6; if (len > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_LOCKS; cmd[3] = UPDATER_UPDATE_ADD; cmd[4] = i1->i_len; cmd[5] = n1->n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 6)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, i1->i_id, i1->i_len)) { return (false); } if (!mux_send(fca->fca_mux, MUX_UPDATER, n1->n_str, n1->n_len)) { return (false); } c++; } } while (c < rcs->locks.rl_count) { lock1 = &rcs->locks.rl_locks[c]; i1 = &lock1->id; n1 = &lock1->num; if ((len = i1->i_len + n1->n_len + 6) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_LOCKS; cmd[3] = UPDATER_UPDATE_ADD; cmd[4] = i1->i_len; cmd[5] = n1->n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 6)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, i1->i_id, i1->i_len)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, n1->n_str, n1->n_len)) return (false); c++; } return (true); } bool filecmp_rcs_delta(struct filecmp_args *fca, struct rcslib_file *rcs, uint32_t *ndeltas) { const struct hash_args *hashops = fca->fca_hash_ops; struct rcslib_revision *rev; struct rcsnum num; uint32_t n, i = 0; uint8_t *cmd = fca->fca_cmd, *hash = NULL; size_t len, c = 0; int rv; bool fetched = false; if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 4)) return (false); if ((n = GetDWord(cmd)) == 0) return (false); while (i < n) { if (!fetched) { uint8_t nlen; if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 2)) return (false); len = GetWord(cmd); if ((len < 2) || (len > fca->fca_cmdmax - 2)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, fca->fca_rvcmd, len)) { return (false); } if (fca->fca_rvcmd[0] != FILECMP_UPDATE_RCS_DELTA) return (false); if ((nlen = fca->fca_rvcmd[1]) == 0) return (false); if (len != nlen + hashops->length + 2) return (false); hash = &fca->fca_rvcmd[nlen + 2]; if (!rcslib_str2num(&fca->fca_rvcmd[2], nlen, &num)) return (false); fetched = true; } if (c == rcs->delta.rd_count) { if (!filecmp_rcs_delta_remove(fca, &num)) return (false); fetched = false; i++; continue; } rev = &rcs->delta.rd_rev[c]; rv = rcslib_cmp_num(&rev->num, &num); if (rv == 0) { if (!filecmp_rcs_delta_update(fca, rev, hash)) return (false); fetched = false; c++; i++; } else if (rv > 0) { if (!filecmp_rcs_delta_remove(fca, &num)) return (false); fetched = false; i++; } else { /* rv < 0 */ if (!filecmp_rcs_delta_add(fca, rev)) return (false); c++; } } while (c < rcs->delta.rd_count) { rev = &rcs->delta.rd_rev[c++]; if (!filecmp_rcs_delta_add(fca, rev)) return (false); } if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); if (GetWord(cmd) != 1) return (false); if (cmd[2] != FILECMP_UPDATE_END) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, _cmde, sizeof(_cmde))) return (false); *ndeltas = n; return (true); } bool filecmp_rcs_delta_add(struct filecmp_args *fca, struct rcslib_revision *rev) { const struct hash_args *hashops = fca->fca_hash_ops; struct rcslib_branches *branches = &rev->branches; uint8_t *cmd = fca->fca_cmd; size_t len, i; if (!(*hashops->init)(&fca->fca_hash_ctx)) return (false); len = rev->num.n_len + rev->date.rd_num.n_len + rev->author.i_len; len += rev->state.i_len + rev->next.n_len + hashops->length + 11; for (i = 0 ; i < branches->rb_count ; i++) len += branches->rb_num[i].n_len + 1; if (len > fca->fca_cmdmax) { (*hashops->destroy)(fca->fca_hash_ctx); return (false); } SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_DELTA; cmd[3] = UPDATER_UPDATE_ADD; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 4)) return (false); /* num */ cmd[0] = rev->num.n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 1)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, rev->num.n_str, rev->num.n_len)) { return (false); } /* date */ cmd[0] = rev->date.rd_num.n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 1)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, rev->date.rd_num.n_str, rev->date.rd_num.n_len)) { return (false); } (*hashops->update)(fca->fca_hash_ctx, rev->date.rd_num.n_str, rev->date.rd_num.n_len); /* author */ cmd[0] = rev->author.i_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 1)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, rev->author.i_id, rev->author.i_len)) { return (false); } (*hashops->update)(fca->fca_hash_ctx, rev->author.i_id, rev->author.i_len); /* state */ cmd[0] = rev->state.i_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 1)) return (false); if (rev->state.i_len > 0) { if (!mux_send(fca->fca_mux, MUX_UPDATER, rev->state.i_id, rev->state.i_len)) { return (false); } (*hashops->update)(fca->fca_hash_ctx, rev->state.i_id, rev->state.i_len); } /* branches */ SetWord(cmd, branches->rb_count); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 2)) return (false); for (i = 0 ; i < branches->rb_count ; i++) { struct rcsnum *num = &branches->rb_num[i]; cmd[0] = num->n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 1)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, num->n_str, num->n_len)) { return (false); } (*hashops->update)(fca->fca_hash_ctx, num->n_str, num->n_len); } /* next */ cmd[0] = rev->next.n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 1)) return (false); if (rev->next.n_len > 0) { if (!mux_send(fca->fca_mux, MUX_UPDATER, rev->next.n_str, rev->next.n_len)) { return (false); } (*hashops->update)(fca->fca_hash_ctx, rev->next.n_str, rev->next.n_len); } (*hashops->final)(fca->fca_hash_ctx, cmd); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, hashops->length)) return (false); return (true); } bool filecmp_rcs_delta_remove(struct filecmp_args *fca, struct rcsnum *num) { uint8_t *cmd = fca->fca_cmd; size_t len; if ((len = num->n_len + 5) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_DELTA; cmd[3] = UPDATER_UPDATE_REMOVE; cmd[4] = num->n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 5)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, num->n_str, num->n_len)) return (false); return (true); } bool filecmp_rcs_delta_update(struct filecmp_args *fca, struct rcslib_revision *rev, uint8_t *hash) { const struct hash_args *hashops = fca->fca_hash_ops; struct rcslib_branches *branches = &rev->branches; struct rcsnum *num; uint8_t *cmd = fca->fca_cmd; size_t len, i; if (!(*hashops->init)(&fca->fca_hash_ctx)) return (false); /* date */ (*hashops->update)(fca->fca_hash_ctx, rev->date.rd_num.n_str, rev->date.rd_num.n_len); /* author */ (*hashops->update)(fca->fca_hash_ctx, rev->author.i_id, rev->author.i_len); /* state */ if (rev->state.i_len > 0) { (*hashops->update)(fca->fca_hash_ctx, rev->state.i_id, rev->state.i_len); } /* branches */ for (i = 0 ; i < branches->rb_count ; i++) { num = &branches->rb_num[i]; (*hashops->update)(fca->fca_hash_ctx, num->n_str, num->n_len); } /* next */ if (rev->next.n_len > 0) { (*hashops->update)(fca->fca_hash_ctx, rev->next.n_str, rev->next.n_len); } (*hashops->final)(fca->fca_hash_ctx, fca->fca_hash); if (memcmp(hash, fca->fca_hash, hashops->length) == 0) return (true); len = rev->num.n_len + rev->date.rd_num.n_len + rev->author.i_len; len += rev->state.i_len + rev->next.n_len + hashops->length + 11; for (i = 0 ; i < branches->rb_count ; i++) len += branches->rb_num[i].n_len + 1; if (len > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_DELTA; cmd[3] = UPDATER_UPDATE_UPDATE; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 4)) return (false); /* num */ cmd[0]= rev->num.n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 1)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, rev->num.n_str, rev->num.n_len)) { return (false); } /* date */ cmd[0] = rev->date.rd_num.n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 1)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, rev->date.rd_num.n_str, rev->date.rd_num.n_len)) { return (false); } /* author */ cmd[0] = rev->author.i_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 1)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, rev->author.i_id, rev->author.i_len)) { return (false); } /* state */ cmd[0] = rev->state.i_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 1)) return (false); if (rev->state.i_len > 0) { if (!mux_send(fca->fca_mux, MUX_UPDATER, rev->state.i_id, rev->state.i_len)) { return (false); } } /* branches */ SetWord(cmd, rev->branches.rb_count); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 2)) return (false); for (i = 0 ; i < branches->rb_count ; i++) { num = &branches->rb_num[i]; cmd[0] = num->n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 1)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, num->n_str, num->n_len)) { return (false); } } /* next */ cmd[0] = rev->next.n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 1)) return (false); if (rev->next.n_len > 0) { if (!mux_send(fca->fca_mux, MUX_UPDATER, rev->next.n_str, rev->next.n_len)) { return (false); } } if (!mux_send(fca->fca_mux, MUX_UPDATER, fca->fca_hash, hashops->length)) { return (false); } return (true); } bool filecmp_rcs_desc(struct filecmp_args *fca, struct rcslib_file *rcs) { uint8_t *cmd = fca->fca_cmd; size_t len; /* desc */ if ((len = rcs->desc.s_len + 4) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_DESC; cmd[3] = rcs->desc.s_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 4)) return (false); if (rcs->desc.s_len > 0) { if (!mux_send(fca->fca_mux, MUX_UPDATER, rcs->desc.s_str, rcs->desc.s_len)) { return (false); } } return (true); } bool filecmp_rcs_deltatext(struct filecmp_args *fca, struct rcslib_file *rcs, uint32_t ndeltas) { const struct hash_args *hashops = fca->fca_hash_ops; struct rcslib_revision *rev; struct rcsnum num; uint32_t n, i = 0; uint8_t *cmd = fca->fca_cmd, *hash = NULL; size_t len, c = 0; int rv; bool fetched = false; if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 4)) return (false); if ((n = GetDWord(cmd)) != ndeltas) return (false); /* deltatext */ while (i < n) { if (!fetched) { uint8_t nlen; if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 2)) return (false); len = GetWord(cmd); if ((len < 2) || (len > fca->fca_cmdmax - 2)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, fca->fca_rvcmd, len)) { return (false); } if (fca->fca_rvcmd[0] != FILECMP_UPDATE_RCS_DELTATEXT) return (false); if ((nlen = fca->fca_rvcmd[1]) == 0) return (false); if (len != nlen + hashops->length + 2) return (false); hash = &fca->fca_rvcmd[nlen + 2]; if (!rcslib_str2num(&fca->fca_rvcmd[2], nlen, &num)) return (false); fetched = true; } if (c == rcs->delta.rd_count) { if (!filecmp_rcs_deltatext_remove(fca, &num)) return (false); fetched = false; i++; continue; } rev = &rcs->delta.rd_rev[c]; rv = rcslib_cmp_num(&rev->num, &num); if (rv == 0) { if (!filecmp_rcs_deltatext_update(fca, rev, hash)) return (false); fetched = false; c++; i++; } else if (rv > 0) { if (!filecmp_rcs_deltatext_remove(fca, &num)) return (false); fetched = false; i++; } else { /* rv < 0 */ if (!filecmp_rcs_deltatext_add(fca, rev)) return (false); c++; } } while (c < rcs->delta.rd_count) { rev = &rcs->delta.rd_rev[c++]; if (!filecmp_rcs_deltatext_add(fca, rev)) return (false); } if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); if (GetWord(cmd) != 1) return (false); if (cmd[2] != FILECMP_UPDATE_END) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, _cmde, sizeof(_cmde))) return (false); return (true); } bool filecmp_rcs_deltatext_add(struct filecmp_args *fca, struct rcslib_revision *rev) { const struct hash_args *hashops = fca->fca_hash_ops; uint8_t *cmd = fca->fca_cmd; size_t len; if ((len = rev->num.n_len + 5) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_DELTATEXT; cmd[3] = UPDATER_UPDATE_ADD; cmd[4] = rev->num.n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 5)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, rev->num.n_str, rev->num.n_len)) { return (false); } if (!(*hashops->init)(&fca->fca_hash_ctx)) return (false); /* log */ SetDWord(cmd, rev->log.s_len); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 4)) { (*hashops->destroy)(fca->fca_hash_ctx); return (false); } if (rev->log.s_len > 0) { (*hashops->update)(fca->fca_hash_ctx, rev->log.s_str, rev->log.s_len); if (!mux_send(fca->fca_mux, MUX_UPDATER, rev->log.s_str, rev->log.s_len)) { (*hashops->destroy)(fca->fca_hash_ctx); return (false); } } /* text */ SetDDWord(cmd, rev->text.s_len); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 8)) { (*hashops->destroy)(fca->fca_hash_ctx); return (false); } if (rev->text.s_len > 0) { (*hashops->update)(fca->fca_hash_ctx, rev->text.s_str, rev->text.s_len); if (!mux_send(fca->fca_mux, MUX_UPDATER, rev->text.s_str, rev->text.s_len)) { (*hashops->destroy)(fca->fca_hash_ctx); return (false); } } (*hashops->final)(fca->fca_hash_ctx, cmd); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, hashops->length)) return (false); return (true); } bool filecmp_rcs_deltatext_remove(struct filecmp_args *fca, struct rcsnum *num) { uint8_t *cmd = fca->fca_cmd; size_t len; if ((len = num->n_len + 5) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_DELTATEXT; cmd[3] = UPDATER_UPDATE_REMOVE; cmd[4] = num->n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 5)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, num->n_str, num->n_len)) return (false); return (true); } bool filecmp_rcs_deltatext_update(struct filecmp_args *fca, struct rcslib_revision *rev, uint8_t *hash) { const struct hash_args *hashops = fca->fca_hash_ops; uint8_t *cmd = fca->fca_cmd; size_t len; if (!(*hashops->init)(&fca->fca_hash_ctx)) return (false); /* log */ if (rev->log.s_len > 0) { (*hashops->update)(fca->fca_hash_ctx, rev->log.s_str, rev->log.s_len); } /* text */ if (rev->text.s_len > 0) { (*hashops->update)(fca->fca_hash_ctx, rev->text.s_str, rev->text.s_len); } (*hashops->final)(fca->fca_hash_ctx, fca->fca_hash); if (memcmp(hash, fca->fca_hash, hashops->length) == 0) return (true); if ((len = rev->num.n_len + 5) > fca->fca_cmdmax) return (false); SetWord(cmd, len - 2); cmd[2] = UPDATER_UPDATE_RCS_DELTATEXT; cmd[3] = UPDATER_UPDATE_UPDATE; cmd[4] = rev->num.n_len; if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 5)) return (false); if (!mux_send(fca->fca_mux, MUX_UPDATER, rev->num.n_str, rev->num.n_len)) { return (false); } /* log */ SetDWord(cmd, rev->log.s_len); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 4)) return (false); if (rev->log.s_len > 0) { if (!mux_send(fca->fca_mux, MUX_UPDATER, rev->log.s_str, rev->log.s_len)) { return (false); } } /* text */ SetDDWord(cmd, rev->text.s_len); if (!mux_send(fca->fca_mux, MUX_UPDATER, cmd, 8)) return (false); if (rev->text.s_len > 0) { if (!mux_send(fca->fca_mux, MUX_UPDATER, rev->text.s_str, rev->text.s_len)) { return (false); } } if (!mux_send(fca->fca_mux, MUX_UPDATER, fca->fca_hash, hashops->length)) { return (false); } return (true); } bool filecmp_rcs_ignore_rcs(struct filecmp_args *fca) { uint32_t n; uint8_t *cmd = fca->fca_cmd; size_t len; /* head */ if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 2)) return (false); len = GetWord(cmd); if ((len < 2) || (len > fca->fca_cmdmax - 2)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, len)) return (false); if (cmd[0] != FILECMP_UPDATE_RCS_HEAD) return (false); if (len != (size_t)cmd[1] + 2) return (false); /* branch */ if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 2)) return (false); len = GetWord(cmd); if ((len < 2) || (len > fca->fca_cmdmax - 2)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, len)) return (false); if (cmd[0] != FILECMP_UPDATE_RCS_BRANCH) return (false); if (len != (size_t)cmd[1] + 2) return (false); /* access */ if (!filecmp_rcs_ignore_rcs_list(fca, FILECMP_UPDATE_RCS_ACCESS)) return (false); /* symbols */ if (!filecmp_rcs_ignore_rcs_list(fca, FILECMP_UPDATE_RCS_SYMBOLS)) return (false); /* locks */ if (!filecmp_rcs_ignore_rcs_list(fca, FILECMP_UPDATE_RCS_LOCKS)) return (false); /* comment */ if (!filecmp_rcs_ignore_rcs_string(fca, FILECMP_UPDATE_RCS_COMMENT)) return (false); /* expand */ if (!filecmp_rcs_ignore_rcs_string(fca, FILECMP_UPDATE_RCS_EXPAND)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); if (GetWord(cmd) != 1) return (false); if (cmd[2] != FILECMP_UPDATE_END) return (false); /* delta */ if (!filecmp_rcs_ignore_rcs_delta(fca, &n)) return (false); /* deltatext */ if (!filecmp_rcs_ignore_rcs_deltatext(fca, n)) return (false); return (true); } bool filecmp_rcs_ignore_rcs_delta(struct filecmp_args *fca, uint32_t *ndeltas) { const struct hash_args *hashops = fca->fca_hash_ops; uint32_t n, i; uint8_t *cmd = fca->fca_cmd; size_t len; if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 4)) return (false); if ((n = GetDWord(cmd)) == 0) return (false); for (i = 0 ; i < n ; i++) { if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 2)) return (false); len = GetWord(cmd); if ((len < 2) || (len > fca->fca_cmdmax - 2)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, len)) return (false); if (cmd[0] != FILECMP_UPDATE_RCS_DELTA) return (false); if (len != cmd[1] + hashops->length + 2) return (false); } if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); if (GetWord(cmd) != 1) return (false); if (cmd[2] != FILECMP_UPDATE_END) return (false); *ndeltas = n; return (true); } bool filecmp_rcs_ignore_rcs_deltatext(struct filecmp_args *fca, uint32_t ndeltas) { const struct hash_args *hashops = fca->fca_hash_ops; uint32_t n, i; uint8_t *cmd = fca->fca_cmd; size_t len; if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 4)) return (false); if ((n = GetDWord(cmd)) != ndeltas) return (false); for (i = 0 ; i < n ; i++) { if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 2)) return (false); len = GetWord(cmd); if ((len < 2) || (len > fca->fca_cmdmax - 2)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, len)) return (false); if (cmd[0] != FILECMP_UPDATE_RCS_DELTATEXT) return (false); if (len != cmd[1] + hashops->length + 2) return (false); } if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); if (GetWord(cmd) != 1) return (false); if (cmd[2] != FILECMP_UPDATE_END) return (false); return (true); } bool filecmp_rcs_ignore_rcs_list(struct filecmp_args *fca, uint8_t type) { uint8_t *cmd = fca->fca_cmd; size_t len, n; switch (type) { case FILECMP_UPDATE_RCS_LOCKS: len = 3; break; case FILECMP_UPDATE_RCS_SYMBOLS: if (fca->fca_proto < CVSYNC_PROTO(0, 24)) len = 2; else len = 5; break; default: len = 2; break; } if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 2)) return (false); if (GetWord(cmd) != (uint16_t)len) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, len)) return (false); if (cmd[0] != type) return (false); if ((type != FILECMP_UPDATE_RCS_SYMBOLS) || (fca->fca_proto < CVSYNC_PROTO(0, 24))) { n = cmd[len - 1]; } else { n = GetDWord(&cmd[1]); } while (n > 0) { if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 2)) return (false); if ((cmd[0] == 0) || (cmd[1] == 1)) return (false); if ((len = cmd[0] + cmd[1]) > fca->fca_cmdmax - 2) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, len)) return (false); n--; } if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 3)) return (false); if (GetWord(cmd) != 1) return (false); if (cmd[2] != FILECMP_UPDATE_END) return (false); return (true); } bool filecmp_rcs_ignore_rcs_string(struct filecmp_args *fca, uint8_t type) { uint8_t *cmd = fca->fca_cmd; size_t len; if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, 2)) return (false); len = GetWord(cmd); if ((len < 2) || (len > fca->fca_cmdmax - 2)) return (false); if (!mux_recv(fca->fca_mux, MUX_FILECMP_IN, cmd, len)) return (false); if (cmd[0] != type) return (false); if (len != (size_t)cmd[1] + 2) return (false); return (true); }