Simple interface for Mbed Cloud Client

Dependents:  

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_uc_pal_linux_implementation_internal.c Source File

arm_uc_pal_linux_implementation_internal.c

00001 // ----------------------------------------------------------------------------
00002 // Copyright 2016-2017 ARM Ltd.
00003 //
00004 // SPDX-License-Identifier: Apache-2.0
00005 //
00006 // Licensed under the Apache License, Version 2.0 (the "License");
00007 // you may not use this file except in compliance with the License.
00008 // You may obtain a copy of the License at
00009 //
00010 //     http://www.apache.org/licenses/LICENSE-2.0
00011 //
00012 // Unless required by applicable law or agreed to in writing, software
00013 // distributed under the License is distributed on an "AS IS" BASIS,
00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015 // See the License for the specific language governing permissions and
00016 // limitations under the License.
00017 // ----------------------------------------------------------------------------
00018 
00019 #if defined(TARGET_IS_PC_LINUX)
00020 
00021 #include "update-client-pal-linux/arm_uc_pal_linux_implementation_internal.h"
00022 
00023 #include "update-client-common/arm_uc_trace.h"
00024 #include "update-client-common/arm_uc_utilities.h"
00025 #include "update-client-common/arm_uc_metadata_header_v2.h"
00026 
00027 #define __STDC_FORMAT_MACROS
00028 #include <inttypes.h>
00029 #include <stdio.h>
00030 #include <errno.h>
00031 #include <pthread.h>
00032 #include <stdlib.h>
00033 #include <sys/stat.h>
00034 #include <sys/wait.h>
00035 
00036 /* pointer to external callback handler */
00037 static ARM_UC_PAAL_UPDATE_SignalEvent_t arm_uc_pal_external_callback = NULL;
00038 
00039 linux_worker_thread_info_t linux_worker_thread = {0, PTHREAD_MUTEX_INITIALIZER};
00040 
00041 void arm_uc_pal_linux_signal_callback(uint32_t event)
00042 {
00043     if (arm_uc_pal_external_callback)
00044     {
00045         arm_uc_pal_external_callback(event);
00046     }
00047     pthread_mutex_unlock(&linux_worker_thread.mutex);
00048 }
00049 
00050 void arm_uc_pal_linux_internal_set_callback(ARM_UC_PAAL_UPDATE_SignalEvent_t callback)
00051 {
00052     arm_uc_pal_external_callback = callback;
00053 }
00054 
00055 static uint32_t arm_uc_offset = 0;
00056 static arm_uc_buffer_t* arm_uc_buffer = NULL;
00057 static arm_uc_firmware_details_t* arm_uc_details = NULL;
00058 static arm_uc_installer_details_t* arm_uc_installer = NULL;
00059 static uint32_t* arm_uc_location = NULL;
00060 static uint32_t arm_uc_location_buffer = 0;
00061 
00062 void arm_uc_pal_linux_internal_set_offset(uint32_t offset)
00063 {
00064     arm_uc_offset = offset;
00065 }
00066 
00067 void arm_uc_pal_linux_internal_set_buffer(arm_uc_buffer_t* buffer)
00068 {
00069     arm_uc_buffer = buffer;
00070 }
00071 
00072 void arm_uc_pal_linux_internal_set_details(arm_uc_firmware_details_t* details)
00073 {
00074     arm_uc_details = details;
00075 }
00076 
00077 void arm_uc_pal_linux_internal_set_installer(arm_uc_installer_details_t* details)
00078 {
00079     arm_uc_installer = details;
00080 }
00081 
00082 void arm_uc_pal_linux_internal_set_location(uint32_t* location)
00083 {
00084     if (location)
00085     {
00086         arm_uc_location_buffer = *location;
00087         arm_uc_location = &arm_uc_location_buffer;
00088     }
00089     else
00090     {
00091         arm_uc_location = NULL;
00092     }
00093 }
00094 
00095 arm_uc_error_t arm_uc_pal_linux_internal_file_path(char* buffer,
00096                                                    size_t buffer_length,
00097                                                    const char* folder,
00098                                                    const char* type,
00099                                                    uint32_t* location)
00100 {
00101     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00102 
00103     if (buffer && folder && type)
00104     {
00105         int actual_length = 0;
00106 
00107         if (location)
00108         {
00109             /* construct file path using location */
00110             actual_length = snprintf(buffer, buffer_length,
00111                                      "%s/%s_%" PRIu32 ".bin", folder, type, *location);
00112         }
00113         else
00114         {
00115             /* construct file path without location */
00116             actual_length = snprintf(buffer, buffer_length,
00117                                      "%s/%s.bin", folder, type);
00118         }
00119 
00120         /* check that the buffer is large enough */
00121         if (actual_length < buffer_length)
00122         {
00123             result.code = ERR_NONE;
00124         }
00125     }
00126 
00127     return result;
00128 }
00129 
00130 static bool arm_uc_pal_linux_internal_command(arm_ucp_worker_t* parameters,
00131                                               char* command,
00132                                               size_t command_length)
00133 {
00134     /* default to failed */
00135     bool valid = false;
00136 
00137     if (parameters && command)
00138     {
00139         /* invert status */
00140         valid = true;
00141 
00142         int length = snprintf(command,
00143                               command_length,
00144                               "%s ",
00145                               parameters->command);
00146 
00147         /* initialize remaining */
00148         int remaining = command_length - length;
00149 
00150         /* add header parameter if requested */
00151         if ((remaining > 0) && (parameters->header))
00152         {
00153             char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 };
00154 
00155             /* construct header file path */
00156             arm_uc_error_t result =
00157                 arm_uc_pal_linux_internal_file_path(file_path,
00158                                                     sizeof(file_path),
00159                                                     ARM_UC_HEADER_FOLDER_PATH,
00160                                                     "header",
00161                                                     arm_uc_location);
00162 
00163             /* generated valid file path */
00164             if (result.error == ERR_NONE)
00165             {
00166                 /* add parameter to command line */
00167                 length += snprintf(&command[length],
00168                                    remaining,
00169                                    "-h %s ",
00170                                    file_path);
00171             }
00172 
00173             /* update remaining */
00174             remaining = ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH - length;
00175 
00176             /* check validity */
00177             valid = ((result.error == ERR_NONE) && (remaining > 0));
00178         }
00179 
00180         /* add firmware parameter if requested */
00181         if ((valid) && (parameters->firmware))
00182         {
00183             char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 };
00184 
00185             /* construct firmware file path */
00186             arm_uc_error_t result =
00187                 arm_uc_pal_linux_internal_file_path(file_path,
00188                                                     sizeof(file_path),
00189                                                     ARM_UC_FIRMWARE_FOLDER_PATH,
00190                                                     "firmware",
00191                                                     arm_uc_location);
00192 
00193             /* generated valid file path */
00194             if (result.error == ERR_NONE)
00195             {
00196                 /* add parameter to command line */
00197                 length += snprintf(&command[length],
00198                                    remaining,
00199                                    "-f %s ",
00200                                    file_path);
00201             }
00202 
00203             /* update remaining */
00204             remaining = ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH - length;
00205 
00206             /* check validity */
00207             valid = ((result.error == ERR_NONE) && (remaining > 0));
00208         }
00209 
00210         /* add location parameter if requested */
00211         if ((valid) && (parameters->location))
00212         {
00213             /* add parameter to command line */
00214             length += snprintf(&command[length],
00215                                remaining,
00216                                "-l %" PRIu32 " ",
00217                                *arm_uc_location);
00218 
00219             /* update remaining */
00220             remaining = ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH - length;
00221 
00222             /* check validity */
00223             valid = (remaining > 0);
00224         }
00225 
00226         /* add offset parameter if requested */
00227         if ((valid) && (parameters->offset))
00228         {
00229             /* add parameter to command line */
00230             length += snprintf(&command[length],
00231                                remaining,
00232                                "-o %" PRIu32 " ",
00233                                arm_uc_offset);
00234 
00235             /* update remaining */
00236             remaining = ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH - length;
00237 
00238             /* check validity */
00239             valid = (remaining > 0);
00240         }
00241 
00242         /* add size parameter if requested */
00243         if ((valid) && (parameters->size))
00244         {
00245             if (arm_uc_buffer)
00246             {
00247                 /* add parameter to command line */
00248                 length += snprintf(&command[length],
00249                                    remaining,
00250                                    "-s %" PRIu32 " ",
00251                                    arm_uc_buffer->size_max);
00252 
00253                 /* update remaining */
00254                 remaining = ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH - length;
00255 
00256                 /* check validity */
00257                 valid = (remaining > 0);
00258             }
00259             else
00260             {
00261                 valid = false;
00262             }
00263         }
00264     }
00265 
00266     return valid;
00267 }
00268 
00269 arm_uc_error_t arm_uc_pal_linux_internal_read(const char* file_path,
00270                                               uint32_t offset,
00271                                               arm_uc_buffer_t* buffer)
00272 {
00273     /* default to failure result */
00274     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00275 
00276     if (file_path && buffer)
00277     {
00278         /* open file */
00279         errno = 0;
00280         FILE* descriptor = fopen(file_path, "rb");
00281 
00282         /* continue if file is open */
00283         if (descriptor != NULL)
00284         {
00285             /* set read position */
00286             int status = fseek(descriptor, offset, SEEK_SET);
00287 
00288             /* continue if position is set */
00289             if (status == 0)
00290             {
00291                 /* read buffer */
00292                 errno = 0;
00293                 size_t xfer_size = fread(buffer->ptr,
00294                                          sizeof(uint8_t),
00295                                          buffer->size,
00296                                          descriptor);
00297 
00298                 /* set buffer size if read succeeded */
00299                 status = ferror(descriptor);
00300 
00301                 if (status == 0)
00302                 {
00303                     buffer->size = xfer_size;
00304 
00305                     /* set successful result */
00306                     result.code = ERR_NONE;
00307                 }
00308                 else
00309                 {
00310                     /* set error code if read failed */
00311                     UC_PAAL_ERR_MSG("failed to read %s: %s", file_path, strerror(errno));
00312                     buffer->size = 0;
00313                 }
00314 
00315                 /* close file after read */
00316                 fclose(descriptor);
00317             }
00318             else
00319             {
00320                 UC_PAAL_ERR_MSG("failed to seek in: %s", file_path);
00321             }
00322         }
00323         else
00324         {
00325             UC_PAAL_ERR_MSG("failed to open %s: %s", file_path, strerror(errno));
00326         }
00327     }
00328 
00329     return result;
00330 }
00331 
00332 arm_uc_error_t arm_uc_pal_linux_internal_read_header(uint32_t* location,
00333                                                      arm_uc_firmware_details_t* details)
00334 {
00335     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00336 
00337     if (details)
00338     {
00339         /* construct header file path */
00340         char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 };
00341 
00342         result = arm_uc_pal_linux_internal_file_path(file_path,
00343                                                      ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH,
00344                                                      ARM_UC_HEADER_FOLDER_PATH,
00345                                                      "header",
00346                                                      location);
00347 
00348         /* file path is valid */
00349         if (result.error == ERR_NONE)
00350         {
00351             /* allocate external header sized read buffer since it will be
00352                large enough to hold either an internal or external header.
00353              */
00354             uint8_t read_buffer[ARM_UC_EXTERNAL_HEADER_SIZE_V2] = { 0 };
00355 
00356             arm_uc_buffer_t buffer = {
00357                 .size_max = sizeof(read_buffer),
00358                 .size     = sizeof(read_buffer),
00359                 .ptr      = read_buffer
00360             };
00361 
00362             /* read metadata header */
00363             result = arm_uc_pal_linux_internal_read(file_path, 0, &buffer);
00364 
00365             /* check return code */
00366             if (result.error == ERR_NONE)
00367             {
00368                 UC_PAAL_TRACE("header bytes: %u", buffer.size);
00369 
00370                 /* read out header magic */
00371                 uint32_t headerMagic = arm_uc_parse_uint32(&read_buffer[0]);
00372 
00373                 /* read out header magic */
00374                 uint32_t headerVersion = arm_uc_parse_uint32(&read_buffer[4]);
00375 
00376                 /* choose version to decode */
00377                 if ((headerMagic == ARM_UC_INTERNAL_HEADER_MAGIC_V2) &&
00378                     (headerVersion == ARM_UC_INTERNAL_HEADER_VERSION_V2) &&
00379                     (buffer.size == ARM_UC_INTERNAL_HEADER_SIZE_V2))
00380                 {
00381                     result = arm_uc_parse_internal_header_v2(read_buffer, details);
00382                 }
00383                 else if ((headerMagic == ARM_UC_EXTERNAL_HEADER_MAGIC_V2) &&
00384                          (headerVersion == ARM_UC_EXTERNAL_HEADER_VERSION_V2) &&
00385                          (buffer.size == ARM_UC_EXTERNAL_HEADER_SIZE_V2))
00386                 {
00387                     result = arm_uc_parse_external_header_v2(read_buffer, details);
00388                 }
00389                 else
00390                 {
00391                     UC_PAAL_ERR_MSG("invalid header in slot %" PRIu32, location);
00392 
00393                     /* invalid header format */
00394                     result.code = ERR_INVALID_PARAMETER;
00395                 }
00396             }
00397             else
00398             {
00399                 /* unsuccessful read */
00400                 UC_PAAL_ERR_MSG("unable to read header in slot %" PRIX32, location);
00401             }
00402         }
00403         else
00404         {
00405             UC_PAAL_ERR_MSG("header file name and path too long");
00406         }
00407     }
00408 
00409     return result;
00410 }
00411 
00412 arm_uc_error_t arm_uc_pal_linux_internal_read_installer(arm_uc_installer_details_t* details)
00413 {
00414     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00415 
00416     if (details)
00417     {
00418         /* construct file path */
00419         char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 };
00420 
00421         result = arm_uc_pal_linux_internal_file_path(file_path,
00422                                                      ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH,
00423                                                      ARM_UC_INSTALLER_FOLDER_PATH,
00424                                                      "installer",
00425                                                      NULL);
00426 
00427         /* file path is valid */
00428         if (result.error == ERR_NONE)
00429         {
00430             uint8_t read_buffer[2 * sizeof(arm_uc_hash_t) + sizeof(uint32_t)] = { 0 };
00431 
00432             arm_uc_buffer_t buffer = {
00433                 .size_max = sizeof(read_buffer),
00434                 .size     = 0,
00435                 .ptr      = read_buffer
00436             };
00437 
00438             /* read installer details */
00439             result = arm_uc_pal_linux_internal_read(file_path, 0, &buffer);
00440 
00441             UC_PAAL_TRACE("installer bytes: %u", buffer.size);
00442 
00443             /* check return code */
00444             if ((result.error == ERR_NONE) &&
00445                 (buffer.size == sizeof(read_buffer)))
00446             {
00447                 memcpy(details->arm_hash,
00448                        buffer.ptr,
00449                        sizeof(arm_uc_hash_t));
00450 
00451                 memcpy(details->oem_hash,
00452                        &buffer.ptr[sizeof(arm_uc_hash_t)],
00453                        sizeof(arm_uc_hash_t));
00454 
00455                 details->layout = arm_uc_parse_uint32(&buffer.ptr[2 * sizeof(arm_uc_hash_t)]);
00456             }
00457             else
00458             {
00459                 /* unsuccessful read */
00460                 UC_PAAL_ERR_MSG("unable to read installer details");
00461             }
00462         }
00463         else
00464         {
00465             UC_PAAL_ERR_MSG("installer file name and path too long");
00466         }
00467     }
00468 
00469     return result;
00470 }
00471 
00472 arm_uc_error_t arm_uc_pal_linux_internal_write_header(uint32_t* location,
00473                                                       const arm_uc_firmware_details_t* details)
00474 {
00475     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00476 
00477     if (details)
00478     {
00479         /* allocate external header sized buffer since it will be
00480            large enough to hold either an internal or external header.
00481          */
00482         uint8_t temp_buffer[ARM_UC_EXTERNAL_HEADER_SIZE_V2] = { 0 };
00483 
00484         arm_uc_buffer_t buffer = {
00485             .size_max = sizeof(temp_buffer),
00486             .size     = 0,
00487             .ptr      = temp_buffer
00488         };
00489 
00490         /* encode firmware details in buffer */
00491 #if ARM_UC_USE_EXTERNAL_HEADER
00492         result = arm_uc_create_external_header_v2(details, &buffer);
00493 #else
00494         result = arm_uc_create_internal_header_v2(details, &buffer);
00495 #endif
00496 
00497         /* write header file */
00498         if (result.error == ERR_NONE)
00499         {
00500             char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 };
00501 
00502             /* construct header file path */
00503             result = arm_uc_pal_linux_internal_file_path(file_path,
00504                                                          ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH,
00505                                                          ARM_UC_HEADER_FOLDER_PATH,
00506                                                          "header",
00507                                                          location);
00508 
00509             if (result.error == ERR_NONE)
00510             {
00511                 /* inverse result */
00512                 result.code = ERR_INVALID_PARAMETER;
00513 
00514                 /* open file and get file handler */
00515                 errno = 0;
00516                 FILE* file = fopen(file_path, "wb");
00517 
00518                 if (file != NULL)
00519                 {
00520                     /* write buffer to file */
00521                     size_t xfer_size = fwrite(buffer.ptr,
00522                                               sizeof(uint8_t),
00523                                               buffer.size,
00524                                               file);
00525 
00526                     UC_PAAL_TRACE("written: %u", xfer_size);
00527 
00528                     /* close file after write */
00529                     int status = fclose(file);
00530 
00531                     if ((xfer_size == buffer.size) &&
00532                         (status != EOF))
00533                     {
00534                         /* set return code if write was successful */
00535                         result.code = ERR_NONE;
00536                     }
00537                     else
00538                     {
00539                         UC_PAAL_ERR_MSG("failed to write header");
00540                     }
00541                 }
00542                 else
00543                 {
00544                     UC_PAAL_ERR_MSG("file open failed: %s", strerror(errno));
00545                 }
00546             }
00547             else
00548             {
00549                 UC_PAAL_ERR_MSG("header file name and path too long");
00550             }
00551         }
00552         else
00553         {
00554             UC_PAAL_ERR_MSG("header too large for buffer");
00555         }
00556 
00557     }
00558 
00559     return result;
00560 }
00561 
00562 /**
00563  * @brief Function to run script in a worker thread before file operations.
00564  *
00565  * @param params Pointer to arm_ucp_worker_t struct.
00566  */
00567 void* arm_uc_pal_linux_extended_pre_worker(void* params)
00568 {
00569     /* default to failure */
00570     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00571 
00572     /* get parameters */
00573     arm_ucp_worker_t* parameters = (arm_ucp_worker_t*) params;
00574 
00575     /* file path to script result */
00576     char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 };
00577 
00578     /* construct script command */
00579     char command[ARM_UC_MAXIMUM_COMMAND_LENGTH] = { 0 };
00580 
00581     int error = 0;
00582     int valid = arm_uc_pal_linux_internal_command(parameters,
00583                                                   command,
00584                                                   ARM_UC_MAXIMUM_COMMAND_LENGTH);
00585 
00586     /* command is valid */
00587     if (valid)
00588     {
00589         UC_PAAL_TRACE("Extended pre-script command: %s", command);
00590 
00591         /* execute script */
00592         errno = 0;
00593         FILE* pipe = popen(command, "r");
00594 
00595         if (pipe)
00596         {
00597             /* read pipe */
00598             size_t xfer_size = fread(file_path,
00599                                      sizeof(uint8_t),
00600                                      ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH,
00601                                      pipe);
00602 
00603             /* trim non-printable characters */
00604             for (size_t index = 0; index < xfer_size; index++)
00605             {
00606                 /* space is the first printable character */
00607                 if (file_path[index] < ' ')
00608                 {
00609                     /* truncate string */
00610                     file_path[index] = '\0';
00611                     break;
00612                 }
00613             }
00614 
00615             int status = 0;
00616 
00617             /* check fread error status */
00618             status = ferror(pipe);
00619             if (status == 0)
00620             {
00621                 /* Wait for child thread termination and check exit status */
00622                 status = pclose(pipe);
00623 
00624                 /* make sure child thread terminated correctly and scirpt exit status is 0 */
00625                 if (status != -1 && WIFEXITED(status))
00626                 {
00627                     if (WEXITSTATUS(status) == 0)
00628                     {
00629                         /* switch from boolean result to arm_uc_error_t */
00630                         result.code = ERR_NONE;
00631                     }
00632                     else
00633                     {
00634                         UC_PAAL_ERR_MSG("Script exited with non-zero status %" PRId32, status);
00635                     }
00636                 }
00637                 else
00638                 {
00639                     UC_PAAL_ERR_MSG("pipe terminated incorrectly %" PRId32, status);
00640                 }
00641             }
00642             else
00643             {
00644                 UC_PAAL_ERR_MSG("failed to read pipe: %" PRId32, status);
00645             }
00646         }
00647         else
00648         {
00649             UC_PAAL_ERR_MSG("failed to execute script: %" PRId32, errno);
00650         }
00651     }
00652 
00653     /* file path is valid */
00654     if (result.error == ERR_NONE)
00655     {
00656         /* invert status */
00657         result.code = ERR_INVALID_PARAMETER;
00658 
00659         extern arm_ucp_worker_config_t arm_uc_worker_parameters;
00660 
00661         /* perform read operation */
00662         if ((parameters == arm_uc_worker_parameters.read) &&
00663             (arm_uc_buffer != NULL))
00664         {
00665             result = arm_uc_pal_linux_internal_read(file_path, 0, arm_uc_buffer);
00666 
00667             /* reset global buffer */
00668             arm_uc_buffer = NULL;
00669         }
00670 
00671         /* read details */
00672         if ((parameters == arm_uc_worker_parameters.details) &&
00673                  (arm_uc_details != NULL))
00674         {
00675             result = arm_uc_pal_linux_internal_read_header(arm_uc_location,
00676                                                            arm_uc_details);
00677 
00678             /* reset global details pointer */
00679             arm_uc_details = NULL;
00680         }
00681 
00682         /* read active details */
00683         if ((parameters == arm_uc_worker_parameters.active_details) &&
00684                  (arm_uc_details != NULL))
00685         {
00686             result = arm_uc_pal_linux_internal_read_header(NULL,
00687                                                            arm_uc_details);
00688 
00689             /* reset global details pointer */
00690             arm_uc_details = NULL;
00691         }
00692 
00693         /* read installer details */
00694         if ((parameters == arm_uc_worker_parameters.installer) &&
00695                  (arm_uc_installer != NULL))
00696         {
00697             result = arm_uc_pal_linux_internal_read_installer(arm_uc_installer);
00698 
00699             /* reset global installer pointer */
00700             arm_uc_installer = NULL;
00701         }
00702     }
00703 
00704     if (result.error == ERR_NONE)
00705     {
00706         UC_PAAL_TRACE("pre-script complete");
00707 
00708         arm_uc_pal_linux_signal_callback(parameters->success_event);
00709     }
00710     else
00711     {
00712         UC_PAAL_ERR_MSG("pre-script failed");
00713 
00714         arm_uc_pal_linux_signal_callback(parameters->failure_event);
00715     }
00716 }
00717 
00718 /**
00719  * @brief Function to run script in a worker thread before file operations.
00720  *
00721  * @param params Pointer to arm_ucp_worker_t struct.
00722  */
00723 void* arm_uc_pal_linux_extended_post_worker(void* params)
00724 {
00725     /* get parameters */
00726     arm_ucp_worker_t* parameters = (arm_ucp_worker_t*) params;
00727 
00728     /* construct script command */
00729     char command[ARM_UC_MAXIMUM_COMMAND_LENGTH] = { 0 };
00730 
00731     int error = 0;
00732     int32_t event = 0;
00733     int valid = arm_uc_pal_linux_internal_command(parameters,
00734                                                   command,
00735                                                   ARM_UC_MAXIMUM_COMMAND_LENGTH);
00736 
00737     if (valid)
00738     {
00739         UC_PAAL_TRACE("Extended post-script command: %s", command);
00740 
00741         /* execute script command */
00742         error = system(command);
00743         error = WEXITSTATUS(error);
00744 
00745         /* update valid flag */
00746         valid = (error == 0);
00747     }
00748 
00749     if (valid)
00750     {
00751         UC_PAAL_TRACE("post-script completed");
00752 
00753         event = parameters->success_event;
00754 
00755         /* execute the post runner if it exists and the script succeeded */
00756         if (parameters->post_runner)
00757         {
00758             event = parameters->post_runner();
00759             UC_PAAL_TRACE("post runner returned event %" PRId32, event);
00760         }
00761     }
00762     else
00763     {
00764         UC_PAAL_ERR_MSG("post-script failed: %" PRId32, error);
00765 
00766         event = parameters->failure_event;
00767     }
00768 
00769     arm_uc_pal_linux_signal_callback(event);
00770 }
00771 
00772 #endif