Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers storage.c Source File

storage.c

00001 // ----------------------------------------------------------------------------
00002 // Copyright 2016-2017 ARM Ltd.
00003 //
00004 // Licensed under the Apache License, Version 2.0 (the "License");
00005 // you may not use this file except in compliance with the License.
00006 // You may obtain a copy of the License at
00007 //
00008 //     http://www.apache.org/licenses/LICENSE-2.0
00009 //
00010 // Unless required by applicable law or agreed to in writing, software
00011 // distributed under the License is distributed on an "AS IS" BASIS,
00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 // See the License for the specific language governing permissions and
00014 // limitations under the License.
00015 // ----------------------------------------------------------------------------
00016 
00017 #include <stdbool.h>
00018 #include "pv_error_handling.h"
00019 #include "storage.h"
00020 #include "esfs.h"
00021 
00022 static kcm_status_e  error_handler(esfs_result_e esfs_status)
00023 {
00024     switch (esfs_status) {
00025         case ESFS_SUCCESS:
00026             return KCM_STATUS_SUCCESS;
00027         case ESFS_INVALID_PARAMETER:
00028             return KCM_STATUS_INVALID_PARAMETER;
00029         case ESFS_BUFFER_TOO_SMALL:
00030             return KCM_STATUS_INSUFFICIENT_BUFFER;
00031         case ESFS_EXISTS:
00032             return KCM_STATUS_FILE_EXIST;
00033         case ESFS_NOT_EXISTS:
00034             return KCM_STATUS_ITEM_NOT_FOUND;
00035         case ESFS_INVALID_FILE_VERSION:
00036             return KCM_STATUS_INVALID_FILE_VERSION;
00037         case ESFS_CMAC_DOES_NOT_MATCH:
00038             return KCM_STATUS_FILE_CORRUPTED;
00039         case ESFS_ERROR:
00040             return KCM_STATUS_STORAGE_ERROR;
00041         case ESFS_HASH_CONFLICT:
00042             return KCM_STATUS_FILE_NAME_CORRUPTED;
00043         case ESFS_FILE_OPEN_FOR_READ:
00044         case ESFS_FILE_OPEN_FOR_WRITE:
00045             return KCM_STATUS_INVALID_FILE_ACCESS_MODE;
00046         default:
00047             return  KCM_STATUS_UNKNOWN_STORAGE_ERROR;
00048     }
00049 }
00050 
00051 
00052 static bool is_file_accessible(const kcm_ctx_s *ctx)
00053 {
00054     // FIXME - We need to check file access availability by comparing KCM context TLVs vs the target file header stored in ESFS that contains
00055     //         TLVs and access rights. In order to retrieve ESFS file TLVs and access rights we should use the following methods
00056     //         that are currently not implemented:
00057     //              - esfs_get_meta_data_qty
00058     //              - esfs_get_meta_data_types
00059     //              - esfs_get_meta_data_buffer_size
00060     //              - esfs_read_meta_data
00061     //              - esfs_get_meta_data_qty
00062 
00063     ctx = ctx;                 // currently unused
00064 
00065     return true;
00066 }
00067 
00068 kcm_status_e  storage_init()
00069 {
00070     esfs_result_e esfs_status;
00071 
00072     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00073 
00074     esfs_status = esfs_init();
00075     SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed initializing ESFS (esfs_status %d)", esfs_status);
00076 
00077     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00078 
00079     return KCM_STATUS_SUCCESS;
00080 }
00081 
00082 kcm_status_e  storage_finalize()
00083 {
00084     esfs_result_e esfs_status;
00085 
00086     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00087 
00088     esfs_status = esfs_finalize();
00089     SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed finalizing ESFS (esfs_status %d)", esfs_status);
00090 
00091     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00092 
00093     return KCM_STATUS_SUCCESS;
00094 }
00095 
00096 kcm_status_e  storage_reset()
00097 {
00098     esfs_result_e esfs_status;
00099 
00100     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00101 
00102     esfs_status = esfs_reset();
00103     SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed reset ESFS (esfs_status %d)", esfs_status);
00104 
00105     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00106 
00107     return KCM_STATUS_SUCCESS;
00108 }
00109 
00110 
00111 kcm_status_e  storage_factory_reset()
00112 {
00113     esfs_result_e esfs_status;
00114 
00115     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00116 
00117     esfs_status = esfs_factory_reset();
00118     SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed factory reset ESFS (esfs_status %d)", esfs_status);
00119 
00120     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00121 
00122     return KCM_STATUS_SUCCESS;
00123 }
00124 
00125 kcm_status_e  storage_file_write(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length, const uint8_t *data, size_t data_length, const kcm_meta_data_list_s *kcm_meta_data_list, bool is_factory, bool is_encrypted)
00126 {
00127     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00128     kcm_status_e  close_file_status = KCM_STATUS_SUCCESS;
00129 
00130     kcm_status = storage_file_create(ctx, file_name, file_name_length, kcm_meta_data_list, is_factory, is_encrypted);
00131     SA_PV_ERR_RECOVERABLE_RETURN_IF(kcm_status != KCM_STATUS_SUCCESS, kcm_status, "Failed to create new file");
00132 
00133     kcm_status = storage_file_write_with_ctx(ctx, data, data_length);// we don't check error because we need to close the file in any case
00134 
00135     // Data is only guaranteed to be flushed to the media on efs_close.
00136     close_file_status = storage_file_close(ctx);
00137 
00138     if (kcm_status != KCM_STATUS_SUCCESS) { // delete the file if didn't succeed to write
00139         (void)storage_file_delete(ctx, file_name, file_name_length);
00140         SA_PV_ERR_RECOVERABLE_RETURN(kcm_status, "Failed to write data");
00141     }
00142 
00143     SA_PV_ERR_RECOVERABLE_RETURN_IF(close_file_status != KCM_STATUS_SUCCESS, close_file_status, "Failed to close file");
00144 
00145     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00146 
00147     return kcm_status;
00148 }
00149 
00150 kcm_status_e  storage_file_size_get(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length, size_t *file_size_out)
00151 {
00152     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00153     kcm_status_e  close_staus = KCM_STATUS_SUCCESS;
00154 
00155     SA_PV_LOG_TRACE_FUNC_ENTER("file_name_length=%" PRIu32 "", (uint32_t)file_name_length);
00156 
00157     kcm_status = storage_file_open(ctx, file_name, file_name_length);
00158     if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
00159         goto exit;
00160     }
00161     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to open the given file");
00162 
00163     kcm_status = storage_file_size_get_with_ctx(ctx, file_size_out);
00164     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, exit, "Failed getting file size");
00165 
00166 exit:
00167     if (kcm_status != KCM_STATUS_ITEM_NOT_FOUND) {
00168         close_staus = storage_file_close(ctx);
00169     }
00170     if (kcm_status == KCM_STATUS_SUCCESS) {
00171         kcm_status = close_staus;
00172     }
00173 
00174     return kcm_status;
00175 }
00176 
00177 kcm_status_e  storage_file_read(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length, uint8_t *buffer_out, size_t buffer_size, size_t *buffer_actual_size_out)
00178 {
00179     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00180     kcm_status_e  close_status = KCM_STATUS_SUCCESS;
00181 
00182     kcm_status = storage_file_open(ctx, file_name, file_name_length);
00183     if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
00184         goto exit;
00185     }
00186     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to open the given file");
00187 
00188     kcm_status = storage_file_read_with_ctx(ctx, buffer_out, buffer_size, buffer_actual_size_out);
00189     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, exit, "Failed ti read file");
00190 
00191 exit:
00192     if (kcm_status != KCM_STATUS_ITEM_NOT_FOUND) {
00193         close_status = storage_file_close(ctx);
00194     }
00195     if (kcm_status == KCM_STATUS_SUCCESS) {
00196         kcm_status = close_status;
00197     }
00198 
00199     return kcm_status;
00200 }
00201 
00202 kcm_status_e  storage_file_delete(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length)
00203 {
00204     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00205     esfs_result_e esfs_status;
00206     uint16_t esfs_mode = 0;        // FIXME - Unused, yet implemented
00207     bool success;
00208 
00209     SA_PV_LOG_TRACE_FUNC_ENTER("file_name_length=%" PRIu32 "", (uint32_t)file_name_length);
00210 
00211     SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid file name context");
00212     SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name_length == 0), KCM_STATUS_INVALID_PARAMETER, "Got empty file name");
00213 
00214     esfs_status = esfs_open(file_name, file_name_length, &esfs_mode, &ctx->esfs_file_h);
00215 
00216     //file does not exists, exit from delete function
00217     if (esfs_status == ESFS_NOT_EXISTS) {
00218         return error_handler(esfs_status);
00219     }
00220 
00221     if (esfs_status != ESFS_SUCCESS) { //file exists but there is some corruption. We will delete the file without checking it's permissions
00222         SA_PV_LOG_ERR("The file exists but corrupted. Delete it without checking permissions");
00223         esfs_status = ESFS_SUCCESS;
00224 
00225     } else { // check permissions
00226         success = is_file_accessible(ctx);
00227         if (!success) {
00228             SA_PV_LOG_ERR("Caller has no access rights to the given file");
00229             kcm_status = KCM_STATUS_NOT_PERMITTED;
00230         }
00231 
00232         esfs_status = esfs_close(&ctx->esfs_file_h);
00233         SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed closing file (esfs_status %d)", esfs_status);
00234 
00235         if (kcm_status == KCM_STATUS_NOT_PERMITTED) {
00236             return kcm_status;
00237         }
00238     }
00239 
00240     // Delete the file
00241     esfs_status = esfs_delete(file_name, file_name_length);
00242     SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed deleting file (esfs_status %d)", esfs_status);
00243 
00244     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00245 
00246     return kcm_status;
00247 }
00248 
00249 
00250 kcm_status_e  storage_file_create(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length, const kcm_meta_data_list_s *kcm_meta_data_list, bool is_factory, bool is_encrypted)
00251 {
00252     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00253     esfs_result_e esfs_status;
00254     esfs_tlv_item_t meta_data_items[KCM_MD_TYPE_MAX_SIZE];
00255     size_t meta_data_count = 0;
00256     uint16_t access_flags = 0; // owner, signed, encrypted, factory, extended ACL bit mask
00257 
00258     SA_PV_LOG_TRACE_FUNC_ENTER("file_name_length=%" PRIu32 " ", (uint32_t)file_name_length);
00259 
00260     SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context");
00261     SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid file name context");
00262     SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name_length == 0), KCM_STATUS_INVALID_PARAMETER, "Got empty file name");
00263 
00264     memset(ctx, 0, sizeof(kcm_ctx_s));
00265 
00266     if (is_factory) {
00267         access_flags |= ESFS_FACTORY_VAL;
00268     }
00269     if (is_encrypted) {
00270         access_flags |= ESFS_ENCRYPTED;
00271     }
00272 
00273     // Convert kcm_meta_data_list to array of esfs_tlv_item
00274     if (kcm_meta_data_list != NULL) {
00275         for (meta_data_count = 0; meta_data_count < kcm_meta_data_list->meta_data_count; meta_data_count++) {
00276             meta_data_items[meta_data_count].type = kcm_meta_data_list->meta_data[meta_data_count].type;
00277             meta_data_items[meta_data_count].length_in_bytes = (uint16_t)kcm_meta_data_list->meta_data[meta_data_count].data_size;
00278             meta_data_items[meta_data_count].value = (void*)kcm_meta_data_list->meta_data[meta_data_count].data;
00279         }
00280     }
00281 
00282     esfs_status = esfs_create(file_name, file_name_length, meta_data_items, meta_data_count, access_flags, &ctx->esfs_file_h);
00283     SA_PV_ERR_RECOVERABLE_GOTO_IF((esfs_status == ESFS_EXISTS), kcm_status = KCM_STATUS_FILE_EXIST, Exit, "File already exist in ESFS (esfs_status %" PRIu32 ")", (uint32_t)esfs_status);
00284     SA_PV_ERR_RECOVERABLE_GOTO_IF((esfs_status != ESFS_SUCCESS), kcm_status = error_handler(esfs_status), Exit, "Failed creating file (esfs_status %" PRIu32 ")", (uint32_t)esfs_status);
00285 
00286 Exit:
00287     if (kcm_status != KCM_STATUS_SUCCESS) {
00288         memset(ctx, 0, sizeof(kcm_ctx_s));
00289     }
00290 
00291     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00292 
00293     return kcm_status;
00294 }
00295 
00296 /** Open existing file
00297 *
00298 *   @param ctx KCM operation context.
00299 *   @param file_name A binary blob that uniquely identifies the file
00300 *   @param file_name_length The binary blob length in bytes.
00301 @param is_factory True if KCM item is factory item, or false otherwise
00302 @param is_encrypted True if KCM item should be encrypted, or false otherwise
00303 *
00304 *   @returns
00305 *       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
00306 */
00307 kcm_status_e  storage_file_open(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length)
00308 {
00309 
00310     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00311     esfs_result_e esfs_status;
00312     uint16_t esfs_mode = 0;        // FIXME - Unused, yet implemented
00313     bool success;
00314 
00315     SA_PV_LOG_TRACE_FUNC_ENTER("file_name_length=%" PRIu32 "", (uint32_t)file_name_length);
00316 
00317     SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context");
00318     SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid file name context");
00319     SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name_length == 0), KCM_STATUS_INVALID_PARAMETER, "Got empty file name");
00320 
00321     memset(ctx, 0, sizeof(kcm_ctx_s));
00322 
00323     esfs_status = esfs_open(file_name, file_name_length, &esfs_mode, &ctx->esfs_file_h);
00324     if (esfs_status == ESFS_NOT_EXISTS) {
00325         kcm_status = error_handler(esfs_status);
00326         goto Exit;
00327     }
00328     SA_PV_ERR_RECOVERABLE_GOTO_IF((esfs_status != ESFS_SUCCESS), kcm_status = error_handler(esfs_status), Exit, "Failed opening file (esfs_status %d)", esfs_status);
00329 
00330     success = is_file_accessible(ctx);
00331     if (!success) {
00332         kcm_status = KCM_STATUS_NOT_PERMITTED;
00333         esfs_close(&ctx->esfs_file_h);
00334         memset(ctx, 0, sizeof(kcm_ctx_s));
00335     }
00336     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, Exit, "Caller has no access rights to the given file");
00337 
00338 Exit:
00339     if (kcm_status != KCM_STATUS_SUCCESS) {
00340         memset(ctx, 0, sizeof(kcm_ctx_s));
00341     }
00342     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00343 
00344     return kcm_status;
00345 }
00346 
00347 /** Close file in storage
00348 *
00349 *   @param ctx KCM operation context.
00350 @param is_factory True if KCM item is factory item, or false otherwise
00351 @param is_encrypted True if KCM item should be encrypted, or false otherwise
00352 *
00353 *   @returns
00354 *       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
00355 */
00356 kcm_status_e  storage_file_close(kcm_ctx_s *ctx)
00357 {
00358     esfs_result_e esfs_status;
00359 
00360     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00361 
00362     SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context");
00363 
00364     // Data is only guaranteed to be flushed to the media on efs_close.
00365     esfs_status = esfs_close(&ctx->esfs_file_h);
00366     SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed closing file (esfs_status %d)", esfs_status);
00367 
00368     memset(ctx, 0, sizeof(kcm_ctx_s));
00369     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00370 
00371     return KCM_STATUS_SUCCESS;
00372 }
00373 
00374 
00375 kcm_status_e  storage_file_write_with_ctx(kcm_ctx_s *ctx, const uint8_t *data, size_t data_length)
00376 {
00377     esfs_result_e esfs_status;
00378 
00379     SA_PV_LOG_TRACE_FUNC_ENTER("data_length=%" PRIu32 "", (uint32_t)data_length);
00380 
00381     SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context");
00382     SA_PV_ERR_RECOVERABLE_RETURN_IF(((data == NULL) && (data_length > 0)), KCM_STATUS_INVALID_PARAMETER, "Provided NULL data buffer and data_length greater than 0");
00383 
00384     if (data_length != 0) {
00385         esfs_status = esfs_write(&ctx->esfs_file_h, data, data_length);
00386         SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed writing (%" PRIu32 " B) size to file (esfs_status %" PRIu32 ")", (uint32_t)data_length, (uint32_t)esfs_status);
00387     }
00388 
00389     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00390 
00391     return KCM_STATUS_SUCCESS;
00392 
00393 }
00394 
00395 kcm_status_e  storage_file_size_get_with_ctx(kcm_ctx_s *ctx, size_t *file_size_out)
00396 {
00397     esfs_result_e esfs_status;
00398 
00399     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00400 
00401     SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context");
00402     SA_PV_ERR_RECOVERABLE_RETURN_IF((file_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to file size");
00403 
00404     esfs_status = esfs_file_size(&ctx->esfs_file_h, file_size_out);
00405     SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed getting file size (esfs_status %d)", esfs_status);
00406 
00407     ctx->is_file_size_checked = true;
00408     ctx->file_size = *file_size_out;
00409 
00410     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00411 
00412     return KCM_STATUS_SUCCESS;
00413 }
00414 
00415 
00416 kcm_status_e  storage_file_read_with_ctx(kcm_ctx_s *ctx, uint8_t *buffer_out, size_t buffer_size, size_t *buffer_actual_size_out)
00417 {
00418     esfs_result_e esfs_status;
00419     kcm_status_e  kcm_status;
00420 
00421     SA_PV_LOG_TRACE_FUNC_ENTER("buffer_size=%" PRIu32 "", (uint32_t)buffer_size);
00422 
00423     SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context");
00424     SA_PV_ERR_RECOVERABLE_RETURN_IF((buffer_out == NULL && buffer_size != 0), KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to read buffer");
00425     SA_PV_ERR_RECOVERABLE_RETURN_IF((buffer_actual_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to output size");
00426 
00427     *buffer_actual_size_out = 0;
00428 
00429     if (ctx->is_file_size_checked == false) {
00430         kcm_status = storage_file_size_get_with_ctx(ctx, buffer_actual_size_out);
00431         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed getting file data size (kcm_status %d)", kcm_status);
00432     }
00433 
00434     SA_PV_ERR_RECOVERABLE_RETURN_IF((buffer_size < ctx->file_size), KCM_STATUS_INSUFFICIENT_BUFFER, "Buffer too small");
00435 
00436     if (ctx->file_size != 0) {
00437         esfs_status = esfs_read(&ctx->esfs_file_h, buffer_out, buffer_size, buffer_actual_size_out);
00438         SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed reading file data (esfs_status %d)", esfs_status);
00439     }
00440 
00441     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00442 
00443     return KCM_STATUS_SUCCESS;
00444 }
00445 
00446 static kcm_status_e  storage_file_get_meta_data_size_and_index(kcm_ctx_s *ctx, kcm_meta_data_type_e type, size_t *meta_data_size_out, uint32_t *meta_data_index_out)
00447 {
00448     esfs_result_e esfs_status;
00449     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00450     esfs_tlv_properties_t *meta_data_properties = NULL;
00451     uint32_t index = 0;
00452 
00453     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00454 
00455     SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context");
00456     SA_PV_ERR_RECOVERABLE_RETURN_IF((meta_data_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to meta_data_size_out");
00457     SA_PV_ERR_RECOVERABLE_RETURN_IF((meta_data_index_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to meta_data_index_out");
00458     SA_PV_ERR_RECOVERABLE_RETURN_IF((type >= KCM_MD_TYPE_MAX_SIZE), KCM_STATUS_INVALID_PARAMETER, "Invalid meta data type");
00459 
00460     esfs_status = esfs_get_meta_data_properties(&ctx->esfs_file_h, &meta_data_properties);
00461     SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed reading meta data properties (esfs_status %d)", esfs_status);
00462 
00463     for (index = 0; index < meta_data_properties->number_of_items; index++) {
00464         if (type == meta_data_properties->tlv_items[index].type) {
00465 
00466             *meta_data_size_out = (size_t)meta_data_properties->tlv_items[index].length_in_bytes;
00467             *meta_data_index_out = index;
00468             kcm_status = KCM_STATUS_SUCCESS;
00469             break;
00470         }
00471     }
00472 
00473     if (index >= meta_data_properties->number_of_items) {
00474         return KCM_STATUS_META_DATA_NOT_FOUND;
00475     }
00476 
00477     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00478     return kcm_status;
00479 }
00480 
00481 kcm_status_e  storage_file_get_meta_data_size(kcm_ctx_s *ctx, kcm_meta_data_type_e type, size_t *meta_data_size_out)
00482 {
00483     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00484     uint32_t index = 0;
00485 
00486     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00487 
00488     kcm_status = storage_file_get_meta_data_size_and_index(ctx, type, meta_data_size_out, &index);
00489 
00490     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00491     return kcm_status;
00492 }
00493 
00494 kcm_status_e  storage_file_read_meta_data_by_type(kcm_ctx_s *ctx, kcm_meta_data_type_e type, uint8_t *buffer_out, size_t buffer_size, size_t *buffer_actual_size_out)
00495 {
00496     esfs_result_e esfs_status;
00497     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00498     esfs_tlv_item_t meta_data_item;
00499     uint32_t index = 0;
00500 
00501     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00502 
00503     SA_PV_ERR_RECOVERABLE_RETURN_IF(buffer_out == NULL, KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to kcm_meta_data");
00504 
00505     kcm_status = storage_file_get_meta_data_size_and_index(ctx, type, buffer_actual_size_out, &index);
00506     if (kcm_status == KCM_STATUS_META_DATA_NOT_FOUND) {
00507         return kcm_status;
00508     }
00509     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed reading meta data size and index");
00510 
00511     // return error in case the data buffer to read is too small
00512     SA_PV_ERR_RECOVERABLE_RETURN_IF((buffer_size < *buffer_actual_size_out), KCM_STATUS_INSUFFICIENT_BUFFER, "Data buffer to read is too small");
00513 
00514     meta_data_item.value = buffer_out;
00515     esfs_status = esfs_read_meta_data(&ctx->esfs_file_h, index, &meta_data_item);
00516     SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed reading meta data (esfs_status %d)", esfs_status);
00517 
00518     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00519 
00520     return kcm_status;
00521 }
00522