diff options
| author | Wayne Davison <wayned@samba.org> | 2006-11-24 08:38:44 +0000 |
|---|---|---|
| committer | Wayne Davison <wayned@samba.org> | 2006-11-24 08:38:44 +0000 |
| commit | 482f48cca9055325330094991378561b603f988f (patch) | |
| tree | 7faa88d73a9a878d39c66d9837739afe4c44653f /io.c | |
| parent | 36e6594dce8b6a5a2dbc8369bff1ded914443fd1 (diff) | |
| download | android_external_rsync-482f48cca9055325330094991378561b603f988f.tar.gz android_external_rsync-482f48cca9055325330094991378561b603f988f.tar.bz2 android_external_rsync-482f48cca9055325330094991378561b603f988f.zip | |
- Fixed a bug when sending a negative 64-bit number (which may not
be needed, but it at least works right now).
- Improved the transmission of 32-bit negative numbers on systems
where the 32-bit type is larger than 32 bits.
- Changed the sending of 64-bit numbers for protocol 30: we send
them in MSB-first order with the number of bytes used in the
transmission encoded into the earliest bits. This lets us save
transmitted bytes for both small and large numbers. The new
method sends from 3 to 9 bytes, the old sent either 4 or 12.
Diffstat (limited to 'io.c')
| -rw-r--r-- | io.c | 180 |
1 files changed, 152 insertions, 28 deletions
@@ -85,6 +85,25 @@ static int select_timeout = SELECT_TIMEOUT; static int active_filecnt = 0; static OFF_T active_bytecnt = 0; +static char int_byte_cnt[256] = { + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 00 - 0F */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 10 - 1F */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 20 - 2F */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 30 - 3F */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 40 - 4F */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 50 - 5F */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 60 - 6F */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 70 - 7F */ + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 80 - 8F */ + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 90 - 9F */ + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* A0 - AF */ + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* B0 - BF */ + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, /* C0 - CF */ + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, /* D0 - DF */ + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, /* E0 - EF */ + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, /* F0 - FF */ +}; + static void read_loop(int fd, char *buf, size_t len); struct flist_ndx_item { @@ -857,9 +876,9 @@ static void readfd(int fd, char *buffer, size_t N) int read_shortint(int f) { - uchar b[2]; - readfd(f, (char *)b, 2); - return (b[1] << 8) + b[0]; + char b[2]; + readfd(f, b, 2); + return (UVAL(b, 1) << 8) + UVAL(b, 0); } int32 read_int(int f) @@ -867,29 +886,65 @@ int32 read_int(int f) char b[4]; int32 num; - readfd(f,b,4); - num = IVAL(b,0); - if (num == (int32)0xffffffff) - return -1; + readfd(f, b, 4); + num = IVAL(b, 0); +#if SIZEOF_INT32 > 4 + if (num & (int32)0x80000000) + num |= ~(int32)0xffffffff; +#endif return num; } int64 read_longint(int f) { int64 num; - char b[8]; - num = read_int(f); + char b[9]; + + if (protocol_version < 30) { + num = read_int(f); - if ((int32)num != (int32)0xffffffff) - return num; + if ((int32)num != (int32)0xffffffff) + return num; #if SIZEOF_INT64 < 8 - rprintf(FERROR, "Integer overflow: attempted 64-bit offset\n"); - exit_cleanup(RERR_UNSUPPORTED); + rprintf(FERROR, "Integer overflow: attempted 64-bit offset\n"); + exit_cleanup(RERR_UNSUPPORTED); #else - readfd(f,b,8); - num = IVAL(b,0) | (((int64)IVAL(b,4))<<32); + readfd(f, b, 8); + num = IVAL(b,0) | (((int64)IVAL(b,4))<<32); #endif + } else { + int cnt; + readfd(f, b, 3); + cnt = int_byte_cnt[CVAL(b, 0)]; + if (cnt > 3) + readfd(f, b + 3, cnt - 3); + switch (cnt) { + case 3: + num = NVAL3(b, 0); + break; + case 4: + num = NVAL4(b, 0x80); + break; + case 5: + num = NVAL5(b, 0xC0); + break; + case 6: + num = NVAL6(b, 0xE0); + break; + case 7: + num = NVAL7(b, 0xF0); + break; + case 8: + num = NVAL8(b, 0xF8); + break; + case 9: + num = NVAL8(b+1, 0); + break; + default: + exit_cleanup(RERR_PROTOCOL); // XXX impossible + } + } return num; } @@ -1239,11 +1294,11 @@ void write_shortint(int f, int x) writefd(f, (char *)b, 2); } -void write_int(int f,int32 x) +void write_int(int f, int32 x) { char b[4]; - SIVAL(b,0,x); - writefd(f,b,4); + SIVAL(b, 0, x); + writefd(f, b, 4); } /* @@ -1252,23 +1307,92 @@ void write_int(int f,int32 x) */ void write_longint(int f, int64 x) { - char b[8]; + char b[12]; - if (x <= 0x7FFFFFFF) { - write_int(f, (int)x); - return; +#if SIZEOF_INT64 < 8 + if (x < 0 || x > 0x7FFFFFFF) { + rprintf(FERROR, "Integer overflow: attempted 64-bit offset\n"); + exit_cleanup(RERR_UNSUPPORTED); } +#endif + if (protocol_version < 30) { + char * const s = b+4; + SIVAL(s, 0, x); #if SIZEOF_INT64 < 8 - rprintf(FERROR, "Integer overflow: attempted 64-bit offset\n"); - exit_cleanup(RERR_UNSUPPORTED); + writefd(f, s, 4); #else - write_int(f, (int32)0xFFFFFFFF); - SIVAL(b,0,(x&0xFFFFFFFF)); - SIVAL(b,4,((x>>32)&0xFFFFFFFF)); + if (x <= 0x7FFFFFFF && x >= 0) { + writefd(f, s, 4); + return; + } - writefd(f,b,8); + memset(b, 0xFF, 4); + SIVAL(s, 4, x >> 32); + writefd(f, b, 12); + } else if (x < 0) { + goto all_bits; #endif + } else if (x < ((int32)1<<(3*8-1))) { + b[0] = (x >> 16); + b[1] = x >> 8; + b[2] = x; + writefd(f, b, 3); + } else if (x < ((int64)1<<(4*8-2))) { + b[0] = (x >> 24) | 0x80; + b[1] = x >> 16; + b[2] = x >> 8; + b[3] = x; + writefd(f, b, 4); + } else if (x < ((int64)1<<(5*8-3))) { + b[0] = (x >> 32) | 0xC0; + b[1] = x >> 24; + b[2] = x >> 16; + b[3] = x >> 8; + b[4] = x; + writefd(f, b, 5); +#if SIZEOF_INT64 >= 8 + } else if (x < ((int64)1<<(6*8-4))) { + b[0] = (x >> 40) | 0xE0; + b[1] = x >> 32; + b[2] = x >> 24; + b[3] = x >> 16; + b[4] = x >> 8; + b[5] = x; + writefd(f, b, 6); + } else if (x < ((int64)1<<(7*8-5))) { + b[0] = (x >> 48) | 0xF0; + b[1] = x >> 40; + b[2] = x >> 32; + b[3] = x >> 24; + b[4] = x >> 16; + b[5] = x >> 8; + b[6] = x; + writefd(f, b, 7); + } else if (x < ((int64)1<<(8*8-6))) { + b[0] = (x >> 56) | 0xF8; + b[1] = x >> 48; + b[2] = x >> 40; + b[3] = x >> 32; + b[4] = x >> 24; + b[5] = x >> 16; + b[6] = x >> 8; + b[7] = x; + writefd(f, b, 8); + } else { + all_bits: + b[0] = 0xFC; + b[1] = x >> 56; + b[2] = x >> 48; + b[3] = x >> 40; + b[4] = x >> 32; + b[5] = x >> 24; + b[6] = x >> 16; + b[7] = x >> 8; + b[8] = x; + writefd(f, b, 9); +#endif + } } void write_buf(int f, const char *buf, size_t len) |
