measured_strings.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2009 Lukas Mejdrech
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00038 #include <adt/measured_strings.h>
00039 #include <malloc.h>
00040 #include <mem.h>
00041 #include <unistd.h>
00042 #include <errno.h>
00043 #include <async.h>
00044 
00060 measured_string_t *
00061 measured_string_create_bulk(const uint8_t *string, size_t length)
00062 {
00063         measured_string_t *new;
00064 
00065         if (length == 0) {
00066                 while (string[length])
00067                         length++;
00068         }
00069         new = (measured_string_t *) malloc(sizeof(measured_string_t) +
00070             (sizeof(uint8_t) * (length + 1)));
00071         if (!new)
00072                 return NULL;
00073 
00074         new->length = length;
00075         new->value = ((uint8_t *) new) + sizeof(measured_string_t);
00076         /* Append terminating zero explicitly - to be safe */
00077         memcpy(new->value, string, new->length);
00078         new->value[new->length] = '\0';
00079 
00080         return new;
00081 }
00082 
00090 measured_string_t *measured_string_copy(measured_string_t *source)
00091 {
00092         measured_string_t *new;
00093 
00094         if (!source)
00095                 return NULL;
00096 
00097         new = (measured_string_t *) malloc(sizeof(measured_string_t));
00098         if (new) {
00099                 new->value = (uint8_t *) malloc(source->length + 1);
00100                 if (new->value) {
00101                         new->length = source->length;
00102                         memcpy(new->value, source->value, new->length);
00103                         new->value[new->length] = '\0';
00104                         return new;
00105                 }
00106                 free(new);
00107         }
00108 
00109         return NULL;
00110 }
00111 
00132 int
00133 measured_strings_receive(measured_string_t **strings, uint8_t **data,
00134     size_t count)
00135 {
00136         size_t *lengths;
00137         size_t index;
00138         size_t length;
00139         uint8_t *next;
00140         ipc_callid_t callid;
00141         int rc;
00142 
00143         if ((!strings) || (!data) || (count <= 0))
00144                 return EINVAL;
00145 
00146         lengths = (size_t *) malloc(sizeof(size_t) * (count + 1));
00147         if (!lengths)
00148                 return ENOMEM;
00149 
00150         if ((!async_data_write_receive(&callid, &length)) ||
00151             (length != sizeof(size_t) * (count + 1))) {
00152                 free(lengths);
00153                 return EINVAL;
00154         }
00155         rc = async_data_write_finalize(callid, lengths, length);
00156         if (rc != EOK) {
00157                 free(lengths);
00158                 return rc;
00159         }
00160 
00161         *data = malloc(lengths[count]);
00162         if (!*data) {
00163                 free(lengths);
00164                 return ENOMEM;
00165         }
00166         (*data)[lengths[count] - 1] = '\0';
00167 
00168         *strings = (measured_string_t *) malloc(sizeof(measured_string_t) *
00169             count);
00170         if (!*strings) {
00171                 free(lengths);
00172                 free(*data);
00173                 return ENOMEM;
00174         }
00175 
00176         next = *data;
00177         for (index = 0; index < count; index++) {
00178                 (*strings)[index].length = lengths[index];
00179                 if (lengths[index] > 0) {
00180                         if (!async_data_write_receive(&callid, &length) ||
00181                             (length != lengths[index])) {
00182                                 free(*data);
00183                                 free(*strings);
00184                                 free(lengths);
00185                                 return EINVAL;
00186                         }
00187                         rc = async_data_write_finalize(callid, next,
00188                             lengths[index]);
00189                         if (rc != EOK) {
00190                                 free(*data);
00191                                 free(*strings);
00192                                 free(lengths);
00193                                 return rc;
00194                         }
00195                         (*strings)[index].value = next;
00196                         next += lengths[index];
00197                         *next++ = '\0';
00198                 } else {
00199                         (*strings)[index].value = NULL;
00200                 }
00201         }
00202 
00203         free(lengths);
00204         return EOK;
00205 }
00206 
00214 static size_t *prepare_lengths(const measured_string_t *strings, size_t count)
00215 {
00216         size_t *lengths;
00217         size_t index;
00218         size_t length;
00219 
00220         lengths = (size_t *) malloc(sizeof(size_t) * (count + 1));
00221         if (!lengths)
00222                 return NULL;
00223 
00224         length = 0;
00225         for (index = 0; index < count; index++) {
00226                 lengths[index] = strings[index].length;
00227                 length += lengths[index] + 1;
00228         }
00229         lengths[count] = length;
00230         return lengths;
00231 }
00232 
00250 int measured_strings_reply(const measured_string_t *strings, size_t count)
00251 {
00252         size_t *lengths;
00253         size_t index;
00254         size_t length;
00255         ipc_callid_t callid;
00256         int rc;
00257 
00258         if ((!strings) || (count <= 0))
00259                 return EINVAL;
00260 
00261         lengths = prepare_lengths(strings, count);
00262         if (!lengths)
00263                 return ENOMEM;
00264 
00265         if (!async_data_read_receive(&callid, &length) ||
00266             (length != sizeof(size_t) * (count + 1))) {
00267                 free(lengths);
00268                 return EINVAL;
00269         }
00270         rc = async_data_read_finalize(callid, lengths, length);
00271         if (rc != EOK) {
00272                 free(lengths);
00273                 return rc;
00274         }
00275         free(lengths);
00276 
00277         for (index = 0; index < count; index++) {
00278                 if (strings[index].length > 0) {
00279                         if (!async_data_read_receive(&callid, &length) ||
00280                             (length != strings[index].length)) {
00281                                 return EINVAL;
00282                         }
00283                         rc = async_data_read_finalize(callid,
00284                             strings[index].value, strings[index].length);
00285                         if (rc != EOK)
00286                                 return rc;
00287                 }
00288         }
00289 
00290         return EOK;
00291 }
00292 
00312 int
00313 measured_strings_return(int phone, measured_string_t **strings, uint8_t **data,
00314     size_t count)
00315 {
00316         size_t *lengths;
00317         size_t index;
00318         uint8_t *next;
00319         int rc;
00320 
00321         if ((phone < 0) || (!strings) || (!data) || (count <= 0))
00322                 return EINVAL;
00323 
00324         lengths = (size_t *) malloc(sizeof(size_t) * (count + 1));
00325         if (!lengths)
00326                 return ENOMEM;
00327 
00328         rc = async_data_read_start(phone, lengths,
00329             sizeof(size_t) * (count + 1));
00330         if (rc != EOK) {
00331                 free(lengths);
00332                 return rc;
00333         }
00334 
00335         *data = malloc(lengths[count]);
00336         if (!*data) {
00337                 free(lengths);
00338                 return ENOMEM;
00339         }
00340 
00341         *strings = (measured_string_t *) malloc(sizeof(measured_string_t) *
00342             count);
00343         if (!*strings) {
00344                 free(lengths);
00345                 free(*data);
00346                 return ENOMEM;
00347         }
00348 
00349         next = *data;
00350         for (index = 0; index < count; index++) {
00351                 (*strings)[index].length = lengths[index];
00352                 if (lengths[index] > 0) {
00353                         rc = async_data_read_start(phone, next, lengths[index]);
00354                         if (rc != EOK) {
00355                                 free(lengths);
00356                                 free(data);
00357                                 free(strings);
00358                                 return rc;
00359                         }
00360                         (*strings)[index].value = next;
00361                         next += lengths[index];
00362                         *next++ = '\0';
00363                 } else {
00364                         (*strings)[index].value = NULL;
00365                 }
00366         }
00367 
00368         free(lengths);
00369         return EOK;
00370 }
00371 
00386 int
00387 measured_strings_send(int phone, const measured_string_t *strings,
00388     size_t count)
00389 {
00390         size_t *lengths;
00391         size_t index;
00392         int rc;
00393 
00394         if ((phone < 0) || (!strings) || (count <= 0))
00395                 return EINVAL;
00396 
00397         lengths = prepare_lengths(strings, count);
00398         if (!lengths)
00399                 return ENOMEM;
00400 
00401         rc = async_data_write_start(phone, lengths,
00402             sizeof(size_t) * (count + 1));
00403         if (rc != EOK) {
00404                 free(lengths);
00405                 return rc;
00406         }
00407 
00408         free(lengths);
00409 
00410         for (index = 0; index < count; index++) {
00411                 if (strings[index].length > 0) {
00412                         rc = async_data_write_start(phone, strings[index].value,
00413                             strings[index].length);
00414                         if (rc != EOK)
00415                                 return rc;
00416                 }
00417         }
00418 
00419         return EOK;
00420 }
00421 

Generated on Thu Jun 2 07:45:45 2011 for HelenOS/USB by  doxygen 1.4.7