librsync  2.0.1
netint.c
1 /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*-
2  *
3  * librsync -- library for network deltas
4  *
5  * Copyright (C) 1999, 2000, 2001 by Martin Pool <[email protected]>
6  * Copyright (C) 1999 by Andrew Tridgell <[email protected]>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this program; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23  /*
24  | Ummm, well, OK. The network's the
25  | network, the computer's the
26  | computer. Sorry for the confusion.
27  | -- Sun Microsystems
28  */
29 
30 /*
31  * Network-byte-order output to the tube.
32  *
33  * All the `suck' routines return a result code. The most common
34  * values are RS_DONE if they have enough data, or RS_BLOCKED if there
35  * is not enough input to proceed.
36  *
37  * All the netint operations are done in a fairly simpleminded way,
38  * since we don't want to rely on stdint types that may not be
39  * available on some platforms.
40  */
41 
42 /*
43  * TODO: If we don't have <stdint.h> (or perhaps even if we do),
44  * determine endianness and integer size by hand and use that to do
45  * our own conversion routines. We possibly need this anyhow to do
46  * 64-bit integers, since there seems to be no ntohs() analog.
47  */
48 
49 #include "config.h"
50 
51 #include <assert.h>
52 #include <sys/types.h>
53 #include <stdlib.h>
54 #include <stdio.h>
55 #include <string.h>
56 
57 #include "librsync.h"
58 
59 #include "job.h"
60 #include "netint.h"
61 #include "trace.h"
62 #include "stream.h"
63 
64 #define RS_MAX_INT_BYTES 8
65 
66 
67 /**
68  * \brief Write a single byte to a stream output.
69  */
71 rs_squirt_byte(rs_job_t *job, unsigned char d)
72 {
73  rs_tube_write(job, &d, 1);
74  return RS_DONE;
75 }
76 
77 
78 /**
79  * \brief Write a variable-length integer to a stream.
80  *
81  * \param job Job of data.
82  *
83  * \param d Datum to write out.
84  *
85  * \param len Length of integer, in bytes.
86  */
88 rs_squirt_netint(rs_job_t *job, rs_long_t d, int len)
89 {
90  unsigned char buf[RS_MAX_INT_BYTES];
91  int i;
92 
93  if (len <= 0 || len > RS_MAX_INT_BYTES) {
94  rs_error("Illegal integer length %d", len);
95  return RS_INTERNAL_ERROR;
96  }
97 
98  /* Fill the output buffer with a bigendian representation of the
99  * number. */
100  for (i = len-1; i >=0; i--) {
101  buf[i] = d; /* truncated */
102  d >>= 8;
103  }
104 
105  rs_tube_write(job, buf, len);
106 
107  return RS_DONE;
108 }
109 
110 
111 
112 rs_result
113 rs_squirt_n4(rs_job_t *job, int val)
114 {
115  return rs_squirt_netint(job, val, 4);
116 }
117 
118 
119 
120 rs_result
121 rs_suck_netint(rs_job_t *job, rs_long_t *v, int len)
122 {
123  unsigned char *buf;
124  int i;
125  rs_result result;
126 
127  if (len <= 0 || len > RS_MAX_INT_BYTES) {
128  rs_error("Illegal integer length %d", len);
129  return RS_INTERNAL_ERROR;
130  }
131 
132  if ((result = rs_scoop_read(job, len, (void **) &buf)) != RS_DONE)
133  return result;
134 
135  *v = 0;
136 
137  for (i = 0; i < len; i++) {
138  *v = *v<<8 | buf[i];
139  }
140 
141  return RS_DONE;
142 }
143 
144 
145 rs_result
146 rs_suck_byte(rs_job_t *job, unsigned char *v)
147 {
148  void *inb;
149  rs_result result;
150 
151  if ((result = rs_scoop_read(job, 1, &inb)) == RS_DONE)
152  *v = *((unsigned char *) inb);
153 
154  return result;
155 }
156 
157 
158 rs_result
159 rs_suck_n4(rs_job_t *job, int *v)
160 {
161  rs_result result;
162  rs_long_t d;
163 
164  result = rs_suck_netint(job, &d, 4);
165  *v = d;
166  return result;
167 }
168 
169 
170 int rs_int_len(rs_long_t val)
171 {
172  if (!(val & ~(rs_long_t)0xff))
173  return 1;
174  else if (!(val & ~(rs_long_t)0xffff))
175  return 2;
176  else if (!(val & ~(rs_long_t)0xffffffff))
177  return 4;
178  else if (!(val & ~(rs_long_t)0xffffffffffffffff))
179  return 8;
180  else {
181  rs_fatal("can't encode integer " PRINTF_FORMAT_U64 " yet", PRINTF_CAST_U64(val));
182  return -1;
183  }
184 }
long long rs_long_t
A long integer type that can handle the largest file offsets.
Public header for librsync.
rs_result
Return codes from nonblocking rsync operations.
Definition: librsync.h:192
Probably a library bug.
Definition: librsync.h:215
Completed successfully.
Definition: librsync.h:193
The contents of this structure are private.
Definition: job.h:29