diff options
-rw-r--r-- | checksum.c | 209 | ||||
-rw-r--r-- | compat.c | 284 | ||||
-rw-r--r-- | io.c | 2 | ||||
-rw-r--r-- | options.c | 5 | ||||
-rw-r--r-- | rsync.h | 21 |
5 files changed, 310 insertions, 211 deletions
@@ -52,26 +52,19 @@ extern char *checksum_choice; #define CSUM_MD5 5 #define CSUM_XXH64 6 -#define CSUM_COUNT 7 - -struct csum_struct { - int num; - const char *name, *main_name; -} valid_checksums[] = { +struct name_num_obj valid_checksums = { + "checksum", NULL, NULL, 0, 0, { #ifdef SUPPORT_XXHASH - { CSUM_XXH64, "xxh64", NULL }, - { CSUM_XXH64, "xxhash", NULL }, + { CSUM_XXH64, "xxh64", NULL }, + { CSUM_XXH64, "xxhash", NULL }, #endif - { CSUM_MD5, "md5", NULL }, - { CSUM_MD4, "md4", NULL }, - { CSUM_NONE, "none", NULL }, - { 0, NULL, NULL } + { CSUM_MD5, "md5", NULL }, + { CSUM_MD4, "md4", NULL }, + { CSUM_NONE, "none", "" }, /* The "" prevents us from listing this name by default */ + { 0, NULL, NULL } + } }; -struct csum_struct auto_cs = { 0, "auto", NULL }; - -#define MAX_CHECKSUM_LIST 1024 - #ifndef USE_OPENSSL #define MD5_CTX md_context #define MD5_Init md5_begin @@ -81,74 +74,59 @@ struct csum_struct auto_cs = { 0, "auto", NULL }; int xfersum_type = 0; /* used for the file transfer checksums */ int checksum_type = 0; /* used for the pre-transfer (--checksum) checksums */ -const char *negotiated_csum_name = NULL; -static struct csum_struct *parse_csum_name(const char *name, int len, int allow_auto) +static int parse_csum_name(const char *name, int len) { - struct csum_struct *cs; + struct name_num_item *nni; if (len < 0 && name) len = strlen(name); - if (!name || (allow_auto && len == 4 && strncasecmp(name, "auto", 4) == 0)) { - cs = &auto_cs; + if (!name || (len == 4 && strncasecmp(name, "auto", 4) == 0)) { if (protocol_version >= 30) - cs->num = CSUM_MD5; - else if (protocol_version >= 27) - cs->num = CSUM_MD4_OLD; - else if (protocol_version >= 21) - cs->num = CSUM_MD4_BUSTED; - else - cs->num = CSUM_MD4_ARCHAIC; - return cs; + return CSUM_MD5; + if (protocol_version >= 27) + return CSUM_MD4_OLD; + if (protocol_version >= 21) + return CSUM_MD4_BUSTED; + return CSUM_MD4_ARCHAIC; } - for (cs = valid_checksums; cs->name; cs++) { - if (strncasecmp(name, cs->name, len) == 0 && cs->name[len] == '\0') - return cs; - } + nni = get_nni_by_name(&valid_checksums, name, len); - if (allow_auto) { + if (!nni) { rprintf(FERROR, "unknown checksum name: %s\n", name); exit_cleanup(RERR_UNSUPPORTED); } - return NULL; + return nni->num; } static const char *checksum_name(int num) { - struct csum_struct *cs; - - for (cs = valid_checksums; cs->name; cs++) { - if (num == cs->num) - return cs->name; - } + struct name_num_item *nni = get_nni_by_num(&valid_checksums, num); - if (num < CSUM_MD4) - return "MD4"; - - return "UNKNOWN"; /* IMPOSSIBLE */ + return nni ? nni->name : num < CSUM_MD4 ? "MD4" : "UNKNOWN"; } void parse_checksum_choice(int final_call) { - if (!negotiated_csum_name) { + if (!valid_checksums.negotiated_name) { char *cp = checksum_choice ? strchr(checksum_choice, ',') : NULL; if (cp) { - xfersum_type = parse_csum_name(checksum_choice, cp - checksum_choice, 1)->num; - checksum_type = parse_csum_name(cp+1, -1, 1)->num; + xfersum_type = parse_csum_name(checksum_choice, cp - checksum_choice); + checksum_type = parse_csum_name(cp+1, -1); } else - xfersum_type = checksum_type = parse_csum_name(checksum_choice, -1, 1)->num; + xfersum_type = checksum_type = parse_csum_name(checksum_choice, -1); } if (xfersum_type == CSUM_NONE) whole_file = 1; - if (final_call && DEBUG_GTE(CSUM, am_server ? 2 : 1)) { + if (final_call && DEBUG_GTE(NSTR, am_server ? 2 : 1)) { const char *c_s = am_server ? "Server" : "Client"; - if (negotiated_csum_name) - rprintf(FINFO, "%s negotiated checksum: %s\n", c_s, negotiated_csum_name); + if (valid_checksums.negotiated_name) + rprintf(FINFO, "%s negotiated checksum: %s\n", c_s, valid_checksums.negotiated_name); else if (xfersum_type == checksum_type) { rprintf(FINFO, "%s %s checksum: %s\n", c_s, checksum_choice ? "chosen" : "protocol-based", @@ -162,128 +140,6 @@ void parse_checksum_choice(int final_call) } } -static int parse_checksum_list(const char *from, char *sumbuf, int sumbuf_len, uchar *saw) -{ - char *to = sumbuf, *tok = NULL; - int cnt = 0; - - while (1) { - if (*from == ' ' || !*from) { - if (tok) { - struct csum_struct *cs = parse_csum_name(tok, to - tok, 0); - if (cs && !saw[cs->num]) { - saw[cs->num] = ++cnt; - if (cs->main_name) { - to = tok + strlcpy(tok, cs->main_name, sumbuf_len - (tok - sumbuf)); - if (to - sumbuf >= sumbuf_len) { - to = tok - 1; - break; - } - } - } else - to = tok - (tok != sumbuf); - tok = NULL; - } - if (!*from++) - break; - continue; - } - if (!tok) { - if (to != sumbuf) - *to++ = ' '; - tok = to; - } - if (to - sumbuf >= sumbuf_len - 1) { - to = tok - (tok != sumbuf); - break; - } - *to++ = *from++; - } - *to = '\0'; - - return to - sumbuf; -} - -void negotiate_checksum(int f_in, int f_out, const char *csum_list, int fail_if_empty) -{ - char *tok, sumbuf[MAX_CHECKSUM_LIST]; - uchar saw[CSUM_COUNT]; - struct csum_struct *cs; - int len; - - memset(saw, 0, sizeof saw); - for (len = 1, cs = valid_checksums; cs->name; len++, cs++) { - assert(len <= CSUM_COUNT); - if (saw[cs->num]) - cs->main_name = valid_checksums[saw[cs->num]-1].name; - else - saw[cs->num] = len; - } - memset(saw, 0, sizeof saw); - - /* Simplify the user-provided string so that it contains valid - * checksum names without any duplicates. The client side also - * makes use of the saw values when scanning the server's list. */ - if (csum_list && *csum_list && (!am_server || local_server)) { - len = parse_checksum_list(csum_list, sumbuf, sizeof sumbuf, saw); - if (fail_if_empty && !len) - len = strlcpy(sumbuf, "FAIL", sizeof sumbuf); - csum_list = sumbuf; - } else - csum_list = NULL; - - if (!csum_list || !*csum_list) { - int cnt = 0; - for (cs = valid_checksums, len = 0; cs->name; cs++) { - if (cs->num == CSUM_NONE || cs->main_name) - continue; - if (len) - sumbuf[len++]= ' '; - len += strlcpy(sumbuf+len, cs->name, sizeof sumbuf - len); - if (len >= (int)sizeof sumbuf - 1) - exit_cleanup(RERR_UNSUPPORTED); /* IMPOSSIBLE... */ - saw[cs->num] = ++cnt; - } - } - - if (!am_server && DEBUG_GTE(CSUM, 2)) - rprintf(FINFO, "Client checksum list: %s\n", sumbuf); - - /* Each side sends their list of valid checksum names to the other side and - * then both sides pick the first name in the client's list that is also in - * the server's list. */ - if (!local_server) - write_vstring(f_out, sumbuf, len); - - if (!local_server || read_batch) - len = read_vstring(f_in, sumbuf, sizeof sumbuf); - - if (!am_server && DEBUG_GTE(CSUM, 2)) - rprintf(FINFO, "Server checksum list: %s\n", sumbuf); - - if (len > 0) { - int best = CSUM_COUNT+1; /* We want best == 1 from the client list, so start with a big number. */ - if (am_server) - memset(saw, 1, sizeof saw); /* Since we're parsing client names, anything we parse first is #1. */ - for (tok = strtok(sumbuf, " \t"); tok; tok = strtok(NULL, " \t")) { - cs = parse_csum_name(tok, -1, 0); - if (!cs || !saw[cs->num] || best <= saw[cs->num]) - continue; - xfersum_type = checksum_type = cs->num; - negotiated_csum_name = cs->main_name ? cs->main_name : cs->name; - best = saw[cs->num]; - if (best == 1) - break; - } - if (negotiated_csum_name) - return; - } - - if (!am_server) - rprintf(FERROR, "Failed to negotiate a common checksum\n"); - exit_cleanup(RERR_UNSUPPORTED); -} - int csum_len_for_type(int cst, BOOL flist_csum) { switch (cst) { @@ -525,7 +381,8 @@ void file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum) } #endif default: - rprintf(FERROR, "invalid checksum-choice for the --checksum option (%d)\n", checksum_type); + rprintf(FERROR, "Invalid checksum-choice for --checksum: %s (%d)\n", + checksum_name(checksum_type), checksum_type); exit_cleanup(RERR_UNSUPPORTED); } @@ -551,7 +408,7 @@ void sum_init(int csum_type, int seed) char s[4]; if (csum_type < 0) - csum_type = parse_csum_name(NULL, 0, 1)->num; + csum_type = parse_csum_name(NULL, 0); cursum_type = csum_type; switch (csum_type) { @@ -21,15 +21,6 @@ #include "rsync.h" -int remote_protocol = 0; -int file_extra_cnt = 0; /* count of file-list extras that everyone gets */ -int inc_recurse = 0; -int compat_flags = 0; -int use_safe_inc_flist = 0; -int want_xattr_optim = 0; -int proper_seed_order = 0; -int inplace_partial = 0; - extern int am_server; extern int am_sender; extern int local_server; @@ -56,19 +47,33 @@ extern int preserve_xattrs; extern int xfer_flags_as_varint; extern int need_messages_from_generator; extern int delete_mode, delete_before, delete_during, delete_after; +extern int xfersum_type; +extern int checksum_type; +extern int do_compression; extern char *shell_cmd; extern char *partial_dir; extern char *dest_option; extern char *files_from; extern char *filesfrom_host; extern char *checksum_choice; +extern char *compress_choice; extern filter_rule_list filter_list; extern int need_unsorted_flist; #ifdef ICONV_OPTION extern iconv_t ic_send, ic_recv; extern char *iconv_opt; #endif -extern const char *negotiated_csum_name; +extern struct name_num_obj valid_checksums; + +int remote_protocol = 0; +int file_extra_cnt = 0; /* count of file-list extras that everyone gets */ +int inc_recurse = 0; +int compat_flags = 0; +int use_safe_inc_flist = 0; +int want_xattr_optim = 0; +int proper_seed_order = 0; +int inplace_partial = 0; +int do_negotiated_strings = 0; /* These index values are for the file-list's extra-attribute array. */ int pathname_ndx, depth_ndx, atimes_ndx, uid_ndx, gid_ndx, acls_ndx, xattrs_ndx, unsort_ndx; @@ -80,6 +85,19 @@ int sender_symlink_iconv = 0; /* sender should convert symlink content */ int filesfrom_convert = 0; #endif +#define MAX_NSTR_STRLEN 256 + +#define CPRES_NONE 0 +#define CPRES_ZLIB 1 + +struct name_num_obj valid_compressions = { + "compress", NULL, NULL, 0, 0, { + { CPRES_ZLIB, "zlib", NULL }, + { CPRES_NONE, "none", "" }, /* The "" prevents us from listing this name by default */ + { 0, NULL, NULL } + } +}; + #define CF_INC_RECURSE (1<<0) #define CF_SYMLINK_TIMES (1<<1) #define CF_SYMLINK_ICONV (1<<2) @@ -142,10 +160,227 @@ void set_allow_inc_recurse(void) allow_inc_recurse = 0; } -void setup_protocol(int f_out,int f_in) +struct name_num_item *get_nni_by_name(struct name_num_obj *nno, const char *name, int len) +{ + struct name_num_item *nni; + + if (len < 0) + len = strlen(name); + + for (nni = nno->list; nni->name; nni++) { + if (strncasecmp(name, nni->name, len) == 0 && nni->name[len] == '\0') + return nni; + } + + return NULL; +} + +struct name_num_item *get_nni_by_num(struct name_num_obj *nno, int num) +{ + struct name_num_item *nni; + + for (nni = nno->list; nni->name; nni++) { + if (num == nni->num) + return nni; + } + + return NULL; +} + +static void init_nno_saw(struct name_num_obj *nno, int val) +{ + struct name_num_item *nni; + int cnt; + + if (!nno->saw_len) { + for (nni = nno->list; nni->name; nni++) { + if (nni->num >= nno->saw_len) + nno->saw_len = nni->num + 1; + } + } + + if (!nno->saw) { + if (!(nno->saw = new_array0(uchar, nno->saw_len))) + out_of_memory("init_nno_saw"); + + /* We'll take this opportunity to make sure that the main_name values are set right. */ + for (cnt = 1, nni = nno->list; nni->name; nni++, cnt++) { + if (nno->saw[nni->num]) + nni->main_name = nno->list[nno->saw[nni->num]-1].name; + else + nno->saw[nni->num] = cnt; + } + } + + memset(nno->saw, val, nno->saw_len); +} + +/* Simplify the user-provided string so that it contains valid names without any duplicates. + * It also sets the "saw" flags to a 1-relative count of which name was seen first. */ +static int parse_nni_str(struct name_num_obj *nno, const char *from, char *tobuf, int tobuf_len) +{ + char *to = tobuf, *tok = NULL; + int cnt = 0; + + while (1) { + if (*from == ' ' || !*from) { + if (tok) { + struct name_num_item *nni = get_nni_by_name(nno, tok, to - tok); + if (nni && !nno->saw[nni->num]) { + nno->saw[nni->num] = ++cnt; + if (nni->main_name && *nni->main_name) { + to = tok + strlcpy(tok, nni->main_name, tobuf_len - (tok - tobuf)); + if (to - tobuf >= tobuf_len) { + to = tok - 1; + break; + } + } else + nni->main_name = NULL; /* Override a "" entry */ + } else + to = tok - (tok != tobuf); + tok = NULL; + } + if (!*from++) + break; + continue; + } + if (!tok) { + if (to != tobuf) + *to++ = ' '; + tok = to; + } + if (to - tobuf >= tobuf_len - 1) { + to = tok - (tok != tobuf); + break; + } + *to++ = *from++; + } + *to = '\0'; + + return to - tobuf; +} + +static void recv_negotiate_str(int f_in, struct name_num_obj *nno, char *tmpbuf, int len) +{ + struct name_num_item *ret = NULL; + + if (len < 0) + len = read_vstring(f_in, tmpbuf, MAX_NSTR_STRLEN); + + if (DEBUG_GTE(NSTR, am_server ? 4 : 2)) + rprintf(FINFO, "Server %s list: %s%s\n", nno->type, tmpbuf, am_server ? " (on server)" : ""); + + if (len > 0) { + int best = nno->saw_len; /* We want best == 1 from the client list, so start with a big number. */ + char *tok; + if (am_server) + init_nno_saw(nno, 1); /* Since we're parsing client names, anything we parse first is #1. */ + for (tok = strtok(tmpbuf, " \t"); tok; tok = strtok(NULL, " \t")) { + struct name_num_item *nni = get_nni_by_name(nno, tok, -1); + if (!nni || !nno->saw[nni->num] || best <= nno->saw[nni->num]) + continue; + ret = nni; + best = nno->saw[nni->num]; + if (best == 1) + break; + } + if (ret) { + free(nno->saw); + nno->saw = NULL; + nno->negotiated_name = ret->main_name ? ret->main_name : ret->name; + nno->negotiated_num = ret->num; + return; + } + } + + if (!am_server) + rprintf(FERROR, "Failed to negotiate a common %s\n", nno->type); + exit_cleanup(RERR_UNSUPPORTED); +} + +static void send_negotiate_str(int f_out, struct name_num_obj *nno, const char *env_name) +{ + char tmpbuf[MAX_NSTR_STRLEN]; + struct name_num_item *nni; + const char *list_str = getenv(env_name); + int len, fail_if_empty = list_str && strstr(list_str, "FAIL"); + + if (!do_negotiated_strings) { + if (!am_server && fail_if_empty) { + rprintf(FERROR, "Remote rsync is too old for %s negotation\n", nno->type); + exit_cleanup(RERR_UNSUPPORTED); + } + return; + } + + init_nno_saw(nno, 0); + + if (list_str && *list_str && (!am_server || local_server)) { + len = parse_nni_str(nno, list_str, tmpbuf, MAX_NSTR_STRLEN); + if (fail_if_empty && !len) + len = strlcpy(tmpbuf, "FAIL", MAX_NSTR_STRLEN); + list_str = tmpbuf; + } else + list_str = NULL; + + if (!list_str || !*list_str) { + int cnt = 0; + for (nni = nno->list, len = 0; nni->name; nni++) { + if (nni->main_name) + continue; + if (len) + tmpbuf[len++]= ' '; + len += strlcpy(tmpbuf+len, nni->name, MAX_NSTR_STRLEN - len); + if (len >= (int)MAX_NSTR_STRLEN - 1) + exit_cleanup(RERR_UNSUPPORTED); /* IMPOSSIBLE... */ + nno->saw[nni->num] = ++cnt; + } + } + + if (DEBUG_GTE(NSTR, am_server ? 4 : 2)) + rprintf(FINFO, "Client %s list: %s%s\n", nno->type, tmpbuf, am_server ? " (on server)" : ""); + + if (local_server) { + /* A local server doesn't bother to send/recv the strings, it just constructs + * and parses the same string on both sides. */ + if (!read_batch) + recv_negotiate_str(-1, nno, tmpbuf, len); + } else { + /* Each side sends their list of valid names to the other side and then both sides + * pick the first name in the client's list that is also in the server's list. */ + write_vstring(f_out, tmpbuf, len); + } +} + +static void negotiate_the_strings(int f_in, int f_out) { - int csum_exchange = 0; + /* We send all the negotiation strings before we start to read them to help avoid a slow startup. */ + if (!checksum_choice) + send_negotiate_str(f_out, &valid_checksums, "RSYNC_CHECKSUM_LIST"); + + if (do_compression && !compress_choice) + send_negotiate_str(f_out, &valid_compressions, "RSYNC_COMPRESS_LIST"); + + if (valid_checksums.saw) { + char tmpbuf[MAX_NSTR_STRLEN]; + recv_negotiate_str(f_in, &valid_checksums, tmpbuf, -1); + } + if (valid_checksums.negotiated_name) + xfersum_type = checksum_type = valid_checksums.negotiated_num; + + if (valid_compressions.saw) { + char tmpbuf[MAX_NSTR_STRLEN]; + recv_negotiate_str(f_in, &valid_compressions, tmpbuf, -1); + } +#if 0 + if (valid_compressions.negotiated_name) + compress_type = valid_checksums.negotiated_num; +#endif +} + +void setup_protocol(int f_out,int f_in) +{ assert(file_extra_cnt == 0); assert(EXTRA64_CNT == 2 || EXTRA64_CNT == 1); @@ -296,7 +531,7 @@ void setup_protocol(int f_out,int f_in) compat_flags |= CF_INPLACE_PARTIAL_DIR; if (local_server || strchr(client_info, 'v') != NULL) { if (!write_batch || protocol_version >= 30) { - csum_exchange = 1; + do_negotiated_strings = 1; compat_flags |= CF_VARINT_FLIST_FLAGS; } } @@ -309,7 +544,7 @@ void setup_protocol(int f_out,int f_in) } else { /* read_varint() is compatible with the older write_byte() when the 0x80 bit isn't on. */ compat_flags = read_varint(f_in); if (compat_flags & CF_VARINT_FLIST_FLAGS) - csum_exchange = 1; + do_negotiated_strings = 1; } /* The inc_recurse var MUST be set to 0 or 1. */ inc_recurse = compat_flags & CF_INC_RECURSE ? 1 : 0; @@ -367,16 +602,7 @@ void setup_protocol(int f_out,int f_in) } #endif - if (!checksum_choice) { - const char *rcl = getenv("RSYNC_CHECKSUM_LIST"); - int saw_fail = rcl && strstr(rcl, "FAIL"); - if (csum_exchange) - negotiate_checksum(f_in, f_out, rcl, saw_fail); - else if (!am_server && saw_fail) { - rprintf(FERROR, "Remote rsync is too old for checksum negotation\n"); - exit_cleanup(RERR_UNSUPPORTED); - } - } + negotiate_the_strings(f_in, f_out); if (am_server) { if (!checksum_seed) @@ -389,9 +615,11 @@ void setup_protocol(int f_out,int f_in) init_flist(); } -void maybe_write_checksum(int batch_fd) +void maybe_write_negotiated_strings(int batch_fd) { - assert(negotiated_csum_name != NULL); - if (compat_flags & CF_VARINT_FLIST_FLAGS) - write_vstring(batch_fd, negotiated_csum_name, strlen(negotiated_csum_name)); + if (valid_checksums.negotiated_name) + write_vstring(batch_fd, valid_checksums.negotiated_name, strlen(valid_checksums.negotiated_name)); + + if (valid_compressions.negotiated_name) + write_vstring(batch_fd, valid_compressions.negotiated_name, strlen(valid_compressions.negotiated_name)); } @@ -2369,7 +2369,7 @@ void start_write_batch(int fd) write_int(batch_fd, protocol_version); if (protocol_version >= 30) write_varint(batch_fd, compat_flags); - maybe_write_checksum(batch_fd); + maybe_write_negotiated_strings(batch_fd); write_int(batch_fd, checksum_seed); if (am_sender) @@ -188,6 +188,7 @@ static int remote_option_alloc = 0; int remote_option_cnt = 0; const char **remote_options = NULL; const char *checksum_choice = NULL; +const char *compress_choice = NULL; int quiet = 0; int output_motd = 1; @@ -276,7 +277,6 @@ static struct output_struct debug_words[COUNT_DEBUG+1] = { DEBUG_WORD(CHDIR, W_CLI|W_SRV, "Debug when the current directory changes"), DEBUG_WORD(CONNECT, W_CLI, "Debug connection events (levels 1-2)"), DEBUG_WORD(CMD, W_CLI, "Debug commands+options that are issued (levels 1-2)"), - DEBUG_WORD(CSUM, W_CLI|W_SRV, "Debug checksum negotiation"), DEBUG_WORD(DEL, W_REC, "Debug delete actions (levels 1-3)"), DEBUG_WORD(DELTASUM, W_SND|W_REC, "Debug delta-transfer checksumming (levels 1-4)"), DEBUG_WORD(DUP, W_REC, "Debug weeding of duplicate names"), @@ -289,6 +289,7 @@ static struct output_struct debug_words[COUNT_DEBUG+1] = { DEBUG_WORD(HLINK, W_SND|W_REC, "Debug hard-link actions (levels 1-3)"), DEBUG_WORD(ICONV, W_CLI|W_SRV, "Debug iconv character conversions (levels 1-2)"), DEBUG_WORD(IO, W_CLI|W_SRV, "Debug I/O routines (levels 1-4)"), + DEBUG_WORD(NSTR, W_CLI|W_SRV, "Debug negotiation strings"), DEBUG_WORD(OWN, W_REC, "Debug ownership changes in users & groups (levels 1-2)"), DEBUG_WORD(PROTO, W_CLI|W_SRV, "Debug protocol information"), DEBUG_WORD(RECV, W_REC, "Debug receiver functions"), @@ -451,7 +452,7 @@ static void parse_output_words(struct output_struct *words, short *levels, break; } } - if (len && !words[j].name) { + if (len && !words[j].name && !am_server) { rprintf(FERROR, "Unknown %s item: \"%.*s\"\n", words[j].help, len, str); exit_cleanup(RERR_SYNTAX); @@ -1061,6 +1061,20 @@ typedef struct { #define ACL_READY(sx) ((sx).acc_acl != NULL) #define XATTR_READY(sx) ((sx).xattr != NULL) +struct name_num_item { + int num; + const char *name, *main_name; +}; + +struct name_num_obj { + const char *type; + const char *negotiated_name; + uchar *saw; + int saw_len; + int negotiated_num; + struct name_num_item list[]; +}; + #ifndef __cplusplus #include "proto.h" #endif @@ -1090,7 +1104,6 @@ int vsnprintf(char *str, size_t count, const char *fmt, va_list args); int snprintf(char *str, size_t count, const char *fmt,...); #endif - #ifndef HAVE_STRERROR extern char *sys_errlist[]; #define strerror(i) sys_errlist[i] @@ -1317,8 +1330,7 @@ extern short info_levels[], debug_levels[]; #define DEBUG_CHDIR (DEBUG_BIND+1) #define DEBUG_CONNECT (DEBUG_CHDIR+1) #define DEBUG_CMD (DEBUG_CONNECT+1) -#define DEBUG_CSUM (DEBUG_CMD+1) -#define DEBUG_DEL (DEBUG_CSUM+1) +#define DEBUG_DEL (DEBUG_CMD+1) #define DEBUG_DELTASUM (DEBUG_DEL+1) #define DEBUG_DUP (DEBUG_DELTASUM+1) #define DEBUG_EXIT (DEBUG_DUP+1) @@ -1330,7 +1342,8 @@ extern short info_levels[], debug_levels[]; #define DEBUG_HLINK (DEBUG_HASH+1) #define DEBUG_ICONV (DEBUG_HLINK+1) #define DEBUG_IO (DEBUG_ICONV+1) -#define DEBUG_OWN (DEBUG_IO+1) +#define DEBUG_NSTR (DEBUG_IO+1) +#define DEBUG_OWN (DEBUG_NSTR+1) #define DEBUG_PROTO (DEBUG_OWN+1) #define DEBUG_RECV (DEBUG_PROTO+1) #define DEBUG_SEND (DEBUG_RECV+1) |