D-Bus
1.6.8
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-marshal-byteswap.c Swap a block of marshaled data 00003 * 00004 * Copyright (C) 2005 Red Hat, Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 * 00022 */ 00023 00024 #include <config.h> 00025 #include "dbus-marshal-byteswap.h" 00026 #include "dbus-marshal-basic.h" 00027 #include "dbus-signature.h" 00028 00034 static void 00035 byteswap_body_helper (DBusTypeReader *reader, 00036 dbus_bool_t walk_reader_to_end, 00037 int old_byte_order, 00038 int new_byte_order, 00039 unsigned char *p, 00040 unsigned char **new_p) 00041 { 00042 int current_type; 00043 00044 while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID) 00045 { 00046 switch (current_type) 00047 { 00048 case DBUS_TYPE_BYTE: 00049 ++p; 00050 break; 00051 00052 case DBUS_TYPE_INT16: 00053 case DBUS_TYPE_UINT16: 00054 { 00055 p = _DBUS_ALIGN_ADDRESS (p, 2); 00056 *((dbus_uint16_t*)p) = DBUS_UINT16_SWAP_LE_BE (*((dbus_uint16_t*)p)); 00057 p += 2; 00058 } 00059 break; 00060 00061 case DBUS_TYPE_BOOLEAN: 00062 case DBUS_TYPE_INT32: 00063 case DBUS_TYPE_UINT32: 00064 { 00065 p = _DBUS_ALIGN_ADDRESS (p, 4); 00066 *((dbus_uint32_t*)p) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)p)); 00067 p += 4; 00068 } 00069 break; 00070 00071 case DBUS_TYPE_INT64: 00072 case DBUS_TYPE_UINT64: 00073 case DBUS_TYPE_DOUBLE: 00074 { 00075 p = _DBUS_ALIGN_ADDRESS (p, 8); 00076 #ifdef DBUS_HAVE_INT64 00077 *((dbus_uint64_t*)p) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)p)); 00078 #else 00079 _dbus_swap_array (p, 1, 8); 00080 #endif 00081 p += 8; 00082 } 00083 break; 00084 00085 case DBUS_TYPE_ARRAY: 00086 case DBUS_TYPE_STRING: 00087 case DBUS_TYPE_OBJECT_PATH: 00088 { 00089 dbus_uint32_t array_len; 00090 00091 p = _DBUS_ALIGN_ADDRESS (p, 4); 00092 00093 array_len = _dbus_unpack_uint32 (old_byte_order, p); 00094 00095 *((dbus_uint32_t*)p) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)p)); 00096 p += 4; 00097 00098 if (current_type == DBUS_TYPE_ARRAY) 00099 { 00100 int elem_type; 00101 int alignment; 00102 00103 elem_type = _dbus_type_reader_get_element_type (reader); 00104 alignment = _dbus_type_get_alignment (elem_type); 00105 00106 _dbus_assert ((array_len / alignment) < DBUS_MAXIMUM_ARRAY_LENGTH); 00107 00108 p = _DBUS_ALIGN_ADDRESS (p, alignment); 00109 00110 if (dbus_type_is_fixed (elem_type)) 00111 { 00112 if (alignment > 1) 00113 _dbus_swap_array (p, array_len / alignment, alignment); 00114 p += array_len; 00115 } 00116 else 00117 { 00118 DBusTypeReader sub; 00119 const unsigned char *array_end; 00120 00121 array_end = p + array_len; 00122 00123 _dbus_type_reader_recurse (reader, &sub); 00124 00125 while (p < array_end) 00126 { 00127 byteswap_body_helper (&sub, 00128 FALSE, 00129 old_byte_order, 00130 new_byte_order, 00131 p, &p); 00132 } 00133 } 00134 } 00135 else 00136 { 00137 _dbus_assert (current_type == DBUS_TYPE_STRING || 00138 current_type == DBUS_TYPE_OBJECT_PATH); 00139 00140 p += (array_len + 1); /* + 1 for nul */ 00141 } 00142 } 00143 break; 00144 00145 case DBUS_TYPE_SIGNATURE: 00146 { 00147 dbus_uint32_t sig_len; 00148 00149 sig_len = *p; 00150 00151 p += (sig_len + 2); /* +2 for len and nul */ 00152 } 00153 break; 00154 00155 case DBUS_TYPE_VARIANT: 00156 { 00157 /* 1 byte sig len, sig typecodes, align to 00158 * contained-type-boundary, values. 00159 */ 00160 dbus_uint32_t sig_len; 00161 DBusString sig; 00162 DBusTypeReader sub; 00163 int contained_alignment; 00164 00165 sig_len = *p; 00166 ++p; 00167 00168 _dbus_string_init_const_len (&sig, p, sig_len); 00169 00170 p += (sig_len + 1); /* 1 for nul */ 00171 00172 contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (&sig, 0)); 00173 00174 p = _DBUS_ALIGN_ADDRESS (p, contained_alignment); 00175 00176 _dbus_type_reader_init_types_only (&sub, &sig, 0); 00177 00178 byteswap_body_helper (&sub, FALSE, old_byte_order, new_byte_order, p, &p); 00179 } 00180 break; 00181 00182 case DBUS_TYPE_STRUCT: 00183 case DBUS_TYPE_DICT_ENTRY: 00184 { 00185 DBusTypeReader sub; 00186 00187 p = _DBUS_ALIGN_ADDRESS (p, 8); 00188 00189 _dbus_type_reader_recurse (reader, &sub); 00190 00191 byteswap_body_helper (&sub, TRUE, old_byte_order, new_byte_order, p, &p); 00192 } 00193 break; 00194 00195 case DBUS_TYPE_UNIX_FD: 00196 /* fds can only be passed on a local machine, so byte order must always match */ 00197 _dbus_assert_not_reached("attempted to byteswap unix fds which makes no sense"); 00198 break; 00199 00200 default: 00201 _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature"); 00202 break; 00203 } 00204 00205 if (walk_reader_to_end) 00206 _dbus_type_reader_next (reader); 00207 else 00208 break; 00209 } 00210 00211 if (new_p) 00212 *new_p = p; 00213 } 00214 00225 void 00226 _dbus_marshal_byteswap (const DBusString *signature, 00227 int signature_start, 00228 int old_byte_order, 00229 int new_byte_order, 00230 DBusString *value_str, 00231 int value_pos) 00232 { 00233 DBusTypeReader reader; 00234 00235 _dbus_assert (value_pos >= 0); 00236 _dbus_assert (value_pos <= _dbus_string_get_length (value_str)); 00237 00238 if (old_byte_order == new_byte_order) 00239 return; 00240 00241 _dbus_type_reader_init_types_only (&reader, 00242 signature, signature_start); 00243 00244 byteswap_body_helper (&reader, TRUE, 00245 old_byte_order, new_byte_order, 00246 _dbus_string_get_data_len (value_str, value_pos, 0), 00247 NULL); 00248 } 00249 00252 /* Tests in dbus-marshal-byteswap-util.c */