Use the latest F_*() accessors.
[rsync/rsync.git] / io.c
diff --git a/io.c b/io.c
index fc2ec29..05a755f 100644 (file)
--- a/io.c
+++ b/io.c
@@ -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 {
@@ -323,13 +342,13 @@ void increment_active_files(int ndx, int itemizing, enum logcode code)
        }
 
        active_filecnt++;
-       active_bytecnt += the_file_list->files[ndx]->length;
+       active_bytecnt += F_LENGTH(the_file_list->files[ndx]);
 }
 
 void decrement_active_files(int ndx)
 {
        active_filecnt--;
-       active_bytecnt -= the_file_list->files[ndx]->length;
+       active_bytecnt -= F_LENGTH(the_file_list->files[ndx]);
 }
 
 /* Try to push messages off the list onto the wire.  If we leave with more
@@ -386,6 +405,13 @@ int send_msg(enum msgcode code, const char *buf, int len)
        return 1;
 }
 
+void send_msg_int(enum msgcode code, int num)
+{
+       char numbuf[4];
+       SIVAL(numbuf, 0, num);
+       send_msg(code, numbuf, 4);
+}
+
 int get_redo_num(int itemizing, enum logcode code)
 {
        while (1) {
@@ -855,11 +881,11 @@ static void readfd(int fd, char *buffer, size_t N)
                stats.total_read += total;
 }
 
-int read_shortint(int f)
+unsigned short 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 +893,73 @@ 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 SIZEOF_INT64 < 8
+               if (cnt > 5 || (cnt == 5 && (CVAL(b,0)&0x3F || CVAL(b,1)&0x80))) {
+                       rprintf(FERROR, "Integer overflow: attempted 64-bit offset\n");
+                       exit_cleanup(RERR_UNSUPPORTED);
+               }
+#endif
+               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;
+#if SIZEOF_INT64 >= 8
+               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;
+#endif
+               default:
+                       exit_cleanup(RERR_PROTOCOL); /* impossible... */
+               }
+       }
 
        return num;
 }
@@ -1231,19 +1301,19 @@ static void writefd(int fd, const char *buf, size_t len)
        }
 }
 
-void write_shortint(int f, int x)
+void write_shortint(int f, unsigned short x)
 {
-       uchar b[2];
-       b[0] = x;
-       b[1] = x >> 8;
-       writefd(f, (char *)b, 2);
+       char b[2];
+       b[0] = (char)x;
+       b[1] = (char)(x >> 8);
+       writefd(f, 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,22 +1322,100 @@ 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] = (char)(x >> 16);
+               b[1] = (char)(x >> 8);
+               b[2] = (char)x;
+               writefd(f, b, 3);
+       } else if (x < ((int64)1<<(4*8-2))) {
+               b[0] = (char)((x >> 24) | 0x80);
+               b[1] = (char)(x >> 16);
+               b[2] = (char)(x >> 8);
+               b[3] = (char)x;
+               writefd(f, b, 4);
+#if SIZEOF_INT64 < 8
+       } else {
+               b[0] = 0xC0;
+               b[1] = (char)(x >> 24);
+               b[2] = (char)(x >> 16);
+               b[3] = (char)(x >> 8);
+               b[4] = (char)x;
+               writefd(f, b, 5);
+       }
+#else
+       } else if (x < ((int64)1<<(5*8-3))) {
+               b[0] = (char)((x >> 32) | 0xC0);
+               b[1] = (char)(x >> 24);
+               b[2] = (char)(x >> 16);
+               b[3] = (char)(x >> 8);
+               b[4] = (char)x;
+               writefd(f, b, 5);
+       } else if (x < ((int64)1<<(6*8-4))) {
+               b[0] = (char)((x >> 40) | 0xE0);
+               b[1] = (char)(x >> 32);
+               b[2] = (char)(x >> 24);
+               b[3] = (char)(x >> 16);
+               b[4] = (char)(x >> 8);
+               b[5] = (char)x;
+               writefd(f, b, 6);
+       } else if (x < ((int64)1<<(7*8-5))) {
+               b[0] = (char)((x >> 48) | 0xF0);
+               b[1] = (char)(x >> 40);
+               b[2] = (char)(x >> 32);
+               b[3] = (char)(x >> 24);
+               b[4] = (char)(x >> 16);
+               b[5] = (char)(x >> 8);
+               b[6] = (char)x;
+               writefd(f, b, 7);
+       } else if (x < ((int64)1<<(8*8-6))) {
+               b[0] = (char)((x >> 56) | 0xF8);
+               b[1] = (char)(x >> 48);
+               b[2] = (char)(x >> 40);
+               b[3] = (char)(x >> 32);
+               b[4] = (char)(x >> 24);
+               b[5] = (char)(x >> 16);
+               b[6] = (char)(x >> 8);
+               b[7] = (char)x;
+               writefd(f, b, 8);
+       } else {
+         all_bits:
+               b[0] = (char)0xFC;
+               b[1] = (char)(x >> 56);
+               b[2] = (char)(x >> 48);
+               b[3] = (char)(x >> 40);
+               b[4] = (char)(x >> 32);
+               b[5] = (char)(x >> 24);
+               b[6] = (char)(x >> 16);
+               b[7] = (char)(x >> 8);
+               b[8] = (char)x;
+               writefd(f, b, 9);
+       }
 #endif
 }