D-Bus 1.2.24
|
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 "dbus-marshal-byteswap.h" 00025 #include "dbus-marshal-basic.h" 00026 #include "dbus-signature.h" 00027 00033 static void 00034 byteswap_body_helper (DBusTypeReader *reader, 00035 dbus_bool_t walk_reader_to_end, 00036 int old_byte_order, 00037 int new_byte_order, 00038 unsigned char *p, 00039 unsigned char **new_p) 00040 { 00041 int current_type; 00042 00043 while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID) 00044 { 00045 switch (current_type) 00046 { 00047 case DBUS_TYPE_BYTE: 00048 ++p; 00049 break; 00050 00051 case DBUS_TYPE_INT16: 00052 case DBUS_TYPE_UINT16: 00053 { 00054 p = _DBUS_ALIGN_ADDRESS (p, 2); 00055 *((dbus_uint16_t*)p) = DBUS_UINT16_SWAP_LE_BE (*((dbus_uint16_t*)p)); 00056 p += 2; 00057 } 00058 break; 00059 00060 case DBUS_TYPE_BOOLEAN: 00061 case DBUS_TYPE_INT32: 00062 case DBUS_TYPE_UINT32: 00063 { 00064 p = _DBUS_ALIGN_ADDRESS (p, 4); 00065 *((dbus_uint32_t*)p) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)p)); 00066 p += 4; 00067 } 00068 break; 00069 00070 case DBUS_TYPE_INT64: 00071 case DBUS_TYPE_UINT64: 00072 case DBUS_TYPE_DOUBLE: 00073 { 00074 p = _DBUS_ALIGN_ADDRESS (p, 8); 00075 #ifdef DBUS_HAVE_INT64 00076 *((dbus_uint64_t*)p) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)p)); 00077 #else 00078 _dbus_swap_array (p, 1, 8); 00079 #endif 00080 p += 8; 00081 } 00082 break; 00083 00084 case DBUS_TYPE_ARRAY: 00085 case DBUS_TYPE_STRING: 00086 case DBUS_TYPE_OBJECT_PATH: 00087 { 00088 dbus_uint32_t array_len; 00089 00090 p = _DBUS_ALIGN_ADDRESS (p, 4); 00091 00092 array_len = _dbus_unpack_uint32 (old_byte_order, p); 00093 00094 *((dbus_uint32_t*)p) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)p)); 00095 p += 4; 00096 00097 if (current_type == DBUS_TYPE_ARRAY) 00098 { 00099 int elem_type; 00100 int alignment; 00101 00102 elem_type = _dbus_type_reader_get_element_type (reader); 00103 alignment = _dbus_type_get_alignment (elem_type); 00104 00105 _dbus_assert ((array_len / alignment) < DBUS_MAXIMUM_ARRAY_LENGTH); 00106 00107 p = _DBUS_ALIGN_ADDRESS (p, alignment); 00108 00109 if (dbus_type_is_fixed (elem_type)) 00110 { 00111 if (alignment > 1) 00112 _dbus_swap_array (p, array_len / alignment, alignment); 00113 p += array_len; 00114 } 00115 else 00116 { 00117 DBusTypeReader sub; 00118 const unsigned char *array_end; 00119 00120 array_end = p + array_len; 00121 00122 _dbus_type_reader_recurse (reader, &sub); 00123 00124 while (p < array_end) 00125 { 00126 byteswap_body_helper (&sub, 00127 FALSE, 00128 old_byte_order, 00129 new_byte_order, 00130 p, &p); 00131 } 00132 } 00133 } 00134 else 00135 { 00136 _dbus_assert (current_type == DBUS_TYPE_STRING || 00137 current_type == DBUS_TYPE_OBJECT_PATH); 00138 00139 p += (array_len + 1); /* + 1 for nul */ 00140 } 00141 } 00142 break; 00143 00144 case DBUS_TYPE_SIGNATURE: 00145 { 00146 dbus_uint32_t sig_len; 00147 00148 sig_len = *p; 00149 00150 p += (sig_len + 2); /* +2 for len and nul */ 00151 } 00152 break; 00153 00154 case DBUS_TYPE_VARIANT: 00155 { 00156 /* 1 byte sig len, sig typecodes, align to 00157 * contained-type-boundary, values. 00158 */ 00159 dbus_uint32_t sig_len; 00160 DBusString sig; 00161 DBusTypeReader sub; 00162 int contained_alignment; 00163 00164 sig_len = *p; 00165 ++p; 00166 00167 _dbus_string_init_const_len (&sig, p, sig_len); 00168 00169 p += (sig_len + 1); /* 1 for nul */ 00170 00171 contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (&sig, 0)); 00172 00173 p = _DBUS_ALIGN_ADDRESS (p, contained_alignment); 00174 00175 _dbus_type_reader_init_types_only (&sub, &sig, 0); 00176 00177 byteswap_body_helper (&sub, FALSE, old_byte_order, new_byte_order, p, &p); 00178 } 00179 break; 00180 00181 case DBUS_TYPE_STRUCT: 00182 case DBUS_TYPE_DICT_ENTRY: 00183 { 00184 DBusTypeReader sub; 00185 00186 p = _DBUS_ALIGN_ADDRESS (p, 8); 00187 00188 _dbus_type_reader_recurse (reader, &sub); 00189 00190 byteswap_body_helper (&sub, TRUE, old_byte_order, new_byte_order, p, &p); 00191 } 00192 break; 00193 00194 default: 00195 _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature"); 00196 break; 00197 } 00198 00199 if (walk_reader_to_end) 00200 _dbus_type_reader_next (reader); 00201 else 00202 break; 00203 } 00204 00205 if (new_p) 00206 *new_p = p; 00207 } 00208 00219 void 00220 _dbus_marshal_byteswap (const DBusString *signature, 00221 int signature_start, 00222 int old_byte_order, 00223 int new_byte_order, 00224 DBusString *value_str, 00225 int value_pos) 00226 { 00227 DBusTypeReader reader; 00228 00229 _dbus_assert (value_pos >= 0); 00230 _dbus_assert (value_pos <= _dbus_string_get_length (value_str)); 00231 00232 if (old_byte_order == new_byte_order) 00233 return; 00234 00235 _dbus_type_reader_init_types_only (&reader, 00236 signature, signature_start); 00237 00238 byteswap_body_helper (&reader, TRUE, 00239 old_byte_order, new_byte_order, 00240 _dbus_string_get_data_len (value_str, value_pos, 0), 00241 NULL); 00242 } 00243 00246 /* Tests in dbus-marshal-byteswap-util.c */